📄 chap.c
字号:
/* * chap.c - support for (mutual) CHAP authentication. * (C) 2004 Xiranet Communications GmbH <arne.redlich@xiranet.com> * available under the terms of the GNU GPL v2.0 * * heavily based on code from iscsid.c: * Copyright (C) 2002-2003 Ardis Technolgies <roman@ardistech.com>, * licensed under the terms of the GNU GPL v2.0, * * and code taken from UNH iSCSI software: * Copyright (C) 2001-2003 InterOperability Lab (IOL) * University of New Hampshire (UNH) * Durham, NH 03824 * licensed under the terms of the GNU GPL v2.0 */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <openssl/sha.h>#include <openssl/md5.h>#include "iscsid.h"#define HEX_FORMAT 0x01#define BASE64_FORMAT 0x02#define CHAP_DIGEST_ALG_MD5 5#define CHAP_DIGEST_ALG_SHA1 7#define CHAP_MD5_DIGEST_LEN 16#define CHAP_SHA1_DIGEST_LEN 20#define CHAP_INITIATOR_ERROR -1#define CHAP_AUTH_ERROR -2#define CHAP_TARGET_ERROR -3#define CHAP_AUTH_STATE_START AUTH_STATE_START#define CHAP_AUTH_STATE_CHALLENGE 1#define CHAP_AUTH_STATE_RESPONSE 2#define CHAP_INITIATOR_AUTH 0#define CHAP_TARGET_AUTH 1#define CHAP_CHALLENGE_MAX 50static inline int decode_hex_digit(char c){ switch (c) { case '0' ... '9': return c - '0'; case 'a' ... 'f': return c - 'a' + 10; case 'A' ... 'F': return c - 'A' + 10; } return 0;}static void decode_hex_string(char *hex_string, u8 *intnum, int intlen){ char *ptr; int j; j = strlen(hex_string); ptr = hex_string + j; j = --intlen; do { intnum[j] = decode_hex_digit(*--ptr); intnum[j] |= decode_hex_digit(*--ptr) << 4; j--; } while (ptr > hex_string); while (j >= 0) intnum[j--] = 0;}/* Base64 decoding, taken from UNH-iSCSI "Base64codeToNumber()" */static u8 decode_base64_digit(char base64){ switch (base64) { case '=': return 64; case '/': return 63; case '+': return 62; default: if ((base64 >= 'A') && (base64 <= 'Z')) return base64 - 'A'; else if ((base64 >= 'a') && (base64 <= 'z')) return 26 + (base64 - 'a'); else if ((base64 >= '0') && (base64 <= '9')) return 52 + (base64 - '0'); else return -1; }}/* Base64 decoding, taken from UNH-iSCSI "Base64StringToInteger()" */static void decode_base64_string(char *string, u8 *intnum, int int_len){ int len; int count; int intptr; u8 num[4]; int octets; if ((string == NULL) || (intnum == NULL)) return; len = strlen(string); if (len == 0) return; if ((len % 4) != 0) return; count = 0; intptr = 0; while (count < len - 4) { num[0] = decode_base64_digit(string[count]); num[1] = decode_base64_digit(string[count + 1]); num[2] = decode_base64_digit(string[count + 2]); num[3] = decode_base64_digit(string[count + 3]); if ((num[0] == 65) || (num[1] == 65) || (num[2] == 65) || (num[3] == 65)) return; count += 4; octets = (num[0] << 18) | (num[1] << 12) | (num[2] << 6) | num[3]; intnum[intptr] = (octets & 0xFF0000) >> 16; intnum[intptr + 1] = (octets & 0x00FF00) >> 8; intnum[intptr + 2] = octets & 0x0000FF; intptr += 3; } num[0] = decode_base64_digit(string[count]); num[1] = decode_base64_digit(string[count + 1]); num[2] = decode_base64_digit(string[count + 2]); num[3] = decode_base64_digit(string[count + 3]); if ((num[0] == 64) || (num[1] == 64)) return; if (num[2] == 64) { if (num[3] != 64) return; intnum[intptr] = (num[0] << 2) | (num[1] >> 4); } else if (num[3] == 64) { intnum[intptr] = (num[0] << 2) | (num[1] >> 4); intnum[intptr + 1] = (num[1] << 4) | (num[2] >> 2); } else { octets = (num[0] << 18) | (num[1] << 12) | (num[2] << 6) | num[3]; intnum[intptr] = (octets & 0xFF0000) >> 16; intnum[intptr + 1] = (octets & 0x00FF00) >> 8; intnum[intptr + 2] = octets & 0x0000FF; }}static inline void encode_hex_string(u8 *intnum, long length, char *string){ int i; char *strptr; strptr = string; for (i = 0; i < length; i++, strptr += 2) sprintf(strptr, "%.2hhx", intnum[i]);}/* Base64 encoding, taken from UNH iSCSI "IntegerToBase64String()" */static void encode_base64_string(u8 *intnum, long length, char *string){ int count, octets, strptr, delta; static const char base64code[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '=' }; if ((!intnum) || (!string) || (!length)) return; count = 0; octets = 0; strptr = 0; while ((delta = (length - count)) > 2) { octets = (intnum[count] << 16) | (intnum[count + 1] << 8) | intnum[count + 2]; string[strptr] = base64code[(octets & 0xfc0000) >> 18]; string[strptr + 1] = base64code[(octets & 0x03f000) >> 12]; string[strptr + 2] = base64code[(octets & 0x000fc0) >> 6]; string[strptr + 3] = base64code[octets & 0x00003f]; count += 3; strptr += 4; } if (delta == 1) { string[strptr] = base64code[(intnum[count] & 0xfc) >> 2]; string[strptr + 1] = base64code[(intnum[count] & 0x03) << 4]; string[strptr + 2] = base64code[64]; string[strptr + 3] = base64code[64]; strptr += 4; } else if (delta == 2) { string[strptr] = base64code[(intnum[count] & 0xfc) >> 2]; string[strptr + 1] = base64code[((intnum[count] & 0x03) << 4) | ((intnum[count + 1] & 0xf0) >> 4)]; string[strptr + 2] = base64code[(intnum[count + 1] & 0x0f) << 2]; string[strptr + 3] = base64code[64]; strptr += 4; } string[strptr] = '\0';}static inline int chap_check_encoding_format(char *encoded){ int encoding_fmt; if (!encoded) return -1; if ((strlen(encoded) < 3) || (encoded[0] != '0')) return -1; if (encoded[1] == 'x' || encoded[1] == 'X') encoding_fmt = HEX_FORMAT; else if (encoded[1] == 'b' || encoded[1] == 'B') encoding_fmt = BASE64_FORMAT; else return -1; return encoding_fmt;}static int chap_alloc_decode_buffer(char *encoded, u8 **decode_buf, int encoding_fmt){ int i; int decode_len = 0; i = strlen(encoded); i -= 2; if (encoding_fmt == HEX_FORMAT) decode_len = (i - 1) / 2 + 1; else if (encoding_fmt == BASE64_FORMAT) { if (i % 4) return CHAP_INITIATOR_ERROR; decode_len = i / 4 * 3; if (encoded[i + 1] == '=') decode_len--; if (encoded[i] == '=') decode_len--; } if (!decode_len) return CHAP_INITIATOR_ERROR; *decode_buf = malloc(decode_len); if (!*decode_buf) return CHAP_TARGET_ERROR; return decode_len;}static int chap_decode_string(char *encoded, u8 *decode_buf, int buf_len, int encoding_fmt){ if (encoding_fmt == HEX_FORMAT) { if ((strlen(encoded) - 2) > (2 * buf_len)) { log_error("%s(%d) BUG? " " buf[%d] !sufficient to decode string[%d]", __FUNCTION__, __LINE__, buf_len, (int) strlen(encoded)); return CHAP_TARGET_ERROR; } decode_hex_string(encoded + 2, decode_buf, buf_len); } else if (encoding_fmt == BASE64_FORMAT) { if ((strlen(encoded) - 2) > ((buf_len - 1) / 3 + 1) * 4) { log_error("%s(%d) BUG? " " buf[%d] !sufficient to decode string[%d]", __FUNCTION__, __LINE__, buf_len, (int) strlen(encoded)); return CHAP_TARGET_ERROR; } decode_base64_string(encoded + 2, decode_buf, buf_len); } else return CHAP_INITIATOR_ERROR; return 0;}static inline void chap_encode_string(u8 *intnum, int buf_len, char *encode_buf, int encoding_fmt){ encode_buf[0] = '0'; if (encoding_fmt == HEX_FORMAT) { encode_buf[1] = 'x'; encode_hex_string(intnum, buf_len, encode_buf + 2); } else if (encoding_fmt == BASE64_FORMAT) { encode_buf[1] = 'b'; encode_base64_string(intnum, buf_len, encode_buf + 2); }}static inline void chap_calc_digest_md5(char chap_id, char *secret, int secret_len, u8 *challenge, int challenge_len, u8 *digest){ MD5_CTX ctx; MD5_Init(&ctx); MD5_Update(&ctx, &chap_id, 1); MD5_Update(&ctx, secret, secret_len); MD5_Update(&ctx, challenge, challenge_len); MD5_Final(digest, &ctx);}static inline void chap_calc_digest_sha1(char chap_id, char *secret, int secret_len, u8 *challenge, int challenge_len, u8 *digest){ SHA_CTX ctx;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -