source: rtems-libbsd/ipsec-tools/src/racoon/racoonctl.c @ ff36f5e

5-freebsd-12
Last change on this file since ff36f5e was ff36f5e, checked in by Christian Mauderer <christian.mauderer@…>, on May 30, 2018 at 12:27:35 PM

Import ipsec-tools 0.8.2.

Import unchanged ipsec-tools sources in the release version 0.8.2. The
homepage of ipsec-tools is http://ipsec-tools.sourceforge.net/. The
sources can be obtained from there.

  • Property mode set to 100644
File size: 30.1 KB
Line 
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
88char *adminsock_path = ADMINSOCK_PATH;
89
90static void usage __P((void));
91static vchar_t *get_combuf __P((int, char **));
92static int handle_recv __P((vchar_t *));
93static vchar_t *f_reload __P((int, char **));
94static vchar_t *f_getsched __P((int, char **));
95static vchar_t *f_getsa __P((int, char **));
96static vchar_t *f_getsacert __P((int, char **));
97static vchar_t *f_flushsa __P((int, char **));
98static vchar_t *f_deletesa __P((int, char **));
99static vchar_t *f_exchangesa __P((int, char **));
100static vchar_t *f_vpnc __P((int, char **));
101static vchar_t *f_vpnd __P((int, char **));
102static vchar_t *f_getevt __P((int, char **));
103#ifdef ENABLE_HYBRID
104static vchar_t *f_logoutusr __P((int, char **));
105#endif
106
107struct 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
138struct 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
161static vchar_t *get_proto_and_index __P((int, char **, u_int16_t *));
162static int get_proto __P((char *));
163static vchar_t *get_index __P((int, char **));
164static int get_family __P((char *));
165static vchar_t *get_comindexes __P((int, int, char **));
166static int get_comindex __P((char *, char **, char **, char **));
167static int get_ulproto __P((char *));
168
169struct 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
181struct 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
193int so;
194
195static char _addr1_[NI_MAXHOST], _addr2_[NI_MAXHOST];
196
197char *pname;
198int long_format = 0;
199int evt_quit_event = 0;
200
201void dump_isakmp_sa __P((char *, int));
202void dump_internal __P((char *, int));
203char *pindex_isakmp __P((isakmp_index *));
204void print_schedule __P((caddr_t, int));
205void print_evt __P((struct evt_async *));
206char * fixed_addr __P((char *, char *, int));
207
208static void
209usage()
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
250int
251main(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
322bad:
323        close(so);
324        if (errno == EEXIST)
325                exit(0);
326        exit(1);
327}
328
329/* %%% */
330/*
331 * return command buffer.
332 */
333static vchar_t *
334get_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
362static vchar_t *
363make_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
381static vchar_t *
382f_reload(ac, av)
383        int ac;
384        char **av;
385{
386        return make_request(ADMIN_RELOAD_CONF, 0, 0);
387}
388
389static vchar_t *
390f_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
401static vchar_t *
402f_getsched(ac, av)
403        int ac;
404        char **av;
405{
406        return make_request(ADMIN_SHOW_SCHED, 0, 0);
407}
408
409static vchar_t *
410f_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
426static vchar_t *
427f_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
450static vchar_t *
451f_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
469static vchar_t *
470f_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
510out:
511        if (index != NULL)
512                vfree(index);
513
514        return buf;
515}
516
517static vchar_t *
518f_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
535out:
536        if (index != NULL)
537                vfree(index);
538
539        return buf;
540}
541
542static vchar_t *
543f_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
644static vchar_t *
645f_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
708static vchar_t *
709f_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
736static vchar_t *
737f_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
763static vchar_t *
764get_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
794static int
795get_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
815static vchar_t *
816get_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
837static int
838get_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
851static vchar_t *
852get_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
941static int
942get_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
1000static int
1001get_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/* %%% */
1022void
1023dump_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*/
1036char *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*/
1042char *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*/
1048char *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/* %%% */
1143void
1144dump_internal(buf, tlen)
1145        char *buf;
1146        int tlen;
1147{
1148        struct ph2handle *iph2;
1149        struct sockaddr *addr;
1150
1151/*
1152short header;
1153 source address         destination address   
1154 1234567890123456789012 1234567890123456789012
1155*/
1156char *short_h1 = 
1157"Source                 Destination            ";
1158
1159/*
1160long 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*/
1165char *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/* %%% */
1195char *
1196pindex_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 */
1223char *str_sched_stat[] = {
1224"off",
1225"on",
1226"dead",
1227};
1228
1229char *str_sched_id[] = {
1230"PH1resend",
1231"PH1lifetime",
1232"PH2resend",
1233"PSTacquire",
1234"PSTlifetime",
1235};
1236
1237void
1238print_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
1269void
1270print_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 */
1301void
1302print_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
1391char *
1392fixed_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
1420static int
1421handle_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
1527bad:
1528        return -1;
1529}
Note: See TracBrowser for help on using the repository browser.