Annotation of embedaddon/ipsec-tools/src/racoon/admin.c, revision 1.1.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>