full support of ikev1 and ikev2 connection flags
[strongswan.git] / src / pluto / rcv_whack.c
1 /* whack communicating routines
2 * Copyright (C) 1997 Angelos D. Keromytis.
3 * Copyright (C) 1998-2001 D. Hugh Redelmeier.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 *
15 * RCSID $Id: rcv_whack.c,v 1.18 2006/05/25 11:33:57 as Exp $
16 */
17
18 #include <stdio.h>
19 #include <stddef.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <errno.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <sys/un.h>
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
29 #include <resolv.h>
30 #include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
31 #include <sys/queue.h>
32 #include <fcntl.h>
33
34 #include <freeswan.h>
35
36 #include "constants.h"
37 #include "defs.h"
38 #include "id.h"
39 #include "ca.h"
40 #include "certs.h"
41 #include "ac.h"
42 #include "smartcard.h"
43 #include "connections.h"
44 #include "foodgroups.h"
45 #include "whack.h" /* needs connections.h */
46 #include "packet.h"
47 #include "demux.h" /* needs packet.h */
48 #include "state.h"
49 #include "ipsec_doi.h" /* needs demux.h and state.h */
50 #include "kernel.h"
51 #include "rcv_whack.h"
52 #include "log.h"
53 #include "keys.h"
54 #include "adns.h" /* needs <resolv.h> */
55 #include "dnskey.h" /* needs keys.h and adns.h */
56 #include "server.h"
57 #include "fetch.h"
58 #include "ocsp.h"
59 #include "crl.h"
60
61 #include "kernel_alg.h"
62 #include "ike_alg.h"
63 /* helper variables and function to decode strings from whack message */
64
65 static char *next_str
66 , *str_roof;
67
68 static bool
69 unpack_str(char **p)
70 {
71 char *end = memchr(next_str, '\0', str_roof - next_str);
72
73 if (end == NULL)
74 {
75 return FALSE; /* fishy: no end found */
76 }
77 else
78 {
79 *p = next_str == end? NULL : next_str;
80 next_str = end + 1;
81 return TRUE;
82 }
83 }
84
85 /* bits loading keys from asynchronous DNS */
86
87 enum key_add_attempt {
88 ka_TXT,
89 #ifdef USE_KEYRR
90 ka_KEY,
91 #endif
92 ka_roof /* largest value + 1 */
93 };
94
95 struct key_add_common {
96 int refCount;
97 char *diag[ka_roof];
98 int whack_fd;
99 bool success;
100 };
101
102 struct key_add_continuation {
103 struct adns_continuation ac; /* common prefix */
104 struct key_add_common *common; /* common data */
105 enum key_add_attempt lookingfor;
106 };
107
108 static void
109 key_add_ugh(const struct id *keyid, err_t ugh)
110 {
111 char name[BUF_LEN]; /* longer IDs will be truncated in message */
112
113 (void)idtoa(keyid, name, sizeof(name));
114 loglog(RC_NOKEY
115 , "failure to fetch key for %s from DNS: %s", name, ugh);
116 }
117
118 /* last one out: turn out the lights */
119 static void
120 key_add_merge(struct key_add_common *oc, const struct id *keyid)
121 {
122 if (oc->refCount == 0)
123 {
124 enum key_add_attempt kaa;
125
126 /* if no success, print all diagnostics */
127 if (!oc->success)
128 for (kaa = ka_TXT; kaa != ka_roof; kaa++)
129 key_add_ugh(keyid, oc->diag[kaa]);
130
131 for (kaa = ka_TXT; kaa != ka_roof; kaa++)
132 pfreeany(oc->diag[kaa]);
133
134 close(oc->whack_fd);
135 pfree(oc);
136 }
137 }
138
139 static void
140 key_add_continue(struct adns_continuation *ac, err_t ugh)
141 {
142 struct key_add_continuation *kc = (void *) ac;
143 struct key_add_common *oc = kc->common;
144
145 passert(whack_log_fd == NULL_FD);
146 whack_log_fd = oc->whack_fd;
147
148 if (ugh != NULL)
149 {
150 oc->diag[kc->lookingfor] = clone_str(ugh, "key add error");
151 }
152 else
153 {
154 oc->success = TRUE;
155 transfer_to_public_keys(kc->ac.gateways_from_dns
156 #ifdef USE_KEYRR
157 , &kc->ac.keys_from_dns
158 #endif /* USE_KEYRR */
159 );
160 }
161
162 oc->refCount--;
163 key_add_merge(oc, &ac->id);
164 whack_log_fd = NULL_FD;
165 }
166
167 static void
168 key_add_request(const whack_message_t *msg)
169 {
170 struct id keyid;
171 err_t ugh = atoid(msg->keyid, &keyid, FALSE);
172
173 if (ugh != NULL)
174 {
175 loglog(RC_BADID, "bad --keyid \"%s\": %s", msg->keyid, ugh);
176 }
177 else
178 {
179 if (!msg->whack_addkey)
180 delete_public_keys(&keyid, msg->pubkey_alg
181 , empty_chunk, empty_chunk);
182
183 if (msg->keyval.len == 0)
184 {
185 struct key_add_common *oc
186 = alloc_thing(struct key_add_common
187 , "key add common things");
188 enum key_add_attempt kaa;
189
190 /* initialize state shared by queries */
191 oc->refCount = 0;
192 oc->whack_fd = dup_any(whack_log_fd);
193 oc->success = FALSE;
194
195 for (kaa = ka_TXT; kaa != ka_roof; kaa++)
196 {
197 struct key_add_continuation *kc
198 = alloc_thing(struct key_add_continuation
199 , "key add continuation");
200
201 oc->diag[kaa] = NULL;
202 oc->refCount++;
203 kc->common = oc;
204 kc->lookingfor = kaa;
205 switch (kaa)
206 {
207 case ka_TXT:
208 ugh = start_adns_query(&keyid
209 , &keyid /* same */
210 , T_TXT
211 , key_add_continue
212 , &kc->ac);
213 break;
214 #ifdef USE_KEYRR
215 case ka_KEY:
216 ugh = start_adns_query(&keyid
217 , NULL
218 , T_KEY
219 , key_add_continue
220 , &kc->ac);
221 break;
222 #endif /* USE_KEYRR */
223 default:
224 bad_case(kaa); /* suppress gcc warning */
225 }
226 if (ugh != NULL)
227 {
228 oc->diag[kaa] = clone_str(ugh, "early key add failure");
229 oc->refCount--;
230 }
231 }
232
233 /* Done launching queries.
234 * Handle total failure case.
235 */
236 key_add_merge(oc, &keyid);
237 }
238 else
239 {
240 ugh = add_public_key(&keyid, DAL_LOCAL, msg->pubkey_alg
241 , &msg->keyval, &pubkeys);
242 if (ugh != NULL)
243 loglog(RC_LOG_SERIOUS, "%s", ugh);
244 }
245 }
246 }
247
248 /* Handle a kernel request. Supposedly, there's a message in
249 * the kernelsock socket.
250 */
251 void
252 whack_handle(int whackctlfd)
253 {
254 whack_message_t msg;
255 struct sockaddr_un whackaddr;
256 int whackaddrlen = sizeof(whackaddr);
257 int whackfd = accept(whackctlfd, (struct sockaddr *)&whackaddr, &whackaddrlen);
258 /* Note: actual value in n should fit in int. To print, cast to int. */
259 ssize_t n;
260
261 if (whackfd < 0)
262 {
263 log_errno((e, "accept() failed in whack_handle()"));
264 return;
265 }
266 if (fcntl(whackfd, F_SETFD, FD_CLOEXEC) < 0)
267 {
268 log_errno((e, "failed to set CLOEXEC in whack_handle()"));
269 close(whackfd);
270 return;
271 }
272
273 n = read(whackfd, &msg, sizeof(msg));
274
275 if (n == -1)
276 {
277 log_errno((e, "read() failed in whack_handle()"));
278 close(whackfd);
279 return;
280 }
281
282 whack_log_fd = whackfd;
283
284 /* sanity check message */
285 {
286 err_t ugh = NULL;
287
288 next_str = msg.string;
289 str_roof = (char *)&msg + n;
290
291 if ((size_t)n < offsetof(whack_message_t, whack_shutdown) + sizeof(msg.whack_shutdown))
292 {
293 ugh = builddiag("ignoring runt message from whack: got %d bytes", (int)n);
294 }
295 else if (msg.magic != WHACK_MAGIC)
296 {
297 if (msg.magic == WHACK_BASIC_MAGIC)
298 {
299 /* Only shutdown command. Simpler inter-version compatability. */
300 if (msg.whack_shutdown)
301 {
302 plog("shutting down");
303 exit_pluto(0); /* delete lock and leave, with 0 status */
304 }
305 ugh = ""; /* bail early, but without complaint */
306 }
307 else
308 {
309 ugh = builddiag("ignoring message from whack with bad magic %d; should be %d; probably wrong version"
310 , msg.magic, WHACK_MAGIC);
311 }
312 }
313 else if (next_str > str_roof)
314 {
315 ugh = builddiag("ignoring truncated message from whack: got %d bytes; expected %u"
316 , (int) n, (unsigned) sizeof(msg));
317 }
318 else if (!unpack_str(&msg.name) /* string 1 */
319 || !unpack_str(&msg.left.id) /* string 2 */
320 || !unpack_str(&msg.left.cert) /* string 3 */
321 || !unpack_str(&msg.left.ca) /* string 4 */
322 || !unpack_str(&msg.left.groups) /* string 5 */
323 || !unpack_str(&msg.left.updown) /* string 6 */
324 #ifdef VIRTUAL_IP
325 || !unpack_str(&msg.left.virt)
326 #endif
327 || !unpack_str(&msg.right.id) /* string 7 */
328 || !unpack_str(&msg.right.cert) /* string 8 */
329 || !unpack_str(&msg.right.ca) /* string 9 */
330 || !unpack_str(&msg.right.groups) /* string 10 */
331 || !unpack_str(&msg.right.updown) /* string 11 */
332 #ifdef VIRTUAL_IP
333 || !unpack_str(&msg.right.virt)
334 #endif
335 || !unpack_str(&msg.keyid) /* string 12 */
336 || !unpack_str(&msg.myid) /* string 13 */
337 || !unpack_str(&msg.cacert) /* string 14 */
338 || !unpack_str(&msg.ldaphost) /* string 15 */
339 || !unpack_str(&msg.ldapbase) /* string 16 */
340 || !unpack_str(&msg.crluri) /* string 17 */
341 || !unpack_str(&msg.crluri2) /* string 18 */
342 || !unpack_str(&msg.ocspuri) /* string 19 */
343 || !unpack_str(&msg.ike) /* string 20 */
344 || !unpack_str(&msg.esp) /* string 21 */
345 || !unpack_str(&msg.sc_data) /* string 22 */
346 || str_roof - next_str != (ptrdiff_t)msg.keyval.len) /* check chunk */
347 {
348 ugh = "message from whack contains bad string";
349 }
350 else
351 {
352 msg.keyval.ptr = next_str; /* grab chunk */
353 }
354
355 if (ugh != NULL)
356 {
357 if (*ugh != '\0')
358 loglog(RC_BADWHACKMESSAGE, "%s", ugh);
359 whack_log_fd = NULL_FD;
360 close(whackfd);
361 return;
362 }
363 }
364
365 if (msg.whack_options)
366 {
367 #ifdef DEBUG
368 if (msg.name == NULL)
369 {
370 /* we do a two-step so that if either old or new would
371 * cause the message to print, it will be printed.
372 */
373 cur_debugging |= msg.debugging;
374 DBG(DBG_CONTROL
375 , DBG_log("base debugging = %s"
376 , bitnamesof(debug_bit_names, msg.debugging)));
377 cur_debugging = base_debugging = msg.debugging;
378 }
379 else if (!msg.whack_connection)
380 {
381 struct connection *c = con_by_name(msg.name, TRUE);
382
383 if (c != NULL)
384 {
385 c->extra_debugging = msg.debugging;
386 DBG(DBG_CONTROL
387 , DBG_log("\"%s\" extra_debugging = %s"
388 , c->name
389 , bitnamesof(debug_bit_names, c->extra_debugging)));
390 }
391 }
392 #endif
393 }
394
395 if (msg.whack_myid)
396 set_myid(MYID_SPECIFIED, msg.myid);
397
398 /* Deleting combined with adding a connection works as replace.
399 * To make this more useful, in only this combination,
400 * delete will silently ignore the lack of the connection.
401 */
402 if (msg.whack_delete)
403 {
404 if (msg.whack_ca)
405 find_ca_info_by_name(msg.name, TRUE);
406 else
407 delete_connections_by_name(msg.name, !msg.whack_connection);
408 }
409
410 if (msg.whack_deletestate)
411 {
412 struct state *st = state_with_serialno(msg.whack_deletestateno);
413
414 if (st == NULL)
415 {
416 loglog(RC_UNKNOWN_NAME, "no state #%lu to delete"
417 , msg.whack_deletestateno);
418 }
419 else
420 {
421 delete_state(st);
422 }
423 }
424
425 if (msg.whack_crash)
426 delete_states_by_peer(&msg.whack_crash_peer);
427
428 if (msg.whack_connection)
429 add_connection(&msg);
430
431 if (msg.whack_ca && msg.cacert != NULL)
432 add_ca_info(&msg);
433
434 /* process "listen" before any operation that could require it */
435 if (msg.whack_listen)
436 {
437 close_peerlog(); /* close any open per-peer logs */
438 plog("listening for IKE messages");
439 listening = TRUE;
440 daily_log_reset();
441 reset_adns_restart_count();
442 set_myFQDN();
443 find_ifaces();
444 load_preshared_secrets(NULL_FD);
445 load_groups();
446 }
447 if (msg.whack_unlisten)
448 {
449 plog("no longer listening for IKE messages");
450 listening = FALSE;
451 }
452
453 if (msg.whack_reread & REREAD_SECRETS)
454 {
455 load_preshared_secrets(whackfd);
456 }
457
458 if (msg.whack_reread & REREAD_CACERTS)
459 {
460 load_authcerts("CA cert", CA_CERT_PATH, AUTH_CA);
461 }
462
463 if (msg.whack_reread & REREAD_AACERTS)
464 {
465 load_authcerts("AA cert", AA_CERT_PATH, AUTH_AA);
466 }
467
468 if (msg.whack_reread & REREAD_OCSPCERTS)
469 {
470 load_authcerts("OCSP cert", OCSP_CERT_PATH, AUTH_OCSP);
471 }
472
473 if (msg.whack_reread & REREAD_ACERTS)
474 {
475 load_acerts();
476 }
477
478 if (msg.whack_reread & REREAD_CRLS)
479 {
480 load_crls();
481 }
482
483 if (msg.whack_purgeocsp)
484 {
485 free_ocsp_fetch();
486 free_ocsp_cache();
487 }
488
489 if (msg.whack_list & LIST_ALGS)
490 {
491 ike_alg_list();
492 kernel_alg_list();
493 }
494 if (msg.whack_list & LIST_PUBKEYS)
495 {
496 list_public_keys(msg.whack_utc);
497 }
498
499 if (msg.whack_list & LIST_CERTS)
500 {
501 list_certs(msg.whack_utc);
502 }
503
504 if (msg.whack_list & LIST_CACERTS)
505 {
506 list_authcerts("CA", AUTH_CA, msg.whack_utc);
507 }
508
509 if (msg.whack_list & LIST_AACERTS)
510 {
511 list_authcerts("AA", AUTH_AA, msg.whack_utc);
512 }
513
514 if (msg.whack_list & LIST_OCSPCERTS)
515 {
516 list_authcerts("OCSP", AUTH_OCSP, msg.whack_utc);
517 }
518
519 if (msg.whack_list & LIST_ACERTS)
520 {
521 list_acerts(msg.whack_utc);
522 }
523
524 if (msg.whack_list & LIST_GROUPS)
525 {
526 list_groups(msg.whack_utc);
527 }
528
529 if (msg.whack_list & LIST_CAINFOS)
530 {
531 list_ca_infos(msg.whack_utc);
532 }
533
534 if (msg.whack_list & LIST_CRLS)
535 {
536 list_crls(msg.whack_utc, strict_crl_policy);
537 list_crl_fetch_requests(msg.whack_utc);
538 }
539
540 if (msg.whack_list & LIST_OCSP)
541 {
542 list_ocsp_cache(msg.whack_utc, strict_crl_policy);
543 list_ocsp_fetch_requests(msg.whack_utc);
544 }
545
546 if (msg.whack_list & LIST_CARDS)
547 {
548 scx_list(msg.whack_utc);
549 }
550
551 if (msg.whack_key)
552 {
553 /* add a public key */
554 key_add_request(&msg);
555 }
556
557 if (msg.whack_route)
558 {
559 if (!listening)
560 {
561 whack_log(RC_DEAF, "need --listen before --route");
562 }
563 if (msg.name == NULL)
564 {
565 whack_log(RC_UNKNOWN_NAME
566 , "whack --route requires a connection name");
567 }
568 else
569 {
570 struct connection *c = con_by_name(msg.name, TRUE);
571
572 if (c != NULL && c->ikev1)
573 {
574 set_cur_connection(c);
575 if (!oriented(*c))
576 whack_log(RC_ORIENT
577 , "we have no ipsecN interface for either end of this connection");
578 else if (c->policy & POLICY_GROUP)
579 route_group(c);
580 else if (!trap_connection(c))
581 whack_log(RC_ROUTE, "could not route");
582 reset_cur_connection();
583 }
584 }
585 }
586
587 if (msg.whack_unroute)
588 {
589 if (msg.name == NULL)
590 {
591 whack_log(RC_UNKNOWN_NAME
592 , "whack --unroute requires a connection name");
593 }
594 else
595 {
596 struct connection *c = con_by_name(msg.name, TRUE);
597
598 if (c != NULL && c->ikev1)
599 {
600 struct spd_route *sr;
601 int fail = 0;
602
603 set_cur_connection(c);
604
605 for (sr = &c->spd; sr != NULL; sr = sr->next)
606 {
607 if (sr->routing >= RT_ROUTED_TUNNEL)
608 fail++;
609 }
610 if (fail > 0)
611 whack_log(RC_RTBUSY, "cannot unroute: route busy");
612 else if (c->policy & POLICY_GROUP)
613 unroute_group(c);
614 else
615 unroute_connection(c);
616 reset_cur_connection();
617 }
618 }
619 }
620
621 if (msg.whack_initiate)
622 {
623 if (!listening)
624 {
625 whack_log(RC_DEAF, "need --listen before --initiate");
626 }
627 else if (msg.name == NULL)
628 {
629 whack_log(RC_UNKNOWN_NAME
630 , "whack --initiate requires a connection name");
631 }
632 else
633 {
634 initiate_connection(msg.name
635 , msg.whack_async? NULL_FD : dup_any(whackfd));
636 }
637 }
638
639 if (msg.whack_oppo_initiate)
640 {
641 if (!listening)
642 whack_log(RC_DEAF, "need --listen before opportunistic initiation");
643 else
644 initiate_opportunistic(&msg.oppo_my_client, &msg.oppo_peer_client, 0
645 , FALSE
646 , msg.whack_async? NULL_FD : dup_any(whackfd));
647 }
648
649 if (msg.whack_terminate)
650 {
651 if (msg.name == NULL)
652 {
653 whack_log(RC_UNKNOWN_NAME
654 , "whack --terminate requires a connection name");
655 }
656 else
657 {
658 terminate_connection(msg.name);
659 }
660 }
661
662 if (msg.whack_status)
663 show_status(msg.whack_statusall, msg.name);
664
665 if (msg.whack_shutdown)
666 {
667 plog("shutting down");
668 exit_pluto(0); /* delete lock and leave, with 0 status */
669 }
670
671 if (msg.whack_sc_op != SC_OP_NONE)
672 {
673 if (pkcs11_proxy)
674 scx_op_via_whack(msg.sc_data, msg.inbase, msg.outbase
675 , msg.whack_sc_op, msg.keyid, whackfd);
676 else
677 plog("pkcs11 access to smartcard not allowed (set pkcs11proxy=yes)");
678 }
679
680 whack_log_fd = NULL_FD;
681 close(whackfd);
682 }
683
684 /*
685 * Local Variables:
686 * c-basic-offset:4
687 * c-style: pluto
688 * End:
689 */