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>