📄 auth.c
字号:
/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author : F. Tarek Rogers - 01 Sept 2004 * Russell Roy * Wolfgang Beck * Dragos Vingarzan - 02 February 2006 vingarzan@gmail.com * - split in the auth architecture * - introduced AKAv1-MD5 * Frederique Aurouet */#ifdef __FreeBSD__#include <sys/types.h>#endif#include <stdlib.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include <openssl/md5.h>#include "milenage.h"#define MAX_HEADER_LEN 2049#define MD5_HASH_SIZE 16#define HASH_HEX_SIZE 2*MD5_HASH_SIZEextern char *auth_uri;/* AKA */#define KLEN 16typedef u_char K[KLEN];#define RANDLEN 16typedef u_char RAND[RANDLEN];#define AUTNLEN 16typedef u_char AUTN[AUTNLEN];#define AKLEN 6typedef u_char AK[AKLEN];#define AMFLEN 2typedef u_char AMF[AMFLEN];#define MACLEN 8typedef u_char MAC[MACLEN];#define CKLEN 16typedef u_char CK[CKLEN];#define IKLEN 16typedef u_char IK[IKLEN];#define SQNLEN 6typedef u_char SQN[SQNLEN];#define AUTSLEN 14typedef char AUTS[AUTSLEN];#define AUTS64LEN 29typedef char AUTS64[AUTS64LEN];#define RESLEN 8typedef unsigned char RES[RESLEN+1];#define RESHEXLEN 17typedef char RESHEX[RESHEXLEN];#define OPLEN 16typedef u_char OP[OPLEN];AMF amfstar="\0\0";SQN sqn_he={0x00,0x00,0x00,0x00,0x00,0x00};/* end AKA */int createAuthHeaderMD5(char * user, char * password, char * method, char * uri, char * msgbody, char * auth, char * algo, char * result);int createAuthHeaderAKAv1MD5(char * user, char * OP, char * AMF, char * K, char * method, char * uri, char * msgbody, char * auth, char *algo, char * result);/* This function is from RFC 2617 Section 5 */void hashToHex (unsigned char *_b, unsigned char *_h){ unsigned short i; unsigned char j; for (i = 0; i < MD5_HASH_SIZE; i++) { j = (_b[i] >> 4) & 0xf; if (j <= 9) { _h[i * 2] = (j + '0'); } else { _h[i * 2] = (j + 'a' - 10); } j = _b[i] & 0xf; if (j <= 9) { _h[i * 2 + 1] = (j + '0'); } else { _h[i * 2 + 1] = (j + 'a' - 10); } }; _h[HASH_HEX_SIZE] = '\0';}char *stristr (const char *s1, const char *s2) { char *cp = (char*) s1; char *p1, *p2, *endp; char l, r; endp = (char*)s1 + (strlen(s1) - strlen(s2)) ; while (*cp && (cp <= endp)) { p1 = cp; p2 = (char*)s2; while (*p1 && *p2) { l = toupper(*p1); r = toupper(*p2); if (l != r) { break; } p1++; p2++; } if (*p2 == 0) { return cp; } cp++; } return 0;}int createAuthHeader(char * user, char * password, char * method, char * uri, char * msgbody, char * auth, char * aka_OP, char * aka_AMF, char * aka_K, char * result) { char algo[32]="MD5"; char *start, *end; if ((start = stristr(auth, "Digest")) == NULL) { sprintf(result, "createAuthHeader: authentication must be digest"); return 0; } if ((start = stristr(auth, "algorithm=")) != NULL) { start = start + strlen("algorithm="); if (*start == '"') { start++; } end = start + strcspn(start, " ,\"\r\n"); strncpy(algo, start, end - start); algo[end - start] ='\0'; } if (strncasecmp(algo, "MD5", 3)==0) { return createAuthHeaderMD5(user,password,method,uri,msgbody,auth,algo,result); } else if (strncasecmp(algo, "AKAv1-MD5", 9)==0) { return createAuthHeaderAKAv1MD5(user, aka_OP, aka_AMF, aka_K, method,uri,msgbody,auth,algo,result); }else{ sprintf(result, "createAuthHeader: authentication must use MD5 or AKAv1-MD5"); return 0; } }int createAuthHeaderMD5(char * user, char * password, char * method, char * uri, char * msgbody, char * auth, char * algo, char * result) { unsigned char ha1[MD5_HASH_SIZE], ha2[MD5_HASH_SIZE]; unsigned char resp[MD5_HASH_SIZE], body[MD5_HASH_SIZE]; unsigned char ha1_hex[HASH_HEX_SIZE+1], ha2_hex[HASH_HEX_SIZE+1]; unsigned char resp_hex[HASH_HEX_SIZE+1], body_hex[HASH_HEX_SIZE+1]; char tmp[MAX_HEADER_LEN], authtype[16], cnonce[32], nc[32], opaque[64]; char *start, *end; static unsigned int mync = 1; int has_opaque = 0; MD5_CTX Md5Ctx; // Extract the Auth Type - If not present, using 'none' cnonce[0] = '\0'; authtype[0] = '\0'; if ((start = stristr(auth, "qop=")) != NULL) { start = start + strlen("qop="); if (*start == '"') { start++; } end = start + strcspn(start, " ,\"\r\n"); strncpy(authtype, start, end - start); authtype[end - start] ='\0'; sprintf(cnonce, "%x", rand()); sprintf(nc, "%08x", mync); } // Extract the Opaque value - if present opaque[0] = '\0'; if ((start = stristr(auth, "opaque=")) != NULL) { start = start + strlen("opaque="); if (*start == '"') { start++; } end = start + strcspn(start, " ,\"\r\n"); strncpy(opaque, start, end - start); opaque[end - start] ='\0'; has_opaque = 1; } // Extract the Realm if ((start = stristr(auth, "realm=")) == NULL) { sprintf(result, "createAuthHeaderMD5: couldn't parse realm in '%s'", auth); return 0; } start = start + strlen("realm="); if (*start == '"') { start++; } end = start + strcspn(start, ",\"\r\n"); strncpy(tmp, start, end - start); tmp[end - start] ='\0'; // Load in A1 MD5_Init(&Md5Ctx); MD5_Update(&Md5Ctx, user, strlen(user)); MD5_Update(&Md5Ctx, ":", 1); MD5_Update(&Md5Ctx, tmp, strlen(tmp)); MD5_Update(&Md5Ctx, ":", 1); MD5_Update(&Md5Ctx, password, strlen(password)); MD5_Final(ha1, &Md5Ctx); hashToHex(&ha1[0], &ha1_hex[0]); sprintf(result, "Digest username=\"%s\",realm=\"%s\"",user,tmp); if (cnonce[0] != '\0') { sprintf(result, "%s,cnonce=\"%s\",nc=%s,qop=%s",result,cnonce,nc,authtype); } // Construct the URI if (auth_uri == NULL) { sprintf(tmp, "sip:%s", uri); } else { sprintf(tmp, "sip:%s", auth_uri); } // If using Auth-Int make a hash of the body - which is NULL for REG if (stristr(authtype, "auth-int") != NULL) { MD5_Init(&Md5Ctx); MD5_Update(&Md5Ctx, msgbody, strlen(msgbody)); MD5_Final(body, &Md5Ctx); hashToHex(&body[0], &body_hex[0]); } // Load in A2 MD5_Init(&Md5Ctx); MD5_Update(&Md5Ctx, method, strlen(method)); MD5_Update(&Md5Ctx, ":", 1); MD5_Update(&Md5Ctx, tmp, strlen(tmp)); if (stristr(authtype, "auth-int") != NULL) { MD5_Update(&Md5Ctx, ":", 1); MD5_Update(&Md5Ctx, &body_hex, HASH_HEX_SIZE); } MD5_Final(ha2, &Md5Ctx); hashToHex(&ha2[0], &ha2_hex[0]); sprintf(result, "%s,uri=\"%s\"",result,tmp); // Extract the Nonce if ((start = stristr(auth, "nonce=")) == NULL) { sprintf(result, "createAuthHeader: couldn't parse nonce"); return 0; } start = start + strlen("nonce="); if (*start == '"') { start++; } end = start + strcspn(start, " ,\"\r\n"); strncpy(tmp, start, end - start); tmp[end - start] ='\0'; MD5_Init(&Md5Ctx); MD5_Update(&Md5Ctx, &ha1_hex, HASH_HEX_SIZE); MD5_Update(&Md5Ctx, ":", 1); MD5_Update(&Md5Ctx, tmp, strlen(tmp)); if (cnonce[0] != '\0') { MD5_Update(&Md5Ctx, ":", 1); MD5_Update(&Md5Ctx, nc, strlen(nc)); MD5_Update(&Md5Ctx, ":", 1); MD5_Update(&Md5Ctx, cnonce, strlen(cnonce)); MD5_Update(&Md5Ctx, ":", 1); MD5_Update(&Md5Ctx, authtype, strlen(authtype)); } MD5_Update(&Md5Ctx, ":", 1); MD5_Update(&Md5Ctx, &ha2_hex, HASH_HEX_SIZE); MD5_Final(resp, &Md5Ctx); hashToHex(&resp[0], &resp_hex[0]); sprintf(result, "%s,nonce=\"%s\",response=\"%s\",algorithm=%s",result,tmp,resp_hex,algo); if (has_opaque) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -