Annotation of embedaddon/freevrrpd/vrrp_ah.c, revision 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>