⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rsvp_key.c

📁 radius协议源码÷The Radius Stack will connect to a Radius Server. This stack implementation is built upo
💻 C
字号:
/* * @(#) $Id: rsvp_key.c,v 1.1.1.1 2000/05/08 22:51:24 wenqing Exp $ *//************************ rsvp_key.c  ******************************** *                                                                   * *      Routines to compute and verify INTEGRITY objects	     * *                                                                   * *                                                                   * *********************************************************************//****************************************************************************            RSVPD -- ReSerVation Protocol Daemon                USC Information Sciences Institute                Marina del Rey, California	    Current Version:  Bob Braden, June 1996.  Copyright (c) 1996 by the University of Southern California  All rights reserved.  Permission to use, copy, modify, and distribute this software and its  documentation in source and binary forms for any purpose and without  fee is hereby granted, provided that both the above copyright notice  and this permission notice appear in all copies, and that any  documentation, advertising materials, and other materials related to  such distribution and use acknowledge that the software was developed  in part by the University of Southern California, Information  Sciences Institute.  The name of the University may not be used to  endorse or promote products derived from this software without  specific prior written permission.  THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about  the suitability of this software for any purpose.  THIS SOFTWARE IS  PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,  INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  Other copyrights might apply to parts of this software and are so  noted when applicable.********************************************************************//* This code adapted from an experimental implementation of * INTEGRITY by Prakash Jayaraman of USC. *//* CAVEAT :  * For MD5  *    Block Length (B)  = 64B *    Digest Length (L) = 16B * * For HMAC, the authors recommend a minimum key length of L (the digest * length of the corresponding hash algorithm used) and allow keys to be * of variable length. Key lengths less than L are strongly discouraged * as they would decrese the security strength of the function. * * This code assumes a key length of 16B (see load_key()). */#include <limits.h>#include "rsa_hmac_md5.h"/* External declarations */int		tolower(int);/* Forward declarations */void		incr_key_assoc_seqno(KEY_ASSOC *kap);void		set_integrity(struct packet *, int);void		fin_integrity(struct packet *);int             check_integrity(struct packet *);KEY_ASSOC	*get_send_key(int);KEY_ASSOC	*get_recv_key(INTEGRITY *, int);KEY_ASSOC	*load_key(char *, char *);int		hexcnv2(u_char *, char *);INTEGRITY       *extract_integrity(struct packet *pkt, INTEGRITY *intp);int             check_seqno(INTEGRITY *intp, KEY_ASSOC *kap);/* Global variables */INTEGRITY                Auth_Obj;KEY_ASSOC		 key_assoc_table[KEY_TABLE_SIZE];int			 Key_Assoc_Max;#ifdef SECURITY/* *	incr_key_assoc_seqno(): Increment sequence number to send. */voidincr_key_assoc_seqno(KEY_ASSOC *kap){  struct timeval tv;  gettimeofday(&tv, NULL);  if (kap->kas_seqno[0] == tv.tv_sec)     kap->kas_seqno[1]++; /* Increment message counter           */  else     {			 /* Time advanced, reset message countr */      kap->kas_seqno[0] = tv.tv_sec;      kap->kas_seqno[1] = 0;    }}/* *	set_integrity() *		Initialize INTEGRITY object, if one is required, for *		sending packet through specified vif. */voidset_integrity(struct packet *pkt, int vif){  INTEGRITY	*intgp;  KEY_ASSOC	*kap;   /*	Look up key for specified vif.  If none is found,   *	return without creating INTEGRITY object.   */  kap = get_send_key(vif);  if (!kap)    return;  /*	Create and initialize INTEGRITY object   */  intgp = pkt->pkt_map->rsvp_integrity = &Auth_Obj;  Init_Object(intgp, INTEGRITY, INTEGRITY_MD5);  memset(intgp->intgr_keyid, 0, KEYID_LENG);  memcpy(intgp->intgr_keyid, kap->kas_keyid, KEYID_LENG);  /*	Increment sequence number for this INTEGRITY   *	associations.   */  incr_key_assoc_seqno(kap);    intgp->intgr_seqno[0] = kap->kas_seqno[0];  intgp->intgr_seqno[1] = kap->kas_seqno[1];  memset(intgp->intgr_digest, 0, MD5_LENG);  memcpy(intgp->intgr_digest, kap->kas_key, MD5_LENG);}/* *	fin_integrity() *		Compute crypto digest over given packet and complete *		the INTEGRITY object. */voidfin_integrity(struct packet *pkt){  INTEGRITY	*intgp = pkt->pkt_map->rsvp_integrity;  unsigned char key[MD5_LENG];  unsigned char digest[MD5_LENG];  assert(intgp);  /*    Extract Key stored in the digest field (length is MD5_LENG).   *    [The key is stored with the packet and not read in again in    *     fin_integrity() cause the key might have been deleted between   *     calls to set and fin. If this assumption is false then the two    *     functions can be simplified and we might do all key related    *     stuff here]   *    Zero out digest field.   *    Compute HMAC-MD5 keyed-hash   *    Store final value back into digest field.   */  memcpy(key, intgp->intgr_digest, MD5_LENG);  memset(intgp->intgr_digest, 0, MD5_LENG);  hmac_md5((POINTER) pkt->pkt_data, pkt->pkt_len,	   key, MD5_LENG, digest);  memcpy(intgp->intgr_digest, digest, MD5_LENG);  log(LOG_DEBUG, 0, "INTEGRITY fin: Digest\n");  MDPrint(digest);  log(LOG_DEBUG, 0, "\n");}/* check_integrity *    Check integrity object. * * Input *    pkt : raw input received from the network (in NET byte order). * * Output *    1   If No Integrity Object Present *    0   No Error *    <0  (Error Code) if Check Fails */ intcheck_integrity(struct packet *pkt){  unsigned char	*received_digest;  unsigned char computed_digest[MD5_LENG];  KEY_ASSOC	*kap;  INTEGRITY	integrity, *intp;  int i;  pkt->pkt_data->rsvp_cksum = 0;             /* Clear checksum field     */  if (!(intp = extract_integrity(pkt, &integrity))) /* Copy intgrty obj  */    return 1;	                             /* No integrity obj found   */  received_digest = integrity.intgr_digest;  memset(intp->intgr_digest, 0, MD5_LENG);   /* Clear digest field       */  for (i = 0; (kap = get_recv_key(&integrity, i)); i++)    {      hmac_md5((POINTER) pkt->pkt_data, pkt->pkt_len,	       kap->kas_key, MD5_LENG, computed_digest);      log(LOG_DEBUG, 0, 	  "INTEGRITY chk: SeqNoOld, SeqNoNew, DigestIn, DigestCompute\n");      log(LOG_DEBUG, 0, "%u-%u\n%u-%u\n", 	  kap->kas_seqno[0], kap->kas_seqno[1],	  integrity.intgr_seqno[0], integrity.intgr_seqno[1]);      MDPrint(received_digest);      log(LOG_DEBUG, 0, "\n");      MDPrint(computed_digest);      log(LOG_DEBUG, 0, "\n");            /*	Check that recomputed digest matches what arrived.       */      if (!(memcmp(received_digest, computed_digest, MD5_LENG)))	if(check_seqno(&integrity, kap))     /* Valid sequence number    */	  break;	else	  return PKT_ERR_REPLAY;    }  if (!kap)    if (i == 0)      return PKT_ERR_NOINTASS;	             /* No matching key          */    else      return PKT_ERR_INTEGRITY;              /* No satisfactory key      */  return 0;                                /* OK                         */}/*	Return pointer to first entry of the Key Assocation table for *	given send interface, or NULL. */KEY_ASSOC *get_send_key(int vif){  KEY_ASSOC	*kap;  int		i;    kap = &key_assoc_table[0];  for (i = 0; i < Key_Assoc_Max; i++, kap++)    if (kap->kas_keylen && (kap->kas_if == vif))      break;  if (i == Key_Assoc_Max)    return(NULL);  return(kap);}/*	Return pointer to ith receive entry of the Key Assocation table *	for given keyid, or NULL. */KEY_ASSOC *get_recv_key(INTEGRITY *intp, int index){  KEY_ASSOC	*kap;  int		i;    if (Obj_Class(intp) != class_INTEGRITY)    return(NULL);  kap = &key_assoc_table[0];  for (i= 0; i < Key_Assoc_Max; i++, kap++) {    if (!kap->kas_keylen)      continue;    if (kap->kas_if >= 0)      continue;    if (memcmp(kap->kas_keyid, intp->intgr_keyid, KEYID_LENG))      continue;    if (!(index--))		/* Find ith key */      break;    }  if (i == Key_Assoc_Max)    return(NULL);  return(kap);}KEY_ASSOC *load_key(char *keyidstr, char *keystr){  KEY_ASSOC	*kap;  u_char	ascikey[2*MD5_LENG], ascikeyid[2*KEYID_LENG], *cp;  int 		i;	  kap = &key_assoc_table[0];  for (i = 0; i < Key_Assoc_Max; i++, kap++)    if (kap->kas_keylen == 0)      break;  if (i == Key_Assoc_Max) {    if (i == KEY_TABLE_SIZE) {      log(LOG_ERR, 0, "Too many key associations\n");      return(NULL);    }    Key_Assoc_Max++;  }  if (strlen(keyidstr) > 2*KEYID_LENG) {    log(LOG_ERR, 0, "Key ID too long\n");    return(NULL);  }  /*   *	Convert hex key id string   */  memset(kap->kas_keyid, 0, KEYID_LENG);  memset(ascikeyid, '0', 2*KEYID_LENG);  strncpy((char *) (cp = ascikeyid), keyidstr, strlen(keyidstr));    for (i = 0; i < KEYID_LENG; i++) {    if (!hexcnv2(&kap->kas_keyid[i], (char *) cp)) {      log(LOG_ERR, 0, "Bad hex char: %c\n", *cp);      exit(1);    }    cp += 2;  }  if (strlen(keystr) > 2*MD5_LENG) {    log(LOG_ERR, 0, "Send key too long\n");    return(NULL);  }  /*   *	Convert hex key string   */  memset(kap->kas_key, 0, MD5_LENG);  memset(ascikey, '0', 2*MD5_LENG);  strncpy((char *) (cp = ascikey), keystr, strlen(keystr));    for (i = 0; i < MD5_LENG; i++) {    if (!hexcnv2(&kap->kas_key[i], (char *) cp)) {      log(LOG_ERR, 0, "Bad hex char: %c\n", *cp);      exit(1);    }    cp += 2;  }  kap->kas_keylen = MD5_LENG;  kap->kas_seqno[0] = kap->kas_seqno[1] = 0xffffffff; /* Initial SeqNo */  return(kap); /* OK */}char hextab[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',		 'a', 'b', 'c', 'd', 'e', 'f'};inthexcnv2(u_char *rp, char *cp){  char *xp = strchr(hextab, tolower(*cp++));  char *yp = strchr(hextab, tolower(*cp));    if (!xp || !yp)    return 0;  *rp = ((xp-hextab)<<4) + (yp-hextab);  return 1;}/* extract_integrity *    Extract the integrity object from the raw packet, converting the  *    fields from NET to HOST byte order before storing them. Needed to  *    extract information about Seq # before integrity check can be  *    performed. * * Input *    pkt  : raw input received from the network (in NET byte order). *    intp : pointer to object where integrity fields will be stored. * * Output *    pointer to integrity object in packet (if integrity present) *    NULL                                  (else) */ INTEGRITY *extract_integrity(struct packet *pkt, INTEGRITY *intp){  common_header	*hdrp = pkt->pkt_data;  char		*end_of_data = (char *) pkt->pkt_data + pkt->pkt_len;  Object_header	*objp, *next;    objp = (Object_header *) (hdrp + 1);  while (objp <  (Object_header *) end_of_data) {    if (Obj_Class(objp) == class_INTEGRITY) {      memcpy(intp, objp, sizeof(INTEGRITY));#if BYTE_ORDER == LITTLE_ENDIAN      ntoh_object((Object_header *) intp);#endif      return ((INTEGRITY *) objp);    }    NTOH16(Obj_Length(objp));	/* Find length */    next = Next_Object(objp);    NTOH16(Obj_Length(objp));	/* Restore byte order */    objp = next;  }  return NULL;			/* Integrity Object not found */}/* check_seqno *    Check the sequence number in the integrity object for replays. * * Input *    intp : pointer to integrity object. *    kap  : pointer to key association object.  * * Output *    1   (if sequence number valid) *    0   (else) * * Note *    The initial seq no is always accepted (no handshake for now).  *    Safe if the real sender is actively generating RSVP messages,  *    as it would then bump the stored sequence number field. * *    No tolerance to out of order packets yet. * *    A valid sequence number updates the sequence number field in the *    key association. */ intcheck_seqno(INTEGRITY *intp, KEY_ASSOC *kap){#define new   intp->intgr_seqno#define old   kap->kas_seqno  /* Previous field not invalid */  if (!((old[0] == 0xffffffff) && (old[1] == 0xffffffff)))    if (LT(new[0], old[0]) && ((old[0] - new[0]) < UINT_MAX/2))      return 0;    else if ((new[0] == old[0]) && (LT(new[1], old[1])))      return 0;    else if (LT(old[0], new[0]) && ((new[0] - old[0]) > UINT_MAX/2))      return 0;  /* Valid sequence number, update stored value */  old[0] =  new[0];  old[1] =  new[1];  return 1;}#endif /* SECURITY */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -