📄 jauth.c
字号:
/* eXosip - This is the eXtended osip library. Copyright (C) 2002,2003,2004,2005,2006,2007 Aymeric MOIZARD - jack@atosc.org eXosip 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. eXosip 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*/#ifdef ENABLE_MPATROL#include <mpatrol.h>#endif#include "eXosip2.h"#include <eXosip2/eXosip.h>#include <osip2/osip_mt.h>#include <osip2/osip_condv.h>/* #include <osip2/global.h> */#include <osipparser2/osip_md5.h>#include "milenage.h"/* TAKEN from rcf2617.txt */#define HASHLEN 16typedef char HASH[HASHLEN];#define HASHHEXLEN 32typedef char HASHHEX[HASHHEXLEN + 1];#define IN#define OUT/* AKA */#define MAX_HEADER_LEN 2049#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 21typedef char AUTS64[AUTS64LEN];#define RESLEN 8typedef unsigned char RES[RESLEN];#define RESHEXLEN 17typedef char RESHEX[RESHEXLEN];typedef char RESHEXAKA2[RESHEXLEN+IKLEN*2+CKLEN*2];AMF amf="\0\0";AMF amfstar="\0\0";/* end AKA */extern eXosip_t eXosip;/* Private functions */void CvtHex (IN HASH Bin, OUT HASHHEX Hex);static void DigestCalcHA1 (IN const char *pszAlg, IN const char *pszUserName, IN const char *pszRealm, IN const char *pszPassword, IN const char *pszNonce, IN const char *pszCNonce, OUT HASHHEX SessionKey);static void DigestCalcResponse (IN HASHHEX HA1, IN const char *pszNonce, IN const char *pszNonceCount, IN const char *pszCNonce, IN const char *pszQop, IN int Aka, IN const char *pszMethod, IN const char *pszDigestUri, IN HASHHEX HEntity, OUT HASHHEX Response);static void DigestCalcResponseAka(IN const char *pszPassword, IN const char *pszNonce, IN const char *pszCNonce, IN const char *pszQop, IN const char *pszMethod, IN const char *pszDigestUri, IN int version, OUT HASHHEX Response);voidCvtHex (IN HASH Bin, OUT HASHHEX Hex){ unsigned short i; unsigned char j; for (i = 0; i < HASHLEN; i++) { j = (Bin[i] >> 4) & 0xf; if (j <= 9) Hex[i * 2] = (j + '0'); else Hex[i * 2] = (j + 'a' - 10); j = Bin[i] & 0xf; if (j <= 9) Hex[i * 2 + 1] = (j + '0'); else Hex[i * 2 + 1] = (j + 'a' - 10); }; Hex[HASHHEXLEN] = '\0';}/* calculate H(A1) as per spec */static voidDigestCalcHA1 (IN const char *pszAlg, IN const char *pszUserName, IN const char *pszRealm, IN const char *pszPassword, IN const char *pszNonce, IN const char *pszCNonce, OUT HASHHEX SessionKey){ osip_MD5_CTX Md5Ctx; HASH HA1; osip_MD5Init (&Md5Ctx); osip_MD5Update (&Md5Ctx, (unsigned char *) pszUserName, strlen (pszUserName)); osip_MD5Update (&Md5Ctx, (unsigned char *) ":", 1); osip_MD5Update (&Md5Ctx, (unsigned char *) pszRealm, strlen (pszRealm)); osip_MD5Update (&Md5Ctx, (unsigned char *) ":", 1); osip_MD5Update (&Md5Ctx, (unsigned char *) pszPassword, strlen (pszPassword)); osip_MD5Final ((unsigned char *) HA1, &Md5Ctx); if ((pszAlg != NULL) && osip_strcasecmp (pszAlg, "md5-sess") == 0) { osip_MD5Init (&Md5Ctx); osip_MD5Update (&Md5Ctx, (unsigned char *) HA1, HASHLEN); osip_MD5Update (&Md5Ctx, (unsigned char *) ":", 1); osip_MD5Update (&Md5Ctx, (unsigned char *) pszNonce, strlen (pszNonce)); osip_MD5Update (&Md5Ctx, (unsigned char *) ":", 1); osip_MD5Update (&Md5Ctx, (unsigned char *) pszCNonce, strlen (pszCNonce)); osip_MD5Final ((unsigned char *) HA1, &Md5Ctx); } CvtHex (HA1, SessionKey);}/* calculate request-digest/response-digest as per HTTP Digest spec */static voidDigestCalcResponse (IN HASHHEX HA1, /* H(A1) */ IN const char *pszNonce, /* nonce from server */ IN const char *pszNonceCount, /* 8 hex digits */ IN const char *pszCNonce, /* client nonce */ IN const char *pszQop, /* qop-value: "", "auth", "auth-int" */ IN int Aka, /* Calculating AKAv1-MD5 response */ IN const char *pszMethod, /* method from the request */ IN const char *pszDigestUri, /* requested URL */ IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */ OUT HASHHEX Response /* request-digest or response-digest */ ){ osip_MD5_CTX Md5Ctx; HASH HA2; HASH RespHash; HASHHEX HA2Hex; /* calculate H(A2) */ osip_MD5Init (&Md5Ctx); osip_MD5Update (&Md5Ctx, (unsigned char *) pszMethod, strlen (pszMethod)); osip_MD5Update (&Md5Ctx, (unsigned char *) ":", 1); osip_MD5Update (&Md5Ctx, (unsigned char *) pszDigestUri, strlen (pszDigestUri)); if (pszQop == NULL) { goto auth_withoutqop; } else if (0 == strcmp (pszQop, "auth-int")) { goto auth_withauth_int; } else if (0 == strcmp (pszQop, "auth")) { goto auth_withauth; }auth_withoutqop: osip_MD5Final ((unsigned char *) HA2, &Md5Ctx); CvtHex (HA2, HA2Hex); /* calculate response */ osip_MD5Init (&Md5Ctx); osip_MD5Update (&Md5Ctx, (unsigned char *) HA1, HASHHEXLEN); osip_MD5Update (&Md5Ctx, (unsigned char *) ":", 1); osip_MD5Update (&Md5Ctx, (unsigned char *) pszNonce, strlen (pszNonce)); osip_MD5Update (&Md5Ctx, (unsigned char *) ":", 1); goto end;auth_withauth_int: osip_MD5Update (&Md5Ctx, (unsigned char *) ":", 1); osip_MD5Update (&Md5Ctx, (unsigned char *) HEntity, HASHHEXLEN);auth_withauth: osip_MD5Final ((unsigned char *) HA2, &Md5Ctx); CvtHex (HA2, HA2Hex); /* calculate response */ osip_MD5Init (&Md5Ctx); osip_MD5Update (&Md5Ctx, (unsigned char *) HA1, HASHHEXLEN); osip_MD5Update (&Md5Ctx, (unsigned char *) ":", 1); osip_MD5Update (&Md5Ctx, (unsigned char *) pszNonce, strlen (pszNonce)); osip_MD5Update (&Md5Ctx, (unsigned char *) ":", 1); if(Aka == 0){ osip_MD5Update (&Md5Ctx, (unsigned char *) pszNonceCount, strlen (pszNonceCount)); osip_MD5Update (&Md5Ctx, (unsigned char *) ":", 1); osip_MD5Update (&Md5Ctx, (unsigned char *) pszCNonce, strlen (pszCNonce)); osip_MD5Update (&Md5Ctx, (unsigned char *) ":", 1); osip_MD5Update (&Md5Ctx, (unsigned char *) pszQop, strlen (pszQop)); osip_MD5Update (&Md5Ctx, (unsigned char *) ":", 1); }end: osip_MD5Update (&Md5Ctx, (unsigned char *) HA2Hex, HASHHEXLEN); osip_MD5Final ((unsigned char *) RespHash, &Md5Ctx); CvtHex (RespHash, Response);}/*"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";*/static int base64_val(char x)\{ switch(x){ case '=': return -1; case 'A': return 0; case 'B': return 1; case 'C': return 2; case 'D': return 3; case 'E': return 4; case 'F': return 5; case 'G': return 6; case 'H': return 7; case 'I': return 8; case 'J': return 9; case 'K': return 10; case 'L': return 11; case 'M': return 12; case 'N': return 13; case 'O': return 14; case 'P': return 15; case 'Q': return 16; case 'R': return 17; case 'S': return 18; case 'T': return 19; case 'U': return 20; case 'V': return 21; case 'W': return 22; case 'X': return 23; case 'Y': return 24; case 'Z': return 25; case 'a': return 26; case 'b': return 27; case 'c': return 28; case 'd': return 29; case 'e': return 30; case 'f': return 31; case 'g': return 32; case 'h': return 33; case 'i': return 34; case 'j': return 35; case 'k': return 36; case 'l': return 37; case 'm': return 38; case 'n': return 39; case 'o': return 40; case 'p': return 41; case 'q': return 42; case 'r': return 43; case 's': return 44; case 't': return 45; case 'u': return 46; case 'v': return 47; case 'w': return 48; case 'x': return 49; case 'y': return 50; case 'z': return 51; case '0': return 52; case '1': return 53; case '2': return 54; case '3': return 55; case '4': return 56; case '5': return 57; case '6': return 58; case '7': return 59; case '8': return 60; case '9': return 61; case '+': return 62; case '/': return 63; } return 0;}static char *base64_decode_string(const char *buf, unsigned int len, int *newlen){ int i,j,x1,x2,x3,x4; char *out; out = (char *)malloc( ( len * 3/4 ) + 8 ); for(i=0,j=0;i+3<len;i+=4){ x1=base64_val(buf[i]); x2=base64_val(buf[i+1]); x3=base64_val(buf[i+2]); x4=base64_val(buf[i+3]); out[j++]=(x1<<2) | ((x2 & 0x30)>>4); out[j++]=((x2 & 0x0F)<<4) | ((x3 & 0x3C)>>2); out[j++]=((x3 & 0x03)<<6) | (x4 & 0x3F); } if (i<len) { x1 = base64_val(buf[i]); if (i+1<len) x2=base64_val(buf[i+1]); else x2=-1; if (i+2<len) x3=base64_val(buf[i+2]); else x3=-1; if(i+3<len) x4=base64_val(buf[i+3]); else x4=-1; if (x2!=-1) { out[j++]=(x1<<2) | ((x2 & 0x30)>>4); if (x3==-1) { out[j++]=((x2 & 0x0F)<<4) | ((x3 & 0x3C)>>2); if (x4==-1) { out[j++]=((x3 & 0x03)<<6) | (x4 & 0x3F); } } } } out[j++] = 0; *newlen=j; return out;}char base64[64]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";static char *base64_encode_string(const char *buf, unsigned int len, int *newlen){ int i,k; int triplets,rest; char *out,*ptr; triplets = len/3; rest = len%3; out = (char *)malloc( ( triplets * 4 ) + 8 ); ptr = out; for(i=0;i<triplets*3;i+=3){ k = (((unsigned char) buf[i])&0xFC)>>2; *ptr=base64[k];ptr++; k = (((unsigned char) buf[i])&0x03)<<4; k |=(((unsigned char) buf[i+1])&0xF0)>>4; *ptr=base64[k];ptr++; k = (((unsigned char) buf[i+1])&0x0F)<<2; k |=(((unsigned char) buf[i+2])&0xC0)>>6; *ptr=base64[k];ptr++; k = (((unsigned char) buf[i+2])&0x3F); *ptr=base64[k];ptr++; } i=triplets*3; switch(rest){ case 0: break; case 1: k = (((unsigned char) buf[i])&0xFC)>>2; *ptr=base64[k];ptr++; k = (((unsigned char) buf[i])&0x03)<<4; *ptr=base64[k];ptr++; *ptr='=';ptr++; *ptr='=';ptr++; break; case 2: k = (((unsigned char) buf[i])&0xFC)>>2; *ptr=base64[k];ptr++; k = (((unsigned char) buf[i])&0x03)<<4; k |=(((unsigned char) buf[i+1])&0xF0)>>4; *ptr=base64[k];ptr++; k = (((unsigned char) buf[i+1])&0x0F)<<2; *ptr=base64[k];ptr++; *ptr='=';ptr++; break; } *newlen = ptr-out; return out;}char hexa[16]="0123456789abcdef";/* calculate AKA request-digest/response-digest as per HTTP Digest spec */void DigestCalcResponseAka(IN const char *pszPassword, IN const char *pszNonce, /* nonce from server */ IN const char *pszCNonce, /* client nonce */ IN const char *pszQop, /* qop-value: "", "auth", "auth-int" */ IN const char *pszMethod, /* method from the request */ IN const char *pszDigestUri, /* requested URL */ IN int version, /* AKA version */ OUT RESHEXAKA2 resp_hex /* request-digest or response-digest */ ) { char tmp[MAX_HEADER_LEN]; /* static unsigned int mync = 1; */ /* int has_opaque = 0; */ char *nonce64, *nonce; int noncelen; RAND rnd; MAC mac,xmac; SQN sqn_he; K k; RES res; CK ck; IK ik; AK ak; int i,j; /* Compute the AKA response */ resp_hex[0]=0; sprintf(tmp,"%s",pszNonce); nonce64 = tmp; nonce = base64_decode_string(nonce64,strlen(tmp),&noncelen); if (noncelen<RANDLEN+AUTNLEN) { /* Nonce is too short */ goto done; } memcpy(rnd,nonce,RANDLEN); /* memcpy(autn,nonce+RANDLEN,AUTNLEN); */ memcpy(sqn_he,nonce+RANDLEN,SQNLEN); memcpy(mac,nonce+RANDLEN+SQNLEN+AMFLEN,MACLEN); j = strlen(pszPassword); memcpy(k,pszPassword,j); memset(k+j,0,KLEN-j); /* compute XMAC */ f1(k,rnd,sqn_he,amf,xmac); if (memcmp(mac,xmac,MACLEN)!=0) { /* createAuthHeaderAKAv1MD5 : MAC != eXpectedMAC -> Server might not know the secret (man-in-the-middle attack?) return 0; */ } /* compute the response and keys */ f2345(k,rnd,res,ck,ik,ak); /* no check for sqn is performed, so no AUTS synchronization performed */ /* Format data for output in the SIP message */ for(i=0;i<RESLEN;i++){ resp_hex[2*i]=hexa[(res[i]&0xF0)>>4]; resp_hex[2*i+1]=hexa[res[i]&0x0F]; } resp_hex[RESHEXLEN-1]=0;done: switch (version){ case 1: /* AKA v1 */ /* Nothing to do */ break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -