Annotation of embedaddon/ipsec-tools/src/libipsec/ipsec_dump_policy.c, revision 1.1

1.1     ! misho       1: /*     $NetBSD: ipsec_dump_policy.c,v 1.9 2010/12/03 15:01:11 tteras Exp $     */
        !             2: 
        !             3: /* Id: ipsec_dump_policy.c,v 1.10 2005/06/29 09:12:37 manubsd Exp */
        !             4: 
        !             5: /*
        !             6:  * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
        !             7:  * All rights reserved.
        !             8:  *
        !             9:  * Redistribution and use in source and binary forms, with or without
        !            10:  * modification, are permitted provided that the following conditions
        !            11:  * are met:
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  * 2. Redistributions in binary form must reproduce the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer in the
        !            16:  *    documentation and/or other materials provided with the distribution.
        !            17:  * 3. Neither the name of the project nor the names of its contributors
        !            18:  *    may be used to endorse or promote products derived from this software
        !            19:  *    without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
        !            22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
        !            25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            31:  * SUCH DAMAGE.
        !            32:  */
        !            33: 
        !            34: #ifdef HAVE_CONFIG_H
        !            35: #include "config.h"
        !            36: #endif
        !            37: 
        !            38: #include <sys/types.h>
        !            39: #include <sys/param.h>
        !            40: #include <sys/socket.h>
        !            41: 
        !            42: #include <netinet/in.h>
        !            43: #include PATH_IPSEC_H
        !            44: 
        !            45: #include <arpa/inet.h>
        !            46: 
        !            47: #include <stdio.h>
        !            48: #include <stdlib.h>
        !            49: #include <string.h>
        !            50: #include <netdb.h>
        !            51: 
        !            52: #include "ipsec_strerror.h"
        !            53: #include "libpfkey.h"
        !            54: 
        !            55: static const char *ipsp_dir_strs[] = {
        !            56:        "any", "in", "out", "fwd",
        !            57: #ifdef __linux__
        !            58:        "in(socket)", "out(socket)"
        !            59: #endif
        !            60: };
        !            61: 
        !            62: static const char *ipsp_policy_strs[] = {
        !            63:        "discard", "none", "ipsec", "entrust", "bypass",
        !            64: };
        !            65: 
        !            66: static char *ipsec_dump_ipsecrequest __P((char *, size_t,
        !            67:        struct sadb_x_ipsecrequest *, size_t, int));
        !            68: static char *ipsec_dump_policy1 __P((void *, const char *, int));
        !            69: static int set_addresses __P((char *, size_t, struct sockaddr *,
        !            70:        struct sockaddr *, int));
        !            71: static char *set_address __P((char *, size_t, struct sockaddr *, int));
        !            72: 
        !            73: /*
        !            74:  * policy is sadb_x_policy buffer.
        !            75:  * Must call free() later.
        !            76:  * When delimiter == NULL, alternatively ' '(space) is applied.
        !            77:  */
        !            78: char *
        !            79: ipsec_dump_policy(policy, delimiter)
        !            80:        ipsec_policy_t policy;
        !            81:        __ipsec_const char *delimiter;
        !            82: {
        !            83:        return ipsec_dump_policy1(policy, delimiter, 0);
        !            84: }
        !            85: 
        !            86: char *
        !            87: ipsec_dump_policy_withports(policy, delimiter)
        !            88:        void *policy;
        !            89:        const char *delimiter;
        !            90: {
        !            91:        return ipsec_dump_policy1(policy, delimiter, 1);
        !            92: }
        !            93: 
        !            94: static char *
        !            95: ipsec_dump_policy1(policy, delimiter, withports)
        !            96:        void *policy;
        !            97:        const char *delimiter;
        !            98:        int withports;
        !            99: {
        !           100:        struct sadb_x_policy *xpl = policy;
        !           101:        struct sadb_x_ipsecrequest *xisr;
        !           102:        size_t off, buflen;
        !           103:        char *buf;
        !           104:        char isrbuf[1024];
        !           105:        char *newbuf;
        !           106: 
        !           107: #ifdef HAVE_PFKEY_POLICY_PRIORITY
        !           108:        int32_t priority_offset;
        !           109:        char *priority_str;
        !           110:        char operator;
        !           111: #endif
        !           112: 
        !           113:        /* sanity check */
        !           114:        if (policy == NULL)
        !           115:                return NULL;
        !           116:        if (xpl->sadb_x_policy_exttype != SADB_X_EXT_POLICY) {
        !           117:                __ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
        !           118:                return NULL;
        !           119:        }
        !           120: 
        !           121:        /* set delimiter */
        !           122:        if (delimiter == NULL)
        !           123:                delimiter = " ";
        !           124: 
        !           125: #ifdef HAVE_PFKEY_POLICY_PRIORITY
        !           126:        if (xpl->sadb_x_policy_priority == 0)
        !           127:        {
        !           128:                priority_offset = 0;
        !           129:                priority_str = "";
        !           130:        }
        !           131:        /* find which constant the priority is closest to */
        !           132:        else if (xpl->sadb_x_policy_priority < 
        !           133:                 (u_int32_t) (PRIORITY_DEFAULT / 4) * 3)
        !           134:        {
        !           135:                priority_offset = xpl->sadb_x_policy_priority - PRIORITY_HIGH;
        !           136:                priority_str = "prio high";
        !           137:        }
        !           138:        else if (xpl->sadb_x_policy_priority >= 
        !           139:                 (u_int32_t) (PRIORITY_DEFAULT / 4) * 3 &&
        !           140:                 xpl->sadb_x_policy_priority < 
        !           141:                 (u_int32_t) (PRIORITY_DEFAULT / 4) * 5)
        !           142:        {
        !           143:                priority_offset = xpl->sadb_x_policy_priority - PRIORITY_DEFAULT;
        !           144:                priority_str = "prio def";
        !           145:        }
        !           146:        else
        !           147:        {
        !           148:                priority_offset = xpl->sadb_x_policy_priority - PRIORITY_LOW;
        !           149:                priority_str = "prio low";
        !           150:        }
        !           151: 
        !           152:        /* fix sign to match the way it is input */
        !           153:        priority_offset *= -1;
        !           154:        if (priority_offset < 0)
        !           155:        {
        !           156:                operator = '-';
        !           157:                priority_offset *= -1;
        !           158:        }
        !           159:        else
        !           160:        {
        !           161:                operator = '+';
        !           162:        }
        !           163: #endif
        !           164:        
        !           165:        switch (xpl->sadb_x_policy_dir) {
        !           166:        case IPSEC_DIR_ANY:
        !           167:        case IPSEC_DIR_INBOUND:
        !           168:        case IPSEC_DIR_OUTBOUND:
        !           169: #ifdef HAVE_POLICY_FWD
        !           170:        case IPSEC_DIR_FWD:
        !           171:        case IPSEC_DIR_FWD + 1:
        !           172:        case IPSEC_DIR_FWD + 2:
        !           173: #endif
        !           174:                break;
        !           175:        default:
        !           176:                __ipsec_errcode = EIPSEC_INVAL_DIR;
        !           177:                return NULL;
        !           178:        }
        !           179: 
        !           180:        switch (xpl->sadb_x_policy_type) {
        !           181:        case IPSEC_POLICY_DISCARD:
        !           182:        case IPSEC_POLICY_NONE:
        !           183:        case IPSEC_POLICY_IPSEC:
        !           184:        case IPSEC_POLICY_BYPASS:
        !           185:        case IPSEC_POLICY_ENTRUST:
        !           186:                break;
        !           187:        default:
        !           188:                __ipsec_errcode = EIPSEC_INVAL_POLICY;
        !           189:                return NULL;
        !           190:        }
        !           191: 
        !           192:        buflen = strlen(ipsp_dir_strs[xpl->sadb_x_policy_dir])
        !           193:                + 1     /* space */
        !           194: #ifdef HAVE_PFKEY_POLICY_PRIORITY
        !           195:                + strlen(priority_str)
        !           196:                + ((priority_offset != 0) ? 13 : 0) /* [space operator space int] */
        !           197:                + ((strlen(priority_str) != 0) ? 1 : 0) /* space */
        !           198: #endif
        !           199:                + strlen(ipsp_policy_strs[xpl->sadb_x_policy_type])
        !           200:                + 1;    /* NUL */
        !           201: 
        !           202:        if ((buf = malloc(buflen)) == NULL) {
        !           203:                __ipsec_errcode = EIPSEC_NO_BUFS;
        !           204:                return NULL;
        !           205:        }
        !           206: #ifdef HAVE_PFKEY_POLICY_PRIORITY
        !           207:        if (priority_offset != 0)
        !           208:        {
        !           209:                snprintf(buf, buflen, "%s %s %c %u %s", 
        !           210:                ipsp_dir_strs[xpl->sadb_x_policy_dir], priority_str, operator, 
        !           211:                        priority_offset, ipsp_policy_strs[xpl->sadb_x_policy_type]);
        !           212:        }
        !           213:        else if (strlen (priority_str) != 0)
        !           214:        {
        !           215:                snprintf(buf, buflen, "%s %s %s", 
        !           216:                ipsp_dir_strs[xpl->sadb_x_policy_dir], priority_str, 
        !           217:                        ipsp_policy_strs[xpl->sadb_x_policy_type]);
        !           218:        }
        !           219:        else
        !           220:        {
        !           221:                snprintf(buf, buflen, "%s %s", 
        !           222:                ipsp_dir_strs[xpl->sadb_x_policy_dir],
        !           223:                        ipsp_policy_strs[xpl->sadb_x_policy_type]);
        !           224:        }
        !           225: #else
        !           226:        snprintf(buf, buflen, "%s %s", ipsp_dir_strs[xpl->sadb_x_policy_dir],
        !           227:            ipsp_policy_strs[xpl->sadb_x_policy_type]);
        !           228: #endif
        !           229: 
        !           230:        if (xpl->sadb_x_policy_type != IPSEC_POLICY_IPSEC) {
        !           231:                __ipsec_errcode = EIPSEC_NO_ERROR;
        !           232:                return buf;
        !           233:        }
        !           234: 
        !           235:        /* count length of buffer for use */
        !           236:        off = sizeof(*xpl);
        !           237:        while (off < PFKEY_EXTLEN(xpl)) {
        !           238:                xisr = (void *)((caddr_t)(void *)xpl + off);
        !           239:                off += xisr->sadb_x_ipsecrequest_len;
        !           240:        }
        !           241: 
        !           242:        /* validity check */
        !           243:        if (off != PFKEY_EXTLEN(xpl)) {
        !           244:                __ipsec_errcode = EIPSEC_INVAL_SADBMSG;
        !           245:                free(buf);
        !           246:                return NULL;
        !           247:        }
        !           248: 
        !           249:        off = sizeof(*xpl);
        !           250:        while (off < PFKEY_EXTLEN(xpl)) {
        !           251:                int offset;
        !           252:                xisr = (void *)((caddr_t)(void *)xpl + off);
        !           253: 
        !           254:                if (ipsec_dump_ipsecrequest(isrbuf, sizeof(isrbuf), xisr,
        !           255:                    PFKEY_EXTLEN(xpl) - off, withports) == NULL) {
        !           256:                        free(buf);
        !           257:                        return NULL;
        !           258:                }
        !           259: 
        !           260:                offset = strlen(buf);
        !           261:                buflen = offset + strlen(delimiter) + strlen(isrbuf) + 1;
        !           262:                newbuf = (char *)realloc(buf, buflen);
        !           263:                if (newbuf == NULL) {
        !           264:                        __ipsec_errcode = EIPSEC_NO_BUFS;
        !           265:                        free(buf);
        !           266:                        return NULL;
        !           267:                }
        !           268:                buf = newbuf;
        !           269:                snprintf(buf+offset, buflen-offset, "%s%s", delimiter, isrbuf);
        !           270: 
        !           271:                off += xisr->sadb_x_ipsecrequest_len;
        !           272:        }
        !           273: 
        !           274:        __ipsec_errcode = EIPSEC_NO_ERROR;
        !           275:        return buf;
        !           276: }
        !           277: 
        !           278: static char *
        !           279: ipsec_dump_ipsecrequest(buf, len, xisr, bound, withports)
        !           280:        char *buf;
        !           281:        size_t len;
        !           282:        struct sadb_x_ipsecrequest *xisr;
        !           283:        size_t bound;   /* boundary */
        !           284:        int withports;
        !           285: {
        !           286:        const char *proto, *mode, *level;
        !           287:        char abuf[NI_MAXHOST * 2 + 2];
        !           288: 
        !           289:        if (xisr->sadb_x_ipsecrequest_len > bound) {
        !           290:                __ipsec_errcode = EIPSEC_INVAL_PROTO;
        !           291:                return NULL;
        !           292:        }
        !           293: 
        !           294:        switch (xisr->sadb_x_ipsecrequest_proto) {
        !           295:        case IPPROTO_ESP:
        !           296:                proto = "esp";
        !           297:                break;
        !           298:        case IPPROTO_AH:
        !           299:                proto = "ah";
        !           300:                break;
        !           301:        case IPPROTO_IPCOMP:
        !           302:                proto = "ipcomp";
        !           303:                break;
        !           304:        default:
        !           305:                __ipsec_errcode = EIPSEC_INVAL_PROTO;
        !           306:                return NULL;
        !           307:        }
        !           308: 
        !           309:        switch (xisr->sadb_x_ipsecrequest_mode) {
        !           310:        case IPSEC_MODE_ANY:
        !           311:                mode = "any";
        !           312:                break;
        !           313:        case IPSEC_MODE_TRANSPORT:
        !           314:                mode = "transport";
        !           315:                break;
        !           316:        case IPSEC_MODE_TUNNEL:
        !           317:                mode = "tunnel";
        !           318:                break;
        !           319:        default:
        !           320:                __ipsec_errcode = EIPSEC_INVAL_MODE;
        !           321:                return NULL;
        !           322:        }
        !           323: 
        !           324:        abuf[0] = '\0';
        !           325:        if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) {
        !           326:                struct sockaddr *sa1, *sa2;
        !           327:                caddr_t p;
        !           328: 
        !           329:                p = (void *)(xisr + 1);
        !           330:                sa1 = (void *)p;
        !           331:                sa2 = (void *)(p + sysdep_sa_len(sa1));
        !           332:                if (sizeof(*xisr) + sysdep_sa_len(sa1) + sysdep_sa_len(sa2) !=
        !           333:                    xisr->sadb_x_ipsecrequest_len) {
        !           334:                        __ipsec_errcode = EIPSEC_INVAL_ADDRESS;
        !           335:                        return NULL;
        !           336:                }
        !           337:                if (set_addresses(abuf, sizeof(abuf), 
        !           338:                    sa1, sa2, withports) != 0) {
        !           339:                        __ipsec_errcode = EIPSEC_INVAL_ADDRESS;
        !           340:                        return NULL;
        !           341:                }
        !           342:        }
        !           343: 
        !           344:        switch (xisr->sadb_x_ipsecrequest_level) {
        !           345:        case IPSEC_LEVEL_DEFAULT:
        !           346:                level = "default";
        !           347:                break;
        !           348:        case IPSEC_LEVEL_USE:
        !           349:                level = "use";
        !           350:                break;
        !           351:        case IPSEC_LEVEL_REQUIRE:
        !           352:                level = "require";
        !           353:                break;
        !           354:        case IPSEC_LEVEL_UNIQUE:
        !           355:                level = "unique";
        !           356:                break;
        !           357:        default:
        !           358:                __ipsec_errcode = EIPSEC_INVAL_LEVEL;
        !           359:                return NULL;
        !           360:        }
        !           361: 
        !           362:        if (xisr->sadb_x_ipsecrequest_reqid == 0)
        !           363:                snprintf(buf, len, "%s/%s/%s/%s", proto, mode, abuf, level);
        !           364:        else {
        !           365:                int ch;
        !           366: 
        !           367:                if (xisr->sadb_x_ipsecrequest_reqid > IPSEC_MANUAL_REQID_MAX)
        !           368:                        ch = '#';
        !           369:                else
        !           370:                        ch = ':';
        !           371:                snprintf(buf, len, "%s/%s/%s/%s%c%u", proto, mode, abuf, level,
        !           372:                    ch, xisr->sadb_x_ipsecrequest_reqid);
        !           373:        }
        !           374: 
        !           375:        return buf;
        !           376: }
        !           377: 
        !           378: static int
        !           379: set_addresses(buf, len, sa1, sa2, withports)
        !           380:        char *buf;
        !           381:        size_t len;
        !           382:        struct sockaddr *sa1;
        !           383:        struct sockaddr *sa2;
        !           384:        int withports;
        !           385: {
        !           386:        char tmp1[NI_MAXHOST], tmp2[NI_MAXHOST];
        !           387: 
        !           388:        if (set_address(tmp1, sizeof(tmp1), sa1, withports) == NULL ||
        !           389:            set_address(tmp2, sizeof(tmp2), sa2, withports) == NULL)
        !           390:                return -1;
        !           391:        if (strlen(tmp1) + 1 + strlen(tmp2) + 1 > len)
        !           392:                return -1;
        !           393:        snprintf(buf, len, "%s-%s", tmp1, tmp2);
        !           394:        return 0;
        !           395: }
        !           396: 
        !           397: static char *
        !           398: set_address(buf, len, sa, withports)
        !           399:        char *buf;
        !           400:        size_t len;
        !           401:        struct sockaddr *sa;
        !           402:        int withports;
        !           403: {
        !           404:        const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
        !           405:        char host[NI_MAXHOST];
        !           406:        char serv[NI_MAXSERV];
        !           407: 
        !           408:        if (len < 1)
        !           409:                return NULL;
        !           410:        buf[0] = '\0';
        !           411:        if (getnameinfo(sa, (socklen_t)sysdep_sa_len(sa), host, sizeof(host), 
        !           412:            serv, sizeof(serv), niflags) != 0)
        !           413:                return NULL;
        !           414: 
        !           415:        if (withports)
        !           416:                snprintf(buf, len, "%s[%s]", host, serv);
        !           417:        else
        !           418:                snprintf(buf, len, "%s", host);
        !           419: 
        !           420:        return buf;
        !           421: }

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