1 /* $NetBSD: racoonctl.c,v 1.18 2010/11/12 09:08:26 tteras Exp $ */
2
3 /* Id: racoonctl.c,v 1.11 2006/04/06 17:06:25 manubsd Exp */
4
5 /*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Copyright (C) 2008 Timo Teras.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the project nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #include "config.h"
36
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <sys/socket.h>
40 #include <sys/un.h>
41
42 #include <netinet/in.h>
43 #include <arpa/inet.h>
44 #include <net/pfkeyv2.h>
45
46 #include <stdlib.h>
47 #include <stdio.h>
48 #include <string.h>
49 #include <errno.h>
50 #if TIME_WITH_SYS_TIME
51 # include <sys/time.h>
52 # include <time.h>
53 #else
54 # if HAVE_SYS_TIME_H
55 # include <sys/time.h>
56 # else
57 # include <time.h>
58 # endif
59 #endif
60 #include <netdb.h>
61 #ifdef HAVE_UNISTD_H
62 #include <unistd.h>
63 #endif
64 #include <err.h>
65 #include <sys/ioctl.h>
66 #include <resolv.h>
67
68 #include "var.h"
69 #include "vmbuf.h"
70 #include "misc.h"
71 #include "gcmalloc.h"
72
73 #include "racoonctl.h"
74 #include "admin.h"
75 #include "schedule.h"
76 #include "handler.h"
77 #include "sockmisc.h"
78 #include "vmbuf.h"
79 #include "plog.h"
80 #include "isakmp_var.h"
81 #include "isakmp.h"
82 #include "isakmp_xauth.h"
83 #include "isakmp_cfg.h"
84 #include "isakmp_unity.h"
85 #include "ipsec_doi.h"
86 #include "evt.h"
87
88 char *adminsock_path = ADMINSOCK_PATH;
89
90 static void usage __P((void));
91 static vchar_t *get_combuf __P((int, char **));
92 static int handle_recv __P((vchar_t *));
93 static vchar_t *f_reload __P((int, char **));
94 static vchar_t *f_getsched __P((int, char **));
95 static vchar_t *f_getsa __P((int, char **));
96 static vchar_t *f_getsacert __P((int, char **));
97 static vchar_t *f_flushsa __P((int, char **));
98 static vchar_t *f_deletesa __P((int, char **));
99 static vchar_t *f_exchangesa __P((int, char **));
100 static vchar_t *f_vpnc __P((int, char **));
101 static vchar_t *f_vpnd __P((int, char **));
102 static vchar_t *f_getevt __P((int, char **));
103 #ifdef ENABLE_HYBRID
104 static vchar_t *f_logoutusr __P((int, char **));
105 #endif
106
107 struct cmd_tag {
108 vchar_t *(*func) __P((int, char **));
109 char *str;
110 } cmdtab[] = {
111 { f_reload, "reload-config" },
112 { f_reload, "rc" },
113 { f_getsched, "show-schedule" },
114 { f_getsched, "sc" },
115 { f_getsa, "show-sa" },
116 { f_getsa, "ss" },
117 { f_getsacert, "get-cert" },
118 { f_getsacert, "gc" },
119 { f_flushsa, "flush-sa" },
120 { f_flushsa, "fs" },
121 { f_deletesa, "delete-sa" },
122 { f_deletesa, "ds" },
123 { f_exchangesa, "establish-sa" },
124 { f_exchangesa, "es" },
125 { f_vpnc, "vpn-connect" },
126 { f_vpnc, "vc" },
127 { f_vpnd, "vpn-disconnect" },
128 { f_vpnd, "vd" },
129 { f_getevt, "show-event" },
130 { f_getevt, "se" },
131 #ifdef ENABLE_HYBRID
132 { f_logoutusr, "logout-user" },
133 { f_logoutusr, "lu" },
134 #endif
135 { NULL, NULL },
136 };
137
138 struct evtmsg {
139 int type;
140 char *msg;
141 } evtmsg[] = {
142 { EVT_RACOON_QUIT, "Racoon terminated" },
143
144 { EVT_PHASE1_UP, "Phase 1 established" },
145 { EVT_PHASE1_DOWN, "Phase 1 deleted" },
146 { EVT_PHASE1_NO_RESPONSE, "Phase 1 error: peer not responding" },
147 { EVT_PHASE1_NO_PROPOSAL, "Phase 1 error: no proposal chosen" },
148 { EVT_PHASE1_AUTH_FAILED,
149 "Phase 1 error: authentication failed (bad certificate?)" },
150 { EVT_PHASE1_DPD_TIMEOUT, "Phase 1 error: dead peer detected" },
151 { EVT_PHASE1_MODE_CFG, "Phase 1 mode configuration done" },
152 { EVT_PHASE1_XAUTH_SUCCESS, "Phase 1 Xauth succeeded" },
153 { EVT_PHASE1_XAUTH_FAILED, "Phase 1 Xauth failed" },
154
155 { EVT_PHASE2_NO_PHASE1, "Phase 2 error: no suitable phase 1" },
156 { EVT_PHASE2_UP, "Phase 2 established" },
157 { EVT_PHASE2_DOWN, "Phase 2 deleted" },
158 { EVT_PHASE2_NO_RESPONSE, "Phase 2 error: no response" },
159 };
160
161 static vchar_t *get_proto_and_index __P((int, char **, u_int16_t *));
162 static int get_proto __P((char *));
163 static vchar_t *get_index __P((int, char **));
164 static int get_family __P((char *));
165 static vchar_t *get_comindexes __P((int, int, char **));
166 static int get_comindex __P((char *, char **, char **, char **));
167 static int get_ulproto __P((char *));
168
169 struct proto_tag {
170 int proto;
171 char *str;
172 } prototab[] = {
173 { ADMIN_PROTO_ISAKMP, "isakmp" },
174 { ADMIN_PROTO_IPSEC, "ipsec" },
175 { ADMIN_PROTO_AH, "ah" },
176 { ADMIN_PROTO_ESP, "esp" },
177 { ADMIN_PROTO_INTERNAL, "internal" },
178 { 0, NULL },
179 };
180
181 struct ulproto_tag {
182 int ul_proto;
183 char *str;
184 } ulprototab[] = {
185 { 0, "any" },
186 { IPPROTO_ICMP, "icmp" },
187 { IPPROTO_TCP, "tcp" },
188 { IPPROTO_UDP, "udp" },
189 { IPPROTO_GRE, "gre" },
190 { 0, NULL },
191 };
192
193 int so;
194
195 static char _addr1_[NI_MAXHOST], _addr2_[NI_MAXHOST];
196
197 char *pname;
198 int long_format = 0;
199 int evt_quit_event = 0;
200
201 void dump_isakmp_sa __P((char *, int));
202 void dump_internal __P((char *, int));
203 char *pindex_isakmp __P((isakmp_index *));
204 void print_schedule __P((caddr_t, int));
205 void print_evt __P((struct evt_async *));
206 char * fixed_addr __P((char *, char *, int));
207
208 static void
usage()209 usage()
210 {
211 printf(
212 "Usage:\n"
213 " %s [opts] reload-config\n"
214 " %s [opts] show-schedule\n"
215 " %s [opts] show-sa [protocol]\n"
216 " %s [opts] flush-sa [protocol]\n"
217 " %s [opts] delete-sa <saopts>\n"
218 " %s [opts] establish-sa [-u identity] [-n remoteconf] [-w] <saopts>\n"
219 " %s [opts] vpn-connect [-u identity] vpn_gateway\n"
220 " %s [opts] vpn-disconnect vpn_gateway\n"
221 " %s [opts] show-event\n"
222 " %s [opts] logout-user login\n"
223 "\n"
224 "General options:\n"
225 " -d Debug: hexdump admin messages before sending\n"
226 " -l Increase output verbosity (mainly for show-sa)\n"
227 " -s <socket> Specify adminport socket to use (default: %s)\n"
228 "\n"
229 "Parameter specifications:\n"
230 " <protocol>: \"isakmp\", \"esp\" or \"ah\".\n"
231 " In the case of \"show-sa\" or \"flush-sa\", you can use \"ipsec\".\n"
232 "\n"
233 " <saopts>: \"isakmp\" <family> <src> <dst>\n"
234 " : {\"esp\",\"ah\"} <family> <src/prefixlen/port> <dst/prefixlen/port>\n"
235 " <ul_proto>\n"
236 " <family>: \"inet\" or \"inet6\"\n"
237 " <ul_proto>: \"icmp\", \"tcp\", \"udp\", \"gre\" or \"any\"\n"
238 "\n",
239 pname, pname, pname, pname, pname, pname, pname, pname, pname, pname,
240 ADMINSOCK_PATH);
241 }
242
243 /*
244 * Check for proper racoonctl interface
245 */
246 #if ((RACOONCTL_INTERFACE_MAJOR != 1) || (RACOONCTL_INTERFACE < 20041230))
247 #error "Incompatible racoonctl interface"
248 #endif
249
250 int
main(ac,av)251 main(ac, av)
252 int ac;
253 char **av;
254 {
255 vchar_t *combuf;
256 int c;
257
258 pname = *av;
259
260 /*
261 * Check for proper racoonctl interface
262 */
263 if ((racoonctl_interface_major != RACOONCTL_INTERFACE_MAJOR) ||
264 (racoonctl_interface < RACOONCTL_INTERFACE))
265 errx(1, "Incompatible racoonctl interface");
266
267 #ifdef __linux__
268 /*
269 * Disable GNU extensions that will prevent racoonct vc -u login
270 * from working (GNU getopt(3) does not like options after vc)
271 */
272 setenv("POSIXLY_CORRECT", "1", 0);
273 #endif
274 while ((c = getopt(ac, av, "lds:")) != -1) {
275 switch(c) {
276 case 'l':
277 long_format++;
278 break;
279
280 case 'd':
281 loglevel++;
282 break;
283
284 case 's':
285 adminsock_path = optarg;
286 break;
287
288 default:
289 usage();
290 exit(0);
291 }
292 }
293
294 ac -= optind;
295 av += optind;
296
297 combuf = get_combuf(ac, av);
298 if (!combuf)
299 err(1, "kmpstat");
300
301 if (loglevel)
302 racoon_hexdump(combuf, ((struct admin_com *)combuf)->ac_len);
303
304 com_init();
305
306 if (com_send(combuf) != 0)
307 goto bad;
308
309 vfree(combuf);
310
311 do {
312 if (com_recv(&combuf) != 0)
313 goto bad;
314 if (handle_recv(combuf) != 0)
315 goto bad;
316 vfree(combuf);
317 } while (evt_quit_event != 0);
318
319 close(so);
320 exit(0);
321
322 bad:
323 close(so);
324 if (errno == EEXIST)
325 exit(0);
326 exit(1);
327 }
328
329 /* %%% */
330 /*
331 * return command buffer.
332 */
333 static vchar_t *
get_combuf(ac,av)334 get_combuf(ac, av)
335 int ac;
336 char **av;
337 {
338 struct cmd_tag *cp;
339
340 if (ac == 0) {
341 usage();
342 exit(0);
343 }
344
345 /* checking the string of command. */
346 for (cp = &cmdtab[0]; cp->str; cp++) {
347 if (strcmp(*av, cp->str) == 0) {
348 break;
349 }
350 }
351 if (!cp->str) {
352 printf("Invalid command [%s]\n", *av);
353 errno = EINVAL;
354 return NULL;
355 }
356
357 ac--;
358 av++;
359 return (cp->func)(ac, av);
360 }
361
362 static vchar_t *
make_request(u_int16_t cmd,u_int16_t proto,size_t len)363 make_request(u_int16_t cmd, u_int16_t proto, size_t len)
364 {
365 vchar_t *buf;
366 struct admin_com *head;
367
368 buf = vmalloc(sizeof(struct admin_com) + len);
369 if (buf == NULL)
370 errx(1, "not enough core");
371
372 head = (struct admin_com *) buf->v;
373 head->ac_len = buf->l;
374 head->ac_cmd = ADMIN_FLAG_VERSION | cmd;
375 head->ac_version = 1;
376 head->ac_proto = proto;
377
378 return buf;
379 }
380
381 static vchar_t *
f_reload(ac,av)382 f_reload(ac, av)
383 int ac;
384 char **av;
385 {
386 return make_request(ADMIN_RELOAD_CONF, 0, 0);
387 }
388
389 static vchar_t *
f_getevt(ac,av)390 f_getevt(ac, av)
391 int ac;
392 char **av;
393 {
394 evt_quit_event = -1;
395 if (ac >= 1)
396 errx(1, "too many arguments");
397
398 return make_request(ADMIN_SHOW_EVT, 0, 0);
399 }
400
401 static vchar_t *
f_getsched(ac,av)402 f_getsched(ac, av)
403 int ac;
404 char **av;
405 {
406 return make_request(ADMIN_SHOW_SCHED, 0, 0);
407 }
408
409 static vchar_t *
f_getsa(ac,av)410 f_getsa(ac, av)
411 int ac;
412 char **av;
413 {
414 int proto;
415
416 /* need protocol */
417 if (ac != 1)
418 errx(1, "insufficient arguments");
419 proto = get_proto(*av);
420 if (proto == -1)
421 errx(1, "unknown protocol %s", *av);
422
423 return make_request(ADMIN_SHOW_SA, proto, 0);
424 }
425
426 static vchar_t *
f_getsacert(ac,av)427 f_getsacert(ac, av)
428 int ac;
429 char **av;
430 {
431 vchar_t *buf, *index;
432 struct admin_com_indexes *com;
433
434 index = get_index(ac, av);
435 if (index == NULL)
436 return NULL;
437
438 com = (struct admin_com_indexes *) index->v;
439 buf = make_request(ADMIN_GET_SA_CERT, ADMIN_PROTO_ISAKMP, index->l);
440 if (buf == NULL)
441 errx(1, "Cannot allocate buffer");
442
443 memcpy(buf->v+sizeof(struct admin_com), index->v, index->l);
444
445 vfree(index);
446
447 return buf;
448 }
449
450 static vchar_t *
f_flushsa(ac,av)451 f_flushsa(ac, av)
452 int ac;
453 char **av;
454 {
455 vchar_t *buf;
456 struct admin_com *head;
457 int proto;
458
459 /* need protocol */
460 if (ac != 1)
461 errx(1, "insufficient arguments");
462 proto = get_proto(*av);
463 if (proto == -1)
464 errx(1, "unknown protocol %s", *av);
465
466 return make_request(ADMIN_FLUSH_SA, proto, 0);
467 }
468
469 static vchar_t *
f_deletesa(ac,av)470 f_deletesa(ac, av)
471 int ac;
472 char **av;
473 {
474 vchar_t *buf, *index;
475 int proto;
476
477 /* need protocol */
478 if (ac < 1)
479 errx(1, "insufficient arguments");
480 proto = get_proto(*av);
481 if (proto == -1)
482 errx(1, "unknown protocol %s", *av);
483
484 /* get index(es) */
485 av++;
486 ac--;
487 switch (proto) {
488 case ADMIN_PROTO_ISAKMP:
489 index = get_index(ac, av);
490 if (index == NULL)
491 return NULL;
492 break;
493 case ADMIN_PROTO_AH:
494 case ADMIN_PROTO_ESP:
495 index = get_index(ac, av);
496 if (index == NULL)
497 return NULL;
498 break;
499 default:
500 errno = EPROTONOSUPPORT;
501 return NULL;
502 }
503
504 buf = make_request(ADMIN_DELETE_SA, proto, index->l);
505 if (buf == NULL)
506 goto out;
507
508 memcpy(buf->v + sizeof(struct admin_com), index->v, index->l);
509
510 out:
511 if (index != NULL)
512 vfree(index);
513
514 return buf;
515 }
516
517 static vchar_t *
f_deleteallsadst(ac,av)518 f_deleteallsadst(ac, av)
519 int ac;
520 char **av;
521 {
522 vchar_t *buf, *index;
523 u_int16_t proto;
524
525 index = get_proto_and_index(ac, av, &proto);
526 if (index == NULL)
527 return NULL;
528
529 buf = make_request(ADMIN_DELETE_ALL_SA_DST, proto, index->l);
530 if (buf == NULL)
531 goto out;
532
533 memcpy(buf->v+sizeof(struct admin_com), index->v, index->l);
534
535 out:
536 if (index != NULL)
537 vfree(index);
538
539 return buf;
540 }
541
542 static vchar_t *
f_exchangesa(ac,av)543 f_exchangesa(ac, av)
544 int ac;
545 char **av;
546 {
547 vchar_t *buf, *index;
548 u_int16_t proto;
549 int cmd = ADMIN_ESTABLISH_SA;
550 size_t com_len = 0;
551 char *id = NULL;
552 char *key = NULL;
553 char *remoteconf = NULL;
554 struct admin_com_psk *acp;
555 int wait = 0;
556
557 if (ac < 1)
558 errx(1, "insufficient arguments");
559
560 /* Optional -u identity */
561 if (strcmp(av[0], "-u") == 0) {
562 if (ac < 2)
563 errx(1, "-u require an argument");
564
565 id = av[1];
566 if ((key = getpass("Password: ")) == NULL)
567 errx(1, "getpass() failed: %s", strerror(errno));
568
569 com_len += sizeof(*acp) + strlen(id) + 1 + strlen(key) + 1;
570 cmd = ADMIN_ESTABLISH_SA_PSK;
571
572 av += 2;
573 ac -= 2;
574 }
575
576 if (ac >= 2 && strcmp(av[0], "-n") == 0) {
577 /* Remoteconf name */
578 remoteconf = av[1];
579 av += 2;
580 ac -= 2;
581 }
582
583 if (ac >= 1 && strcmp(av[0], "-w") == 0) {
584 wait = 1;
585 av++;
586 ac--;
587 }
588
589 index = get_proto_and_index(ac, av, &proto);
590 if (index == NULL)
591 return NULL;
592
593 if (proto == ADMIN_PROTO_ISAKMP && cmd == ADMIN_ESTABLISH_SA &&
594 remoteconf != NULL)
595 com_len += strlen(remoteconf) + 1;
596
597 if (wait) {
598 switch (proto) {
599 case ADMIN_PROTO_ISAKMP:
600 evt_quit_event = EVT_PHASE1_MODE_CFG;
601 break;
602 case ADMIN_PROTO_AH:
603 case ADMIN_PROTO_ESP:
604 evt_quit_event = EVT_PHASE2_UP;
605 break;
606 default:
607 errno = EPROTONOSUPPORT;
608 return NULL;
609 }
610 }
611
612 com_len += index->l;
613 buf = make_request(cmd, proto, com_len);
614 if (buf == NULL)
615 errx(1, "Cannot allocate buffer");
616
617 memcpy(buf->v+sizeof(struct admin_com), index->v, index->l);
618
619 if (proto == ADMIN_PROTO_ISAKMP && cmd == ADMIN_ESTABLISH_SA &&
620 remoteconf != NULL) {
621 strcpy(buf->v + sizeof(struct admin_com) + index->l,
622 remoteconf);
623 } else if (id && key) {
624 char *data;
625 acp = (struct admin_com_psk *)
626 (buf->v + sizeof(struct admin_com) + index->l);
627
628 acp->id_type = IDTYPE_USERFQDN;
629 acp->id_len = strlen(id) + 1;
630 acp->key_len = strlen(key) + 1;
631
632 data = (char *)(acp + 1);
633 strcpy(data, id);
634
635 data = (char *)(data + acp->id_len);
636 strcpy(data, key);
637 }
638
639 vfree(index);
640
641 return buf;
642 }
643
644 static vchar_t *
f_vpnc(ac,av)645 f_vpnc(ac, av)
646 int ac;
647 char **av;
648 {
649 char *nav[] = {NULL, NULL, NULL, NULL, NULL, NULL};
650 int nac = 0;
651 char *isakmp = "isakmp";
652 char *inet = "inet";
653 char *srcaddr;
654 struct addrinfo hints, *res;
655 struct sockaddr *src;
656 char *idx;
657
658 if (ac < 1)
659 errx(1, "insufficient arguments");
660
661 evt_quit_event = EVT_PHASE1_MODE_CFG;
662
663 /* Optional -u identity */
664 if (strcmp(av[0], "-u") == 0) {
665 if (ac < 2)
666 errx(1, "-u require an argument");
667
668 nav[nac++] = av[0];
669 nav[nac++] = av[1];
670
671 ac -= 2;
672 av += 2;
673 }
674
675 if (ac < 1)
676 errx(1, "VPN gateway required");
677 if (ac > 1)
678 warnx("Extra arguments");
679
680 /*
681 * Find the source address
682 */
683 memset(&hints, 0, sizeof(hints));
684 hints.ai_family = PF_UNSPEC;
685 hints.ai_socktype = SOCK_DGRAM;
686 if (getaddrinfo(av[0], "4500", &hints, &res) != 0)
687 errx(1, "Cannot resolve destination address");
688
689 if ((src = getlocaladdr(res->ai_addr)) == NULL)
690 errx(1, "cannot find source address");
691
692 if ((srcaddr = saddr2str(src)) == NULL)
693 errx(1, "cannot read source address");
694
695 /* We get "ip[port]" strip the port */
696 if ((idx = index(srcaddr, '[')) == NULL)
697 errx(1, "unexpected source address format");
698 *idx = '\0';
699
700 nav[nac++] = isakmp;
701 nav[nac++] = inet;
702 nav[nac++] = srcaddr;
703 nav[nac++] = av[0];
704
705 return f_exchangesa(nac, nav);
706 }
707
708 static vchar_t *
f_vpnd(ac,av)709 f_vpnd(ac, av)
710 int ac;
711 char **av;
712 {
713 char *nav[] = {NULL, NULL, NULL, NULL};
714 int nac = 0;
715 char *isakmp = "isakmp";
716 char *inet = "inet";
717 char *anyaddr = "0.0.0.0";
718 char *idx;
719
720 if (ac < 1)
721 errx(1, "VPN gateway required");
722 if (ac > 1)
723 warnx("Extra arguments");
724
725 evt_quit_event = EVT_PHASE1_DOWN;
726
727 nav[nac++] = isakmp;
728 nav[nac++] = inet;
729 nav[nac++] = anyaddr;
730 nav[nac++] = av[0];
731
732 return f_deleteallsadst(nac, nav);
733 }
734
735 #ifdef ENABLE_HYBRID
736 static vchar_t *
f_logoutusr(ac,av)737 f_logoutusr(ac, av)
738 int ac;
739 char **av;
740 {
741 vchar_t *buf;
742 char *user;
743 size_t userlen;
744
745 /* need username */
746 if (ac < 1)
747 errx(1, "insufficient arguments");
748 user = av[0];
749 userlen = strlen(user);
750 if ((user == NULL) || (userlen > LOGINLEN))
751 errx(1, "bad login (too long?)");
752
753 buf = make_request(ADMIN_LOGOUT_USER, 0, userlen);
754 if (buf == NULL)
755 return NULL;
756
757 strncpy(buf->v + sizeof(struct admin_com), user, userlen);
758
759 return buf;
760 }
761 #endif /* ENABLE_HYBRID */
762
763 static vchar_t *
get_proto_and_index(ac,av,proto)764 get_proto_and_index(ac, av, proto)
765 int ac;
766 char **av;
767 u_int16_t *proto;
768 {
769 vchar_t *index = NULL;
770
771 /* need protocol */
772 if (ac < 1)
773 errx(1, "insufficient arguments");
774 *proto = get_proto(*av);
775 if (*proto == (u_int16_t) -1)
776 errx(1, "unknown protocol %s", *av);
777
778 /* get index(es) */
779 av++;
780 ac--;
781 switch (*proto) {
782 case ADMIN_PROTO_ISAKMP:
783 case ADMIN_PROTO_AH:
784 case ADMIN_PROTO_ESP:
785 index = get_index(ac, av);
786 break;
787 default:
788 errno = EPROTONOSUPPORT;
789 break;
790 }
791 return index;
792 }
793
794 static int
get_proto(str)795 get_proto(str)
796 char *str;
797 {
798 struct proto_tag *cp;
799
800 if (str == NULL) {
801 errno = EINVAL;
802 return -1;
803 }
804
805 /* checking the string of command. */
806 for (cp = &prototab[0]; cp->str; cp++) {
807 if (strcmp(str, cp->str) == 0)
808 return cp->proto;
809 }
810
811 errno = EINVAL;
812 return -1;
813 }
814
815 static vchar_t *
get_index(ac,av)816 get_index(ac, av)
817 int ac;
818 char **av;
819 {
820 int family;
821
822 if (ac != 3 && ac != 4) {
823 errno = EINVAL;
824 return NULL;
825 }
826
827 /* checking the string of family */
828 family = get_family(*av);
829 if (family == -1)
830 return NULL;
831 av++;
832 ac--;
833
834 return get_comindexes(family, ac, av);
835 }
836
837 static int
get_family(str)838 get_family(str)
839 char *str;
840 {
841 if (strcmp("inet", str) == 0)
842 return AF_INET;
843 #ifdef INET6
844 else if (strcmp("inet6", str) == 0)
845 return AF_INET6;
846 #endif
847 errno = EAFNOSUPPORT;
848 return -1;
849 }
850
851 static vchar_t *
get_comindexes(family,ac,av)852 get_comindexes(family, ac, av)
853 int family;
854 int ac;
855 char **av;
856 {
857 vchar_t *buf;
858 struct admin_com_indexes *ci;
859 char *p_name = NULL, *p_port = NULL;
860 char *p_prefs = NULL, *p_prefd = NULL;
861 struct sockaddr *src = NULL, *dst = NULL;
862 int ulproto;
863
864 if (ac != 2 && ac != 3) {
865 errno = EINVAL;
866 return NULL;
867 }
868
869 if (get_comindex(*av, &p_name, &p_port, &p_prefs) == -1)
870 goto bad;
871 src = get_sockaddr(family, p_name, p_port);
872 if (p_name) {
873 racoon_free(p_name);
874 p_name = NULL;
875 }
876 if (p_port) {
877 racoon_free(p_port);
878 p_port = NULL;
879 }
880 if (src == NULL)
881 goto bad;
882 av++;
883 ac--;
884 if (get_comindex(*av, &p_name, &p_port, &p_prefd) == -1)
885 goto bad;
886 dst = get_sockaddr(family, p_name, p_port);
887 if (p_name) {
888 racoon_free(p_name);
889 p_name = NULL;
890 }
891 if (p_port) {
892 racoon_free(p_port);
893 p_port = NULL;
894 }
895 if (dst == NULL)
896 goto bad;
897
898 buf = vmalloc(sizeof(*ci));
899 if (buf == NULL)
900 goto bad;
901
902 av++;
903 ac--;
904 if(ac){
905 ulproto = get_ulproto(*av);
906 if (ulproto == -1)
907 goto bad;
908 }else
909 ulproto=0;
910
911 ci = (struct admin_com_indexes *)buf->v;
912 if(p_prefs)
913 ci->prefs = (u_int8_t)atoi(p_prefs); /* XXX should be handled error. */
914 else
915 ci->prefs = 32;
916 if(p_prefd)
917 ci->prefd = (u_int8_t)atoi(p_prefd); /* XXX should be handled error. */
918 else
919 ci->prefd = 32;
920 ci->ul_proto = ulproto;
921 memcpy(&ci->src, src, sysdep_sa_len(src));
922 memcpy(&ci->dst, dst, sysdep_sa_len(dst));
923
924 if (p_name)
925 racoon_free(p_name);
926
927 return buf;
928
929 bad:
930 if (p_name)
931 racoon_free(p_name);
932 if (p_port)
933 racoon_free(p_port);
934 if (p_prefs)
935 racoon_free(p_prefs);
936 if (p_prefd)
937 racoon_free(p_prefd);
938 return NULL;
939 }
940
941 static int
get_comindex(str,name,port,pref)942 get_comindex(str, name, port, pref)
943 char *str, **name, **port, **pref;
944 {
945 char *p;
946
947 *name = *port = *pref = NULL;
948
949 *name = racoon_strdup(str);
950 STRDUP_FATAL(*name);
951 p = strpbrk(*name, "/[");
952 if (p != NULL) {
953 if (*(p + 1) == '\0')
954 goto bad;
955 if (*p == '/') {
956 *p = '\0';
957 *pref = racoon_strdup(p + 1);
958 STRDUP_FATAL(*pref);
959 p = strchr(*pref, '[');
960 if (p != NULL) {
961 if (*(p + 1) == '\0')
962 goto bad;
963 *p = '\0';
964 *port = racoon_strdup(p + 1);
965 STRDUP_FATAL(*port);
966 p = strchr(*pref, ']');
967 if (p == NULL)
968 goto bad;
969 *p = '\0';
970 }
971 } else if (*p == '[') {
972 if (*pref == NULL)
973 goto bad;
974 *p = '\0';
975 *port = racoon_strdup(p + 1);
976 STRDUP_FATAL(*port);
977 p = strchr(*pref, ']');
978 if (p == NULL)
979 goto bad;
980 *p = '\0';
981 } else {
982 /* XXX */
983 }
984 }
985
986 return 0;
987
988 bad:
989
990 if (*name)
991 racoon_free(*name);
992 if (*port)
993 racoon_free(*port);
994 if (*pref)
995 racoon_free(*pref);
996 *name = *port = *pref = NULL;
997 return -1;
998 }
999
1000 static int
get_ulproto(str)1001 get_ulproto(str)
1002 char *str;
1003 {
1004 struct ulproto_tag *cp;
1005
1006 if(str == NULL){
1007 errno = EINVAL;
1008 return -1;
1009 }
1010
1011 /* checking the string of upper layer protocol. */
1012 for (cp = &ulprototab[0]; cp->str; cp++) {
1013 if (strcmp(str, cp->str) == 0)
1014 return cp->ul_proto;
1015 }
1016
1017 errno = EINVAL;
1018 return -1;
1019 }
1020
1021 /* %%% */
1022 void
dump_isakmp_sa(buf,len)1023 dump_isakmp_sa(buf, len)
1024 char *buf;
1025 int len;
1026 {
1027 struct ph1dump *pd;
1028 struct tm *tm;
1029 char tbuf[56];
1030 caddr_t p = NULL;
1031
1032 /* isakmp status header */
1033 /* short header;
1034 1234567890123456789012 0000000000000000:0000000000000000 000000000000
1035 */
1036 char *header1 =
1037 "Destination Cookies Created";
1038
1039 /* semi long header;
1040 1234567890123456789012 0000000000000000:0000000000000000 00 X 00 X 0000-00-00 00:00:00 000000
1041 */
1042 char *header2 =
1043 "Destination Cookies ST S V E Created Phase2";
1044
1045 /* long header;
1046 0000:0000:0000:0000:0000:0000:0000:0000.00000 0000:0000:0000:0000:0000:0000:0000:0000.00000 0000000000000000:0000000000000000 00 X 00 X 0000-00-00 00:00:00 000000
1047 */
1048 char *header3 =
1049 "Source Destination Cookies ST S V E Created Phase2";
1050
1051 /* phase status header */
1052 /* short format;
1053 side stats source address destination address
1054 xxx xxxxx 1234567890123456789012 1234567890123456789012
1055 */
1056
1057 static char *estr[] = { "", "B", "M", "U", "A", "I", };
1058
1059 switch (long_format) {
1060 case 0:
1061 printf("%s\n", header1);
1062 break;
1063 case 1:
1064 printf("%s\n", header2);
1065 break;
1066 case 2:
1067 default:
1068 printf("%s\n", header3);
1069 break;
1070 }
1071
1072 if (len % sizeof(*pd))
1073 printf("invalid length %d\n", len);
1074 len /= sizeof(*pd);
1075
1076 pd = (struct ph1dump *)buf;
1077
1078 while (len-- > 0) {
1079 /* source address */
1080 if (long_format >= 2) {
1081 GETNAMEINFO((struct sockaddr *)&pd->local, _addr1_, _addr2_);
1082 switch (long_format) {
1083 case 0:
1084 break;
1085 case 1:
1086 p = fixed_addr(_addr1_, _addr2_, 22);
1087 break;
1088 case 2:
1089 default:
1090 p = fixed_addr(_addr1_, _addr2_, 45);
1091 break;
1092 }
1093 printf("%s ", p);
1094 }
1095
1096 /* destination address */
1097 GETNAMEINFO((struct sockaddr *)&pd->remote, _addr1_, _addr2_);
1098 switch (long_format) {
1099 case 0:
1100 case 1:
1101 p = fixed_addr(_addr1_, _addr2_, 22);
1102 break;
1103 case 2:
1104 default:
1105 p = fixed_addr(_addr1_, _addr2_, 45);
1106 break;
1107 }
1108 printf("%s ", p);
1109
1110 printf("%s ", pindex_isakmp(&pd->index));
1111
1112 /* statuc, side and version */
1113 if (long_format >= 1) {
1114 printf("%2d %c %2x ",
1115 pd->status,
1116 pd->side == INITIATOR ? 'I' : 'R',
1117 pd->version);
1118 if (ARRAYLEN(estr) > pd->etype)
1119 printf("%s ", estr[pd->etype]);
1120 }
1121
1122 /* created date */
1123 if (pd->created) {
1124 tm = localtime(&pd->created);
1125 strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %T", tm);
1126 } else
1127 snprintf(tbuf, sizeof(tbuf), " ");
1128 printf("%s ", tbuf);
1129
1130 /* counter of phase 2 */
1131 if (long_format >= 1)
1132 printf("%6d ", pd->ph2cnt);
1133
1134 printf("\n");
1135
1136 pd++;
1137 }
1138
1139 return;
1140 }
1141
1142 /* %%% */
1143 void
dump_internal(buf,tlen)1144 dump_internal(buf, tlen)
1145 char *buf;
1146 int tlen;
1147 {
1148 struct ph2handle *iph2;
1149 struct sockaddr *addr;
1150
1151 /*
1152 short header;
1153 source address destination address
1154 1234567890123456789012 1234567890123456789012
1155 */
1156 char *short_h1 =
1157 "Source Destination ";
1158
1159 /*
1160 long header;
1161 source address destination address
1162 123456789012345678901234567890123456789012345 123456789012345678901234567890123456789012345
1163 0000:0000:0000:0000:0000:0000:0000:0000.00000 0000:0000:0000:0000:0000:0000:0000:0000.00000 0000:0000:0000:0000:0000:0000:0000:0000.00000
1164 */
1165 char *long_h1 =
1166 "Source Destination ";
1167
1168 printf("%s\n", long_format ? long_h1 : short_h1);
1169
1170 while (tlen > 0) {
1171 iph2 = (struct ph2handle *)buf;
1172 addr = (struct sockaddr *)(++iph2);
1173
1174 GETNAMEINFO(addr, _addr1_, _addr2_);
1175 printf("%s ", long_format ?
1176 fixed_addr(_addr1_, _addr2_, 45)
1177 : fixed_addr(_addr1_, _addr2_, 22));
1178 addr++;
1179 tlen -= sysdep_sa_len(addr);
1180
1181 GETNAMEINFO(addr, _addr1_, _addr2_);
1182 printf("%s ", long_format ?
1183 fixed_addr(_addr1_, _addr2_, 45)
1184 : fixed_addr(_addr1_, _addr2_, 22));
1185 addr++;
1186 tlen -= sysdep_sa_len(addr);
1187
1188 printf("\n");
1189 }
1190
1191 return;
1192 }
1193
1194 /* %%% */
1195 char *
pindex_isakmp(index)1196 pindex_isakmp(index)
1197 isakmp_index *index;
1198 {
1199 static char buf[64];
1200 u_char *p;
1201 int i, j;
1202
1203 memset(buf, 0, sizeof(buf));
1204
1205 /* copy index */
1206 p = (u_char *)index;
1207 for (j = 0, i = 0; i < sizeof(isakmp_index); i++) {
1208 snprintf((char *)&buf[j], sizeof(buf) - j, "%02x", p[i]);
1209 j += 2;
1210 switch (i) {
1211 case 7:
1212 #if 0
1213 case 15:
1214 #endif
1215 buf[j++] = ':';
1216 }
1217 }
1218
1219 return buf;
1220 }
1221
1222 /* print schedule */
1223 char *str_sched_stat[] = {
1224 "off",
1225 "on",
1226 "dead",
1227 };
1228
1229 char *str_sched_id[] = {
1230 "PH1resend",
1231 "PH1lifetime",
1232 "PH2resend",
1233 "PSTacquire",
1234 "PSTlifetime",
1235 };
1236
1237 void
print_schedule(buf,len)1238 print_schedule(buf, len)
1239 caddr_t buf;
1240 int len;
1241 {
1242 struct scheddump *sc = (struct scheddump *)buf;
1243 struct tm *tm;
1244 char tbuf[56];
1245
1246 if (len % sizeof(*sc))
1247 printf("invalid length %d\n", len);
1248 len /= sizeof(*sc);
1249
1250 /* 00000000 00000000 00000000 xxx........*/
1251 printf("index tick xtime created\n");
1252
1253 while (len-- > 0) {
1254 tm = localtime(&sc->created);
1255 strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %T", tm);
1256
1257 printf("%-8ld %-8ld %-8ld %s\n",
1258 sc->id,
1259 (long)sc->tick,
1260 (long)sc->xtime,
1261 tbuf);
1262 sc++;
1263 }
1264
1265 return;
1266 }
1267
1268
1269 void
print_evt(evtdump)1270 print_evt(evtdump)
1271 struct evt_async *evtdump;
1272 {
1273 int i;
1274 char *srcstr;
1275 char *dststr;
1276
1277 for (i = 0; i < sizeof(evtmsg) / sizeof(evtmsg[0]); i++)
1278 if (evtmsg[i].type == evtdump->ec_type)
1279 break;
1280
1281 if (evtmsg[i].msg == NULL)
1282 printf("Event %d: ", evtdump->ec_type);
1283 else
1284 printf("%s : ", evtmsg[i].msg);
1285
1286 if ((srcstr = saddr2str((struct sockaddr *)&evtdump->ec_ph1src)) == NULL)
1287 printf("unknown");
1288 else
1289 printf("%s", srcstr);
1290 printf(" -> ");
1291 if ((dststr = saddr2str((struct sockaddr *)&evtdump->ec_ph1dst)) == NULL)
1292 printf("unknown");
1293 else
1294 printf("%s", dststr);
1295 printf("\n");
1296 }
1297
1298 /*
1299 * Print ISAKMP mode config info (IP and banner)
1300 */
1301 void
print_cfg(buf,len)1302 print_cfg(buf, len)
1303 caddr_t buf;
1304 int len;
1305 {
1306 struct evt_async *evtdump = (struct evt_async *)buf;
1307 struct isakmp_data *attr;
1308 char *banner = NULL;
1309 struct in_addr addr4;
1310
1311 memset(&addr4, 0, sizeof(addr4));
1312
1313 if (evtdump->ec_type != EVT_PHASE1_MODE_CFG)
1314 return;
1315
1316 len -= sizeof(*evtdump);
1317 attr = (struct isakmp_data *)(evtdump + 1);
1318
1319 while (len > 0) {
1320 if (len < sizeof(*attr)) {
1321 printf("short attribute too short\n");
1322 break;
1323 }
1324
1325 if ((ntohs(attr->type) & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) {
1326 /* Short attribute, skip */
1327 len -= sizeof(*attr);
1328 attr++;
1329 } else { /* Long attribute */
1330 char *n;
1331
1332 if (len < (sizeof(*attr) + ntohs(attr->lorv))) {
1333 printf("long attribute too long\n");
1334 break;
1335 }
1336
1337 switch (ntohs(attr->type) & ~ISAKMP_GEN_MASK) {
1338 case INTERNAL_IP4_ADDRESS:
1339 if (ntohs(attr->lorv) < sizeof(addr4)) {
1340 printf("addr4 attribute too short\n");
1341 break;
1342 }
1343 memcpy(&addr4, attr + 1, sizeof(addr4));
1344 break;
1345
1346 case UNITY_BANNER:
1347 banner = racoon_malloc(ntohs(attr->lorv) + 1);
1348 if (banner == NULL) {
1349 printf("malloc failed\n");
1350 break;
1351 }
1352 memcpy(banner, attr + 1, ntohs(attr->lorv));
1353 banner[ntohs(attr->lorv)] = '\0';
1354 break;
1355
1356 default:
1357 break;
1358 }
1359
1360 len -= (sizeof(*attr) + ntohs(attr->lorv));
1361 n = (char *)attr;
1362 attr = (struct isakmp_data *)
1363 (n + sizeof(*attr) + ntohs(attr->lorv));
1364 }
1365 }
1366
1367 if (len > 0)
1368 printf("Bound to address %s\n", inet_ntoa(addr4));
1369 else
1370 printf("VPN connexion established\n");
1371
1372 if (banner) {
1373 struct winsize win;
1374 int col = 0;
1375 int i;
1376
1377 if (ioctl(1, TIOCGWINSZ, &win) != 1)
1378 col = win.ws_col;
1379
1380 for (i = 0; i < col; i++)
1381 printf("%c", '=');
1382 printf("\n%s\n", banner);
1383 for (i = 0; i < col; i++)
1384 printf("%c", '=');
1385 printf("\n");
1386 racoon_free(banner);
1387 }
1388 }
1389
1390
1391 char *
fixed_addr(addr,port,len)1392 fixed_addr(addr, port, len)
1393 char *addr, *port;
1394 int len;
1395 {
1396 static char _addr_buf_[BUFSIZ];
1397 char *p;
1398 int plen, i;
1399
1400 /* initialize */
1401 memset(_addr_buf_, ' ', sizeof(_addr_buf_));
1402
1403 plen = strlen(port);
1404 if (len < plen + 1)
1405 return NULL;
1406
1407 p = _addr_buf_;
1408 for (i = 0; i < len - plen - 1 && addr[i] != '\0'; /*noting*/)
1409 *p++ = addr[i++];
1410 *p++ = '.';
1411
1412 for (i = 0; i < plen && port[i] != '\0'; /*noting*/)
1413 *p++ = port[i++];
1414
1415 _addr_buf_[len] = '\0';
1416
1417 return _addr_buf_;
1418 }
1419
1420 static int
handle_recv(combuf)1421 handle_recv(combuf)
1422 vchar_t *combuf;
1423 {
1424 struct admin_com *com;
1425 caddr_t buf;
1426 int len;
1427
1428 com = (struct admin_com *)combuf->v;
1429 if (com->ac_cmd & ADMIN_FLAG_LONG_REPLY)
1430 len = ((u_int32_t)com->ac_len) + (((u_int32_t)com->ac_len_high) << 16);
1431 else
1432 len = com->ac_len;
1433 len -= sizeof(*com);
1434 buf = combuf->v + sizeof(*com);
1435
1436 switch (com->ac_cmd & ~ADMIN_FLAG_LONG_REPLY) {
1437 case ADMIN_SHOW_SCHED:
1438 print_schedule(buf, len);
1439 break;
1440
1441 case ADMIN_SHOW_EVT: {
1442 struct evt_async *ec;
1443
1444 /* We got no event? */
1445 if (len == 0)
1446 break;
1447
1448 if (len < sizeof(struct evt_async))
1449 errx(1, "Short buffer\n");
1450
1451 ec = (struct evt_async *) buf;
1452 if (evt_quit_event <= 0)
1453 print_evt(ec);
1454 else if (evt_quit_event == ec->ec_type) {
1455 switch (ec->ec_type) {
1456 case EVT_PHASE1_MODE_CFG:
1457 print_cfg(ec, len);
1458 break;
1459 default:
1460 print_evt(ec);
1461 break;
1462 }
1463 evt_quit_event = 0;
1464 }
1465 break;
1466 }
1467
1468 case ADMIN_GET_SA_CERT:
1469 fwrite(buf, len, 1, stdout);
1470 break;
1471
1472 case ADMIN_SHOW_SA:
1473 {
1474 switch (com->ac_proto) {
1475 case ADMIN_PROTO_ISAKMP:
1476 dump_isakmp_sa(buf, len);
1477 break;
1478 case ADMIN_PROTO_IPSEC:
1479 case ADMIN_PROTO_AH:
1480 case ADMIN_PROTO_ESP:
1481 {
1482 struct sadb_msg *msg = (struct sadb_msg *)buf;
1483
1484 switch (msg->sadb_msg_errno) {
1485 case ENOENT:
1486 switch (msg->sadb_msg_type) {
1487 case SADB_DELETE:
1488 case SADB_GET:
1489 printf("No entry.\n");
1490 break;
1491 case SADB_DUMP:
1492 printf("No SAD entries.\n");
1493 break;
1494 }
1495 break;
1496 case 0:
1497 while (1) {
1498 pfkey_sadump(msg);
1499 if (msg->sadb_msg_seq == 0)
1500 break;
1501 msg = (struct sadb_msg *)((caddr_t)msg +
1502 PFKEY_UNUNIT64(msg->sadb_msg_len));
1503 }
1504 break;
1505 default:
1506 printf("%s.\n", strerror(msg->sadb_msg_errno));
1507 }
1508 }
1509 break;
1510 case ADMIN_PROTO_INTERNAL:
1511 dump_internal(buf, len);
1512 break;
1513 default:
1514 printf("Invalid proto [%d]\n", com->ac_proto);
1515 }
1516
1517 }
1518 break;
1519
1520 default:
1521 /* IGNORE */
1522 break;
1523 }
1524
1525 return 0;
1526
1527 bad:
1528 return -1;
1529 }
1530