} transport_peers;
/* Basic operations on transport peer address sets */
+static void transport_peers_init(struct site *st, transport_peers *peers);
static void transport_peers_clear(struct site *st, transport_peers *peers);
static int transport_peers_valid(transport_peers *peers);
static void transport_peers_copy(struct site *st, transport_peers *dst,
struct xinfoadd xia;
append_string_xinfo_start(&st->buffer,&xia,st->localname);
- if ((st->local_capabilities & st->early_capabilities) ||
- (type != LABEL_MSG1)) {
- buf_append_uint32(&st->buffer,st->local_capabilities);
- }
+ buf_append_uint32(&st->buffer,st->local_capabilities);
if (type_is_msg34(type)) {
buf_append_uint16(&st->buffer,st->mtu_target);
}
return False;
privkey_found:
+ slog(st,LOG_SIGKEYS,"using private key #%d " SIGKEYID_PR_FMT,
+ ki, SIGKEYID_PR_VAL(prompt->pubkeys_accepted[ki]));
buf_append_uint8(&st->buffer,ki);
}
static void peerkeys_check_for_update(struct site *st)
{
- /* peerkeys files
- *
- * <F> live file, loaded on startup, updated by secnet
- * (only). * in-memory peerkeys_current is kept
- * synced with this file
- *
- * <F>~update update file from config manager, checked before
- * every key exchange. config manager must rename
- * this file into place; it will be renamed and
- * then removed by secnet.
- *
- * <F>~proc update file being processed by secnet.
- * only secnet may write or remove.
- *
- * <F>~incoming update file from peer, being received by secnet
- * may be incomplete, unverified, or even malicious
- * only secnet may write or remove.
- */
if (!st->peerkeys_path) return;
pathprefix_template_setsuffix(&st->peerkeys_tmpl,"~proc");
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;
}
if (!pubkey->check(pubkey->st,
m->hashstart,m->hashlen,
&m->sig)) {
- slog(st,LOG_SEC,"msg3/msg4 signature failed check!");
+ slog(st,LOG_SEC,"msg3/msg4 signature failed check!"
+ " (key #%d " SIGKEYID_PR_FMT ")",
+ ki, SIGKEYID_PR_VAL(&st->peerkeys_kex->keys[ki].id));
return False;
}
+ slog(st,LOG_SIGKEYS,"verified peer signature with key #%d "
+ SIGKEYID_PR_FMT, ki,
+ SIGKEYID_PR_VAL(&st->peerkeys_kex->keys[ki].id));
st->remote_adv_mtu=m->remote_mtu;
static void enter_state_run(struct site *st)
{
- slog(st,LOG_STATE,"entering state RUN%s",
- current_valid(st) ? " (keyed)" : " (unkeyed)");
+ if (st->state!=SITE_STOP)
+ slog(st,LOG_STATE,"entering state RUN%s",
+ current_valid(st) ? " (keyed)" : " (unkeyed)");
st->state=SITE_RUN;
st->timeout=0;
return False;
}
-static void site_control(void *vst, bool_t run)
+static void site_startup(void *vst)
{
struct site *st=vst;
- if (run) enter_state_run(st);
- else enter_state_stop(st);
+ enter_state_run(st);
}
-static void site_phase_hook(void *sst, uint32_t newphase)
+static void site_phase_shutdown_hook(void *sst, uint32_t newphase)
{
struct site *st=sst;
send_msg7(st,"shutting down");
}
+static void site_phase_run_hook(void *sst, uint32_t newphase)
+{
+ struct site *st=sst;
+ slog(st,LOG_STATE,"entering phase RUN in state %s",
+ state_name(st->state));
+}
+
static void site_childpersist_clearkeys(void *sst, uint32_t newphase)
{
struct site *st=sst;
crypto operations, but that's a task for another day. */
}
-static void setup_sethash(struct site *st, dict_t *dict,
- struct hash_if **hash, 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);
-}
-#define SETUP_SETHASH(k) do{ \
- if ((k)->sethash) \
- setup_sethash(st,dict, &hash,loc, (k)->sethash,(k)->st); \
-}while(0)
-
static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context,
list_t *args)
{
st->cl.apply=NULL;
st->cl.interface=&st->ops;
st->ops.st=st;
- st->ops.control=site_control;
+ st->ops.startup=site_startup;
st->ops.status=site_status;
st->peerkeys_path=0;
st->peerkeys_tmpl.buffer=0;
st->peerkeys_current=st->peerkeys_kex=0;
+ buffer_new(&st->scratch,SETUP_BUFFER_LEN);
+ BUF_ALLOC(&st->scratch,"site:scratch");
+
/* First parameter must be a dict */
item=list_elem(args,0);
if (!item || item->type!=t_dict)
cfgfatal(loc,"site","parameter must be a dictionary\n");
dict=item->data.dict;
+ st->log=find_cl_if(dict,"log",CL_LOG,True,"site",loc);
+ st->log_events=string_list_to_word(dict_lookup(dict,"log-events"),
+ log_event_table,"site");
+
st->localname=dict_read_string(dict, "local-name", True, "site", loc);
st->remotename=dict_read_string(dict, "name", True, "site", loc);
+ st->tunname=safe_malloc(strlen(st->localname)+strlen(st->remotename)+5,
+ "site_apply");
+ sprintf(st->tunname,"%s<->%s",st->localname,st->remotename);
+
+ /* Now slog is working */
+
st->keepalive=dict_read_bool(dict,"keepalive",False,"site",loc,False);
st->peer_mobile=dict_read_bool(dict,"mobile",False,"site",loc,False);
cfgfatal(loc,"site","%s is not a closure\n",dictkey); \
closure_t *cl=item->data.closure; \
if (cl->type!=CL_TYPE) \
- cfgfatal(loc,"site","%s closure wrong type\n",dictkey); \
+ cfgfatal_cl_type(loc,"site",cl,CL_TYPE,dictkey); \
st->things[i]=cl->interface; \
} \
}while(0)
}
st->resolver=find_cl_if(dict,"resolver",CL_RESOLVER,True,"site",loc);
- 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->privkeys=find_cl_if(dict,"key-cache",CL_PRIVCACHE,False,"site",loc);
if (!st->privkeys) {
st->privkey_fixed=
find_cl_if(dict,"local-key",CL_SIGPRIVKEY,True,"site",loc);
- SETUP_SETHASH(st->privkey_fixed);
}
struct sigpubkey_if *fixed_pubkey
}
} else {
assert(fixed_pubkey);
- SETUP_SETHASH(fixed_pubkey);
NEW(st->peerkeys_current);
st->peerkeys_current->refcount=1;
st->peerkeys_current->nkeys=1;
"renegotiate-time must be less than key-lifetime\n");
}
- st->log_events=string_list_to_word(dict_lookup(dict,"log-events"),
- log_event_table,"site");
-
st->resolving_count=0;
st->allow_send_prod=0;
- st->tunname=safe_malloc(strlen(st->localname)+strlen(st->remotename)+5,
- "site_apply");
- sprintf(st->tunname,"%s<->%s",st->localname,st->remotename);
-
/* The information we expect to see in incoming messages of type 1 */
/* fixme: lots of unchecked overflows here, but the results are only
corrupted packets rather than undefined behaviour */
buffer_new(&st->buffer,SETUP_BUFFER_LEN);
- buffer_new(&st->scratch,SETUP_BUFFER_LEN);
- BUF_ALLOC(&st->scratch,"site:scratch");
-
/* We are interested in poll(), but only for timeouts. We don't have
any fds of our own. */
register_for_poll(st, site_beforepoll, site_afterpoll, "site");
st->chosen_transform=0;
st->current.key_timeout=0;
st->auxiliary_key.key_timeout=0;
- transport_peers_clear(st,&st->peers);
- transport_peers_clear(st,&st->setup_peers);
+ transport_peers_init(st,&st->peers);
+ transport_peers_init(st,&st->setup_peers);
/* XXX mlock these */
st->dhsecret=safe_malloc(st->dh->len,"site:dhsecret");
st->sharedsecretlen=st->sharedsecretallocd=0;
enter_state_stop(st);
- add_hook(PHASE_SHUTDOWN,site_phase_hook,st);
+ add_hook(PHASE_SHUTDOWN,site_phase_shutdown_hook,st);
+ add_hook(PHASE_RUN, site_phase_run_hook, st);
add_hook(PHASE_CHILDPERSIST,site_childpersist_clearkeys,st);
return new_closure(&st->cl);
static void transport_peers_expire(struct site *st, transport_peers *peers) {
/* peers must be sorted first */
+ if (st->local_mobile) return;
+
int previous_peers=peers->npeers;
struct timeval oldest;
oldest.tv_sec = tv_now->tv_sec - st->mobile_peer_expiry;
static int transport_peers_valid(transport_peers *peers) {
return peers->npeers;
}
+static void transport_peers_init(struct site *st, transport_peers *peers) {
+ peers->npeers= 0;
+}
static void transport_peers_clear(struct site *st, transport_peers *peers) {
+ bool_t need_debug=!!peers->npeers;
peers->npeers= 0;
- transport_peers_debug(st,peers,"clear",0,0,0);
+ if (need_debug)
+ transport_peers_debug(st,peers,"clear",0,0,0);
}
static void transport_peers_copy(struct site *st, transport_peers *dst,
const transport_peers *src) {