int ncomms;
struct resolver_if *resolver;
struct log_if *log;
+ struct hash_if *defhash;
struct random_if *random;
struct privcache_if *privkeys;
struct sigprivkey_if *privkey_fixed;
int logcl_enoent)
{
struct peer_keyset *atsuffix=
- keyset_load(file,&st->scratch,st->log,logcl_enoent);
+ keyset_load(file,&st->scratch,st->log,logcl_enoent,st->defhash);
if (!atsuffix) return;
if (st->peerkeys_current &&
* may be incomplete, unverified, or even malicious
* only secnet may write or remove.
*
+ * <F>~tmp update file from config manager, only mss may
+ * write or rename
+ *
* secnet discards updates that are not more recent than (by
* serial) the live file. But it may not process updates
* immediately.
* write: rename something onto update
* read: read update,proc,live in that order and take max
*
+ * We support only one concurrent secnet, one concurrent
+ * writing make-secnet-sites, and any number of readers.
+ * We want to maintain a live file at all times as that
+ * is what secnet actually reads at startup and uses.
+ *
* Proof that this is sound:
* Let us regard update,proc,live as i=0,1,2
* Files contain public key sets and are manipulated as
* (a) check live vs proc, proc>live, mv:
* j=2, i=1; S'(i)=-1, so S(i) is being reduced. S'(j) is
* equal to S(i), and the rename is atomic [1], so S'(j) and
- * S'(i) are updated simultaneously.
- * S(j) is being increased.
+ * S'(i) are updated simultaneously. S(j) is being
+ * increased. (There are no hazards from concurrent writers;
+ * only we ourselves (secnet) write to live or proc.)
* (b) check live vs proc, proc<=live, rm:
* j=2, i=1; S'(i)=-1, so S(i) is being reduced. But
- * S(j) is >= $(i) throughout.
- * (c) mv update proc (when update does not exist):
+ * S(j) is >= $(i) throughout. (Again, no concurrent
+ * writer hazards.)
+ * (c) mv update proc (when proc does not exist):
* j=1, i=0; S(i) is being reduced to -1. But simultaneously
- * S(j) is being increased to the old S(i).
+ * S(j) is being increased to the old S(i). Our precondition
+ * (proc not existing) is not subject to a concurrent writer
+ * hazards because only we write to proc; our action is
+ * atomic and takes whatever update is available (if any).
*
* Proof of soundness for the mss reading operation:
* Let M be MAX(\forall S) at the point where mss reads update.
int r=rename(inputp,oursp);
if (r) {
- slog(st,LOG_ERROR,"failed to claim key update file %s as %s: %s\n",
+ slog(st,LOG_ERROR,"failed to claim key update file %s as %s: %s",
inputp,oursp,strerror(errno));
return;
}
}
static void setup_sethash(struct site *st, dict_t *dict,
- struct hash_if **hash, struct cloc loc,
+ struct cloc loc,
sig_sethash_fn *sethash, void *sigkey_st) {
- if (!*hash) *hash=find_cl_if(dict,"hash",CL_HASH,True,"site",loc);
- sethash(sigkey_st,*hash);
+ if (!st->defhash)
+ cfgfatal(loc,"site","other settings imply `hash' key is needed");
+ sethash(sigkey_st,st->defhash);
}
#define SETUP_SETHASH(k) do{ \
if ((k)->sethash) \
- setup_sethash(st,dict, &hash,loc, (k)->sethash,(k)->st); \
+ setup_sethash(st,dict,loc, (k)->sethash,(k)->st); \
}while(0)
static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context,
st->log=find_cl_if(dict,"log",CL_LOG,True,"site",loc);
st->random=find_cl_if(dict,"random",CL_RANDOMSRC,True,"site",loc);
- struct hash_if *hash=0;
+ st->defhash=find_cl_if(dict,"hash",CL_HASH,True,"site",loc);
st->privkeys=find_cl_if(dict,"key-cache",CL_PRIVCACHE,False,"site",loc);
if (!st->privkeys) {
pathprefix_template_init(&st->peerkeys_tmpl,st->peerkeys_path,
PEERKEYS_SUFFIX_MAXLEN + 1 /* nul */);
st->peerkeys_current=keyset_load(st->peerkeys_path,
- &st->scratch,st->log,M_ERR);
+ &st->scratch,st->log,M_ERR,
+ st->defhash);
if (fixed_pubkey) {
fixed_pubkey->dispose(fixed_pubkey->st);
}