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