📄 auth.c
字号:
/* $Id: auth.c,v 1.20 2001/08/03 22:34:09 jm Exp $ * Message Authentication Routines * * Dynamic hierarchial IP tunnel * Copyright (C) 1998-2001, Dynamics group * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See README and COPYING for * more details. */#include <stdlib.h>#include <string.h>#include <assert.h>#include "md5_mac.h"#include "sha1.h"#include "debug.h"#include "util.h"#include "auth.h"#define DEBUG_FLAG 'U'/* #define AUTH_EXTRA_DEBUG *//* RFC 2002, sec. 3.5.1. * MAC protects UDP payload (reg. req or reg. reply), * all prior extension, and Type and Length of this auth. extension * * draft-ietf-mobileip-v2-00.txt adds SPI field of the extension to the * protected area and this is used as a default in our implementation. * There is an automatic fallback to use the RFC 2002 method to provide * compatibility with other implementations. * * Note: data pointer should be to the beginning of the registration * request or reply and auth pointer must be in the same message buffer * (i.e. just after the data to be protected) */#ifdef AUTH_EXTRA_DEBUGstatic void show_hex(unsigned char *data, int len){ int i; for (i = 0; i < len; i++) DEBUG(DEBUG_FLAG, "%02x", data[i]);}#endiftypedef void (*MACfunc)(unsigned char *key, unsigned int key_len, unsigned char *data, unsigned int data_len, unsigned char *mac);static MACfunc auth_get_mac_data(int alg, int *mac_len){ if (alg == AUTH_ALG_MD5 || alg == AUTH_ALG_MD5_RFC2002 || alg == AUTH_ALG_MD5_PREFIX_SUFFIX) { *mac_len = MD5_MAC_LEN; return md5_mac; } else if (alg == AUTH_ALG_HMAC_MD5) { *mac_len = MD5_MAC_LEN; return hmac_md5; } else if (alg == AUTH_ALG_SHA1) { *mac_len = SHA1_MAC_LEN; return sha1_mac; } else if (alg == AUTH_ALG_HMAC_SHA1) { *mac_len = SHA1_MAC_LEN; return hmac_sha1; } return NULL;}/* Add an authentication extension to a message and return the length of the * added authentication extension. * Parameter spi must be in network byte order. */int auth_add(int alg, unsigned char *key, unsigned int keylen, unsigned char *data, struct msg_auth *auth, __u8 auth_type, __u32 spi){ int len; int mac_len; MACfunc mac_func; auth->type = auth_type; auth->spi = spi; mac_func = auth_get_mac_data(alg, &mac_len); if (mac_func != NULL) { auth->length = mac_len + SPI_LEN; len = ((unsigned char *)auth) - data + (alg == AUTH_ALG_MD5_RFC2002 ? 2 : 6); mac_func(key, keylen, data, len, MSG_AUTH_DATA(auth)); } else { DEBUG(DEBUG_FLAG, "auth_add: unknown algorithm %i\n", alg); auth->length = SPI_LEN; mac_len = 0; }#ifdef AUTH_EXTRA_DEBUG DEBUG(DEBUG_FLAG, "auth_add: len=%i, mac=", len); show_hex(MSG_AUTH_DATA(auth), mac_len); DEBUG(DEBUG_FLAG, "\n");#endif return GET_AUTH_EXT_LEN(auth);}/* returns zero on failure and nonzero on successful authentication check */int auth_check(int alg, unsigned char *key, unsigned int keylen, unsigned char *data, struct msg_auth *auth){ int len, ret; unsigned char *mac; int mac_len; MACfunc mac_func; mac_func = auth_get_mac_data(alg, &mac_len); if (mac_func == NULL) { DEBUG(DEBUG_FLAG, "auth_check: unknown algorithm %i\n", alg); return 0; } mac = (unsigned char *) malloc(mac_len); if (mac == NULL) { DEBUG(DEBUG_FLAG, "auth_check: malloc(%i) failed\n", mac_len); return 0; } if (auth->length != mac_len + SPI_LEN) { DEBUG(DEBUG_FLAG, "auth_check: len=%i != %i\n", auth->length, mac_len + SPI_LEN); return 0; } len = ((unsigned char *)auth) - data + (alg == AUTH_ALG_MD5_RFC2002 ? 2 : 6); mac_func(key, keylen, data, len, mac);#ifdef AUTH_EXTRA_DEBUG DEBUG(DEBUG_FLAG, "auth_check: len=%i, recvMAC=", len); show_hex(MSG_AUTH_DATA(auth), mac_len); DEBUG(DEBUG_FLAG, ", expMAC="); show_hex(mac, mac_len); DEBUG(DEBUG_FLAG, "\n");#endif ret = memcmp(mac, MSG_AUTH_DATA(auth), mac_len) == 0; free(mac); return ret;}int auth_add_vendor(int alg, unsigned char *key, unsigned int keylen, unsigned char *data, struct vendor_msg_auth *auth, __u16 auth_type, __u32 spi){ int len; int mac_len; MACfunc mac_func; auth->type = VENDOR_EXT_TYPE2; auth->reserved = 0; auth->vendor_id = htonl(VENDOR_ID_DYNAMICS); auth->sub_type = htons(auth_type); auth->spi = spi; mac_func = auth_get_mac_data(alg, &mac_len); if (mac_func != NULL) { auth->length = mac_len + MIN_VENDOR_AUTH_LEN; len = ((unsigned char *)auth) - data + sizeof(struct vendor_msg_auth); mac_func(key, keylen, data, len, MSG_VENDOR_AUTH_DATA(auth)); } else { DEBUG(DEBUG_FLAG, "auth_add_vendor: unknown algorithm %i\n", alg); auth->length = MIN_VENDOR_AUTH_LEN; mac_len = 0; }#ifdef AUTH_EXTRA_DEBUG DEBUG(DEBUG_FLAG, "auth_add_vendor: len=%i, mac=", len); show_hex(MSG_VENDOR_AUTH_DATA(auth), mac_len); DEBUG(DEBUG_FLAG, "\n");#endif return GET_VENDOR_AUTH_EXT_LEN(auth);}int auth_check_vendor(int alg, unsigned char *key, unsigned int keylen, unsigned char *data, struct vendor_msg_auth *auth){ int len, ret; unsigned char *mac; int mac_len; MACfunc mac_func; mac_func = auth_get_mac_data(alg, &mac_len); if (mac_func == NULL) { DEBUG(DEBUG_FLAG, "auth_check_vendor: unknown algorithm %i\n", alg); return 0; } mac = (unsigned char *) malloc(mac_len); if (mac == NULL) { DEBUG(DEBUG_FLAG, "auth_check_vendor: malloc(%i) failed\n", mac_len); return 0; } if (auth->length != mac_len + MIN_VENDOR_AUTH_LEN) { DEBUG(DEBUG_FLAG, "auth_check_vendor: len=%i != %i\n", auth->length, mac_len + MIN_VENDOR_AUTH_LEN); return 0; } len = ((unsigned char *)auth) - data + sizeof(struct vendor_msg_auth); mac_func(key, keylen, data, len, mac);#ifdef AUTH_EXTRA_DEBUG DEBUG(DEBUG_FLAG, "auth_check_vendor: len=%i, recvMAC=", len); show_hex(MSG_VENDOR_AUTH_DATA(auth), mac_len); DEBUG(DEBUG_FLAG, ", expMAC="); show_hex(mac, mac_len); DEBUG(DEBUG_FLAG, "\n");#endif ret = memcmp(mac, MSG_VENDOR_AUTH_DATA(auth), mac_len) == 0; free(mac); return ret;}/* Add a generalized authentication extension into the message and return the * length of the added authentication extension. * Parameter spi must be in network byte order. */int auth_add_gen(int alg, unsigned char *key, unsigned int keylen, unsigned char *data, unsigned char *challenge, int challenge_len, struct generalized_auth_ext *auth, __u8 auth_subtype, __u32 spi){ int len; int mac_len; MACfunc mac_func; auth->type = GENERALIZED_AUTH_EXT; auth->subtype = auth_subtype; auth->spi = spi; if (alg == AUTH_ALG_RADIUS) { unsigned char tmp[MD5_MAC_LEN]; MD5_CTX context; auth->length = htons(MD5_MAC_LEN + SPI_LEN); MD5Init(&context); len = ((unsigned char *) auth) - data + 8; MD5Update(&context, data, len); MD5Final(tmp, &context); if (challenge_len > 0) MD5Update(&context, challenge, 1); MD5Update(&context, key, keylen); MD5Update(&context, tmp, MD5_MAC_LEN); if (challenge_len > 1) MD5Update(&context, challenge + 1, challenge_len - 1); MD5Final(MSG_GEN_AUTH_DATA(auth), &context); } else { mac_func = auth_get_mac_data(alg, &mac_len); if (mac_func != NULL) { auth->length = htons(mac_len + SPI_LEN); len = ((unsigned char *) auth) - data + 8; mac_func(key, keylen, data, len, MSG_GEN_AUTH_DATA(auth)); } else { DEBUG(DEBUG_FLAG, "auth_add_gen: unknown algorithm %i" "\n", alg); auth->length = htons(SPI_LEN); } } return GET_GEN_AUTH_EXT_LEN(auth);}int auth_check_gen(int alg, unsigned char *key, unsigned int keylen, unsigned char *data, struct generalized_auth_ext *auth){ int len, ret; unsigned char *mac; int mac_len; MACfunc mac_func; /* FIX: add support for AUTH_ALG_RADIUS as a special case like with * auth_add_gen() above (?) */ mac_func = auth_get_mac_data(alg, &mac_len); if (mac_func == NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -