Annotation of embedaddon/freevrrpd/vrrp_ah.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (c) 2003 BurnesOnLine <bol@b0l.org>
                      3:  *
                      4:  * Redistribution and use in source forms, with and without modification,
                      5:  * are permitted provided that the following conditions are met:
                      6:  * 1. Redistributions of source code must retain the above copyright notice,
                      7:  *    this list of conditions and the following disclaimer.
                      8:  * 2. Redistributions in binary form must reproduce the above copyright notice,
                      9:  *    this list of conditions and the following disclaimer in the documentation
                     10:  *    and/or other materials provided with the distribution. Obviously, it
                     11:  *    would be nice if you gave credit where credit is due but requiring it
                     12:  *    would be too onerous.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *      This product includes software developed by Sebastien Petit.
                     16:  * 4. Neither the name of its contributors may be used to endorse or promote
                     17:  *    products derived from this software without specific prior written
                     18:  *    permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     30:  * SUCH DAMAGE.
                     31:  *
                     32:  * $Id: vrrp_ah.c,v 1.13 2004/04/04 19:45:46 rival Exp $  
                     33:  *
                     34:  * MISC COMMENTS :
                     35:  * FreeVRRPd project AH implementation using KAME based ipsec stack.
                     36:  * tested on :
                     37:  *    FreeBSD
                     38:  *    NetBSD
                     39:  * should work on :
                     40:  *    Linux 2.6 or KAME based linux ipsec stack
                     41:  *
                     42:  * this code use KAME not fully implemented :
                     43:  * RFC 2367 - PF_KEY Key Management API, Version 2
                     44:  *
                     45:  * AUTHORS:
                     46:  * this is a working and almost clean "HACK"  :)
                     47:  * problem is, we cant set socket wide SPD and SAD
                     48:  * need to work out with KAME project to know exactly 
                     49:  * the procedure to make process wide changes and NOT
                     50:  * host wide changes.
                     51:  *
                     52:  * b0l.
                     53:  * 
                     54:  */
                     55: #include "vrrp_proto.h"
                     56: #include "vrrp_ah.h"
                     57: #include "md5.h"
                     58: 
                     59: #ifdef ENABLE_VRRP_AH
                     60: #ifdef KAME_BASED
                     61: /* special struct */
                     62: typedef enum {
                     63:     HMAC_MD5 = 2,            /* 128 bits */
                     64:     HMAC_SHA1 = 3,           /* 160 bits */
                     65:     HMAC_NULL,
                     66:     HMAC_SHA2_256,           /* 256 bits */
                     67:     HMAC_SHA2_384,           /* 384 bits */
                     68:     HMAC_SHA2_512,           /* 512 bits */
                     69:     HMAC_RIPEMD160,          /* 160 bits */
                     70:     AES_XCBC_MAC             /* 128 bits */
                     71: } alg_t;
                     72: 
                     73: typedef struct algorithm {
                     74:     alg_t type;
                     75:     size_t keysize;
                     76: } algorithm_t;
                     77: 
                     78: algorithm_t algos[] = {
                     79:     { HMAC_MD5, 128 },
                     80:     { HMAC_SHA1, 160 },
                     81:     { HMAC_NULL, 0 },
                     82:     { HMAC_SHA2_256, 256 },
                     83:     { HMAC_SHA2_384, 384 },
                     84:     { HMAC_SHA2_512, 512 },
                     85:     { HMAC_RIPEMD160, 160 },
                     86:     { AES_XCBC_MAC, 128 }
                     87: };
                     88: 
                     89: /* what we need 
                     90:    ipsec (4)
                     91:    setsockopt(2)  * per socket behavior *
                     92:    sysctl(3) * host wide *
                     93:    ipsec_set_policy(3) * IPsec Policy Control Library (libipsec, -lipsec) *
                     94:    */
                     95: 
                     96: /* STOLEN FROM FreeBSD setkey.c :) */
                     97: struct addrinfo * parse_addr(char *host, char *port) {
                     98:        struct addrinfo hints, *res = NULL;
                     99:        int error;
                    100: 
                    101:        memset(&hints, 0, sizeof(hints));
                    102:        hints.ai_family = PF_UNSPEC;
                    103:        hints.ai_socktype = SOCK_DGRAM;         /*dummy*/
                    104:        hints.ai_protocol = IPPROTO_UDP;        /*dummy*/
                    105:        hints.ai_flags = 0;
                    106:        error = getaddrinfo(host, port, &hints, &res);
                    107:        if (error != 0) {
                    108:                perror(gai_strerror(error));
                    109:                return NULL;
                    110:        }
                    111:        return res;
                    112: }
                    113: 
                    114: int setkeymsg(struct sadb_msg *msg, unsigned int type, unsigned int satype, size_t l) {
                    115: 
                    116:        msg->sadb_msg_version = PF_KEY_V2;
                    117:        msg->sadb_msg_type = type;
                    118:        msg->sadb_msg_errno = 0;
                    119:        msg->sadb_msg_satype = satype;
                    120:        msg->sadb_msg_reserved = 0;
                    121:        msg->sadb_msg_seq = 0;
                    122:        msg->sadb_msg_pid = getpid();
                    123:        msg->sadb_msg_len = PFKEY_UNIT64(l);
                    124:        return 0;
                    125: }
                    126: 
                    127: int setvarbuf(char *buf, int *off, struct sadb_ext *ebuf, int elen, caddr_t vbuf, int vlen) {
                    128:        memset(buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len));
                    129:        memcpy(buf + *off, (caddr_t)ebuf, elen);
                    130:        memcpy(buf + *off + elen, vbuf, vlen);
                    131:        (*off) += PFKEY_ALIGN8(elen + vlen);
                    132:        return 0;
                    133: }
                    134: 
                    135: /* WE NEED :
                    136: setkeymsg_spdaddr(type, upper, policy, srcs, splen, dsts, dplen)
                    137: */
                    138: 
                    139: /* open the PF_KEY socket */
                    140: int vrrp_pfkey_open(void) {
                    141:     int key_fd;
                    142: 
                    143:     /* opening PF_KEY API */
                    144:     key_fd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
                    145:     if (key_fd < 0) {
                    146:        perror("socket(PF_KEY)");
                    147:        return key_fd;
                    148:     }
                    149: 
                    150:     return key_fd;
                    151: }
                    152: 
                    153: /* close PF_KEY socket */
                    154: int vrrp_pfkey_close(int fd) {
                    155:     int rc = 0;
                    156:     rc = close(fd);
                    157:     return rc;
                    158: }
                    159: 
                    160: /* return -1 on failure, 0 on success */
                    161: int vrrp_ah_set_outpolicy(int fd, char *src) {
                    162:     int rc = 0;
                    163: 
                    164:     rc = vrrp_ah_spd(fd, src, VRRP_OUT_POLICY, SADB_X_SPDADD);
                    165:     if (rc < 0) {
                    166:        perror("VRRP_OUT_POLICY setup failed!\n");
                    167:        rc = -1;
                    168:     }
                    169:     return rc;
                    170: }
                    171: 
                    172: /* return -1 on failure, 0 on success */
                    173: int vrrp_ah_rm_outpolicy(int fd, char *src) {
                    174:     int rc = 0;
                    175: 
                    176:     rc = vrrp_ah_spd(fd, src, VRRP_OUT_POLICY, SADB_X_SPDDELETE);
                    177:     if (rc < 0) {
                    178:        perror("VRRP_OUT_POLICY removal failed\n");
                    179:        rc = -1;
                    180:     }
                    181:     return rc;
                    182: }
                    183: 
                    184: /* return -1 on failure, 0 on success */
                    185: int vrrp_ah_set_inpolicy(int fd, char *src) {
                    186:     int rc = 0;
                    187: 
                    188:     rc = vrrp_ah_spd(fd, src, VRRP_IN_POLICY, SADB_X_SPDADD);
                    189:     if (rc < 0) {
                    190:        perror("VRRP_IN_POLICY setup failed\n");
                    191:        rc = -1;
                    192:     }
                    193:     return rc;
                    194: }
                    195: 
                    196: /* return -1 on failure, 0 on success */
                    197: int vrrp_ah_rm_inpolicy(int fd, char *src) {
                    198:     int rc = 0;
                    199: 
                    200:     rc = vrrp_ah_spd(fd, src, VRRP_IN_POLICY, SADB_X_SPDDELETE);
                    201:     if (rc < 0) {
                    202:        perror("VRRP_IN_POLICY setup failed\n");
                    203:        rc = -1;
                    204:     }
                    205:     return rc;
                    206: }
                    207: 
                    208: /* return number of bytes sent to PF_KEY socket/in-kernel */
                    209: int vrrp_ah_spd(int fd, char *src_addr, char *ah_policy, unsigned int cmd) {
                    210:     /* lets see if it works */
                    211:     char *policy;
                    212:     int policy_len;
                    213:     const int bufsiz = 128 * 1024;
                    214:     char * buf = (char *) malloc (bufsiz * sizeof(char));
                    215:     struct sadb_msg *msg;
                    216:     struct sadb_address m_addr;
                    217:     struct sockaddr *sa; 
                    218:     struct addrinfo *src, *dst;
                    219:     int m_size;
                    220:     int salen;
                    221:     int rc;
                    222: 
                    223:     /* sanity checks */
                    224:     if (!buf) {
                    225:        fprintf(stderr,"could not allocate memory\n");
                    226:        return -1;
                    227:     }
                    228: 
                    229:     /* prepare the policy */
                    230:     policy = ipsec_set_policy(VRRP_OUT_POLICY, strlen(VRRP_OUT_POLICY));
                    231:     if (!policy) {
                    232:        perror("ipsec_set_policy()");
                    233:        return -1;
                    234:     }
                    235: 
                    236:     policy_len = ipsec_get_policylen(policy);
                    237:     if (policy_len < 0) {
                    238:        perror("ipsec_get_policylen()");
                    239:        return -1;
                    240:     }
                    241: 
                    242:     /* clearing everything, don't want this bugs to happen again */
                    243:     memset(buf,0,bufsiz);
                    244:     memset(&m_addr, 0, sizeof(m_addr));
                    245: 
                    246:     /* building PF_KEY msg */
                    247:     msg = (struct sadb_msg *) buf;
                    248:     setkeymsg(msg,(unsigned int)cmd,SADB_SATYPE_UNSPEC, 0);
                    249:     m_size = sizeof(struct sadb_msg);
                    250: 
                    251:     /* copying the policy */
                    252:     memcpy(buf+m_size, policy, policy_len);
                    253:     m_size += policy_len;
                    254: 
                    255:     /* parsing from / to */
                    256:     src = parse_addr(src_addr, 0);
                    257:     if (!src) {
                    258:        free(policy);
                    259:        free(buf);
                    260:        return -1;
                    261:     }
                    262: 
                    263:     dst = parse_addr(VRRP_ADDRESS, 0);
                    264:     if (!dst) {
                    265:        free(policy);
                    266:        freeaddrinfo(src);
                    267:        free(buf);
                    268:        return -1;
                    269:     }
                    270: 
                    271:     /* SOURCE SETUP */
                    272:     sa = src->ai_addr;
                    273:     salen = src->ai_addr->sa_len;
                    274:     m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr)+PFKEY_ALIGN8(salen));
                    275:     m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
                    276:     m_addr.sadb_address_proto = (unsigned int)IPSEC_IPPROTO_ANY;
                    277:     m_addr.sadb_address_prefixlen = HOST_MASK; 
                    278:     m_addr.sadb_address_reserved = 0;
                    279: 
                    280:     setvarbuf(buf, &m_size, (struct sadb_ext *)&m_addr,sizeof(m_addr),(caddr_t)sa, salen);
                    281: 
                    282:     /* DESTINATION SETUP */
                    283:     sa = dst->ai_addr;
                    284:     salen = src->ai_addr->sa_len;
                    285:     m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr)+PFKEY_ALIGN8(salen));
                    286:     m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
                    287:     m_addr.sadb_address_proto = (unsigned int)IPSEC_IPPROTO_ANY;
                    288:     m_addr.sadb_address_prefixlen = HOST_MASK; /* (splen >= 0 ? -1 : plen ); */
                    289:     m_addr.sadb_address_reserved = 0;
                    290: 
                    291:     setvarbuf(buf, &m_size, (struct sadb_ext *)&m_addr,sizeof(m_addr),(caddr_t)sa, salen);
                    292: 
                    293:     msg->sadb_msg_len = PFKEY_UNIT64(m_size);
                    294: 
                    295:     (void)setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz));
                    296:     (void)setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz));
                    297: 
                    298:     rc = send(fd, buf, m_size, 0);
                    299:     if (rc < 0)
                    300:        perror("could not add entry to SPD: send()");
                    301: 
                    302:     free(policy);
                    303:     free(buf);
                    304:     freeaddrinfo(src);
                    305:     freeaddrinfo(dst);
                    306:     return rc;
                    307: }
                    308: 
                    309: 
                    310: 
                    311: /* status = setkeymsg_add(SADB_ADD, $5, $3, $4); */
                    312: /* DO NOT FORGET TO CLEAN THOSE FUKING LOCAL STRUCTURE 2 DAYS LOST $#@$!@#$#@!
                    313:  * */
                    314: int vrrp_ah_sad(int fd, char *src_addr, alg_t algo, char *key) {
                    315:     const int bufsiz = 128 * 1024;
                    316:     char * buf = (char *) malloc (bufsiz * sizeof(char));
                    317:     struct sadb_msg *msg;
                    318:     struct sadb_address m_addr;
                    319:     struct sockaddr *sa; 
                    320:     struct addrinfo *src, *dst, *s;
                    321:     int m_size;
                    322:     int salen;
                    323:     int rc;
                    324:     /* ADDED */
                    325:     int len;
                    326:     char * p_alg_auth = "hmac-sha1";
                    327:     char * p_key_auth = "12345678901234567890";
                    328:     int p_key_auth_len = strlen(p_key_auth);
                    329:     struct sadb_key m_key;
                    330:     struct sadb_sa m_sa;
                    331:     struct sadb_x_sa2 m_sa2;
                    332:     struct sadb_lifetime m_lt;
                    333: 
                    334:     msg = (struct sadb_msg *) buf;
                    335: 
                    336:     /* clearing the allocated data */
                    337:     memset(buf,0,bufsiz);
                    338: 
                    339:     setkeymsg(msg, SADB_ADD, SADB_SATYPE_AH, 0);
                    340:     /* setkeymsg(msg, SADB_DELETE, SADB_SATYPE_AH, 0); */
                    341: 
                    342:     m_size = sizeof(struct sadb_msg);
                    343:     /* HACK HACK */
                    344:     /* hexdump(msg,m_size); */
                    345: 
                    346:     m_key.sadb_key_len = PFKEY_UNIT64(sizeof(m_key) + PFKEY_ALIGN8(p_key_auth_len));
                    347:     m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
                    348:     m_key.sadb_key_bits = p_key_auth_len * 8;
                    349:     m_key.sadb_key_reserved = 0;
                    350:     
                    351:     setvarbuf(buf, &m_size, (struct sadb_ext *)&m_key,sizeof(m_key),(caddr_t)p_key_auth, p_key_auth_len);
                    352: 
                    353:     /*
                    354:     u_int slen = sizeof(struct sadb_lifetime);
                    355:     m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
                    356:     m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
                    357:     m_lt.sadb_lifetime_allocations = 0;
                    358:     m_lt.sadb_lifetime_bytes = 0;
                    359:     m_lt.sadb_lifetime_addtime = 0;
                    360:     m_lt.sadb_lifetime_usetime = 0;
                    361: 
                    362:     memcpy(buf + m_size, &m_lt, slen);
                    363:     m_size += slen; 
                    364:     */
                    365: 
                    366:     /*
                    367:     m_key.sadb_key_len = PFKEY_UNIT64(sizeof(m_key) + PFKEY_ALIGN8(p_key_auth_len));
                    368:     m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
                    369:     m_key.sadb_key_bits = p_key_auth_len * 8;
                    370:     m_key.sadb_key_reserved = 0;
                    371: 
                    372:     setvarbuf(buf, &m_size, (struct sadb_ext *)&m_key, sizeof(m_key), (caddr_t)p_key_auth, p_key_auth_len);
                    373:     */
                    374: 
                    375:     len = sizeof(struct sadb_sa);
                    376:     m_sa.sadb_sa_len = PFKEY_UNIT64(len);
                    377:     m_sa.sadb_sa_exttype = SADB_EXT_SA;
                    378:     m_sa.sadb_sa_spi = htonl(0x2710);
                    379:     m_sa.sadb_sa_replay = 0;
                    380:     m_sa.sadb_sa_state = 0;
                    381:     m_sa.sadb_sa_auth = 3; /* hmac-sha1 */
                    382:     m_sa.sadb_sa_encrypt = 0; /* no encryption yet */
                    383:     m_sa.sadb_sa_flags = 64; /* BUG HERE */
                    384: 
                    385:     memcpy(buf + m_size, &m_sa, len);
                    386:     m_size += len;
                    387: 
                    388:     bzero(&m_sa2, sizeof(struct sadb_x_sa2));
                    389: 
                    390:     len = sizeof(struct sadb_x_sa2);
                    391:     printf("len: %x  exttype: %x\n",PFKEY_UNIT64(len), SADB_X_EXT_SA2);
                    392:     m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
                    393:     m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
                    394:     m_sa2.sadb_x_sa2_mode = IPSEC_MODE_ANY; 
                    395:     m_sa2.sadb_x_sa2_reqid = 0;
                    396: 
                    397:     memcpy(buf + m_size, &m_sa2, len);
                    398:     m_size += len; 
                    399: 
                    400:     /* parsing from / to */
                    401:     src = parse_addr(src_addr, 0);
                    402:     if (!src) {
                    403:        free(buf);
                    404:        return -1;
                    405:     }
                    406: 
                    407:     dst = parse_addr(VRRP_ADDRESS, 0);
                    408:     if (!dst) {
                    409:        freeaddrinfo(src);
                    410:        free(buf);
                    411:        return -1;
                    412:     }
                    413: 
                    414:     /* SOURCE SETUP */
                    415:     for (s = src; s; s = s->ai_next) {
                    416:        sa = s->ai_addr;
                    417:        salen = s->ai_addr->sa_len; /* POSSIBLE BUG */
                    418:        m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr)+PFKEY_ALIGN8(salen));
                    419:        m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
                    420:        m_addr.sadb_address_proto = (unsigned int)IPSEC_ULPROTO_ANY;
                    421:        m_addr.sadb_address_prefixlen = HOST_MASK; /* (splen >= 0 ? -1 : plen ); */
                    422:        m_addr.sadb_address_reserved = 0; 
                    423:        setvarbuf(buf, &m_size, (struct sadb_ext *)&m_addr,sizeof(m_addr),(caddr_t)sa, salen);
                    424:     }
                    425: 
                    426:     /* DESTINATION SETUP */
                    427:     sa = dst->ai_addr;
                    428:     salen = dst->ai_addr->sa_len;
                    429:     m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr)+PFKEY_ALIGN8(salen));
                    430:     m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
                    431:     m_addr.sadb_address_proto = (unsigned int)IPSEC_ULPROTO_ANY;
                    432:     m_addr.sadb_address_prefixlen = HOST_MASK; /* (splen >= 0 ? -1 : plen ); */
                    433:     m_addr.sadb_address_reserved = 0;
                    434: 
                    435:     setvarbuf(buf, &m_size, (struct sadb_ext *)&m_addr,sizeof(m_addr),(caddr_t)sa, salen);
                    436: 
                    437:     msg->sadb_msg_len = PFKEY_UNIT64(m_size);
                    438: 
                    439:     (void)setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz));
                    440:     (void)setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz));
                    441: 
                    442:     rc = send(fd, buf, m_size, 0);
                    443:     if (rc < 0)
                    444:        perror("could not add entry to SAD: send()");
                    445: 
                    446:     free(buf);
                    447:     freeaddrinfo(src);
                    448:     freeaddrinfo(dst);
                    449:     return rc;
                    450: }
                    451: 
                    452: #else
                    453: /* The simple implementation based on keepalived draft */
                    454: void vrrp_ah_init_ahhdr(unsigned char *buffer, struct vrrp_vr *vr) {
                    455:     struct ip *ip;
                    456:     struct ah_header *ah;
                    457: 
                    458:     ip = (struct ip *) buffer;
                    459:     ah = (struct ah_header *) (buffer+sizeof(struct ip));
                    460:     ah->next = IPPROTO_VRRP;
                    461:     ah->length = 0x04;
                    462:     ah->zero = 0x0000;
                    463:     ah->spi = htonl(vr->vr_if->ip_addrs[0].s_addr);
                    464:     ah->seq = htonl(1);
                    465:     /* clean first */
                    466:     memset(ah->auth,0,sizeof(ah->auth));
                    467: 
                    468:     return;
                    469: }
                    470: 
                    471: void vrrp_ah_hmacmd5(unsigned char *buffer, struct vrrp_vr *vr) {
                    472:     struct ip *ip;
                    473:     struct ah_header *ah;
                    474:     unsigned char md5[16];
                    475: 
                    476:     ip = (struct ip *) buffer;
                    477:     ah = (struct ah_header *) (buffer+sizeof(struct ip));
                    478: 
                    479:     /* clear md5 */
                    480:     memset(md5,0,sizeof(md5));
                    481: 
                    482:     /* hexdump(md5,sizeof(md5)); */
                    483:     /* lets compute digest */
                    484:     hmac_md5(buffer, (sizeof(struct ip)+sizeof(struct ah_header)+sizeof(struct vrrp_hdr)), (unsigned char *)vr->password, strlen(vr->password), md5);
                    485:     /* hexdump(md5,sizeof(md5)); */
                    486: 
                    487:     /* copy it */
                    488:     memcpy(ah->auth, md5, 12);
                    489: 
                    490:     return;
                    491: }
                    492: 
                    493: /* return 0 if packet is valid, -1 else */
                    494: int vrrp_ah_check_ahhdr(char *buffer, struct vrrp_vr *vr) {
                    495:     struct ah_header *ah;
                    496:     unsigned char recv_authdata[HMAC_MD596_SIZE], comp_authdata[HMAC_MD596_SIZE+4];
                    497: 
                    498:     ah = (struct ah_header *) buffer;
                    499:     if (ah->next != IPPROTO_VRRP)
                    500:        return -1;
                    501:     if (ah->length != 0x04)
                    502:        return -1;
                    503:     /*
                    504:     if (ah->seq < vr->ahctx->seq) 
                    505:        return -1;
                    506:     else 
                    507:        vr->ahctx->seq = ah->seq;
                    508:        */
                    509: 
                    510:     /* save auth data and rebuild hmac to see if it match */
                    511:     memcpy(recv_authdata,(caddr_t)ah->auth,HMAC_MD596_SIZE);
                    512:     memset(ah->auth,0, HMAC_MD596_SIZE);
                    513:     hmac_md5((unsigned char *)buffer, sizeof(struct ip)+sizeof(struct ah_header)+sizeof(struct vrrp_hdr), vr->password, strlen(vr->password), comp_authdata);
                    514: 
                    515:     if (memcmp(recv_authdata, comp_authdata, HMAC_MD596_SIZE) == 0)
                    516:        return 0;
                    517: 
                    518:     printf("packet invalid!!!\n");
                    519:     return -1;
                    520: }
                    521: #endif /* end of ifdef KAME_BASED */
                    522: #endif /* endof ENABLE_VRRP_AH */
                    523: 
                    524: 
                    525: int vrrp_ah_ahhdr_len(struct vrrp_vr *vr) {
                    526: #ifdef ENABLE_VRRP_AH
                    527:     if (vr->AHencryption == 1)
                    528:        return (sizeof(struct ah_header));
                    529: #endif
                    530:     return 0;
                    531: }
                    532: 
                    533: 
                    534: /*
                    535: RFC 2104 define this.
                    536: unsigned char*  text;                * pointer to data stream *
                    537: int             text_len;            * length of data stream *
                    538: unsigned char*  key;                 * pointer to authentication key *
                    539: int             key_len;             * length of authentication key *
                    540: caddr_t         digest;              * caller digest to be filled in *
                    541: */
                    542: void hmac_md5(unsigned char *text, int text_len, unsigned char *key, int key_len, caddr_t digest) {
                    543:         MD5_CTX context,tctx;
                    544:         unsigned char k_ipad[65];    /* inner padding - key XORd with ipad */
                    545:         unsigned char k_opad[65];    /* outer padding - key XORd with opad */
                    546:         unsigned char tk[16];
                    547:         int i;
                    548: 
                    549:         /* if key is longer than 64 bytes reset it to key=MD5(key) */
                    550:         if (key_len > 64) {
                    551: 
                    552:                 MD5Init(&tctx);
                    553:                 MD5Update(&tctx, key, key_len);
                    554:                 MD5Final(tk, &tctx);
                    555: 
                    556:                 key = tk;
                    557:                 key_len = 16;
                    558:         }
                    559: 
                    560:         /*
                    561:          * the HMAC_MD5 transform looks like:
                    562:          *
                    563:          * MD5(K XOR opad, MD5(K XOR ipad, text))
                    564:          *
                    565:          * where K is an n byte key
                    566:          * ipad is the byte 0x36 repeated 64 times
                    567:          * opad is the byte 0x5c repeated 64 times
                    568:          * and text is the data being protected
                    569:          */
                    570: 
                    571:         /* start out by storing key in pads */
                    572:         bzero( k_ipad, sizeof k_ipad);
                    573:         bzero( k_opad, sizeof k_opad);
                    574:         bcopy( key, k_ipad, key_len);
                    575:         bcopy( key, k_opad, key_len);
                    576: 
                    577:         /* XOR key with ipad and opad values */
                    578:         for (i=0; i<64; i++) {
                    579:                 k_ipad[i] ^= 0x36;
                    580:                 k_opad[i] ^= 0x5c;
                    581:         }
                    582:         /* perform inner MD5 */
                    583:         MD5Init(&context);                   /* init context for 1st pass */
                    584:         MD5Update(&context, k_ipad, 64);      /* start with inner pad */
                    585:         MD5Update(&context, text, text_len); /* then text of datagram */
                    586:         MD5Final(digest, &context);          /* finish up 1st pass */
                    587: 
                    588:         /* perform outer MD5 */
                    589:        
                    590:         MD5Init(&context);                   /* init context for 2nd */
                    591: 
                    592:         MD5Update(&context, k_opad, 64);     /* start with outer pad */
                    593:         MD5Update(&context, digest, 16);     /* then results of 1st hash */
                    594:         MD5Final(digest, &context);          /* finish up 2nd pass */
                    595: }
                    596: 
                    597: /* Hexdumping on screen in a fancy format for debuging purposes */
                    598: int hexdump(unsigned char *zone, int len) {
                    599:     int rc=0,i;
                    600:     unsigned char *ptr;
                    601: 
                    602:     ptr = zone;
                    603:     fprintf(stderr,"-- hexdump at %p (%d bytes long) --",zone,len);
                    604:     for( i = 0 ;i < len;i++) {
                    605:        if((i%16)==0)
                    606:            fprintf(stderr,"\n%p ",ptr+i);
                    607:        if((i%8)==0)
                    608:            fprintf(stderr," ");
                    609:        fprintf(stderr,"0x%.2x ",*(ptr+i));
                    610:     }
                    611:     fprintf(stderr,"\n");
                    612:     return rc;
                    613: }

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