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