Import release 0.03
[secnet] / site.c
CommitLineData
2fe58dfd
SE
1/* site.c - manage communication with a remote network site */
2
3#include <stdio.h>
4#include <sys/mman.h>
5
6#include "secnet.h"
7#include "util.h"
8
9#define SETUP_BUFFER_LEN 2048
10
11#define DEFAULT_KEY_LIFETIME 15000
12#define DEFAULT_SETUP_RETRIES 5
13#define DEFAULT_SETUP_TIMEOUT 500
14#define DEFAULT_WAIT_TIME 10000
15
16/* Each site can be in one of several possible states. */
17
18/* States:
19 SITE_STOP - nothing is allowed to happen; tunnel is down;
20 all session keys have been erased
21 -> SITE_RUN upon external instruction
22 SITE_RUN - site up, maybe with valid key
23 -> SITE_RESOLVE upon outgoing packet and no valid key
24 we start name resolution for the other end of the tunnel
25 -> SITE_SENTMSG2 upon valid incoming message 1 and suitable time
26 we send an appropriate message 2
27 SITE_RESOLVE - waiting for name resolution
28 -> SITE_SENTMSG1 upon successful resolution
29 we send an appropriate message 1
30 -> SITE_SENTMSG2 upon valid incoming message 1 (then abort resolution)
31 we abort resolution and
32 -> SITE_WAIT on timeout or resolution failure
33 SITE_SENTMSG1
34 -> SITE_SENTMSG2 upon valid incoming message 1 from higher priority end
35 -> SITE_SENTMSG3 upon valid incoming message 2
36 -> SITE_WAIT on timeout
37 SITE_SENTMSG2
38 -> SITE_SENTMSG4 upon valid incoming message 3
39 -> SITE_WAIT on timeout
40 SITE_SENTMSG3
41 -> SITE_SENTMSG5 upon valid incoming message 4
42 -> SITE_WAIT on timeout
43 SITE_SENTMSG4
44 -> SITE_RUN upon valid incoming message 5
45 -> SITE_WAIT on timeout
46 SITE_SENTMSG5
47 -> SITE_RUN upon valid incoming message 6
48 -> SITE_WAIT on timeout
49 SITE_WAIT - failed to establish key; do nothing for a while
50 -> SITE_RUN on timeout
51 */
52
53#define SITE_STOP 0
54#define SITE_RUN 1
55#define SITE_RESOLVE 2
56#define SITE_SENTMSG1 3
57#define SITE_SENTMSG2 4
58#define SITE_SENTMSG3 5
59#define SITE_SENTMSG4 6
60#define SITE_SENTMSG5 7
61#define SITE_WAIT 8
62
63static string_t state_name(uint32_t state)
64{
65 switch (state) {
66 case 0: return "SITE_STOP";
67 case 1: return "SITE_RUN";
68 case 2: return "SITE_RESOLVE";
69 case 3: return "SITE_SENTMSG1";
70 case 4: return "SITE_SENTMSG2";
71 case 5: return "SITE_SENTMSG3";
72 case 6: return "SITE_SENTMSG4";
73 case 7: return "SITE_SENTMSG5";
74 case 8: return "SITE_WAIT";
75 default: return "*bad state*";
76 }
77}
78
79#define LABEL_MSG0 0x00020200
80#define LABEL_MSG1 0x01010101
81#define LABEL_MSG2 0x02020202
82#define LABEL_MSG3 0x03030303
83#define LABEL_MSG4 0x04040404
84#define LABEL_MSG5 0x05050505
85#define LABEL_MSG6 0x06060606
86#define LABEL_MSG7 0x07070707
87#define LABEL_MSG8 0x08080808
88#define LABEL_MSG9 0x09090909
89
90#define NONCELEN 8
91
92#define LOG_UNEXPECTED 0x00000001
93#define LOG_SETUP_INIT 0x00000002
94#define LOG_SETUP_TIMEOUT 0x00000004
95#define LOG_ACTIVATE_KEY 0x00000008
96#define LOG_TIMEOUT_KEY 0x00000010
97#define LOG_SECURITY 0x00000020
98#define LOG_STATE 0x00000040
99#define LOG_DROP 0x00000080
100#define LOG_DUMP 0x00000100
101#define LOG_ERROR 0x00000400
102
103struct site {
104 closure_t cl;
105 struct site_if ops;
106/* configuration information */
107 string_t localname;
108 string_t remotename;
109 string_t address; /* DNS name for bootstrapping, optional */
110 int remoteport;
111 struct netlink_if *netlink;
112 struct comm_if *comm;
113 struct resolver_if *resolver;
114 struct log_if *log;
115 struct random_if *random;
116 struct rsaprivkey_if *privkey;
117 struct subnet_list remotenets;
118 struct rsapubkey_if *pubkey;
119 struct transform_if *transform;
120 struct dh_if *dh;
121 struct hash_if *hash;
122 void *netlink_cid;
123
124 uint32_t setup_retries; /* How many times to send setup packets */
125 uint32_t setup_timeout; /* Initial timeout for setup packets */
126 uint32_t wait_timeout; /* How long to wait if setup unsuccessful */
127 uint32_t key_lifetime; /* How long a key lasts once set up */
128
129 uint8_t *setupsig; /* Expected signature of incoming MSG1 packets */
130 uint32_t setupsiglen; /* Allows us to discard packets quickly if
131 they are not for us */
132 bool_t setup_priority; /* Do we have precedence if both sites emit
133 message 1 simultaneously? */
134 uint32_t log_events;
135
136/* runtime information */
137 uint32_t state;
138 uint64_t now; /* Most recently seen time */
139
140 uint32_t remote_session_id;
141 struct transform_inst_if *current_transform;
142 bool_t current_valid;
143 uint64_t current_key_timeout; /* End of life of current key */
144 struct sockaddr_in peer; /* Current address of peer */
145 bool_t peer_valid; /* Peer address becomes invalid when key times out,
146 but only if we have a DNS name for our peer */
147
148 uint32_t setup_session_id;
149 struct sockaddr_in setup_peer;
150 uint8_t localN[NONCELEN]; /* Nonces for key exchange */
151 uint8_t remoteN[NONCELEN];
152 struct buffer_if buffer; /* Current outgoing key exchange packet */
153 uint32_t retries; /* Number of retries remaining */
154 uint64_t timeout; /* Timeout for current state */
155 uint8_t *dhsecret;
156 uint8_t *sharedsecret;
157
158 struct transform_inst_if *new_transform; /* For key setup/verify */
159};
160
161static void slog(struct site *st, uint32_t event, string_t msg, ...)
162{
163 va_list ap;
164 uint8_t buf[240];
165
166 va_start(ap,msg);
167
168 if (event&st->log_events) {
169 vsnprintf(buf,240,msg,ap);
170 st->log->log(st->log->st,0,"%s<->%s: %s",st->localname,st->remotename,
171 buf);
172 }
173 va_end(ap);
174}
175
176static void enter_state_run(struct site *st);
177static bool_t enter_state_resolve(struct site *st);
178static bool_t enter_state_sentmsg1(struct site *st);
179static bool_t enter_state_sentmsg2(struct site *st);
180static bool_t enter_state_sentmsg3(struct site *st);
181static bool_t enter_state_sentmsg4(struct site *st);
182static bool_t enter_state_sentmsg5(struct site *st);
183static void enter_state_wait(struct site *st);
184
185#define CHECK_AVAIL(b,l) do { if ((b)->size<(l)) return False; } while(0)
186#define CHECK_EMPTY(b) do { if ((b)->size!=0) return False; } while(0)
187#define CHECK_TYPE(b,t) do { uint32_t type; \
188 CHECK_AVAIL((b),4); \
189 type=*(uint32_t *)buf_unprepend((b),4); \
190 if (type!=(t)) return False; } while(0)
191
192struct msg {
193 uint8_t *hashstart;
194 uint32_t dest;
195 uint32_t source;
196 uint32_t remlen;
197 uint8_t *remote;
198 uint32_t loclen;
199 uint8_t *local;
200 uint8_t *nR;
201 uint8_t *nL;
202 uint32_t pklen;
203 uint8_t *pk;
204 uint32_t hashlen;
205 uint32_t siglen;
206 uint8_t *sig;
207};
208
209/* Build any of msg1 to msg4. msg5 and msg6 are built from the inside out
210 using a transform. */
211static bool_t generate_msg(struct site *st, uint32_t type, string_t what)
212{
213 void *hst;
214 uint8_t *hash=alloca(st->hash->len);
215 string_t dhpub, sig;
216
217 st->retries=st->setup_retries;
218 BUF_ALLOC(&st->buffer,what);
219 buffer_init(&st->buffer,0);
220 *(uint32_t *)buf_append(&st->buffer,4)=
221 (type==LABEL_MSG1?0:st->setup_session_id);
222 *(uint32_t *)buf_append(&st->buffer,4)=(uint32_t)st;
223 *(uint32_t *)buf_append(&st->buffer,4)=type;
224 buf_append_string(&st->buffer,st->localname);
225 buf_append_string(&st->buffer,st->remotename);
226 memcpy(buf_append(&st->buffer,NONCELEN),st->localN,NONCELEN);
227 if (type==LABEL_MSG1) return True;
228 memcpy(buf_append(&st->buffer,NONCELEN),st->remoteN,NONCELEN);
229 if (type==LABEL_MSG2) return True;
230 dhpub=st->dh->makepublic(st->dh->st,st->dhsecret,st->dh->len);
231 buf_append_string(&st->buffer,dhpub);
232 free(dhpub);
233 hst=st->hash->init();
234 st->hash->update(hst,st->buffer.start,st->buffer.size);
235 st->hash->final(hst,hash);
236 sig=st->privkey->sign(st->privkey->st,hash,st->hash->len);
237 buf_append_string(&st->buffer,sig);
238 free(sig);
239 return True;
240}
241
242static bool_t unpick_msg(struct site *st, uint32_t type,
243 struct buffer_if *msg, struct msg *m)
244{
245 m->hashstart=msg->start;
246 CHECK_AVAIL(msg,4);
247 m->dest=*(uint32_t *)buf_unprepend(msg,4);
248 CHECK_AVAIL(msg,4);
249 m->source=*(uint32_t *)buf_unprepend(msg,4);
250 CHECK_TYPE(msg,type);
251 CHECK_AVAIL(msg,2);
252 m->remlen=ntohs(*(uint16_t *)buf_unprepend(msg,2));
253 CHECK_AVAIL(msg,m->remlen);
254 m->remote=buf_unprepend(msg,m->remlen);
255 CHECK_AVAIL(msg,2);
256 m->loclen=ntohs(*(uint16_t *)buf_unprepend(msg,2));
257 CHECK_AVAIL(msg,m->loclen);
258 m->local=buf_unprepend(msg,m->loclen);
259 CHECK_AVAIL(msg,NONCELEN);
260 m->nR=buf_unprepend(msg,NONCELEN);
261 if (type==LABEL_MSG1) {
262 CHECK_EMPTY(msg);
263 return True;
264 }
265 CHECK_AVAIL(msg,NONCELEN);
266 m->nL=buf_unprepend(msg,NONCELEN);
267 if (type==LABEL_MSG2) {
268 CHECK_EMPTY(msg);
269 return True;
270 }
271 CHECK_AVAIL(msg,2);
272 m->pklen=ntohs(*(uint16_t *)buf_unprepend(msg,2));
273 CHECK_AVAIL(msg,m->pklen);
274 m->pk=buf_unprepend(msg,m->pklen);
275 m->hashlen=msg->start-m->hashstart;
276 CHECK_AVAIL(msg,2);
277 m->siglen=ntohs(*(uint16_t *)buf_unprepend(msg,2));
278 CHECK_AVAIL(msg,m->siglen);
279 m->sig=buf_unprepend(msg,m->siglen);
280 CHECK_EMPTY(msg);
281 return True;
282}
283
284static bool_t generate_msg1(struct site *st)
285{
286 st->random->generate(st->random->st,NONCELEN,st->localN);
287 return generate_msg(st,LABEL_MSG1,"site:MSG1");
288}
289
290static bool_t process_msg1(struct site *st, struct buffer_if *msg1,
291 struct sockaddr_in *src)
292{
293 struct msg m;
294
295 /* We've already determined we're in an appropriate state to
296 process an incoming MSG1, and that the MSG1 has correct values
297 of A and B. */
298
299 if (!unpick_msg(st,LABEL_MSG1,msg1,&m)) return False;
300
301 /* XXX save src as our peer address here? */
302 st->setup_peer=*src;
303
304 st->setup_session_id=m.source;
305 memcpy(st->remoteN,m.nR,NONCELEN);
306 return True;
307}
308
309static bool_t generate_msg2(struct site *st)
310{
311 st->random->generate(st->random->st,NONCELEN,st->localN);
312 return generate_msg(st,LABEL_MSG2,"site:MSG2");
313}
314
315static bool_t process_msg2(struct site *st, struct buffer_if *msg2,
316 struct sockaddr_in *src)
317{
318 struct msg m;
319
320 if (!unpick_msg(st,LABEL_MSG2,msg2,&m)) return False;
321
322 /* Check that the site names and our nonce have been sent
323 back correctly, and then store our peer's nonce. */
324 if (memcmp(m.remote,st->remotename,strlen(st->remotename)!=0)) {
325 slog(st,LOG_SECURITY,"msg2: bad B (remote site name)");
326 return False;
327 }
328 if (memcmp(m.local,st->localname,strlen(st->localname)!=0)) {
329 slog(st,LOG_SECURITY,"msg2: bad A (local site name)");
330 return False;
331 }
332 if (memcmp(m.nL,st->localN,NONCELEN)!=0) {
333 slog(st,LOG_SECURITY,"msg2: bad nA (locally generated nonce)");
334 return False;
335 }
336 st->setup_session_id=m.source;
337 memcpy(st->remoteN,m.nR,NONCELEN);
338 return True;
339}
340
341static bool_t generate_msg3(struct site *st)
342{
343 /* Now we have our nonce and their nonce. Think of a secret key,
344 and create message number 3. */
345 st->random->generate(st->random->st,st->dh->len,st->dhsecret);
346 return generate_msg(st,LABEL_MSG3,"site:MSG3");
347}
348
349static bool_t process_msg3(struct site *st, struct buffer_if *msg3,
350 struct sockaddr_in *src)
351{
352 struct msg m;
353 uint8_t *hash=alloca(st->hash->len);
354 void *hst;
355
356 if (!unpick_msg(st,LABEL_MSG3,msg3,&m)) return False;
357
358 /* Check that the site names and nonces have been sent back
359 correctly */
360 if (memcmp(m.remote,st->remotename,strlen(st->remotename)!=0)) {
361 slog(st,LOG_SECURITY,"msg3: bad A (remote site name)");
362 return False;
363 }
364 if (memcmp(m.local,st->localname,strlen(st->localname)!=0)) {
365 slog(st,LOG_SECURITY,"msg3: bad B (local site name)");
366 return False;
367 }
368 if (memcmp(m.nR,st->remoteN,NONCELEN)!=0) {
369 slog(st,LOG_SECURITY,"msg3: bad nA (remotely generated nonce)");
370 return False;
371 }
372 if (memcmp(m.nL,st->localN,NONCELEN)!=0) {
373 slog(st,LOG_SECURITY,"msg3: bad nB (locally generated nonce)");
374 return False;
375 }
376
377 /* Check signature and store g^x mod m */
378 hst=st->hash->init();
379 st->hash->update(hst,m.hashstart,m.hashlen);
380 st->hash->final(hst,hash);
381 /* Terminate signature with a '0' - cheating, but should be ok */
382 m.sig[m.siglen]=0;
383 if (!st->pubkey->check(st->pubkey->st,hash,st->hash->len,m.sig)) {
384 slog(st,LOG_SECURITY,"msg3 signature failed check!");
385 return False;
386 }
387
388 /* Terminate their DH public key with a '0' */
389 m.pk[m.pklen]=0;
390 /* Invent our DH secret key */
391 st->random->generate(st->random->st,st->dh->len,st->dhsecret);
392
393 /* Generate the shared key */
394 st->dh->makeshared(st->dh->st,st->dhsecret,st->dh->len,m.pk,
395 st->sharedsecret,st->transform->keylen);
396
397 /* Set up the transform */
398 st->new_transform->setkey(st->new_transform->st,st->sharedsecret,
399 st->transform->keylen);
400
401 return True;
402}
403
404static bool_t generate_msg4(struct site *st)
405{
406 /* We have both nonces, their public key and our private key. Generate
407 our public key, sign it and send it to them. */
408 return generate_msg(st,LABEL_MSG4,"site:MSG4");
409}
410
411static bool_t process_msg4(struct site *st, struct buffer_if *msg4,
412 struct sockaddr_in *src)
413{
414 struct msg m;
415 uint8_t *hash=alloca(st->hash->len);
416 void *hst;
417
418 if (!unpick_msg(st,LABEL_MSG4,msg4,&m)) return False;
419
420 /* Check that the site names and nonces have been sent back
421 correctly */
422 if (memcmp(m.remote,st->remotename,strlen(st->remotename)!=0)) {
423 slog(st,LOG_SECURITY,"msg4: bad B (remote site name)");
424 return False;
425 }
426 if (memcmp(m.local,st->localname,strlen(st->localname)!=0)) {
427 slog(st,LOG_SECURITY,"msg4: bad A (local site name)");
428 return False;
429 }
430 if (memcmp(m.nR,st->remoteN,NONCELEN)!=0) {
431 slog(st,LOG_SECURITY,"msg4: bad nB (remotely generated nonce)");
432 return False;
433 }
434 if (memcmp(m.nL,st->localN,NONCELEN)!=0) {
435 slog(st,LOG_SECURITY,"msg4: bad nA (locally generated nonce)");
436 return False;
437 }
438
439 /* Check signature and store g^x mod m */
440 hst=st->hash->init();
441 st->hash->update(hst,m.hashstart,m.hashlen);
442 st->hash->final(hst,hash);
443 /* Terminate signature with a '0' - cheating, but should be ok */
444 m.sig[m.siglen]=0;
445 if (!st->pubkey->check(st->pubkey->st,hash,st->hash->len,m.sig)) {
446 slog(st,LOG_SECURITY,"msg4 signature failed check!");
447 return False;
448 }
449
450 /* Terminate their DH public key with a '0' */
451 m.pk[m.pklen]=0;
452 /* Generate the shared key */
453 st->dh->makeshared(st->dh->st,st->dhsecret,st->dh->len,m.pk,
454 st->sharedsecret,st->transform->keylen);
455 /* Set up the transform */
456 st->new_transform->setkey(st->new_transform->st,st->sharedsecret,
457 st->transform->keylen);
458
459 return True;
460}
461
462static bool_t generate_msg5(struct site *st)
463{
464 string_t transform_err;
465
466 BUF_ALLOC(&st->buffer,"site:MSG5");
467 /* We are going to add three words to the transformed message */
468 buffer_init(&st->buffer,st->transform->max_start_pad+(4*3));
469 *(uint32_t *)buf_append(&st->buffer,4)=LABEL_MSG5;
470 st->new_transform->forwards(st->new_transform->st,&st->buffer,
471 &transform_err);
472 *(uint32_t *)buf_prepend(&st->buffer,4)=LABEL_MSG5;
473 *(uint32_t *)buf_prepend(&st->buffer,4)=(uint32_t)st;
474 *(uint32_t *)buf_prepend(&st->buffer,4)=st->setup_session_id;
475
476 st->retries=st->setup_retries;
477 return True;
478}
479
480struct msg0 {
481 uint32_t dest;
482 uint32_t source;
483 uint32_t type;
484};
485
486static bool_t unpick_msg0(struct site *st, struct buffer_if *msg0,
487 struct msg0 *m)
488{
489 CHECK_AVAIL(msg0,4);
490 m->dest=*(uint32_t *)buf_unprepend(msg0,4);
491 CHECK_AVAIL(msg0,4);
492 m->source=*(uint32_t *)buf_unprepend(msg0,4);
493 CHECK_AVAIL(msg0,4);
494 m->type=*(uint32_t *)buf_unprepend(msg0,4);
495 return True;
496 /* Leaves transformed part of buffer untouched */
497}
498
499static bool_t process_msg5(struct site *st, struct buffer_if *msg5,
500 struct sockaddr_in *src)
501{
502 struct msg0 m;
503 string_t transform_err;
504
505 if (!unpick_msg0(st,msg5,&m)) return False;
506
507 if (st->new_transform->reverse(st->new_transform->st,
508 msg5,&transform_err)) {
509 /* There's a problem */
510 slog(st,LOG_SECURITY,"process_msg5: transform: %s",transform_err);
511 return False;
512 }
513 /* Buffer should now contain untransformed PING packet data */
514 CHECK_AVAIL(msg5,4);
515 if ((*(uint32_t *)buf_unprepend(msg5,4))!=LABEL_MSG5) {
516 slog(st,LOG_SECURITY,"MSG5/PING packet contained invalid data");
517 return False;
518 }
519 CHECK_EMPTY(msg5);
520 return True;
521}
522
523static bool_t generate_msg6(struct site *st)
524{
525 string_t transform_err;
526
527 BUF_ALLOC(&st->buffer,"site:MSG6");
528 /* We are going to add three words to the transformed message */
529 buffer_init(&st->buffer,st->transform->max_start_pad+(4*3));
530 *(uint32_t *)buf_append(&st->buffer,4)=LABEL_MSG6;
531 st->new_transform->forwards(st->new_transform->st,&st->buffer,
532 &transform_err);
533 *(uint32_t *)buf_prepend(&st->buffer,4)=LABEL_MSG6;
534 *(uint32_t *)buf_prepend(&st->buffer,4)=(uint32_t)st;
535 *(uint32_t *)buf_prepend(&st->buffer,4)=st->setup_session_id;
536
537 st->retries=1; /* Peer will retransmit MSG5 if necessary */
538 return True;
539}
540
541static bool_t process_msg6(struct site *st, struct buffer_if *msg6,
542 struct sockaddr_in *src)
543{
544 struct msg0 m;
545 string_t transform_err;
546
547 if (!unpick_msg0(st,msg6,&m)) return False;
548
549 if (st->new_transform->reverse(st->new_transform->st,
550 msg6,&transform_err)) {
551 /* There's a problem */
552 slog(st,LOG_SECURITY,"process_msg6: transform: %s",transform_err);
553 return False;
554 }
555 /* Buffer should now contain untransformed PING packet data */
556 CHECK_AVAIL(msg6,4);
557 if ((*(uint32_t *)buf_unprepend(msg6,4))!=LABEL_MSG6) {
558 slog(st,LOG_SECURITY,"MSG6/PONG packet contained invalid data");
559 return False;
560 }
561 CHECK_EMPTY(msg6);
562 return True;
563}
564
565static bool_t process_msg0(struct site *st, struct buffer_if *msg0,
566 struct sockaddr_in *src)
567{
568 struct msg0 m;
569 string_t transform_err;
570 uint32_t type;
571
572 if (!st->current_valid) {
573 slog(st,LOG_DROP,"incoming message but no current key -> dropping");
574 if (st->state==SITE_RUN) {
575 slog(st,LOG_SETUP_INIT|LOG_STATE,
576 "now initiating setup of new key");
577 return enter_state_resolve(st);
578 }
579 return False;
580 }
581
582 if (!unpick_msg0(st,msg0,&m)) return False;
583
584 if (st->current_transform->reverse(st->current_transform->st,
585 msg0,&transform_err)) {
586 /* There's a problem */
587 slog(st,LOG_SECURITY,"transform: %s",transform_err);
588 return False;
589 }
590 CHECK_AVAIL(msg0,4);
591 type=*(uint32_t *)buf_unprepend(msg0,4);
592 switch(type) {
593 case LABEL_MSG9:
594 /* Deliver to netlink layer */
595 st->netlink->deliver(st->netlink->st,st->netlink_cid,msg0);
596 return True;
597 break;
598 default:
599 slog(st,LOG_SECURITY,"incoming message of type %08x (unknown)",type);
600 break;
601 }
602 return False;
603}
604
605static void dump_packet(struct site *st, struct buffer_if *buf,
606 struct sockaddr_in *addr, bool_t incoming)
607{
608 uint32_t dest=*(uint32_t *)buf->start;
609 uint32_t source=*(uint32_t *)(buf->start+4);
610 uint32_t msgtype=*(uint32_t *)(buf->start+8);
611
612 if (st->log_events & LOG_DUMP)
613 log(st->log,0,"(%s,%s): %s: %08x<-%08x: %08x:",
614 st->localname,st->remotename,incoming?"incoming":"outgoing",
615 dest,source,msgtype);
616}
617
618static uint32_t site_status(void *st)
619{
620 return 0;
621}
622
623static bool_t send_msg(struct site *st)
624{
625 if (st->retries>0) {
626 dump_packet(st,&st->buffer,&st->setup_peer,False);
627 st->comm->sendmsg(st->comm->st,&st->buffer,&st->setup_peer);
628 st->timeout=st->now+st->setup_timeout;
629 st->retries--;
630 return True;
631 } else {
632 slog(st,LOG_SETUP_TIMEOUT,"timed out sending key setup packet");
633 enter_state_wait(st);
634 return False;
635 }
636}
637
638static void site_resolve_callback(void *sst, struct in_addr *address)
639{
640 struct site *st=sst;
641
642 if (st->state!=SITE_RESOLVE) {
643 slog(st,LOG_UNEXPECTED,"site_resolve_callback called unexpectedly");
644 return;
645 }
646 if (address) {
647 memset(&st->setup_peer,0,sizeof(st->setup_peer));
648 st->setup_peer.sin_family=AF_INET;
649 st->setup_peer.sin_port=htons(st->remoteport);
650 st->setup_peer.sin_addr=*address;
651 enter_state_sentmsg1(st);
652 } else {
653 /* Resolution failed */
654 slog(st,LOG_ERROR,"resolution of %s failed",st->address);
655 enter_state_run(st);
656 }
657}
658
659static void activate_new_key(struct site *st)
660{
661 struct transform_inst_if *t;
662
663 t=st->current_transform;
664 st->current_transform=st->new_transform;
665 st->new_transform=t;
666
667 t->delkey(t->st);
668 st->state=SITE_RUN;
669 st->timeout=0;
670 st->current_valid=True;
671 st->current_key_timeout=st->now+st->key_lifetime;
672 st->peer=st->setup_peer;
673 st->peer_valid=True;
674 st->remote_session_id=st->setup_session_id;
675
676 slog(st,LOG_ACTIVATE_KEY,"new key activated");
677}
678
679static void state_assert(struct site *st, bool_t ok)
680{
681 if (!ok) fatal("state_assert\n");
682}
683
684static void enter_state_stop(struct site *st)
685{
686 st->state=SITE_STOP;
687 st->timeout=0;
688 st->current_transform->delkey(st->current_transform->st);
689 st->current_valid=False;
690 st->current_key_timeout=0;
691
692 st->peer_valid=False;
693
694 st->new_transform->delkey(st->new_transform->st);
695}
696
697static void enter_state_run(struct site *st)
698{
699 slog(st,LOG_STATE,"entering state RUN");
700 st->state=SITE_RUN;
701 st->timeout=0;
702 /* XXX get rid of key setup data */
703}
704
705static bool_t enter_state_resolve(struct site *st)
706{
707 state_assert(st,st->state==SITE_RUN);
708 slog(st,LOG_STATE,"entering state RESOLVE");
709 st->state=SITE_RESOLVE;
710 st->resolver->request(st->resolver->st,st->address,
711 site_resolve_callback,st);
712 return True;
713}
714
715static bool_t enter_state_sentmsg1(struct site *st)
716{
717 state_assert(st,st->state==SITE_RUN || st->state==SITE_RESOLVE);
718 slog(st,LOG_STATE,"entering state SENTMSG1");
719 if (generate_msg1(st) && send_msg(st)) {
720 st->state=SITE_SENTMSG1;
721 return True;
722 }
723 slog(st,LOG_ERROR,"error entering state SENTMSG1");
724 st->buffer.free=False; /* Can't tell which it was, but enter_state_wait()
725 will do a BUF_FREE() */
726 enter_state_wait(st);
727 return False;
728}
729
730static bool_t enter_state_sentmsg2(struct site *st)
731{
732 state_assert(st,st->state==SITE_RUN || st->state==SITE_RESOLVE ||
733 st->state==SITE_SENTMSG1 || st->state==SITE_WAIT);
734 slog(st,LOG_STATE,"entering state SENTMSG2");
735 if (generate_msg2(st) && send_msg(st)) {
736 st->state=SITE_SENTMSG2;
737 return True;
738 }
739 slog(st,LOG_ERROR,"error entering state SENTMSG2");
740 st->buffer.free=False;
741 enter_state_wait(st);
742 return False;
743}
744
745static bool_t enter_state_sentmsg3(struct site *st)
746{
747 state_assert(st,st->state==SITE_SENTMSG1);
748 slog(st,LOG_STATE,"entering state SENTMSG3");
749 BUF_FREE(&st->buffer); /* Free message 1 */
750 if (generate_msg3(st) && send_msg(st)) {
751 st->state=SITE_SENTMSG3;
752 return True;
753 }
754 slog(st,LOG_ERROR,"error entering state SENTMSG3");
755 st->buffer.free=False;
756 enter_state_wait(st);
757 return False;
758}
759
760static bool_t enter_state_sentmsg4(struct site *st)
761{
762 state_assert(st,st->state==SITE_SENTMSG2);
763 slog(st,LOG_STATE,"entering state SENTMSG4");
764 BUF_FREE(&st->buffer); /* Free message 2 */
765 if (generate_msg4(st) && send_msg(st)) {
766 st->state=SITE_SENTMSG4;
767 return True;
768 }
769 slog(st,LOG_ERROR,"error entering state SENTMSG4");
770 st->buffer.free=False;
771 enter_state_wait(st);
772 return False;
773}
774
775static bool_t enter_state_sentmsg5(struct site *st)
776{
777 state_assert(st,st->state==SITE_SENTMSG3);
778 slog(st,LOG_STATE,"entering state SENTMSG5");
779 BUF_FREE(&st->buffer); /* Free message 3 */
780
781 if (generate_msg5(st) && send_msg(st)) {
782 st->state=SITE_SENTMSG5;
783 return True;
784 }
785 slog(st,LOG_ERROR,"error entering state SENTMSG5");
786 st->buffer.free=False;
787 enter_state_wait(st);
788
789 return False;
790}
791
792static bool_t send_msg6(struct site *st)
793{
794 state_assert(st,st->state==SITE_SENTMSG4);
795 slog(st,LOG_STATE,"entering state RUN after sending msg6");
796 BUF_FREE(&st->buffer); /* Free message 4 */
797 if (generate_msg6(st) && send_msg(st)) {
798 BUF_FREE(&st->buffer); /* Never reused */
799 st->timeout=0; /* Never retransmit */
800 activate_new_key(st);
801 return True;
802 }
803 slog(st,LOG_ERROR,"error entering state RUN after sending msg6");
804 st->buffer.free=False;
805 enter_state_wait(st);
806 return False;
807}
808
809/* We go into this state if our peer becomes uncommunicative. Similar to
810 the "stop" state, we forget all session keys for a while, before
811 re-entering the "run" state. */
812static void enter_state_wait(struct site *st)
813{
814 slog(st,LOG_STATE,"entering state WAIT");
815 st->timeout=st->now+st->wait_timeout;
816 st->state=SITE_WAIT;
817 st->peer_valid=False;
818 BUF_FREE(&st->buffer); /* will have had an outgoing packet in it */
819 /* XXX Erase keys etc. */
820}
821
822static int site_beforepoll(void *sst, struct pollfd *fds, int *nfds_io,
823 int *timeout_io, const struct timeval *tv_now,
824 uint64_t *now)
825{
826 struct site *st=sst;
827
828 *nfds_io=0; /* We don't use any file descriptors */
829 st->now=*now;
830
831 /* Work out when our next timeout is. The earlier of 'timeout' or
832 'current_key_timeout'. A stored value of '0' indicates no timeout
833 active. */
834 if (st->timeout && st->timeout-*now < *timeout_io) {
835 *timeout_io=st->timeout-*now;
836 }
837
838 if (st->current_key_timeout && st->current_key_timeout-*now < *timeout_io)
839 *timeout_io=st->current_key_timeout-*now;
840
841 return 0; /* success */
842}
843
844/* NB site_afterpoll will be called before site_beforepoll is ever called */
845static void site_afterpoll(void *sst, struct pollfd *fds, int nfds,
846 const struct timeval *tv_now, uint64_t *now)
847{
848 struct site *st=sst;
849
850 st->now=*now;
851 if (st->timeout && *now>st->timeout) {
852 /* Do stuff */
853 st->timeout=0;
854 if (st->state>=SITE_SENTMSG1 && st->state<=SITE_SENTMSG5)
855 send_msg(st);
856 else if (st->state==SITE_WAIT) {
857 enter_state_run(st);
858 } else {
859 slog(st,LOG_ERROR,"site_afterpoll: unexpected timeout, state=%d",
860 st->state);
861 }
862 }
863 if (st->current_key_timeout && *now>st->current_key_timeout) {
864 slog(st,LOG_TIMEOUT_KEY,"maximum key life exceeded; session closed");
865 st->current_valid=False;
866 st->current_transform->delkey(st->current_transform->st);
867 st->current_key_timeout=0;
868 }
869}
870
871/* This function is called by the netlink device to deliver packets
872 intended for the remote network. The packet is in "raw" wire
873 format, but is guaranteed to be word-aligned. */
874static void site_outgoing(void *sst, void *cid, struct buffer_if *buf)
875{
876 struct site *st=sst;
877 string_t transform_err;
878
879 if (st->state==SITE_STOP) {
880 BUF_FREE(buf);
881 return;
882 }
883
884 /* In all other states we consider delivering the packet if we have
885 a valid key and a valid address to send it to. */
886 if (st->current_valid && st->peer_valid) {
887 /* Transform it and send it */
888 *(uint32_t *)buf_prepend(buf,4)=LABEL_MSG9;
889 st->current_transform->forwards(st->current_transform->st,
890 buf, &transform_err);
891 *(uint32_t *)buf_prepend(buf,4)=LABEL_MSG0;
892 *(uint32_t *)buf_prepend(buf,4)=(uint32_t)st;
893 *(uint32_t *)buf_prepend(buf,4)=st->remote_session_id;
894 st->comm->sendmsg(st->comm->st,buf,&st->peer);
895 BUF_FREE(buf);
896 return;
897 }
898
899 if (st->state==SITE_RUN) {
900 BUF_FREE(buf); /* We throw the outgoing packet away */
901 slog(st,LOG_SETUP_INIT,"initiating key exchange");
902 enter_state_resolve(st);
903 return;
904 }
905
906 /* Otherwise we're in the middle of key setup or a wait - just
907 throw the outgoing packet away */
908 slog(st,LOG_DROP,"discarding outgoing packet");
909 BUF_FREE(buf);
910 return;
911}
912
913/* This function is called by the communication device to deliver
914 packets from our peers. */
915static bool_t site_incoming(void *sst, struct buffer_if *buf,
916 struct sockaddr_in *source)
917{
918 struct site *st=sst;
919 uint32_t dest=*(uint32_t *)buf->start;
920
921 if (dest==0) {
922 if (buf->size<(st->setupsiglen+8+NONCELEN)) return False;
923 /* It could be for any site - it should have LABEL_MSG1 and
924 might have our name and our peer's name in it */
925 if (memcmp(buf->start+8,st->setupsig,st->setupsiglen)==0) {
926 dump_packet(st,buf,source,True);
927 /* It's addressed to us. Decide what to do about it. */
928 if (st->state==SITE_RUN || st->state==SITE_RESOLVE ||
929 st->state==SITE_WAIT) {
930 /* We should definitely process it */
931 if (process_msg1(st,buf,source)) {
932 slog(st,LOG_SETUP_INIT,"key setup initiated by peer");
933 enter_state_sentmsg2(st);
934 } else {
935 slog(st,LOG_ERROR,"failed to process incoming msg1");
936 }
937 BUF_FREE(buf);
938 return True;
939 }
940 if (st->state==SITE_SENTMSG1) {
941 /* We've just sent a message 1! They may have crossed on
942 the wire. If we have priority then we ignore the
943 incoming one, otherwise we process it as usual. */
944 if (st->setup_priority) {
945 BUF_FREE(buf);
946 slog(st,LOG_DUMP,"crossed msg1s; we are higher "
947 "priority => ignore incoming msg1");
948 return True;
949 } else {
950 slog(st,LOG_DUMP,"crossed msg1s; we are lower "
951 "priority => use incoming msg1");
952 if (process_msg1(st,buf,source)) {
953 BUF_FREE(&st->buffer); /* Free our old message 1 */
954 enter_state_sentmsg2(st);
955 } else {
956 slog(st,LOG_ERROR,"failed to process an incoming "
957 "crossed msg1 (we have low priority)");
958 }
959 BUF_FREE(buf);
960 return True;
961 }
962 }
963 /* The message 1 was received at an unexpected stage of the
964 key setup. XXX POLICY - what do we do? */
965 slog(st,LOG_UNEXPECTED,"unexpected incoming message 1");
966 BUF_FREE(buf);
967 return True;
968 }
969 return False; /* Not for us. */
970 }
971 if (dest==(uint32_t)st) {
972 uint32_t msgtype=*(uint32_t *)(buf->start+8);
973 /* Explicitly addressed to us */
974 if (msgtype!=LABEL_MSG0) dump_packet(st,buf,source,True);
975 switch (msgtype) {
976 case LABEL_MSG0:
977 process_msg0(st,buf,source);
978 break;
979 case LABEL_MSG1:
980 /* Setup packet: should not have been explicitly addressed
981 to us */
982 slog(st,LOG_SECURITY,"incoming explicitly addressed msg1");
983 break;
984 case LABEL_MSG2:
985 /* Setup packet: expected only in state SENTMSG1 */
986 if (st->state!=SITE_SENTMSG1) {
987 slog(st,LOG_UNEXPECTED,"unexpected MSG2");
988 } else if (process_msg2(st,buf,source))
989 enter_state_sentmsg3(st);
990 else {
991 slog(st,LOG_SECURITY,"invalid MSG2");
992 }
993 break;
994 case LABEL_MSG3:
995 /* Setup packet: expected only in state SENTMSG2 */
996 if (st->state!=SITE_SENTMSG2) {
997 slog(st,LOG_UNEXPECTED,"unexpected MSG3");
998 } else if (process_msg3(st,buf,source))
999 enter_state_sentmsg4(st);
1000 else {
1001 slog(st,LOG_SECURITY,"invalid MSG3");
1002 }
1003 break;
1004 case LABEL_MSG4:
1005 /* Setup packet: expected only in state SENTMSG3 */
1006 if (st->state!=SITE_SENTMSG3) {
1007 slog(st,LOG_UNEXPECTED,"unexpected MSG4");
1008 } else if (process_msg4(st,buf,source))
1009 enter_state_sentmsg5(st);
1010 else {
1011 slog(st,LOG_SECURITY,"invalid MSG4");
1012 }
1013 break;
1014 case LABEL_MSG5:
1015 /* Setup packet: expected only in state SENTMSG4 or RUN */
1016 if (st->state!=SITE_SENTMSG4 && st->state!=SITE_RUN) {
1017 slog(st,LOG_UNEXPECTED,"unexpected MSG5");
1018 } else if (process_msg5(st,buf,source)) {
1019 send_msg6(st);
1020 } else {
1021 slog(st,LOG_SECURITY,"invalid MSG5");
1022 }
1023 break;
1024 case LABEL_MSG6:
1025 /* Setup packet: expected only in state SENTMSG5 */
1026 if (st->state!=SITE_SENTMSG5) {
1027 slog(st,LOG_UNEXPECTED,"unexpected MSG6");
1028 } else if (process_msg6(st,buf,source)) {
1029 BUF_FREE(&st->buffer); /* Free message 5 */
1030 activate_new_key(st);
1031 } else {
1032 slog(st,LOG_SECURITY,"invalid MSG6");
1033 }
1034 break;
1035 case LABEL_MSG8:
1036 /* NAK packet: enter state where we ping and check for response */
1037 slog(st,LOG_ERROR,"received a NAK");
1038 break;
1039 default:
1040 slog(st,LOG_SECURITY,"received message of unknown type 0x%08x",
1041 msgtype);
1042 break;
1043 }
1044 BUF_FREE(buf);
1045 return True;
1046 }
1047
1048 return False;
1049}
1050
1051static void site_control(void *vst, bool_t run)
1052{
1053 struct site *st=vst;
1054 if (run) enter_state_run(st);
1055 else enter_state_stop(st);
1056}
1057
1058static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context,
1059 list_t *args)
1060{
1061 struct site *st;
1062 item_t *item;
1063 dict_t *dict;
1064
1065 st=safe_malloc(sizeof(*st),"site_apply");
1066
1067 st->cl.description="site";
1068 st->cl.type=CL_SITE;
1069 st->cl.apply=NULL;
1070 st->cl.interface=&st->ops;
1071 st->ops.st=st;
1072 st->ops.control=site_control;
1073 st->ops.status=site_status;
1074
1075 /* First parameter must be a dict */
1076 item=list_elem(args,0);
1077 if (!item || item->type!=t_dict)
1078 cfgfatal(loc,"site","parameter must be a dictionary\n");
1079
1080 dict=item->data.dict;
1081 st->netlink=find_cl_if(dict,"netlink",CL_NETLINK,True,"site",loc);
1082 st->comm=find_cl_if(dict,"comm",CL_COMM,True,"site",loc);
1083 st->resolver=find_cl_if(dict,"resolver",CL_RESOLVER,True,"site",loc);
1084 st->log=find_cl_if(dict,"log",CL_LOG,True,"site",loc);
1085 st->random=find_cl_if(dict,"random",CL_RANDOMSRC,True,"site",loc);
1086
1087 st->localname=dict_read_string(dict, "local-name", True, "site", loc);
1088 st->privkey=find_cl_if(dict,"local-key",CL_RSAPRIVKEY,True,"site",loc);
1089 st->remoteport=dict_read_number(dict,"port",True,"site",loc,0);
1090
1091 st->remotename=dict_read_string(dict, "name", True, "site", loc);
1092 st->address=dict_read_string(dict, "address", False, "site", loc);
1093 dict_read_subnet_list(dict, "networks", True, "site", loc,
1094 &st->remotenets);
1095 st->pubkey=find_cl_if(dict,"key",CL_RSAPUBKEY,True,"site",loc);
1096
1097 st->transform=
1098 find_cl_if(dict,"transform",CL_TRANSFORM,True,"site",loc);
1099
1100 st->dh=find_cl_if(dict,"dh",CL_DH,True,"site",loc);
1101 st->hash=find_cl_if(dict,"hash",CL_HASH,True,"site",loc);
1102
1103 st->key_lifetime=dict_read_number(dict,"key-lifetime",
1104 False,"site",loc,DEFAULT_KEY_LIFETIME);
1105 st->setup_retries=dict_read_number(dict,"setup-retries",
1106 False,"site",loc,DEFAULT_SETUP_RETRIES);
1107 st->setup_timeout=dict_read_number(dict,"setup-timeout",
1108 False,"site",loc,DEFAULT_SETUP_TIMEOUT);
1109 st->wait_timeout=dict_read_number(dict,"wait-time",
1110 False,"site",loc,DEFAULT_WAIT_TIME);
1111 /* XXX should be configurable */
1112 st->log_events=LOG_SECURITY|LOG_ERROR|
1113 LOG_ACTIVATE_KEY|LOG_TIMEOUT_KEY|LOG_SETUP_INIT|LOG_SETUP_TIMEOUT;
1114
1115 /* The information we expect to see in incoming messages of type 1 */
1116 st->setupsiglen=strlen(st->remotename)+strlen(st->localname)+8;
1117 st->setupsig=safe_malloc(st->setupsiglen,"site_apply");
1118 *(uint32_t *)&(st->setupsig[0])=LABEL_MSG1;
1119 *(uint16_t *)&(st->setupsig[4])=htons(strlen(st->remotename));
1120 memcpy(&st->setupsig[6],st->remotename,strlen(st->remotename));
1121 *(uint16_t *)&(st->setupsig[6+strlen(st->remotename)])=
1122 htons(strlen(st->localname));
1123 memcpy(&st->setupsig[8+strlen(st->remotename)],st->localname,
1124 strlen(st->localname));
1125 st->setup_priority=(strcmp(st->localname,st->remotename)>0);
1126
1127 buffer_new(&st->buffer,SETUP_BUFFER_LEN);
1128
1129 /* We are interested in poll(), but only for timeouts. We don't have
1130 any fds of our own. */
1131 register_for_poll(st, site_beforepoll, site_afterpoll, 0, "site");
1132 st->timeout=0;
1133
1134 st->current_valid=False;
1135 st->current_key_timeout=0;
1136 st->peer_valid=False;
1137 /* XXX mlock these */
1138 st->dhsecret=safe_malloc(st->dh->len,"site:dhsecret");
1139 st->sharedsecret=safe_malloc(st->transform->keylen,"site:sharedsecret");
1140
1141 /* We need to register the remote networks with the netlink device */
1142 st->netlink_cid=st->netlink->regnets(st->netlink->st, &st->remotenets,
1143 site_outgoing, st,
1144 st->transform->max_start_pad+(4*4),
1145 st->transform->max_end_pad);
1146
1147 st->comm->request_notify(st->comm->st, st, site_incoming);
1148
1149 st->current_transform=st->transform->create(st->transform->st);
1150 st->new_transform=st->transform->create(st->transform->st);
1151
1152 enter_state_stop(st);
1153
1154 return new_closure(&st->cl);
1155}
1156
1157init_module site_module;
1158void site_module(dict_t *dict)
1159{
1160 add_closure(dict,"site",site_apply);
1161}