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