Return to racoonctl.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon |
1.1 misho 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
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
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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
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 *
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
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 *
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
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
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
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
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 *
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
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
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
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 *
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
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:
1.1.1.1.2.1! misho 1457: print_cfg((caddr_t) ec, len);
1.1 misho 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: }