Annotation of embedaddon/ipsec-tools/src/racoon/admin.c, revision 1.1

1.1     ! misho       1: /*     $NetBSD: admin.c,v 1.38 2010/12/08 07:38:35 tteras Exp $        */
        !             2: 
        !             3: /* Id: admin.c,v 1.25 2006/04/06 14:31:04 manubsd Exp */
        !             4: 
        !             5: /*
        !             6:  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
        !             7:  * All rights reserved.
        !             8:  *
        !             9:  * Redistribution and use in source and binary forms, with or without
        !            10:  * modification, are permitted provided that the following conditions
        !            11:  * are met:
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  * 2. Redistributions in binary form must reproduce the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer in the
        !            16:  *    documentation and/or other materials provided with the distribution.
        !            17:  * 3. Neither the name of the project nor the names of its contributors
        !            18:  *    may be used to endorse or promote products derived from this software
        !            19:  *    without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
        !            22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
        !            25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            31:  * SUCH DAMAGE.
        !            32:  */
        !            33: 
        !            34: #include "config.h"
        !            35: 
        !            36: #include <sys/types.h>
        !            37: #include <sys/param.h>
        !            38: #include <sys/socket.h>
        !            39: #include <sys/signal.h>
        !            40: #include <sys/stat.h>
        !            41: #include <sys/un.h>
        !            42: 
        !            43: #include <net/pfkeyv2.h>
        !            44: 
        !            45: #include <netinet/in.h>
        !            46: #include PATH_IPSEC_H
        !            47: 
        !            48: 
        !            49: #include <stdlib.h>
        !            50: #include <stdio.h>
        !            51: #include <string.h>
        !            52: #include <errno.h>
        !            53: #include <netdb.h>
        !            54: #ifdef HAVE_UNISTD_H
        !            55: #include <unistd.h>
        !            56: #endif
        !            57: #ifdef ENABLE_HYBRID
        !            58: #include <resolv.h>
        !            59: #endif
        !            60: 
        !            61: #include "var.h"
        !            62: #include "misc.h"
        !            63: #include "vmbuf.h"
        !            64: #include "plog.h"
        !            65: #include "sockmisc.h"
        !            66: #include "debug.h"
        !            67: 
        !            68: #include "schedule.h"
        !            69: #include "localconf.h"
        !            70: #include "remoteconf.h"
        !            71: #include "grabmyaddr.h"
        !            72: #include "isakmp_var.h"
        !            73: #include "isakmp.h"
        !            74: #include "oakley.h"
        !            75: #include "handler.h"
        !            76: #include "evt.h"
        !            77: #include "pfkey.h"
        !            78: #include "ipsec_doi.h"
        !            79: #include "policy.h"
        !            80: #include "admin.h"
        !            81: #include "admin_var.h"
        !            82: #include "isakmp_inf.h"
        !            83: #ifdef ENABLE_HYBRID
        !            84: #include "isakmp_cfg.h"
        !            85: #endif
        !            86: #include "session.h"
        !            87: #include "gcmalloc.h"
        !            88: 
        !            89: #ifdef ENABLE_ADMINPORT
        !            90: char *adminsock_path = ADMINSOCK_PATH;
        !            91: uid_t adminsock_owner = 0;
        !            92: gid_t adminsock_group = 0;
        !            93: mode_t adminsock_mode = 0600;
        !            94: 
        !            95: static struct sockaddr_un sunaddr;
        !            96: static int admin_process __P((int, char *));
        !            97: static int admin_reply __P((int, struct admin_com *, int, vchar_t *));
        !            98: 
        !            99: static int
        !           100: admin_handler(ctx, fd)
        !           101:        void *ctx;
        !           102:        int fd;
        !           103: {
        !           104:        int so2;
        !           105:        struct sockaddr_storage from;
        !           106:        socklen_t fromlen = sizeof(from);
        !           107:        struct admin_com com;
        !           108:        char *combuf = NULL;
        !           109:        int len, error = -1;
        !           110: 
        !           111:        so2 = accept(lcconf->sock_admin, (struct sockaddr *)&from, &fromlen);
        !           112:        if (so2 < 0) {
        !           113:                plog(LLV_ERROR, LOCATION, NULL,
        !           114:                        "failed to accept admin command: %s\n",
        !           115:                        strerror(errno));
        !           116:                return -1;
        !           117:        }
        !           118:        close_on_exec(so2);
        !           119: 
        !           120:        /* get buffer length */
        !           121:        while ((len = recv(so2, (char *)&com, sizeof(com), MSG_PEEK)) < 0) {
        !           122:                if (errno == EINTR)
        !           123:                        continue;
        !           124:                plog(LLV_ERROR, LOCATION, NULL,
        !           125:                        "failed to recv admin command: %s\n",
        !           126:                        strerror(errno));
        !           127:                goto end;
        !           128:        }
        !           129: 
        !           130:        /* sanity check */
        !           131:        if (len < sizeof(com)) {
        !           132:                plog(LLV_ERROR, LOCATION, NULL,
        !           133:                        "invalid header length of admin command\n");
        !           134:                goto end;
        !           135:        }
        !           136: 
        !           137:        /* get buffer to receive */
        !           138:        if ((combuf = racoon_malloc(com.ac_len)) == 0) {
        !           139:                plog(LLV_ERROR, LOCATION, NULL,
        !           140:                        "failed to alloc buffer for admin command\n");
        !           141:                goto end;
        !           142:        }
        !           143: 
        !           144:        /* get real data */
        !           145:        while ((len = recv(so2, combuf, com.ac_len, 0)) < 0) {
        !           146:                if (errno == EINTR)
        !           147:                        continue;
        !           148:                plog(LLV_ERROR, LOCATION, NULL,
        !           149:                        "failed to recv admin command: %s\n",
        !           150:                        strerror(errno));
        !           151:                goto end;
        !           152:        }
        !           153: 
        !           154:        error = admin_process(so2, combuf);
        !           155: 
        !           156: end:
        !           157:        if (error == -2) {
        !           158:                plog(LLV_DEBUG, LOCATION, NULL,
        !           159:                        "[%d] admin connection established\n", so2);
        !           160:        } else {
        !           161:                (void)close(so2);
        !           162:        }
        !           163: 
        !           164:        if (combuf)
        !           165:                racoon_free(combuf);
        !           166: 
        !           167:        return error;
        !           168: }
        !           169: 
        !           170: static int admin_ph1_delete_sa(struct ph1handle *iph1, void *arg)
        !           171: {
        !           172:        if (iph1->status >= PHASE1ST_ESTABLISHED)
        !           173:                isakmp_info_send_d1(iph1);
        !           174:        purge_remote(iph1);
        !           175:        return 0;
        !           176: }
        !           177: 
        !           178: /*
        !           179:  * main child's process.
        !           180:  */
        !           181: static int
        !           182: admin_process(so2, combuf)
        !           183:        int so2;
        !           184:        char *combuf;
        !           185: {
        !           186:        struct admin_com *com = (struct admin_com *)combuf;
        !           187:        vchar_t *buf = NULL;
        !           188:        vchar_t *id = NULL;
        !           189:        vchar_t *key = NULL;
        !           190:        int idtype = 0;
        !           191:        int error = 0, l_ac_errno = 0;
        !           192:        struct evt_listener_list *event_list = NULL;
        !           193: 
        !           194:        if (com->ac_cmd & ADMIN_FLAG_VERSION)
        !           195:                com->ac_cmd &= ~ADMIN_FLAG_VERSION;
        !           196:        else
        !           197:                com->ac_version = 0;
        !           198: 
        !           199:        switch (com->ac_cmd) {
        !           200:        case ADMIN_RELOAD_CONF:
        !           201:                signal_handler(SIGHUP);
        !           202:                break;
        !           203: 
        !           204:        case ADMIN_SHOW_SCHED: {
        !           205:                caddr_t p = NULL;
        !           206:                int len;
        !           207: 
        !           208:                if (sched_dump(&p, &len) != -1) {
        !           209:                        buf = vmalloc(len);
        !           210:                        if (buf != NULL)
        !           211:                                memcpy(buf->v, p, len);
        !           212:                        else
        !           213:                                l_ac_errno = ENOMEM;
        !           214:                        racoon_free(p);
        !           215:                } else
        !           216:                        l_ac_errno = ENOMEM;
        !           217:                break;
        !           218:        }
        !           219: 
        !           220:        case ADMIN_SHOW_EVT:
        !           221:                if (com->ac_version == 0) {
        !           222:                        buf = evt_dump();
        !           223:                        l_ac_errno = 0;
        !           224:                }
        !           225:                break;
        !           226: 
        !           227:        case ADMIN_SHOW_SA:
        !           228:                switch (com->ac_proto) {
        !           229:                case ADMIN_PROTO_ISAKMP:
        !           230:                        buf = dumpph1();
        !           231:                        if (buf == NULL)
        !           232:                                l_ac_errno = ENOMEM;
        !           233:                        break;
        !           234:                case ADMIN_PROTO_IPSEC:
        !           235:                case ADMIN_PROTO_AH:
        !           236:                case ADMIN_PROTO_ESP: {
        !           237:                        u_int p;
        !           238:                        p = admin2pfkey_proto(com->ac_proto);
        !           239:                        if (p != -1) {
        !           240:                                buf = pfkey_dump_sadb(p);
        !           241:                                if (buf == NULL)
        !           242:                                        l_ac_errno = ENOMEM;
        !           243:                        } else
        !           244:                                l_ac_errno = EINVAL;
        !           245:                        break;
        !           246:                }
        !           247:                case ADMIN_PROTO_INTERNAL:
        !           248:                default:
        !           249:                        l_ac_errno = ENOTSUP;
        !           250:                        break;
        !           251:                }
        !           252:                break;
        !           253: 
        !           254:        case ADMIN_GET_SA_CERT: {
        !           255:                struct admin_com_indexes *ndx;
        !           256:                struct sockaddr *src, *dst;
        !           257:                struct ph1handle *iph1;
        !           258: 
        !           259:                ndx = (struct admin_com_indexes *) ((caddr_t)com + sizeof(*com));
        !           260:                src = (struct sockaddr *) &ndx->src;
        !           261:                dst = (struct sockaddr *) &ndx->dst;
        !           262: 
        !           263:                if (com->ac_proto != ADMIN_PROTO_ISAKMP) {
        !           264:                        l_ac_errno = ENOTSUP;
        !           265:                        break;
        !           266:                }
        !           267: 
        !           268:                iph1 = getph1byaddr(src, dst, 0);
        !           269:                if (iph1 == NULL) {
        !           270:                        l_ac_errno = ENOENT;
        !           271:                        break;
        !           272:                }
        !           273: 
        !           274:                if (iph1->cert_p != NULL) {
        !           275:                        vchar_t tmp;
        !           276:                        tmp.v = iph1->cert_p->v + 1;
        !           277:                        tmp.l = iph1->cert_p->l - 1;
        !           278:                        buf = vdup(&tmp);
        !           279:                }
        !           280:                break;
        !           281:        }
        !           282: 
        !           283:        case ADMIN_FLUSH_SA:
        !           284:                switch (com->ac_proto) {
        !           285:                case ADMIN_PROTO_ISAKMP:
        !           286:                        flushph1();
        !           287:                        break;
        !           288:                case ADMIN_PROTO_IPSEC:
        !           289:                case ADMIN_PROTO_AH:
        !           290:                case ADMIN_PROTO_ESP:
        !           291:                        pfkey_flush_sadb(com->ac_proto);
        !           292:                        break;
        !           293:                case ADMIN_PROTO_INTERNAL:
        !           294:                        /*XXX flushph2();*/
        !           295:                default:
        !           296:                        l_ac_errno = ENOTSUP;
        !           297:                        break;
        !           298:                }
        !           299:                break;
        !           300: 
        !           301:        case ADMIN_DELETE_SA: {
        !           302:                char *loc, *rem;
        !           303:                struct ph1selector sel;
        !           304: 
        !           305:                memset(&sel, 0, sizeof(sel));
        !           306:                sel.local = (struct sockaddr *)
        !           307:                        &((struct admin_com_indexes *)
        !           308:                            ((caddr_t)com + sizeof(*com)))->src;
        !           309:                sel.remote = (struct sockaddr *)
        !           310:                        &((struct admin_com_indexes *)
        !           311:                            ((caddr_t)com + sizeof(*com)))->dst;
        !           312: 
        !           313:                loc = racoon_strdup(saddr2str(sel.local));
        !           314:                rem = racoon_strdup(saddr2str(sel.remote));
        !           315:                STRDUP_FATAL(loc);
        !           316:                STRDUP_FATAL(rem);
        !           317: 
        !           318:                plog(LLV_INFO, LOCATION, NULL,
        !           319:                     "admin delete-sa %s %s\n", loc, rem);
        !           320:                enumph1(&sel, admin_ph1_delete_sa, NULL);
        !           321:                remcontacted(sel.remote);
        !           322: 
        !           323:                racoon_free(loc);
        !           324:                racoon_free(rem);
        !           325:                break;
        !           326:        }
        !           327: 
        !           328: #ifdef ENABLE_HYBRID
        !           329:        case ADMIN_LOGOUT_USER: {
        !           330:                struct ph1handle *iph1;
        !           331:                char user[LOGINLEN+1];
        !           332:                int found = 0, len = com->ac_len - sizeof(*com);
        !           333: 
        !           334:                if (len > LOGINLEN) {
        !           335:                        plog(LLV_ERROR, LOCATION, NULL,
        !           336:                            "malformed message (login too long)\n");
        !           337:                        break;
        !           338:                }
        !           339: 
        !           340:                memcpy(user, (char *)(com + 1), len);
        !           341:                user[len] = 0;
        !           342: 
        !           343:                found = purgeph1bylogin(user);
        !           344:                plog(LLV_INFO, LOCATION, NULL,
        !           345:                    "deleted %d SA for user \"%s\"\n", found, user);
        !           346: 
        !           347:                break;
        !           348:        }
        !           349: #endif
        !           350: 
        !           351:        case ADMIN_DELETE_ALL_SA_DST: {
        !           352:                struct ph1handle *iph1;
        !           353:                struct sockaddr *dst;
        !           354:                char *loc, *rem;
        !           355: 
        !           356:                dst = (struct sockaddr *)
        !           357:                        &((struct admin_com_indexes *)
        !           358:                            ((caddr_t)com + sizeof(*com)))->dst;
        !           359: 
        !           360:                rem = racoon_strdup(saddrwop2str(dst));
        !           361:                STRDUP_FATAL(rem);
        !           362: 
        !           363:                plog(LLV_INFO, LOCATION, NULL,
        !           364:                    "Flushing all SAs for peer %s\n", rem);
        !           365: 
        !           366:                while ((iph1 = getph1bydstaddr(dst)) != NULL) {
        !           367:                        loc = racoon_strdup(saddrwop2str(iph1->local));
        !           368:                        STRDUP_FATAL(loc);
        !           369: 
        !           370:                        if (iph1->status >= PHASE1ST_ESTABLISHED)
        !           371:                                isakmp_info_send_d1(iph1);
        !           372:                        purge_remote(iph1);
        !           373: 
        !           374:                        racoon_free(loc);
        !           375:                }
        !           376: 
        !           377:                racoon_free(rem);
        !           378:                break;
        !           379:        }
        !           380: 
        !           381:        case ADMIN_ESTABLISH_SA_PSK: {
        !           382:                struct admin_com_psk *acp;
        !           383:                char *data;
        !           384: 
        !           385:                acp = (struct admin_com_psk *)
        !           386:                    ((char *)com + sizeof(*com) +
        !           387:                    sizeof(struct admin_com_indexes));
        !           388: 
        !           389:                idtype = acp->id_type;
        !           390: 
        !           391:                if ((id = vmalloc(acp->id_len)) == NULL) {
        !           392:                        plog(LLV_ERROR, LOCATION, NULL,
        !           393:                            "cannot allocate memory: %s\n",
        !           394:                            strerror(errno));
        !           395:                        break;
        !           396:                }
        !           397:                data = (char *)(acp + 1);
        !           398:                memcpy(id->v, data, id->l);
        !           399: 
        !           400:                if ((key = vmalloc(acp->key_len)) == NULL) {
        !           401:                        plog(LLV_ERROR, LOCATION, NULL,
        !           402:                            "cannot allocate memory: %s\n",
        !           403:                            strerror(errno));
        !           404:                        vfree(id);
        !           405:                        id = NULL;
        !           406:                        break;
        !           407:                }
        !           408:                data = (char *)(data + acp->id_len);
        !           409:                memcpy(key->v, data, key->l);
        !           410:        }
        !           411:        /* FALLTHROUGH */
        !           412:        case ADMIN_ESTABLISH_SA: {
        !           413:                struct admin_com_indexes *ndx;
        !           414:                struct sockaddr *dst;
        !           415:                struct sockaddr *src;
        !           416:                char *name = NULL;
        !           417: 
        !           418:                ndx = (struct admin_com_indexes *) ((caddr_t)com + sizeof(*com));
        !           419:                src = (struct sockaddr *) &ndx->src;
        !           420:                dst = (struct sockaddr *) &ndx->dst;
        !           421: 
        !           422:                if (com->ac_cmd == ADMIN_ESTABLISH_SA &&
        !           423:                    com->ac_len > sizeof(*com) + sizeof(*ndx))
        !           424:                        name = (char *) ((caddr_t) ndx + sizeof(*ndx));
        !           425: 
        !           426:                switch (com->ac_proto) {
        !           427:                case ADMIN_PROTO_ISAKMP: {
        !           428:                        struct ph1handle *ph1;
        !           429:                        struct remoteconf *rmconf;
        !           430:                        u_int16_t port;
        !           431: 
        !           432:                        l_ac_errno = -1;
        !           433: 
        !           434:                        /* connected already? */
        !           435:                        ph1 = getph1byaddr(src, dst, 0);
        !           436:                        if (ph1 != NULL) {
        !           437:                                event_list = &ph1->evt_listeners;
        !           438:                                if (ph1->status == PHASE1ST_ESTABLISHED)
        !           439:                                        l_ac_errno = EEXIST;
        !           440:                                else
        !           441:                                        l_ac_errno = 0;
        !           442:                                break;
        !           443:                        }
        !           444: 
        !           445:                        /* search appropreate configuration */
        !           446:                        if (name == NULL)
        !           447:                                rmconf = getrmconf(dst, 0);
        !           448:                        else
        !           449:                                rmconf = getrmconf_by_name(name);
        !           450:                        if (rmconf == NULL) {
        !           451:                                plog(LLV_ERROR, LOCATION, NULL,
        !           452:                                        "no configuration found "
        !           453:                                        "for %s\n", saddrwop2str(dst));
        !           454:                                break;
        !           455:                        }
        !           456: 
        !           457: #ifdef ENABLE_HYBRID
        !           458:                        /* XXX This overwrites rmconf information globally. */
        !           459:                        /* Set the id and key */
        !           460:                        if (id && key) {
        !           461:                                if (xauth_rmconf_used(&rmconf->xauth) == -1)
        !           462:                                        break;
        !           463: 
        !           464:                                if (rmconf->xauth->login != NULL) {
        !           465:                                        vfree(rmconf->xauth->login);
        !           466:                                        rmconf->xauth->login = NULL;
        !           467:                                }
        !           468:                                if (rmconf->xauth->pass != NULL) {
        !           469:                                        vfree(rmconf->xauth->pass);
        !           470:                                        rmconf->xauth->pass = NULL;
        !           471:                                }
        !           472: 
        !           473:                                rmconf->xauth->login = id;
        !           474:                                rmconf->xauth->pass = key;
        !           475:                        }
        !           476: #endif
        !           477: 
        !           478:                        plog(LLV_INFO, LOCATION, NULL,
        !           479:                                "accept a request to establish IKE-SA: "
        !           480:                                "%s\n", saddrwop2str(dst));
        !           481: 
        !           482:                        /* begin ident mode */
        !           483:                        ph1 = isakmp_ph1begin_i(rmconf, dst, src);
        !           484:                        if (ph1 == NULL)
        !           485:                                break;
        !           486: 
        !           487:                        event_list = &ph1->evt_listeners;
        !           488:                        l_ac_errno = 0;
        !           489:                        break;
        !           490:                }
        !           491:                case ADMIN_PROTO_AH:
        !           492:                case ADMIN_PROTO_ESP: {
        !           493:                        struct ph2handle *iph2;
        !           494:                        struct secpolicy *sp_out = NULL, *sp_in = NULL;
        !           495:                        struct policyindex spidx;
        !           496: 
        !           497:                        l_ac_errno = -1;
        !           498: 
        !           499:                        /* got outbound policy */
        !           500:                        memset(&spidx, 0, sizeof(spidx));
        !           501:                        spidx.dir = IPSEC_DIR_OUTBOUND;
        !           502:                        memcpy(&spidx.src, src, sizeof(spidx.src));
        !           503:                        memcpy(&spidx.dst, dst, sizeof(spidx.dst));
        !           504:                        spidx.prefs = ndx->prefs;
        !           505:                        spidx.prefd = ndx->prefd;
        !           506:                        spidx.ul_proto = ndx->ul_proto;
        !           507: 
        !           508:                        sp_out = getsp_r(&spidx);
        !           509:                        if (sp_out) {
        !           510:                                plog(LLV_DEBUG, LOCATION, NULL,
        !           511:                                        "suitable outbound SP found: %s.\n",
        !           512:                                        spidx2str(&sp_out->spidx));
        !           513:                        } else {
        !           514:                                l_ac_errno = ENOENT;
        !           515:                                plog(LLV_NOTIFY, LOCATION, NULL,
        !           516:                                        "no outbound policy found: %s\n",
        !           517:                                        spidx2str(&spidx));
        !           518:                                break;
        !           519:                        }
        !           520: 
        !           521:                        iph2 = getph2byid(src, dst, sp_out->id);
        !           522:                        if (iph2 != NULL) {
        !           523:                                event_list = &iph2->evt_listeners;
        !           524:                                if (iph2->status == PHASE2ST_ESTABLISHED)
        !           525:                                        l_ac_errno = EEXIST;
        !           526:                                else
        !           527:                                        l_ac_errno = 0;
        !           528:                                break;
        !           529:                        }
        !           530: 
        !           531:                        /* get inbound policy */
        !           532:                        memset(&spidx, 0, sizeof(spidx));
        !           533:                        spidx.dir = IPSEC_DIR_INBOUND;
        !           534:                        memcpy(&spidx.src, dst, sizeof(spidx.src));
        !           535:                        memcpy(&spidx.dst, src, sizeof(spidx.dst));
        !           536:                        spidx.prefs = ndx->prefd;
        !           537:                        spidx.prefd = ndx->prefs;
        !           538:                        spidx.ul_proto = ndx->ul_proto;
        !           539: 
        !           540:                        sp_in = getsp_r(&spidx);
        !           541:                        if (sp_in) {
        !           542:                                plog(LLV_DEBUG, LOCATION, NULL,
        !           543:                                        "suitable inbound SP found: %s.\n",
        !           544:                                        spidx2str(&sp_in->spidx));
        !           545:                        } else {
        !           546:                                l_ac_errno = ENOENT;
        !           547:                                plog(LLV_NOTIFY, LOCATION, NULL,
        !           548:                                        "no inbound policy found: %s\n",
        !           549:                                spidx2str(&spidx));
        !           550:                                break;
        !           551:                        }
        !           552: 
        !           553:                        /* allocate a phase 2 */
        !           554:                        iph2 = newph2();
        !           555:                        if (iph2 == NULL) {
        !           556:                                plog(LLV_ERROR, LOCATION, NULL,
        !           557:                                        "failed to allocate phase2 entry.\n");
        !           558:                                break;
        !           559:                        }
        !           560:                        iph2->side = INITIATOR;
        !           561:                        iph2->satype = admin2pfkey_proto(com->ac_proto);
        !           562:                        iph2->spid = sp_out->id;
        !           563:                        iph2->seq = pk_getseq();
        !           564:                        iph2->status = PHASE2ST_STATUS2;
        !           565: 
        !           566:                        /* set end addresses of SA */
        !           567:                        iph2->sa_dst = dupsaddr(dst);
        !           568:                        iph2->sa_src = dupsaddr(src);
        !           569:                        iph2->dst = dupsaddr(dst);
        !           570:                        iph2->src = dupsaddr(src);
        !           571:                        if (iph2->sa_src == NULL || iph2->sa_dst == NULL ||
        !           572:                            iph2->dst == NULL || iph2->src == NULL) {
        !           573:                                delph2(iph2);
        !           574:                                break;
        !           575:                        }
        !           576:                        set_port(iph2->dst, 0);
        !           577:                        set_port(iph2->src, 0);
        !           578: 
        !           579:                        if (isakmp_get_sainfo(iph2, sp_out, sp_in) < 0) {
        !           580:                                delph2(iph2);
        !           581:                                break;
        !           582:                        }
        !           583: 
        !           584:                        insph2(iph2);
        !           585:                        if (isakmp_post_acquire(iph2, NULL, FALSE) < 0) {
        !           586:                                remph2(iph2);
        !           587:                                delph2(iph2);
        !           588:                                break;
        !           589:                        }
        !           590: 
        !           591:                        event_list = &iph2->evt_listeners;
        !           592:                        l_ac_errno = 0;
        !           593:                        break;
        !           594:                }
        !           595:                default:
        !           596:                        /* ignore */
        !           597:                        l_ac_errno = ENOTSUP;
        !           598:                }
        !           599:                break;
        !           600:        }
        !           601: 
        !           602:        default:
        !           603:                plog(LLV_ERROR, LOCATION, NULL,
        !           604:                        "invalid command: %d\n", com->ac_cmd);
        !           605:                l_ac_errno = ENOTSUP;
        !           606:        }
        !           607: 
        !           608:        if ((error = admin_reply(so2, com, l_ac_errno, buf)) != 0)
        !           609:                goto out;
        !           610: 
        !           611:        /* start pushing events if so requested */
        !           612:        if ((l_ac_errno == 0) &&
        !           613:            (com->ac_version >= 1) &&
        !           614:            (com->ac_cmd == ADMIN_SHOW_EVT || event_list != NULL))
        !           615:                error = evt_subscribe(event_list, so2);
        !           616: out:
        !           617:        if (buf != NULL)
        !           618:                vfree(buf);
        !           619: 
        !           620:        return error;
        !           621: }
        !           622: 
        !           623: static int
        !           624: admin_reply(so, req, l_ac_errno, buf)
        !           625:        int so, l_ac_errno;
        !           626:        struct admin_com *req;
        !           627:        vchar_t *buf;
        !           628: {
        !           629:        int tlen;
        !           630:        struct admin_com *combuf;
        !           631:        char *retbuf = NULL;
        !           632: 
        !           633:        if (buf != NULL)
        !           634:                tlen = sizeof(*combuf) + buf->l;
        !           635:        else
        !           636:                tlen = sizeof(*combuf);
        !           637: 
        !           638:        retbuf = racoon_calloc(1, tlen);
        !           639:        if (retbuf == NULL) {
        !           640:                plog(LLV_ERROR, LOCATION, NULL,
        !           641:                        "failed to allocate admin buffer\n");
        !           642:                return -1;
        !           643:        }
        !           644: 
        !           645:        combuf = (struct admin_com *) retbuf;
        !           646:        combuf->ac_len = (u_int16_t) tlen;
        !           647:        combuf->ac_cmd = req->ac_cmd & ~ADMIN_FLAG_VERSION;
        !           648:        if (tlen != (u_int32_t) combuf->ac_len &&
        !           649:            l_ac_errno == 0) {
        !           650:                combuf->ac_len_high = tlen >> 16;
        !           651:                combuf->ac_cmd |= ADMIN_FLAG_LONG_REPLY;
        !           652:        } else {
        !           653:                combuf->ac_errno = l_ac_errno;
        !           654:        }
        !           655:        combuf->ac_proto = req->ac_proto;
        !           656: 
        !           657:        if (buf != NULL)
        !           658:                memcpy(retbuf + sizeof(*combuf), buf->v, buf->l);
        !           659: 
        !           660:        tlen = send(so, retbuf, tlen, 0);
        !           661:        racoon_free(retbuf);
        !           662:        if (tlen < 0) {
        !           663:                plog(LLV_ERROR, LOCATION, NULL,
        !           664:                        "failed to send admin command: %s\n",
        !           665:                        strerror(errno));
        !           666:                return -1;
        !           667:        }
        !           668: 
        !           669:        return 0;
        !           670: }
        !           671: 
        !           672: /* ADMIN_PROTO -> SADB_SATYPE */
        !           673: int
        !           674: admin2pfkey_proto(proto)
        !           675:        u_int proto;
        !           676: {
        !           677:        switch (proto) {
        !           678:        case ADMIN_PROTO_IPSEC:
        !           679:                return SADB_SATYPE_UNSPEC;
        !           680:        case ADMIN_PROTO_AH:
        !           681:                return SADB_SATYPE_AH;
        !           682:        case ADMIN_PROTO_ESP:
        !           683:                return SADB_SATYPE_ESP;
        !           684:        default:
        !           685:                plog(LLV_ERROR, LOCATION, NULL,
        !           686:                        "unsupported proto for admin: %d\n", proto);
        !           687:                return -1;
        !           688:        }
        !           689:        /*NOTREACHED*/
        !           690: }
        !           691: 
        !           692: int
        !           693: admin_init()
        !           694: {
        !           695:        if (adminsock_path == NULL) {
        !           696:                lcconf->sock_admin = -1;
        !           697:                return 0;
        !           698:        }
        !           699: 
        !           700:        memset(&sunaddr, 0, sizeof(sunaddr));
        !           701:        sunaddr.sun_family = AF_UNIX;
        !           702:        snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path),
        !           703:                "%s", adminsock_path);
        !           704: 
        !           705:        lcconf->sock_admin = socket(AF_UNIX, SOCK_STREAM, 0);
        !           706:        if (lcconf->sock_admin == -1) {
        !           707:                plog(LLV_ERROR, LOCATION, NULL,
        !           708:                        "socket: %s\n", strerror(errno));
        !           709:                return -1;
        !           710:        }
        !           711:        close_on_exec(lcconf->sock_admin);
        !           712: 
        !           713:        unlink(sunaddr.sun_path);
        !           714:        if (bind(lcconf->sock_admin, (struct sockaddr *)&sunaddr,
        !           715:                        sizeof(sunaddr)) != 0) {
        !           716:                plog(LLV_ERROR, LOCATION, NULL,
        !           717:                        "bind(sockname:%s): %s\n",
        !           718:                        sunaddr.sun_path, strerror(errno));
        !           719:                (void)close(lcconf->sock_admin);
        !           720:                return -1;
        !           721:        }
        !           722: 
        !           723:        if (chown(sunaddr.sun_path, adminsock_owner, adminsock_group) != 0) {
        !           724:                plog(LLV_ERROR, LOCATION, NULL,
        !           725:                    "chown(%s, %d, %d): %s\n",
        !           726:                    sunaddr.sun_path, adminsock_owner,
        !           727:                    adminsock_group, strerror(errno));
        !           728:                (void)close(lcconf->sock_admin);
        !           729:                return -1;
        !           730:        }
        !           731: 
        !           732:        if (chmod(sunaddr.sun_path, adminsock_mode) != 0) {
        !           733:                plog(LLV_ERROR, LOCATION, NULL,
        !           734:                    "chmod(%s, 0%03o): %s\n",
        !           735:                    sunaddr.sun_path, adminsock_mode, strerror(errno));
        !           736:                (void)close(lcconf->sock_admin);
        !           737:                return -1;
        !           738:        }
        !           739: 
        !           740:        if (listen(lcconf->sock_admin, 5) != 0) {
        !           741:                plog(LLV_ERROR, LOCATION, NULL,
        !           742:                        "listen(sockname:%s): %s\n",
        !           743:                        sunaddr.sun_path, strerror(errno));
        !           744:                (void)close(lcconf->sock_admin);
        !           745:                return -1;
        !           746:        }
        !           747: 
        !           748:        monitor_fd(lcconf->sock_admin, admin_handler, NULL, 0);
        !           749:        plog(LLV_DEBUG, LOCATION, NULL,
        !           750:             "open %s as racoon management.\n", sunaddr.sun_path);
        !           751: 
        !           752:        return 0;
        !           753: }
        !           754: 
        !           755: int
        !           756: admin_close()
        !           757: {
        !           758:        unmonitor_fd(lcconf->sock_admin);
        !           759:        close(lcconf->sock_admin);
        !           760:        return 0;
        !           761: }
        !           762: 
        !           763: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>