Annotation of embedaddon/ipsec-tools/src/racoon/privsep.c, revision 1.1.1.1

1.1       misho       1: /*     $NetBSD: privsep.c,v 1.21 2011/03/06 08:28:10 tteras Exp $      */
                      2: 
                      3: /* Id: privsep.c,v 1.15 2005/08/08 11:23:44 vanhu Exp */
                      4: 
                      5: /*
                      6:  * Copyright (C) 2004 Emmanuel Dreyfus
                      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 <unistd.h>
                     37: #include <string.h>
                     38: #ifdef __NetBSD__
                     39: #include <stdlib.h>    /* for setproctitle */
                     40: #endif
                     41: #include <errno.h>
                     42: #include <signal.h>
                     43: #include <pwd.h>
                     44: 
                     45: #include <sys/types.h>
                     46: #include <sys/socket.h>
                     47: #include <sys/param.h>
                     48: 
                     49: #include <netinet/in.h>
                     50: 
                     51: #include "gcmalloc.h"
                     52: #include "vmbuf.h"
                     53: #include "misc.h"
                     54: #include "plog.h"
                     55: #include "var.h"
                     56: 
                     57: #include "crypto_openssl.h"
                     58: #include "isakmp_var.h"
                     59: #include "isakmp.h"
                     60: #ifdef ENABLE_HYBRID
                     61: #include "resolv.h"
                     62: #include "isakmp_xauth.h"
                     63: #include "isakmp_cfg.h"
                     64: #endif
                     65: #include "localconf.h"
                     66: #include "remoteconf.h"
                     67: #include "admin.h"
                     68: #include "sockmisc.h"
                     69: #include "privsep.h"
                     70: 
                     71: static int privsep_sock[2] = { -1, -1 };
                     72: 
                     73: static int privsep_recv(int, struct privsep_com_msg **, size_t *);
                     74: static int privsep_send(int, struct privsep_com_msg *, size_t);
                     75: static int safety_check(struct privsep_com_msg *, int i);
                     76: static int port_check(int);
                     77: static int unsafe_env(char *const *);
                     78: static int unknown_name(int);
                     79: static int unsafe_path(char *, int);
                     80: static int rec_fd(int);
                     81: static int send_fd(int, int);
                     82: 
                     83: struct socket_args {
                     84:        int domain;
                     85:        int type;
                     86:        int protocol;
                     87: };
                     88: 
                     89: struct sockopt_args {
                     90:        int s;
                     91:        int level;
                     92:        int optname;
                     93:        const void *optval;
                     94:        socklen_t optlen;
                     95: };
                     96: 
                     97: struct bind_args {
                     98:        int s;
                     99:        const struct sockaddr *addr;
                    100:        socklen_t addrlen;
                    101: };
                    102: 
                    103: static int
                    104: privsep_send(sock, buf, len)
                    105:        int sock;
                    106:        struct privsep_com_msg *buf;
                    107:        size_t len;
                    108: {
                    109:        if (buf == NULL)
                    110:                return 0;
                    111: 
                    112:        if (sendto(sock, (char *)buf, len, 0, NULL, 0) == -1) {
                    113:                plog(LLV_ERROR, LOCATION, NULL,
                    114:                    "privsep_send failed: %s\n", 
                    115:                    strerror(errno));
                    116:                return -1;
                    117:        }
                    118: 
                    119:        racoon_free((char *)buf);
                    120: 
                    121:        return 0;
                    122: }
                    123: 
                    124: 
                    125: static int
                    126: privsep_recv(sock, bufp, lenp)
                    127:        int sock;
                    128:        struct privsep_com_msg **bufp;
                    129:        size_t *lenp;
                    130: {
                    131:        struct admin_com com;
                    132:        struct admin_com *combuf;
                    133:        size_t len;
                    134: 
                    135:        *bufp = NULL;
                    136:        *lenp = 0;
                    137: 
                    138:        /* Get the header */
                    139:        while ((len = recvfrom(sock, (char *)&com, 
                    140:            sizeof(com), MSG_PEEK, NULL, NULL)) == -1) {
                    141:                if (errno == EINTR)
                    142:                        continue;
                    143:                if (errno == ECONNRESET)
                    144:                    return -1;
                    145: 
                    146:                plog(LLV_ERROR, LOCATION, NULL,
                    147:                    "privsep_recv failed: %s\n",
                    148:                    strerror(errno));
                    149:                return -1;
                    150:        }
                    151: 
                    152:        /* EOF, other side has closed. */
                    153:        if (len == 0)
                    154:            return -1;
                    155: 
                    156:        /* Check for short packets */
                    157:        if (len < sizeof(com)) {
                    158:                plog(LLV_ERROR, LOCATION, NULL,
                    159:                    "corrupted privsep message (short header)\n");
                    160:                return -1;
                    161:        }
                    162: 
                    163:        /* Allocate buffer for the whole message */
                    164:        if ((combuf = (struct admin_com *)racoon_malloc(com.ac_len)) == NULL) {
                    165:                plog(LLV_ERROR, LOCATION, NULL,
                    166:                    "failed to allocate memory: %s\n", strerror(errno));
                    167:                return -1;
                    168:        }
                    169: 
                    170:        /* Get the whole buffer */
                    171:        while ((len = recvfrom(sock, (char *)combuf, 
                    172:            com.ac_len, 0, NULL, NULL)) == -1) {
                    173:                if (errno == EINTR)
                    174:                        continue;
                    175:                if (errno == ECONNRESET)
                    176:                    return -1;
                    177:                plog(LLV_ERROR, LOCATION, NULL,
                    178:                    "failed to recv privsep command: %s\n", 
                    179:                    strerror(errno));
                    180:                return -1;
                    181:        }
                    182: 
                    183:        /* We expect len to match */
                    184:        if (len != com.ac_len) {
                    185:                plog(LLV_ERROR, LOCATION, NULL,
                    186:                    "corrupted privsep message (short packet)\n");
                    187:                return -1;
                    188:        }
                    189: 
                    190:        *bufp = (struct privsep_com_msg *)combuf;
                    191:        *lenp = len;
                    192: 
                    193:        return 0;
                    194: }
                    195: 
                    196: int
                    197: privsep_init(void)
                    198: {
                    199:        int i;
                    200:        pid_t child_pid;
                    201: 
                    202:        /* If running as root, we don't use the privsep code path */
                    203:        if (lcconf->uid == 0)
                    204:                return 0;
                    205: 
                    206:        /* 
                    207:         * When running privsep, certificate and script paths 
                    208:         * are mandatory, as they enable us to check path safety
                    209:         * in the privileged instance
                    210:         */
                    211:        if ((lcconf->pathinfo[LC_PATHTYPE_CERT] == NULL) ||
                    212:            (lcconf->pathinfo[LC_PATHTYPE_SCRIPT] == NULL)) {
                    213:                plog(LLV_ERROR, LOCATION, NULL, "privilege separation "
                    214:                   "require path cert and path script in the config file\n");
                    215:                return -1;
                    216:        }
                    217: 
                    218:        if (socketpair(PF_LOCAL, SOCK_STREAM, 0, privsep_sock) != 0) {
                    219:                plog(LLV_ERROR, LOCATION, NULL, 
                    220:                    "Cannot allocate privsep_sock: %s\n", strerror(errno));
                    221:                return -1;
                    222:        }
                    223: 
                    224:        switch (child_pid = fork()) {
                    225:        case -1:
                    226:                plog(LLV_ERROR, LOCATION, NULL, "Cannot fork privsep: %s\n", 
                    227:                    strerror(errno));
                    228:                return -1;
                    229:                break;
                    230: 
                    231:        case 0: /* Child: drop privileges */
                    232:                (void)close(privsep_sock[0]);
                    233: 
                    234:                if (lcconf->chroot != NULL) {
                    235:                        if (chdir(lcconf->chroot) != 0) {
                    236:                                plog(LLV_ERROR, LOCATION, NULL, 
                    237:                                    "Cannot chdir(%s): %s\n", lcconf->chroot, 
                    238:                                    strerror(errno));
                    239:                                return -1;
                    240:                        }
                    241:                        if (chroot(lcconf->chroot) != 0) {
                    242:                                plog(LLV_ERROR, LOCATION, NULL, 
                    243:                                    "Cannot chroot(%s): %s\n", lcconf->chroot, 
                    244:                                    strerror(errno));
                    245:                                return -1;
                    246:                        }
                    247:                }
                    248: 
                    249:                if (setgid(lcconf->gid) != 0) {
                    250:                        plog(LLV_ERROR, LOCATION, NULL, 
                    251:                            "Cannot setgid(%d): %s\n", lcconf->gid,
                    252:                            strerror(errno));
                    253:                        return -1;
                    254:                }
                    255: 
                    256:                if (setegid(lcconf->gid) != 0) {
                    257:                        plog(LLV_ERROR, LOCATION, NULL, 
                    258:                            "Cannot setegid(%d): %s\n", lcconf->gid,
                    259:                            strerror(errno));
                    260:                        return -1;
                    261:                }
                    262: 
                    263:                if (setuid(lcconf->uid) != 0) {
                    264:                        plog(LLV_ERROR, LOCATION, NULL, 
                    265:                            "Cannot setuid(%d): %s\n", lcconf->uid,
                    266:                            strerror(errno));
                    267:                        return -1;
                    268:                }
                    269: 
                    270:                if (seteuid(lcconf->uid) != 0) {
                    271:                        plog(LLV_ERROR, LOCATION, NULL, 
                    272:                            "Cannot seteuid(%d): %s\n", lcconf->uid,
                    273:                            strerror(errno));
                    274:                        return -1;
                    275:                }
                    276: 
                    277:                return 0;
                    278:                break;
                    279: 
                    280:        default: /* Parent: privileged process */
                    281:                break;
                    282:        }
                    283: 
                    284:        /* 
                    285:         * Close everything except the socketpair, 
                    286:         * and stdout if running in the forground.
                    287:         */
                    288:        for (i = sysconf(_SC_OPEN_MAX); i > 0; i--) {
                    289:                if (i == privsep_sock[0])
                    290:                        continue;
                    291:                if ((f_foreground) && (i == 1))
                    292:                        continue;
                    293:                (void)close(i);
                    294:        }
                    295: 
                    296:        /* Above trickery closed the log file, reopen it */
                    297:        ploginit();
                    298: 
                    299:        plog(LLV_INFO, LOCATION, NULL, 
                    300:            "racoon privileged process running with PID %d\n", getpid());
                    301: 
                    302:        plog(LLV_INFO, LOCATION, NULL,
                    303:            "racoon unprivileged process running with PID %d\n", child_pid);
                    304: 
                    305: #if defined(__NetBSD__) || defined(__FreeBSD__)
                    306:        setproctitle("[priv]");
                    307: #endif
                    308:        
                    309:        /*
                    310:         * Don't catch any signal
                    311:         * This duplicate session:signals[], which is static...
                    312:         */
                    313:        signal(SIGPIPE, SIG_IGN);
                    314:        signal(SIGHUP, SIG_DFL);
                    315:        signal(SIGINT, SIG_DFL);
                    316:        signal(SIGTERM, SIG_DFL);
                    317:        signal(SIGUSR1, SIG_DFL);
                    318:        signal(SIGUSR2, SIG_DFL);
                    319:        signal(SIGCHLD, SIG_DFL);
                    320: 
                    321:        while (1) {
                    322:                size_t len;
                    323:                struct privsep_com_msg *combuf;
                    324:                struct privsep_com_msg *reply;
                    325:                char *data;
                    326:                size_t *buflen;
                    327:                size_t totallen;
                    328:                char *bufs[PRIVSEP_NBUF_MAX];
                    329:                int i;
                    330: 
                    331:                if (privsep_recv(privsep_sock[0], &combuf, &len) != 0)
                    332:                        goto out;
                    333: 
                    334:                /* Safety checks and gather the data */
                    335:                if (len < sizeof(*combuf)) {
                    336:                        plog(LLV_ERROR, LOCATION, NULL,
                    337:                            "corrupted privsep message (short buflen)\n");
                    338:                        goto out;
                    339:                }
                    340: 
                    341:                data = (char *)(combuf + 1);
                    342:                totallen = sizeof(*combuf);
                    343:                for (i = 0; i < PRIVSEP_NBUF_MAX; i++) {
                    344:                        bufs[i] = (char *)data;
                    345:                        data += combuf->bufs.buflen[i];
                    346:                        totallen += combuf->bufs.buflen[i];
                    347:                }
                    348: 
                    349:                if (totallen > len) {
                    350:                        plog(LLV_ERROR, LOCATION, NULL,
                    351:                            "corrupted privsep message (bufs too big)\n");
                    352:                        goto out;
                    353:                }
                    354:        
                    355:                /* Prepare the reply buffer */
                    356:                if ((reply = racoon_malloc(sizeof(*reply))) == NULL) {
                    357:                        plog(LLV_ERROR, LOCATION, NULL,
                    358:                            "Cannot allocate reply buffer: %s\n", 
                    359:                            strerror(errno));
                    360:                        goto out;
                    361:                }
                    362:                bzero(reply, sizeof(*reply));
                    363:                reply->hdr.ac_cmd = combuf->hdr.ac_cmd;
                    364:                reply->hdr.ac_len = sizeof(*reply);
                    365: 
                    366:                switch(combuf->hdr.ac_cmd) {
                    367:                /* 
                    368:                 * XXX Improvement: instead of returning the key, 
                    369:                 * stuff eay_get_pkcs1privkey and eay_get_x509sign
                    370:                 * together and sign the hash in the privileged 
                    371:                 * instance? 
                    372:                 * pro: the key remains inaccessible to unpriv
                    373:                 * con: a compromised unpriv racoon can still sign anything
                    374:                 */
                    375:                case PRIVSEP_EAY_GET_PKCS1PRIVKEY: {
                    376:                        vchar_t *privkey;
                    377: 
                    378:                        /* Make sure the string is NULL terminated */
                    379:                        if (safety_check(combuf, 0) != 0)
                    380:                                break;
                    381:                        bufs[0][combuf->bufs.buflen[0] - 1] = '\0';
                    382: 
                    383:                        if (unsafe_path(bufs[0], LC_PATHTYPE_CERT) != 0) {
                    384:                                plog(LLV_ERROR, LOCATION, NULL, 
                    385:                                    "privsep_eay_get_pkcs1privkey: "
                    386:                                    "unsafe cert \"%s\"\n", bufs[0]);
                    387:                        }
                    388: 
                    389:                        plog(LLV_DEBUG, LOCATION, NULL, 
                    390:                            "eay_get_pkcs1privkey(\"%s\")\n", bufs[0]);
                    391: 
                    392:                        if ((privkey = eay_get_pkcs1privkey(bufs[0])) == NULL){
                    393:                                reply->hdr.ac_errno = errno;
                    394:                                break;
                    395:                        }
                    396: 
                    397:                        reply->bufs.buflen[0] = privkey->l;
                    398:                        reply->hdr.ac_len = sizeof(*reply) + privkey->l;
                    399:                        reply = racoon_realloc(reply, reply->hdr.ac_len);
                    400:                        if (reply == NULL) {
                    401:                                plog(LLV_ERROR, LOCATION, NULL,
                    402:                                    "Cannot allocate reply buffer: %s\n", 
                    403:                                    strerror(errno));
                    404:                                goto out;
                    405:                        }
                    406: 
                    407:                        memcpy(reply + 1, privkey->v, privkey->l);
                    408:                        vfree(privkey);
                    409:                        break;
                    410:                }
                    411:                
                    412:                case PRIVSEP_SCRIPT_EXEC: {
                    413:                        char *script;
                    414:                        int name;
                    415:                        char **envp = NULL;
                    416:                        int envc = 0;
                    417:                        int count = 0;
                    418:                        int i;
                    419: 
                    420:                        /*
                    421:                         * First count the bufs, and make sure strings
                    422:                         * are NULL terminated. 
                    423:                         *
                    424:                         * We expect: script, name, envp[], void
                    425:                         */ 
                    426:                        if (safety_check(combuf, 0) != 0)
                    427:                                break;
                    428:                        bufs[0][combuf->bufs.buflen[0] - 1] = '\0';
                    429:                        count++;        /* script */
                    430: 
                    431:                        count++;        /* name */
                    432: 
                    433:                        for (; count < PRIVSEP_NBUF_MAX; count++) {
                    434:                                if (combuf->bufs.buflen[count] == 0)
                    435:                                        break;
                    436:                                bufs[count]
                    437:                                    [combuf->bufs.buflen[count] - 1] = '\0';
                    438:                                envc++;
                    439:                        }
                    440: 
                    441:                        /* count a void buf and perform safety check */
                    442:                        count++;
                    443:                        if (count >= PRIVSEP_NBUF_MAX) {
                    444:                                plog(LLV_ERROR, LOCATION, NULL, 
                    445:                                    "privsep_script_exec: too many args\n");
                    446:                                goto out;
                    447:                        }
                    448: 
                    449: 
                    450:                        /* 
                    451:                         * Allocate the arrays for envp 
                    452:                         */
                    453:                        envp = racoon_malloc((envc + 1) * sizeof(char *));
                    454:                        if (envp == NULL) {
                    455:                                plog(LLV_ERROR, LOCATION, NULL, 
                    456:                                    "cannot allocate memory: %s\n",
                    457:                                    strerror(errno));
                    458:                                goto out;
                    459:                        }
                    460:                        bzero(envp, (envc + 1) * sizeof(char *));
                    461: 
                    462:        
                    463:                        /*
                    464:                         * Populate script, name and envp 
                    465:                         */
                    466:                        count = 0;
                    467:                        script = bufs[count++];
                    468: 
                    469:                        if (combuf->bufs.buflen[count] != sizeof(name)) {
                    470:                                plog(LLV_ERROR, LOCATION, NULL, 
                    471:                                    "privsep_script_exec: corrupted message\n");
                    472:                                goto out;
                    473:                        }
                    474:                        memcpy((char *)&name, bufs[count++], sizeof(name));
                    475: 
                    476:                        for (i = 0; combuf->bufs.buflen[count]; count++)
                    477:                                envp[i++] = bufs[count];
                    478: 
                    479:                        count++;                /* void */
                    480: 
                    481:                        plog(LLV_DEBUG, LOCATION, NULL, 
                    482:                            "script_exec(\"%s\", %d, %p)\n", 
                    483:                            script, name, envp);
                    484: 
                    485:                        /* 
                    486:                         * Check env for dangerous variables
                    487:                         * Check script path and name
                    488:                         * Perform fork and execve
                    489:                         */
                    490:                        if ((unsafe_env(envp) == 0) &&
                    491:                            (unknown_name(name) == 0) &&
                    492:                            (unsafe_path(script, LC_PATHTYPE_SCRIPT) == 0))
                    493:                                (void)script_exec(script, name, envp);
                    494:                        else
                    495:                                plog(LLV_ERROR, LOCATION, NULL, 
                    496:                                    "privsep_script_exec: "
                    497:                                    "unsafe script \"%s\"\n", script);
                    498: 
                    499:                        racoon_free(envp);
                    500:                        break;
                    501:                }
                    502: 
                    503:                case PRIVSEP_GETPSK: {
                    504:                        vchar_t *psk;
                    505:                        int keylen;
                    506: 
                    507:                        /* Make sure the string is NULL terminated */
                    508:                        if (safety_check(combuf, 0) != 0)
                    509:                                break;
                    510:                        bufs[0][combuf->bufs.buflen[0] - 1] = '\0';
                    511: 
                    512:                        if (combuf->bufs.buflen[1] != sizeof(keylen)) {
                    513:                                plog(LLV_ERROR, LOCATION, NULL, 
                    514:                                    "privsep_getpsk: corrupted message\n");
                    515:                                goto out;
                    516:                        }
                    517:                        memcpy(&keylen, bufs[1], sizeof(keylen));
                    518: 
                    519:                        plog(LLV_DEBUG, LOCATION, NULL, 
                    520:                            "getpsk(\"%s\", %d)\n", bufs[0], keylen);
                    521: 
                    522:                        if ((psk = getpsk(bufs[0], keylen)) == NULL) {
                    523:                                reply->hdr.ac_errno = errno;
                    524:                                break;
                    525:                        }
                    526: 
                    527:                        reply->bufs.buflen[0] = psk->l;
                    528:                        reply->hdr.ac_len = sizeof(*reply) + psk->l;
                    529:                        reply = racoon_realloc(reply, reply->hdr.ac_len); 
                    530:                        if (reply == NULL) {
                    531:                                plog(LLV_ERROR, LOCATION, NULL,
                    532:                                    "Cannot allocate reply buffer: %s\n", 
                    533:                                    strerror(errno));
                    534:                                goto out;
                    535:                        }
                    536: 
                    537:                        memcpy(reply + 1, psk->v, psk->l);
                    538:                        vfree(psk);
                    539:                        break;
                    540:                }
                    541: 
                    542:                case PRIVSEP_SOCKET: {
                    543:                        struct socket_args socket_args;
                    544:                        int s;
                    545: 
                    546:                        /* Make sure the string is NULL terminated */
                    547:                        if (safety_check(combuf, 0) != 0)
                    548:                                break;
                    549: 
                    550:                        if (combuf->bufs.buflen[0] !=
                    551:                            sizeof(struct socket_args)) {
                    552:                                plog(LLV_ERROR, LOCATION, NULL, 
                    553:                                    "privsep_socket: corrupted message\n");
                    554:                                goto out;
                    555:                        }
                    556:                        memcpy(&socket_args, bufs[0],
                    557:                               sizeof(struct socket_args));
                    558: 
                    559:                        if (socket_args.domain != PF_INET &&
                    560:                            socket_args.domain != PF_INET6) {
                    561:                                plog(LLV_ERROR, LOCATION, NULL, 
                    562:                                    "privsep_socket: "
                    563:                                     "unauthorized domain (%d)\n",
                    564:                                     socket_args.domain);
                    565:                                goto out;
                    566:                        }
                    567: 
                    568:                        if ((s = socket(socket_args.domain, socket_args.type,
                    569:                                        socket_args.protocol)) == -1) {
                    570:                                reply->hdr.ac_errno = errno;
                    571:                                break;
                    572:                        }
                    573: 
                    574:                        if (send_fd(privsep_sock[0], s) < 0) {
                    575:                                plog(LLV_ERROR, LOCATION, NULL, 
                    576:                                     "privsep_socket: send_fd failed\n");
                    577:                                close(s);
                    578:                                goto out;
                    579:                        }
                    580: 
                    581:                        close(s);
                    582:                        break;
                    583:                }
                    584: 
                    585:                case PRIVSEP_BIND: {
                    586:                        struct bind_args bind_args;
                    587:                        int err, port = 0;
                    588: 
                    589:                        /* Make sure the string is NULL terminated */
                    590:                        if (safety_check(combuf, 0) != 0)
                    591:                                break;
                    592: 
                    593:                        if (combuf->bufs.buflen[0] !=
                    594:                            sizeof(struct bind_args)) {
                    595:                                plog(LLV_ERROR, LOCATION, NULL, 
                    596:                                    "privsep_bind: corrupted message\n");
                    597:                                goto out;
                    598:                        }
                    599:                        memcpy(&bind_args, bufs[0], sizeof(struct bind_args));
                    600: 
                    601:                        if (combuf->bufs.buflen[1] != bind_args.addrlen) {
                    602:                                plog(LLV_ERROR, LOCATION, NULL, 
                    603:                                    "privsep_bind: corrupted message\n");
                    604:                                goto out;
                    605:                        }
                    606:                        bind_args.addr = (const struct sockaddr *)bufs[1];
                    607: 
                    608:                        if ((bind_args.s = rec_fd(privsep_sock[0])) < 0) {
                    609:                                plog(LLV_ERROR, LOCATION, NULL, 
                    610:                                     "privsep_bind: rec_fd failed\n");
                    611:                                goto out;
                    612:                        }
                    613: 
                    614:                        port = extract_port(bind_args.addr);
                    615:                        if (port != PORT_ISAKMP && port != PORT_ISAKMP_NATT &&
                    616:                            port != lcconf->port_isakmp &&
                    617:                            port != lcconf->port_isakmp_natt) {
                    618:                                plog(LLV_ERROR, LOCATION, NULL,
                    619:                                     "privsep_bind: "
                    620:                                     "unauthorized port (%d)\n",
                    621:                                     port);
                    622:                                close(bind_args.s);
                    623:                                goto out;
                    624:                        }
                    625: 
                    626:                        err = bind(bind_args.s, bind_args.addr,
                    627:                                   bind_args.addrlen);
                    628: 
                    629:                        if (err)
                    630:                                reply->hdr.ac_errno = errno;
                    631: 
                    632:                        close(bind_args.s);
                    633:                        break;
                    634:                }
                    635: 
                    636:                case PRIVSEP_SETSOCKOPTS: {
                    637:                        struct sockopt_args sockopt_args;
                    638:                        int err;
                    639: 
                    640:                        /* Make sure the string is NULL terminated */
                    641:                        if (safety_check(combuf, 0) != 0)
                    642:                                break;
                    643: 
                    644:                        if (combuf->bufs.buflen[0] !=
                    645:                            sizeof(struct sockopt_args)) {
                    646:                                plog(LLV_ERROR, LOCATION, NULL, 
                    647:                                    "privsep_setsockopt: "
                    648:                                     "corrupted message\n");
                    649:                                goto out;
                    650:                        }
                    651:                        memcpy(&sockopt_args, bufs[0],
                    652:                               sizeof(struct sockopt_args));
                    653: 
                    654:                        if (combuf->bufs.buflen[1] != sockopt_args.optlen) {
                    655:                                plog(LLV_ERROR, LOCATION, NULL, 
                    656:                                    "privsep_setsockopt: corrupted message\n");
                    657:                                goto out;
                    658:                        }
                    659:                        sockopt_args.optval = bufs[1];
                    660: 
                    661:                        if (sockopt_args.optname != 
                    662:                            (sockopt_args.level == 
                    663:                             IPPROTO_IP ? IP_IPSEC_POLICY :
                    664:                             IPV6_IPSEC_POLICY)) {
                    665:                                plog(LLV_ERROR, LOCATION, NULL, 
                    666:                                    "privsep_setsockopt: "
                    667:                                     "unauthorized option (%d)\n",
                    668:                                     sockopt_args.optname);
                    669:                                goto out;
                    670:                        }
                    671: 
                    672:                        if ((sockopt_args.s = rec_fd(privsep_sock[0])) < 0) {
                    673:                                plog(LLV_ERROR, LOCATION, NULL, 
                    674:                                     "privsep_setsockopt: rec_fd failed\n");
                    675:                                goto out;
                    676:                        }
                    677: 
                    678:                        err = setsockopt(sockopt_args.s,
                    679:                                         sockopt_args.level,
                    680:                                         sockopt_args.optname,
                    681:                                         sockopt_args.optval,
                    682:                                         sockopt_args.optlen);
                    683:                        if (err)
                    684:                                reply->hdr.ac_errno = errno;
                    685: 
                    686:                        close(sockopt_args.s);
                    687:                        break;
                    688:                }
                    689: 
                    690: #ifdef ENABLE_HYBRID
                    691:                case PRIVSEP_ACCOUNTING_SYSTEM: {
                    692:                        int pool_size;
                    693:                        int port;
                    694:                        int inout;
                    695:                        struct sockaddr *raddr;
                    696: 
                    697:                        if (safety_check(combuf, 0) != 0)
                    698:                                break;
                    699:                        if (safety_check(combuf, 1) != 0)
                    700:                                break;
                    701:                        if (safety_check(combuf, 2) != 0)
                    702:                                break;
                    703:                        if (safety_check(combuf, 3) != 0)
                    704:                                break;
                    705: 
                    706:                        memcpy(&port, bufs[0], sizeof(port));
                    707:                        raddr = (struct sockaddr *)bufs[1];
                    708: 
                    709:                        bufs[2][combuf->bufs.buflen[2] - 1] = '\0';
                    710:                        memcpy(&inout, bufs[3], sizeof(port));
                    711: 
                    712:                        if (port_check(port) != 0)
                    713:                                break;
                    714: 
                    715:                        plog(LLV_DEBUG, LOCATION, NULL, 
                    716:                            "accounting_system(%d, %s, %s)\n", 
                    717:                            port, saddr2str(raddr), bufs[2]); 
                    718: 
                    719:                        errno = 0;
                    720:                        if (isakmp_cfg_accounting_system(port, 
                    721:                            raddr, bufs[2], inout) != 0) {
                    722:                                if (errno == 0)
                    723:                                        reply->hdr.ac_errno = EINVAL;
                    724:                                else
                    725:                                        reply->hdr.ac_errno = errno;
                    726:                        }
                    727:                        break;
                    728:                }
                    729:                case PRIVSEP_XAUTH_LOGIN_SYSTEM: {
                    730:                        if (safety_check(combuf, 0) != 0)
                    731:                                break;
                    732:                        bufs[0][combuf->bufs.buflen[0] - 1] = '\0';
                    733: 
                    734:                        if (safety_check(combuf, 1) != 0)
                    735:                                break;
                    736:                        bufs[1][combuf->bufs.buflen[1] - 1] = '\0';
                    737: 
                    738:                        plog(LLV_DEBUG, LOCATION, NULL, 
                    739:                            "xauth_login_system(\"%s\", <password>)\n", 
                    740:                            bufs[0]);
                    741: 
                    742:                        errno = 0;
                    743:                        if (xauth_login_system(bufs[0], bufs[1]) != 0) {
                    744:                                if (errno == 0)
                    745:                                        reply->hdr.ac_errno = EINVAL;
                    746:                                else
                    747:                                        reply->hdr.ac_errno = errno;
                    748:                        }
                    749:                        break;
                    750:                }
                    751: #ifdef HAVE_LIBPAM
                    752:                case PRIVSEP_ACCOUNTING_PAM: {
                    753:                        int port;
                    754:                        int inout;
                    755:                        int pool_size;
                    756: 
                    757:                        if (safety_check(combuf, 0) != 0)
                    758:                                break;
                    759:                        if (safety_check(combuf, 1) != 0)
                    760:                                break;
                    761:                        if (safety_check(combuf, 2) != 0)
                    762:                                break;
                    763: 
                    764:                        memcpy(&port, bufs[0], sizeof(port));
                    765:                        memcpy(&inout, bufs[1], sizeof(inout));
                    766:                        memcpy(&pool_size, bufs[2], sizeof(pool_size));
                    767: 
                    768:                        if (pool_size != isakmp_cfg_config.pool_size)
                    769:                                if (isakmp_cfg_resize_pool(pool_size) != 0)
                    770:                                        break;
                    771: 
                    772:                        if (port_check(port) != 0)
                    773:                                break;
                    774: 
                    775:                        plog(LLV_DEBUG, LOCATION, NULL, 
                    776:                            "isakmp_cfg_accounting_pam(%d, %d)\n", 
                    777:                            port, inout); 
                    778: 
                    779:                        errno = 0;
                    780:                        if (isakmp_cfg_accounting_pam(port, inout) != 0) {
                    781:                                if (errno == 0)
                    782:                                        reply->hdr.ac_errno = EINVAL;
                    783:                                else
                    784:                                        reply->hdr.ac_errno = errno;
                    785:                        }
                    786:                        break;
                    787:                }
                    788: 
                    789:                case PRIVSEP_XAUTH_LOGIN_PAM: {
                    790:                        int port;
                    791:                        int pool_size;
                    792:                        struct sockaddr *raddr;
                    793: 
                    794:                        if (safety_check(combuf, 0) != 0)
                    795:                                break;
                    796:                        if (safety_check(combuf, 1) != 0)
                    797:                                break;
                    798:                        if (safety_check(combuf, 2) != 0)
                    799:                                break;
                    800:                        if (safety_check(combuf, 3) != 0)
                    801:                                break;
                    802:                        if (safety_check(combuf, 4) != 0)
                    803:                                break;
                    804: 
                    805:                        memcpy(&port, bufs[0], sizeof(port));
                    806:                        memcpy(&pool_size, bufs[1], sizeof(pool_size));
                    807:                        raddr = (struct sockaddr *)bufs[2];
                    808:                        
                    809:                        bufs[3][combuf->bufs.buflen[3] - 1] = '\0';
                    810:                        bufs[4][combuf->bufs.buflen[4] - 1] = '\0';
                    811: 
                    812:                        if (pool_size != isakmp_cfg_config.pool_size)
                    813:                                if (isakmp_cfg_resize_pool(pool_size) != 0)
                    814:                                        break;
                    815: 
                    816:                        if (port_check(port) != 0)
                    817:                                break;
                    818: 
                    819:                        plog(LLV_DEBUG, LOCATION, NULL, 
                    820:                            "xauth_login_pam(%d, %s, \"%s\", <password>)\n", 
                    821:                            port, saddr2str(raddr), bufs[3]); 
                    822: 
                    823:                        errno = 0;
                    824:                        if (xauth_login_pam(port, 
                    825:                            raddr, bufs[3], bufs[4]) != 0) {
                    826:                                if (errno == 0)
                    827:                                        reply->hdr.ac_errno = EINVAL;
                    828:                                else
                    829:                                        reply->hdr.ac_errno = errno;
                    830:                        }
                    831:                        break;
                    832:                }
                    833: 
                    834:                case PRIVSEP_CLEANUP_PAM: {
                    835:                        int port;
                    836:                        int pool_size;
                    837: 
                    838:                        if (safety_check(combuf, 0) != 0)
                    839:                                break;
                    840:                        if (safety_check(combuf, 1) != 0)
                    841:                                break;
                    842: 
                    843:                        memcpy(&port, bufs[0], sizeof(port));
                    844:                        memcpy(&pool_size, bufs[1], sizeof(pool_size));
                    845: 
                    846:                        if (pool_size != isakmp_cfg_config.pool_size)
                    847:                                if (isakmp_cfg_resize_pool(pool_size) != 0)
                    848:                                        break;
                    849: 
                    850:                        if (port_check(port) != 0)
                    851:                                break;
                    852: 
                    853:                        plog(LLV_DEBUG, LOCATION, NULL, 
                    854:                            "cleanup_pam(%d)\n", port);
                    855: 
                    856:                        cleanup_pam(port);
                    857:                        reply->hdr.ac_errno = 0;
                    858: 
                    859:                        break;
                    860:                }
                    861: #endif /* HAVE_LIBPAM */
                    862: #endif /* ENABLE_HYBRID */
                    863: 
                    864:                default:
                    865:                        plog(LLV_ERROR, LOCATION, NULL,
                    866:                            "unexpected privsep command %d\n", 
                    867:                            combuf->hdr.ac_cmd);
                    868:                        goto out;
                    869:                        break;
                    870:                }
                    871: 
                    872:                /* This frees reply */
                    873:                if (privsep_send(privsep_sock[0], 
                    874:                    reply, reply->hdr.ac_len) != 0) {
                    875:                        racoon_free(reply);
                    876:                        goto out;
                    877:                }
                    878: 
                    879:                racoon_free(combuf);
                    880:        }
                    881: 
                    882: out:
                    883:        plog(LLV_INFO, LOCATION, NULL, 
                    884:            "racoon privileged process %d terminated\n", getpid());
                    885:        _exit(0);
                    886: }
                    887: 
                    888: 
                    889: vchar_t *
                    890: privsep_eay_get_pkcs1privkey(path) 
                    891:        char *path;
                    892: {
                    893:        vchar_t *privkey;
                    894:        struct privsep_com_msg *msg;
                    895:        size_t len;
                    896: 
                    897:        if (geteuid() == 0)
                    898:                return eay_get_pkcs1privkey(path);
                    899: 
                    900:        len = sizeof(*msg) + strlen(path) + 1;
                    901:        if ((msg = racoon_malloc(len)) == NULL) {
                    902:                plog(LLV_ERROR, LOCATION, NULL, 
                    903:                    "Cannot allocate memory: %s\n", strerror(errno));
                    904:                return NULL;
                    905:        }
                    906:        bzero(msg, len);
                    907:        msg->hdr.ac_cmd = PRIVSEP_EAY_GET_PKCS1PRIVKEY;
                    908:        msg->hdr.ac_len = len;
                    909:        msg->bufs.buflen[0] = len - sizeof(*msg);
                    910:        memcpy(msg + 1, path, msg->bufs.buflen[0]);
                    911: 
                    912:        if (privsep_send(privsep_sock[1], msg, len) != 0)
                    913:                return NULL;
                    914: 
                    915:        if (privsep_recv(privsep_sock[1], &msg, &len) != 0)
                    916:                return NULL;
                    917: 
                    918:        if (msg->hdr.ac_errno != 0) {
                    919:                errno = msg->hdr.ac_errno;
                    920:                goto out;
                    921:        }
                    922: 
                    923:        if ((privkey = vmalloc(len - sizeof(*msg))) == NULL)
                    924:                goto out;
                    925: 
                    926:        memcpy(privkey->v, msg + 1, privkey->l);
                    927:        racoon_free(msg);
                    928:        return privkey;
                    929: 
                    930: out:
                    931:        racoon_free(msg);
                    932:        return NULL;
                    933: }
                    934: 
                    935: int
                    936: privsep_script_exec(script, name, envp)
                    937:        char *script;
                    938:        int name;
                    939:        char *const envp[];
                    940: {
                    941:        int count = 0;
                    942:        char *const *c;
                    943:        char *data;
                    944:        size_t len;
                    945:        struct privsep_com_msg *msg;
                    946: 
                    947:        if (geteuid() == 0)
                    948:                return script_exec(script, name, envp);
                    949: 
                    950:        if ((msg = racoon_malloc(sizeof(*msg))) == NULL) {
                    951:                plog(LLV_ERROR, LOCATION, NULL, 
                    952:                    "Cannot allocate memory: %s\n", strerror(errno));
                    953:                return -1;
                    954:        }
                    955: 
                    956:        bzero(msg, sizeof(*msg));
                    957:        msg->hdr.ac_cmd = PRIVSEP_SCRIPT_EXEC;
                    958:        msg->hdr.ac_len = sizeof(*msg);
                    959: 
                    960:        /*
                    961:         * We send: 
                    962:         * script, name, envp[0], ... envp[N], void
                    963:         */
                    964: 
                    965:        /*
                    966:         * Safety check on the counts: PRIVSEP_NBUF_MAX max
                    967:         */
                    968:        count = 0;
                    969:        count++;                                        /* script */
                    970:        count++;                                        /* name */
                    971:        for (c = envp; *c; c++)                         /* envp */
                    972:                count++;
                    973:        count++;                                        /* void */
                    974: 
                    975:        if (count > PRIVSEP_NBUF_MAX) {
                    976:                plog(LLV_ERROR, LOCATION, NULL, "Unexpected error: "
                    977:                    "privsep_script_exec count > PRIVSEP_NBUF_MAX\n");
                    978:                racoon_free(msg);
                    979:                return -1;
                    980:        }
                    981: 
                    982: 
                    983:        /*
                    984:         * Compute the length
                    985:         */
                    986:        count = 0;
                    987:        msg->bufs.buflen[count] = strlen(script) + 1;   /* script */
                    988:        msg->hdr.ac_len += msg->bufs.buflen[count++];
                    989: 
                    990:        msg->bufs.buflen[count] = sizeof(name);         /* name */
                    991:        msg->hdr.ac_len += msg->bufs.buflen[count++];
                    992: 
                    993:        for (c = envp; *c; c++) {                       /* envp */
                    994:                msg->bufs.buflen[count] = strlen(*c) + 1;
                    995:                msg->hdr.ac_len += msg->bufs.buflen[count++];
                    996:        }
                    997: 
                    998:        msg->bufs.buflen[count] = 0;                    /* void */
                    999:        msg->hdr.ac_len += msg->bufs.buflen[count++];
                   1000: 
                   1001:        if ((msg = racoon_realloc(msg, msg->hdr.ac_len)) == NULL) {
                   1002:                plog(LLV_ERROR, LOCATION, NULL, 
                   1003:                    "Cannot allocate memory: %s\n", strerror(errno));
                   1004:                return -1;
                   1005:        }
                   1006:        
                   1007:        /*
                   1008:         * Now copy the data
                   1009:         */
                   1010:        data = (char *)(msg + 1);
                   1011:        count = 0;
                   1012: 
                   1013:        memcpy(data, (char *)script, msg->bufs.buflen[count]);  /* script */
                   1014:        data += msg->bufs.buflen[count++];
                   1015: 
                   1016:        memcpy(data, (char *)&name, msg->bufs.buflen[count]);   /* name */
                   1017:        data += msg->bufs.buflen[count++];
                   1018: 
                   1019:        for (c = envp; *c; c++) {                               /* envp */
                   1020:                memcpy(data, *c, msg->bufs.buflen[count]); 
                   1021:                data += msg->bufs.buflen[count++];
                   1022:        }
                   1023: 
                   1024:        count++;                                                /* void */
                   1025: 
                   1026:        /*
                   1027:         * And send it!
                   1028:         */
                   1029:        if (privsep_send(privsep_sock[1], msg, msg->hdr.ac_len) != 0)
                   1030:                return -1;
                   1031: 
                   1032:        if (privsep_recv(privsep_sock[1], &msg, &len) != 0)
                   1033:                return -1;
                   1034: 
                   1035:        if (msg->hdr.ac_errno != 0) {
                   1036:                errno = msg->hdr.ac_errno;
                   1037:                racoon_free(msg);
                   1038:                return -1;
                   1039:        }
                   1040: 
                   1041:        racoon_free(msg);
                   1042:        return 0;
                   1043: }
                   1044: 
                   1045: vchar_t *
                   1046: privsep_getpsk(str, keylen)
                   1047:        const char *str;
                   1048:        int keylen;
                   1049: {
                   1050:        vchar_t *psk;
                   1051:        struct privsep_com_msg *msg;
                   1052:        size_t len;
                   1053:        int *keylenp;
                   1054:        char *data;
                   1055: 
                   1056:        if (geteuid() == 0)
                   1057:                return getpsk(str, keylen);
                   1058: 
                   1059:        len = sizeof(*msg) + strlen(str) + 1 + sizeof(keylen);
                   1060:        if ((msg = racoon_malloc(len)) == NULL) {
                   1061:                plog(LLV_ERROR, LOCATION, NULL, 
                   1062:                    "Cannot allocate memory: %s\n", strerror(errno));
                   1063:                return NULL;
                   1064:        }
                   1065:        bzero(msg, len);
                   1066:        msg->hdr.ac_cmd = PRIVSEP_GETPSK;
                   1067:        msg->hdr.ac_len = len;
                   1068: 
                   1069:        data = (char *)(msg + 1);
                   1070:        msg->bufs.buflen[0] = strlen(str) + 1;
                   1071:        memcpy(data, str, msg->bufs.buflen[0]);
                   1072: 
                   1073:        data += msg->bufs.buflen[0];
                   1074:        msg->bufs.buflen[1] = sizeof(keylen);
                   1075:        memcpy(data, &keylen, sizeof(keylen));
                   1076: 
                   1077:        if (privsep_send(privsep_sock[1], msg, len) != 0)
                   1078:                return NULL;
                   1079: 
                   1080:        if (privsep_recv(privsep_sock[1], &msg, &len) != 0)
                   1081:                return NULL;
                   1082: 
                   1083:        if (msg->hdr.ac_errno != 0) {
                   1084:                errno = msg->hdr.ac_errno;
                   1085:                goto out;
                   1086:        }
                   1087: 
                   1088:        if ((psk = vmalloc(len - sizeof(*msg))) == NULL)
                   1089:                goto out;
                   1090: 
                   1091:        memcpy(psk->v, msg + 1, psk->l);
                   1092:        racoon_free(msg);
                   1093:        return psk;
                   1094: 
                   1095: out:
                   1096:        racoon_free(msg);
                   1097:        return NULL;
                   1098: }
                   1099: 
                   1100: /*
                   1101:  * Create a privileged socket.  On BSD systems a socket obtains special
                   1102:  * capabilities if it is created by root; setsockopt(IP_IPSEC_POLICY) will
                   1103:  * succeed but will be ineffective if performed on an unprivileged socket.
                   1104:  */
                   1105: int
                   1106: privsep_socket(domain, type, protocol)
                   1107:        int domain;
                   1108:        int type;
                   1109:        int protocol;
                   1110: {
                   1111:        struct privsep_com_msg *msg;
                   1112:        size_t len;
                   1113:        char *data;
                   1114:        struct socket_args socket_args;
                   1115:        int s, saved_errno = 0;
                   1116: 
                   1117:        if (geteuid() == 0)
                   1118:                return socket(domain, type, protocol);
                   1119: 
                   1120:        len = sizeof(*msg) + sizeof(socket_args);
                   1121: 
                   1122:        if ((msg = racoon_malloc(len)) == NULL) {
                   1123:                plog(LLV_ERROR, LOCATION, NULL, 
                   1124:                    "Cannot allocate memory: %s\n", strerror(errno));
                   1125:                return -1;
                   1126:        }
                   1127:        bzero(msg, len);
                   1128:        msg->hdr.ac_cmd = PRIVSEP_SOCKET;
                   1129:        msg->hdr.ac_len = len;
                   1130: 
                   1131:        socket_args.domain = domain;
                   1132:        socket_args.type = type;
                   1133:        socket_args.protocol = protocol;
                   1134: 
                   1135:        data = (char *)(msg + 1);
                   1136:        msg->bufs.buflen[0] = sizeof(socket_args);
                   1137:        memcpy(data, &socket_args, msg->bufs.buflen[0]);
                   1138: 
                   1139:        /* frees msg */
                   1140:        if (privsep_send(privsep_sock[1], msg, len) != 0)
                   1141:                goto out;
                   1142: 
                   1143:        /* Get the privileged socket descriptor from the privileged process. */
                   1144:        if ((s = rec_fd(privsep_sock[1])) == -1)
                   1145:                return -1;
                   1146: 
                   1147:        if (privsep_recv(privsep_sock[1], &msg, &len) != 0)
                   1148:                goto out;
                   1149: 
                   1150:        if (msg->hdr.ac_errno != 0) {
                   1151:                errno = msg->hdr.ac_errno;
                   1152:                goto out;
                   1153:        }
                   1154: 
                   1155:        racoon_free(msg);
                   1156:        return s;
                   1157: 
                   1158: out:
                   1159:        racoon_free(msg);
                   1160:        return -1;
                   1161: }
                   1162: 
                   1163: /*
                   1164:  * Bind() a socket to a port.  This works just like regular bind(), except that
                   1165:  * if you want to bind to the designated isakmp ports and you don't have the
                   1166:  * privilege to do so, it will ask a privileged process to do it.
                   1167:  */
                   1168: int
                   1169: privsep_bind(s, addr, addrlen)
                   1170:        int s;
                   1171:        const struct sockaddr *addr;
                   1172:        socklen_t addrlen;
                   1173: {
                   1174:        struct privsep_com_msg *msg;
                   1175:        size_t len;
                   1176:        char *data;
                   1177:        struct bind_args bind_args;
                   1178:        int err, saved_errno = 0;
                   1179: 
                   1180:        err = bind(s, addr, addrlen);
                   1181:        if ((err == 0) || (saved_errno = errno) != EACCES || geteuid() == 0) {
                   1182:                if (saved_errno)
                   1183:                        plog(LLV_ERROR, LOCATION, NULL,
                   1184:                             "privsep_bind (%s) = %d\n", strerror(saved_errno), err);
                   1185:                errno = saved_errno;
                   1186:                return err;
                   1187:        }
                   1188: 
                   1189:        len = sizeof(*msg) + sizeof(bind_args) + addrlen;
                   1190: 
                   1191:        if ((msg = racoon_malloc(len)) == NULL) {
                   1192:                plog(LLV_ERROR, LOCATION, NULL, 
                   1193:                    "Cannot allocate memory: %s\n", strerror(errno));
                   1194:                return -1;
                   1195:        }
                   1196:        bzero(msg, len);
                   1197:        msg->hdr.ac_cmd = PRIVSEP_BIND;
                   1198:        msg->hdr.ac_len = len;
                   1199: 
                   1200:        bind_args.s = -1;
                   1201:        bind_args.addr = NULL;
                   1202:        bind_args.addrlen = addrlen;
                   1203: 
                   1204:        data = (char *)(msg + 1);
                   1205:        msg->bufs.buflen[0] = sizeof(bind_args);
                   1206:        memcpy(data, &bind_args, msg->bufs.buflen[0]);
                   1207: 
                   1208:        data += msg->bufs.buflen[0];
                   1209:        msg->bufs.buflen[1] = addrlen;
                   1210:        memcpy(data, addr, addrlen);
                   1211: 
                   1212:        /* frees msg */
                   1213:        if (privsep_send(privsep_sock[1], msg, len) != 0)
                   1214:                goto out;
                   1215: 
                   1216:        /* Send the socket descriptor to the privileged process. */
                   1217:        if (send_fd(privsep_sock[1], s) < 0)
                   1218:                return -1;
                   1219: 
                   1220:        if (privsep_recv(privsep_sock[1], &msg, &len) != 0)
                   1221:                goto out;
                   1222: 
                   1223:        if (msg->hdr.ac_errno != 0) {
                   1224:                errno = msg->hdr.ac_errno;
                   1225:                goto out;
                   1226:        }
                   1227: 
                   1228:        racoon_free(msg);
                   1229:        return 0;
                   1230: 
                   1231: out:
                   1232:        racoon_free(msg);
                   1233:        return -1;
                   1234: }
                   1235: 
                   1236: /*
                   1237:  * Set socket options.  This works just like regular setsockopt(), except that
                   1238:  * if you want to change IP_IPSEC_POLICY or IPV6_IPSEC_POLICY and you don't
                   1239:  * have the privilege to do so, it will ask a privileged process to do it.
                   1240:  */
                   1241: int
                   1242: privsep_setsockopt(s, level, optname, optval, optlen)
                   1243:        int s;
                   1244:        int level;
                   1245:        int optname;
                   1246:        const void *optval;
                   1247:        socklen_t optlen;
                   1248: {
                   1249:        struct privsep_com_msg *msg;
                   1250:        size_t len;
                   1251:        char *data;
                   1252:        struct sockopt_args sockopt_args;
                   1253:        int err, saved_errno = 0;
                   1254: 
                   1255:        if ((err = setsockopt(s, level, optname, optval, optlen) == 0) || 
                   1256:            (saved_errno = errno) != EACCES ||
                   1257:            geteuid() == 0) {
                   1258:                if (saved_errno)
                   1259:                        plog(LLV_ERROR, LOCATION, NULL,
                   1260:                             "privsep_setsockopt (%s)\n",
                   1261:                             strerror(saved_errno));
                   1262: 
                   1263:                errno = saved_errno;
                   1264:                return err;
                   1265:        }
                   1266: 
                   1267:        len = sizeof(*msg) + sizeof(sockopt_args) + optlen;
                   1268: 
                   1269:        if ((msg = racoon_malloc(len)) == NULL) {
                   1270:                plog(LLV_ERROR, LOCATION, NULL, 
                   1271:                    "Cannot allocate memory: %s\n", strerror(errno));
                   1272:                return -1;
                   1273:        }
                   1274:        bzero(msg, len);
                   1275:        msg->hdr.ac_cmd = PRIVSEP_SETSOCKOPTS;
                   1276:        msg->hdr.ac_len = len;
                   1277: 
                   1278:        sockopt_args.s = -1;
                   1279:        sockopt_args.level = level;
                   1280:        sockopt_args.optname = optname;
                   1281:        sockopt_args.optval = NULL;
                   1282:        sockopt_args.optlen = optlen;
                   1283: 
                   1284:        data = (char *)(msg + 1);
                   1285:        msg->bufs.buflen[0] = sizeof(sockopt_args);
                   1286:        memcpy(data, &sockopt_args, msg->bufs.buflen[0]);
                   1287: 
                   1288:        data += msg->bufs.buflen[0];
                   1289:        msg->bufs.buflen[1] = optlen;
                   1290:        memcpy(data, optval, optlen);
                   1291: 
                   1292:        /* frees msg */
                   1293:        if (privsep_send(privsep_sock[1], msg, len) != 0)
                   1294:                goto out;
                   1295: 
                   1296:        if (send_fd(privsep_sock[1], s) < 0)
                   1297:                return -1;
                   1298: 
                   1299:        if (privsep_recv(privsep_sock[1], &msg, &len) != 0) {
                   1300:            plog(LLV_ERROR, LOCATION, NULL,
                   1301:                 "privsep_recv failed\n");
                   1302:                goto out;
                   1303:        }
                   1304: 
                   1305:        if (msg->hdr.ac_errno != 0) {
                   1306:                errno = msg->hdr.ac_errno;
                   1307:                goto out;
                   1308:        }
                   1309: 
                   1310:        racoon_free(msg);
                   1311:        return 0;
                   1312: 
                   1313: out:
                   1314:        racoon_free(msg);
                   1315:        return -1;
                   1316: }
                   1317: 
                   1318: #ifdef ENABLE_HYBRID
                   1319: int
                   1320: privsep_xauth_login_system(usr, pwd)
                   1321:        char *usr;
                   1322:        char *pwd;
                   1323: {
                   1324:        struct privsep_com_msg *msg;
                   1325:        size_t len;
                   1326:        char *data;
                   1327: 
                   1328:        if (geteuid() == 0)
                   1329:                return xauth_login_system(usr, pwd);
                   1330: 
                   1331:        len = sizeof(*msg) + strlen(usr) + 1 + strlen(pwd) + 1;
                   1332:        if ((msg = racoon_malloc(len)) == NULL) {
                   1333:                plog(LLV_ERROR, LOCATION, NULL, 
                   1334:                    "Cannot allocate memory: %s\n", strerror(errno));
                   1335:                return -1;
                   1336:        }
                   1337:        bzero(msg, len);
                   1338:        msg->hdr.ac_cmd = PRIVSEP_XAUTH_LOGIN_SYSTEM;
                   1339:        msg->hdr.ac_len = len;
                   1340: 
                   1341:        data = (char *)(msg + 1);
                   1342:        msg->bufs.buflen[0] = strlen(usr) + 1;
                   1343:        memcpy(data, usr, msg->bufs.buflen[0]);
                   1344:        data += msg->bufs.buflen[0];
                   1345: 
                   1346:        msg->bufs.buflen[1] = strlen(pwd) + 1;
                   1347:        memcpy(data, pwd, msg->bufs.buflen[1]);
                   1348:        
                   1349:        /* frees msg */
                   1350:        if (privsep_send(privsep_sock[1], msg, len) != 0)
                   1351:                return -1;
                   1352: 
                   1353:        if (privsep_recv(privsep_sock[1], &msg, &len) != 0)
                   1354:                return -1;
                   1355: 
                   1356:        if (msg->hdr.ac_errno != 0) {
                   1357:                racoon_free(msg);
                   1358:                return -1;
                   1359:        }
                   1360: 
                   1361:        racoon_free(msg);
                   1362:        return 0;
                   1363: }
                   1364: 
                   1365: int 
                   1366: privsep_accounting_system(port, raddr, usr, inout)
                   1367:        int port;
                   1368:        struct sockaddr *raddr;
                   1369:        char *usr;
                   1370:        int inout;
                   1371: {
                   1372:        struct privsep_com_msg *msg;
                   1373:        size_t len;
                   1374:        char *data;
                   1375:        int result;
                   1376: 
                   1377:        if (geteuid() == 0)
                   1378:                return isakmp_cfg_accounting_system(port, raddr,
                   1379:                                                    usr, inout);
                   1380: 
                   1381:        len = sizeof(*msg) 
                   1382:            + sizeof(port)
                   1383:            + sysdep_sa_len(raddr) 
                   1384:            + strlen(usr) + 1
                   1385:            + sizeof(inout);
                   1386: 
                   1387:        if ((msg = racoon_malloc(len)) == NULL) {
                   1388:                plog(LLV_ERROR, LOCATION, NULL, 
                   1389:                    "Cannot allocate memory: %s\n", strerror(errno));
                   1390:                return -1;
                   1391:        }
                   1392:        bzero(msg, len);
                   1393:        msg->hdr.ac_cmd = PRIVSEP_ACCOUNTING_SYSTEM;
                   1394:        msg->hdr.ac_len = len;
                   1395:        msg->bufs.buflen[0] = sizeof(port);
                   1396:        msg->bufs.buflen[1] = sysdep_sa_len(raddr);
                   1397:        msg->bufs.buflen[2] = strlen(usr) + 1;
                   1398:        msg->bufs.buflen[3] = sizeof(inout);
                   1399: 
                   1400:        data = (char *)(msg + 1);
                   1401:        memcpy(data, &port, msg->bufs.buflen[0]);
                   1402: 
                   1403:        data += msg->bufs.buflen[0];
                   1404:        memcpy(data, raddr, msg->bufs.buflen[1]);
                   1405: 
                   1406:        data += msg->bufs.buflen[1];
                   1407:        memcpy(data, usr, msg->bufs.buflen[2]);
                   1408: 
                   1409:        data += msg->bufs.buflen[2];
                   1410:        memcpy(data, &inout, msg->bufs.buflen[3]);
                   1411: 
                   1412:        /* frees msg */
                   1413:        if (privsep_send(privsep_sock[1], msg, len) != 0)
                   1414:                return -1;
                   1415: 
                   1416:        if (privsep_recv(privsep_sock[1], &msg, &len) != 0)
                   1417:                return -1;
                   1418: 
                   1419:        if (msg->hdr.ac_errno != 0) {
                   1420:                errno = msg->hdr.ac_errno;
                   1421:                goto out;
                   1422:        }
                   1423: 
                   1424:        racoon_free(msg);
                   1425:        return 0;
                   1426: 
                   1427: out:
                   1428:        racoon_free(msg);
                   1429:        return -1;
                   1430: }
                   1431: 
                   1432: static int
                   1433: port_check(port)
                   1434:        int port;
                   1435: {
                   1436:        if ((port < 0) || (port >= isakmp_cfg_config.pool_size)) {
                   1437:                plog(LLV_ERROR, LOCATION, NULL, 
                   1438:                    "privsep: port %d outside of allowed range [0,%zu]\n",
                   1439:                    port, isakmp_cfg_config.pool_size - 1);
                   1440:                return -1;
                   1441:        }
                   1442: 
                   1443:        return 0;
                   1444: }
                   1445: #endif
                   1446: 
                   1447: static int 
                   1448: safety_check(msg, index)
                   1449:        struct privsep_com_msg *msg;
                   1450:        int index;
                   1451: {
                   1452:        if (index >= PRIVSEP_NBUF_MAX) {
                   1453:                plog(LLV_ERROR, LOCATION, NULL, 
                   1454:                    "privsep: Corrupted message, too many buffers\n");
                   1455:                return -1;
                   1456:        }
                   1457:                
                   1458:        if (msg->bufs.buflen[index] == 0) {
                   1459:                plog(LLV_ERROR, LOCATION, NULL, 
                   1460:                    "privsep: Corrupted message, unexpected void buffer\n");
                   1461:                return -1;
                   1462:        }
                   1463: 
                   1464:        return 0;
                   1465: }
                   1466: 
                   1467: /*
                   1468:  * Filter unsafe environment variables
                   1469:  */
                   1470: static int
                   1471: unsafe_env(envp)
                   1472:        char *const *envp;
                   1473: {
                   1474:        char *const *e;
                   1475:        char *const *be;
                   1476:        char *const bad_env[] = { "PATH=", "LD_LIBRARY_PATH=", "IFS=", NULL };
                   1477: 
                   1478:        for (e = envp; *e; e++) {
                   1479:                for (be = bad_env; *be; be++) {
                   1480:                        if (strncmp(*e, *be, strlen(*be)) == 0) {
                   1481:                                goto found;
                   1482:                        }
                   1483:                }
                   1484:        }
                   1485: 
                   1486:        return 0;
                   1487: found:
                   1488:        plog(LLV_ERROR, LOCATION, NULL, 
                   1489:            "privsep_script_exec: unsafe environment variable\n");
                   1490:        return -1;
                   1491: }
                   1492: 
                   1493: /*
                   1494:  * Check path safety
                   1495:  */
                   1496: static int 
                   1497: unsafe_path(script, pathtype)
                   1498:        char *script;
                   1499:        int pathtype;
                   1500: {
                   1501:        char *path;
                   1502:        char rpath[MAXPATHLEN + 1];
                   1503:        size_t len;
                   1504: 
                   1505:        if (script == NULL) 
                   1506:                return -1;
                   1507: 
                   1508:        path = lcconf->pathinfo[pathtype];
                   1509: 
                   1510:        /* No path was given for scripts: skip the check */
                   1511:        if (path == NULL)
                   1512:                return 0;
                   1513: 
                   1514:        if (realpath(script, rpath) == NULL) {
                   1515:                plog(LLV_ERROR, LOCATION, NULL,
                   1516:                    "script path \"%s\" is invalid\n", script);
                   1517:                return -1;
                   1518:        }
                   1519: 
                   1520:        len = strlen(path);
                   1521:        if (strncmp(path, rpath, len) != 0)
                   1522:                return -1;
                   1523: 
                   1524:        return 0;
                   1525: }
                   1526: 
                   1527: static int 
                   1528: unknown_name(name)
                   1529:        int name;
                   1530: {
                   1531:        if ((name < 0) || (name > SCRIPT_MAX)) {
                   1532:                plog(LLV_ERROR, LOCATION, NULL, 
                   1533:                    "privsep_script_exec: unsafe name index\n");
                   1534:                return -1;
                   1535:        }
                   1536: 
                   1537:        return 0;
                   1538: }
                   1539: 
                   1540: /* Receive a file descriptor through the argument socket */
                   1541: static int
                   1542: rec_fd(s)
                   1543:        int s;
                   1544: {
                   1545:        struct msghdr msg;
                   1546:        struct cmsghdr *cmsg;
                   1547:        int *fdptr;
                   1548:        int fd;
                   1549:        char cmsbuf[1024];
                   1550:        struct iovec iov;
                   1551:        char iobuf[1];
                   1552: 
                   1553:        iov.iov_base = iobuf;
                   1554:        iov.iov_len = 1;
                   1555: 
                   1556:        if (sizeof(cmsbuf) < CMSG_SPACE(sizeof(fd))) {
                   1557:                plog(LLV_ERROR, LOCATION, NULL, 
                   1558:                    "send_fd: buffer size too small\n");
                   1559:                return -1;
                   1560:        }
                   1561:        bzero(&msg, sizeof(msg));
                   1562:        msg.msg_name = NULL;
                   1563:        msg.msg_namelen = 0;
                   1564:        msg.msg_iov = &iov;
                   1565:        msg.msg_iovlen = 1;
                   1566:        msg.msg_control = cmsbuf;
                   1567:        msg.msg_controllen = CMSG_SPACE(sizeof(fd));
                   1568: 
                   1569:        if (recvmsg(s, &msg, MSG_WAITALL) == -1)
                   1570:                return -1;
                   1571: 
                   1572:        cmsg = CMSG_FIRSTHDR(&msg);
                   1573:        fdptr = (int *) CMSG_DATA(cmsg);
                   1574:        return fdptr[0];
                   1575: }
                   1576: 
                   1577: /* Send the file descriptor fd through the argument socket s */
                   1578: static int
                   1579: send_fd(s, fd)
                   1580:        int s;
                   1581:        int fd;
                   1582: {
                   1583:        struct msghdr msg;
                   1584:        struct cmsghdr *cmsg;
                   1585:        char cmsbuf[1024];
                   1586:        struct iovec iov;
                   1587:        int *fdptr;
                   1588: 
                   1589:        iov.iov_base = " ";
                   1590:        iov.iov_len = 1;
                   1591: 
                   1592:        if (sizeof(cmsbuf) < CMSG_SPACE(sizeof(fd))) {
                   1593:                plog(LLV_ERROR, LOCATION, NULL, 
                   1594:                    "send_fd: buffer size too small\n");
                   1595:                return -1;
                   1596:        }
                   1597:        bzero(&msg, sizeof(msg));
                   1598:        msg.msg_name = NULL;
                   1599:        msg.msg_namelen = 0;
                   1600:        msg.msg_iov = &iov;
                   1601:        msg.msg_iovlen = 1;
                   1602:        msg.msg_control = cmsbuf;
                   1603:        msg.msg_controllen = CMSG_SPACE(sizeof(fd));
                   1604:        msg.msg_flags = 0;
                   1605: 
                   1606:        cmsg = CMSG_FIRSTHDR(&msg);
                   1607:        cmsg->cmsg_level = SOL_SOCKET;
                   1608:        cmsg->cmsg_type = SCM_RIGHTS;
                   1609:        cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
                   1610:        fdptr = (int *)CMSG_DATA(cmsg);
                   1611:        fdptr[0] = fd;
                   1612:        msg.msg_controllen = cmsg->cmsg_len;
                   1613: 
                   1614:        if (sendmsg(s, &msg, 0) == -1)
                   1615:                return -1;
                   1616: 
                   1617:        return 0;
                   1618: }
                   1619: 
                   1620: #ifdef HAVE_LIBPAM
                   1621: int 
                   1622: privsep_accounting_pam(port, inout)
                   1623:        int port;
                   1624:        int inout;
                   1625: {
                   1626:        struct privsep_com_msg *msg;
                   1627:        size_t len;
                   1628:        int *port_data;
                   1629:        int *inout_data;
                   1630:        int *pool_size_data;
                   1631:        int result;
                   1632: 
                   1633:        if (geteuid() == 0)
                   1634:                return isakmp_cfg_accounting_pam(port, inout);
                   1635: 
                   1636:        len = sizeof(*msg) 
                   1637:            + sizeof(port) 
                   1638:            + sizeof(inout)
                   1639:            + sizeof(isakmp_cfg_config.pool_size);
                   1640: 
                   1641:        if ((msg = racoon_malloc(len)) == NULL) {
                   1642:                plog(LLV_ERROR, LOCATION, NULL, 
                   1643:                    "Cannot allocate memory: %s\n", strerror(errno));
                   1644:                return -1;
                   1645:        }
                   1646:        bzero(msg, len);
                   1647:        msg->hdr.ac_cmd = PRIVSEP_ACCOUNTING_PAM;
                   1648:        msg->hdr.ac_len = len;
                   1649:        msg->bufs.buflen[0] = sizeof(port);
                   1650:        msg->bufs.buflen[1] = sizeof(inout);
                   1651:        msg->bufs.buflen[2] = sizeof(isakmp_cfg_config.pool_size);
                   1652: 
                   1653:        port_data = (int *)(msg + 1);
                   1654:        inout_data = (int *)(port_data + 1);
                   1655:        pool_size_data = (int *)(inout_data + 1);
                   1656: 
                   1657:        *port_data = port;
                   1658:        *inout_data = inout;
                   1659:        *pool_size_data = isakmp_cfg_config.pool_size;
                   1660: 
                   1661:        /* frees msg */
                   1662:        if (privsep_send(privsep_sock[1], msg, len) != 0)
                   1663:                return -1;
                   1664: 
                   1665:        if (privsep_recv(privsep_sock[1], &msg, &len) != 0)
                   1666:                return -1;
                   1667: 
                   1668:        if (msg->hdr.ac_errno != 0) {
                   1669:                errno = msg->hdr.ac_errno;
                   1670:                goto out;
                   1671:        }
                   1672: 
                   1673:        racoon_free(msg);
                   1674:        return 0;
                   1675: 
                   1676: out:
                   1677:        racoon_free(msg);
                   1678:        return -1;
                   1679: }
                   1680: 
                   1681: int 
                   1682: privsep_xauth_login_pam(port, raddr, usr, pwd)
                   1683:        int port;
                   1684:        struct sockaddr *raddr;
                   1685:        char *usr;
                   1686:        char *pwd;
                   1687: {
                   1688:        struct privsep_com_msg *msg;
                   1689:        size_t len;
                   1690:        char *data;
                   1691:        int result;
                   1692: 
                   1693:        if (geteuid() == 0)
                   1694:                return xauth_login_pam(port, raddr, usr, pwd);
                   1695: 
                   1696:        len = sizeof(*msg) 
                   1697:            + sizeof(port)
                   1698:            + sizeof(isakmp_cfg_config.pool_size)
                   1699:            + sysdep_sa_len(raddr) 
                   1700:            + strlen(usr) + 1
                   1701:            + strlen(pwd) + 1;
                   1702: 
                   1703:        if ((msg = racoon_malloc(len)) == NULL) {
                   1704:                plog(LLV_ERROR, LOCATION, NULL, 
                   1705:                    "Cannot allocate memory: %s\n", strerror(errno));
                   1706:                return -1;
                   1707:        }
                   1708:        bzero(msg, len);
                   1709:        msg->hdr.ac_cmd = PRIVSEP_XAUTH_LOGIN_PAM;
                   1710:        msg->hdr.ac_len = len;
                   1711:        msg->bufs.buflen[0] = sizeof(port);
                   1712:        msg->bufs.buflen[1] = sizeof(isakmp_cfg_config.pool_size);
                   1713:        msg->bufs.buflen[2] = sysdep_sa_len(raddr);
                   1714:        msg->bufs.buflen[3] = strlen(usr) + 1;
                   1715:        msg->bufs.buflen[4] = strlen(pwd) + 1;
                   1716: 
                   1717:        data = (char *)(msg + 1);
                   1718:        memcpy(data, &port, msg->bufs.buflen[0]);
                   1719: 
                   1720:        data += msg->bufs.buflen[0];
                   1721:        memcpy(data, &isakmp_cfg_config.pool_size, msg->bufs.buflen[1]);
                   1722: 
                   1723:        data += msg->bufs.buflen[1];
                   1724:        memcpy(data, raddr, msg->bufs.buflen[2]);
                   1725: 
                   1726:        data += msg->bufs.buflen[2];
                   1727:        memcpy(data, usr, msg->bufs.buflen[3]);
                   1728: 
                   1729:        data += msg->bufs.buflen[3];
                   1730:        memcpy(data, pwd, msg->bufs.buflen[4]);
                   1731: 
                   1732:        /* frees msg */
                   1733:        if (privsep_send(privsep_sock[1], msg, len) != 0)
                   1734:                return -1;
                   1735: 
                   1736:        if (privsep_recv(privsep_sock[1], &msg, &len) != 0)
                   1737:                return -1;
                   1738: 
                   1739:        if (msg->hdr.ac_errno != 0) {
                   1740:                errno = msg->hdr.ac_errno;
                   1741:                goto out;
                   1742:        }
                   1743: 
                   1744:        racoon_free(msg);
                   1745:        return 0;
                   1746: 
                   1747: out:
                   1748:        racoon_free(msg);
                   1749:        return -1;
                   1750: }
                   1751: 
                   1752: void
                   1753: privsep_cleanup_pam(port)
                   1754:        int port;
                   1755: {
                   1756:        struct privsep_com_msg *msg;
                   1757:        size_t len;
                   1758:        char *data;
                   1759:        int result;
                   1760: 
                   1761:        if (geteuid() == 0)
                   1762:                return cleanup_pam(port);
                   1763: 
                   1764:        len = sizeof(*msg) 
                   1765:            + sizeof(port)
                   1766:            + sizeof(isakmp_cfg_config.pool_size);
                   1767: 
                   1768:        if ((msg = racoon_malloc(len)) == NULL) {
                   1769:                plog(LLV_ERROR, LOCATION, NULL, 
                   1770:                    "Cannot allocate memory: %s\n", strerror(errno));
                   1771:                return;
                   1772:        }
                   1773:        bzero(msg, len);
                   1774:        msg->hdr.ac_cmd = PRIVSEP_CLEANUP_PAM;
                   1775:        msg->hdr.ac_len = len;
                   1776:        msg->bufs.buflen[0] = sizeof(port);
                   1777:        msg->bufs.buflen[1] = sizeof(isakmp_cfg_config.pool_size);
                   1778: 
                   1779:        data = (char *)(msg + 1);
                   1780:        memcpy(data, &port, msg->bufs.buflen[0]);
                   1781: 
                   1782:        data += msg->bufs.buflen[0];
                   1783:        memcpy(data, &isakmp_cfg_config.pool_size, msg->bufs.buflen[1]);
                   1784: 
                   1785:        /* frees msg */
                   1786:        if (privsep_send(privsep_sock[1], msg, len) != 0)
                   1787:                return;
                   1788: 
                   1789:        if (privsep_recv(privsep_sock[1], &msg, &len) != 0)
                   1790:                return;
                   1791: 
                   1792:        if (msg->hdr.ac_errno != 0)
                   1793:                errno = msg->hdr.ac_errno;
                   1794: 
                   1795:        racoon_free(msg);
                   1796:        return;
                   1797: }
                   1798: #endif

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