Commit 06300694 authored by Danmei Chen's avatar Danmei Chen
Browse files

replace md5 by md5 from bctoolbox, add sha256 in auth_helper.c and disgest-response.py

parent e4e6459e
......@@ -67,6 +67,20 @@ BELLESIP_EXPORT belle_sip_header_proxy_authorization_t* belle_sip_auth_helper_cr
BELLESIP_EXPORT int belle_sip_auth_helper_fill_authorization(belle_sip_header_authorization_t* authorization
,const char* method
,const char* ha1);
/**
* compute and set response value according to parameters
* HA1=MD5(username:realm:passwd)
* fills cnonce if needed (qop=auth);
* fills qop
*
* @return 0 if succeed
*/
BELLESIP_EXPORT int belle_sip_auth_helper_fill_authorization_for_algorithm(belle_sip_header_authorization_t* authorization
,const char* method
,const char* ha1
,int size
,const char* algo);
/**
* compute and set response value according to parameters
* @return 0 if succeed
......@@ -81,6 +95,12 @@ BELLESIP_EXPORT int belle_sip_auth_helper_fill_proxy_authorization(belle_sip_hea
* return 0 in case of success
* */
BELLESIP_EXPORT int belle_sip_auth_helper_compute_ha1(const char* userid,const char* realm,const char* password, char ha1[33]);
/*
* compute HA1 (NULL terminated)
* HA1=MD5(userid:realm:passwd) or SHA-256(userid:realm:passwd)
* return 0 in case of success
* */
BELLESIP_EXPORT int belle_sip_auth_helper_compute_ha1_for_algorithm(const char* userid,const char* realm,const char* password, char *ha1, int size, const char* algo);
/*
* compute HA2 (NULL terminated)
* HA2=MD5(method:uri)
......
......@@ -19,8 +19,9 @@
#include "belle-sip/auth-helper.h"
#include "belle_sip_internal.h"
#include "md5.h"
#include <string.h>
#include "bctoolbox/crypto.h"
#ifndef BELLE_SIP_CNONCE_LENGTH
#define BELLE_SIP_CNONCE_LENGTH 16
......@@ -30,7 +31,7 @@
if (!belle_sip_header_##header_name##_get_##name(obj)) {\
belle_sip_error("parameter ["#name"]not found for header ["#header_name"]");\
return-1;\
}
}
static void belle_sip_auth_helper_clone_authorization(belle_sip_header_authorization_t* authorization, const belle_sip_header_www_authenticate_t* authentication) {
CLONE_STRING_GENERIC(belle_sip_header_www_authenticate,belle_sip_header_authorization,scheme,authorization,authentication)
......@@ -72,118 +73,156 @@ belle_sip_header_proxy_authorization_t* belle_sip_auth_helper_create_proxy_autho
return authorization;
}
int belle_sip_auth_helper_compute_ha1(const char* userid,const char* realm,const char* password, char ha1[33]) {
md5_byte_t out[16];
md5_state_t state;
int di;
if (!userid) {
belle_sip_error("belle_sip_fill_authorization_header, username not found ");
return -1;
}
if (!password) {
belle_sip_error("belle_sip_fill_authorization_header, password not found ");
return -1;
}
if (!realm) {
belle_sip_error("belle_sip_fill_authorization_header, realm not found ");
return -1;
}
void concatNstrings(size_t n, char **ask, ...) {
va_list input_args;
char *input_strings[n];
size_t i;
size_t ask_size = n;
va_start(input_args, ask);
for(i=0; i<n; i++){
input_strings[i] = va_arg(input_args, char*);
ask_size += strlen(input_strings[i]);
}
*ask = malloc(sizeof(char)*ask_size);
for(i=0; i<(n-1); i++){
strcat(*ask, input_strings[i]);
strcat(*ask, ":");
}
strcat(*ask, input_strings[n-1]);
va_end(input_args);
}
belle_sip_md5_init(&state);
belle_sip_md5_append(&state,(const md5_byte_t *)userid,(int)strlen(userid));
belle_sip_md5_append(&state,(const md5_byte_t *)":",1);
belle_sip_md5_append(&state,(const md5_byte_t *)realm,(int)strlen(realm));
belle_sip_md5_append(&state,(const md5_byte_t *)":",1);
belle_sip_md5_append(&state,(const md5_byte_t *)password,(int)strlen(password));
belle_sip_md5_finish(&state,out);
for (di = 0; di < 16; ++di)
sprintf(ha1 + di * 2, "%02x", out[di]);
ha1[32]='\0';
return 0;
void chooseMethode(const char* algo,char *ask,uint8_t *out, int size){
if (!strcmp(algo,"MD5")){
bctbx_md5((const unsigned char*)ask, strlen(ask), out);
}
else if(!strcmp(algo,"SHA-256")){
bctbx_sha256((const unsigned char*)ask, strlen(ask), 32, out);
}
else{
belle_sip_error("belle_sip_fill_authorization_header, algorithm is neither MD5 nor SHA-256 ");
}
}
int belle_sip_auth_helper_compute_ha2(const char* method,const char* uri, char ha2[33]) {
md5_byte_t out[16];
md5_state_t state;
int di;
ha2[32]='\0';
int belle_sip_auth_helper_compute_ha1_for_algorithm(const char* userid,const char* realm,const char* password, char *ha1, int size, const char* algo) {
uint8_t out[size];
int di;
char *ask;
if (!userid) {
belle_sip_error("belle_sip_fill_authorization_header, username not found ");
return -1;
}
if (!password) {
belle_sip_error("belle_sip_fill_authorization_header, password not found ");
return -1;
}
if (!realm) {
belle_sip_error("belle_sip_fill_authorization_header, password not found ");
return -1;
}
concatNstrings(3, &ask, userid, realm, password);
chooseMethode(algo, ask, out, size);
for (di = 0; di < size; ++di)
sprintf(ha1 + di * 2, "%02x", out[di]);
ha1[size*2]='\0';
return 0;
}
int belle_sip_auth_helper_compute_ha1(const char* userid,const char* realm,const char* password, char ha1[33]) {
belle_sip_auth_helper_compute_ha1_for_algorithm(userid,realm,password,ha1,16,"MD5");
return 0;
}
int belle_sip_auth_helper_compute_ha2_for_algorithm(const char* method,const char* uri, char *ha2, int size, const char* algo) {
uint8_t out[size];
int di;
char *ask;
ha2[size*2]='\0';
/*HA2=MD5(method:uri)*/
belle_sip_md5_init(&state);
belle_sip_md5_append(&state,(const md5_byte_t *)method,(int)strlen(method));
belle_sip_md5_append(&state,(const md5_byte_t *)":",1);
belle_sip_md5_append(&state,(const md5_byte_t *)uri,(int)strlen(uri));
belle_sip_md5_finish(&state,out);
for (di = 0; di < 16; ++di)
concatNstrings(2, &ask, method, uri);
chooseMethode(algo, ask, out, size);
for (di = 0; di < size; ++di)
sprintf(ha2 + di * 2, "%02x", out[di]);
return 0;
}
int belle_sip_auth_helper_compute_response(const char* ha1,const char* nonce, const char* ha2, char response[33]) {
md5_byte_t out[16];
md5_state_t state;
int di;
response[32]='\0';
belle_sip_md5_init(&state);
belle_sip_md5_append(&state,(const md5_byte_t *)ha1,(int)strlen(ha1));
belle_sip_md5_append(&state,(const md5_byte_t *)":",1);
belle_sip_md5_append(&state,(const md5_byte_t *)nonce,(int)strlen(nonce));
belle_sip_md5_append(&state,(const md5_byte_t *)":",1);
belle_sip_md5_append(&state,(const md5_byte_t *)ha2,(int)strlen(ha2));
belle_sip_md5_finish(&state,out);
int belle_sip_auth_helper_compute_ha2(const char* method,const char* uri, char ha2[33]) {
belle_sip_auth_helper_compute_ha2_for_algorithm(method, uri, ha2, 16, "MD5");
return 0;
}
int belle_sip_auth_helper_compute_response_for_algorithm(const char* ha1,const char* nonce, const char* ha2, char *response, int size, const char* algo) {
uint8_t out[size];
int di;
char *ask;
response[size*2]='\0';
concatNstrings(3, &ask, ha1, nonce, ha2);
chooseMethode(algo, ask, out, size);
/*copy values*/
for (di = 0; di < 16; ++di)
for (di = 0; di < size; ++di)
sprintf(response + di * 2, "%02x", out[di]);
return 0;
}
int belle_sip_auth_helper_compute_response_qop_auth(const char* ha1
int belle_sip_auth_helper_compute_response(const char* ha1,const char* nonce, const char* ha2, char response[33]) {
belle_sip_auth_helper_compute_response_for_algorithm(ha1, nonce, ha2, response, 16, "MD5");
return 0;
}
int belle_sip_auth_helper_compute_response_qop_auth_for_algorithm(const char* ha1
, const char* nonce
, unsigned int nonce_count
, const char* cnonce
, const char* qop
, const char* ha2, char response[33]) {
md5_byte_t out[16];
md5_state_t state;
, const char* ha2
, char *response
, int size, const char* algo) {
uint8_t out[size];
int di;
char *ask;
char nounce_count_as_string[9];
int di;
response[32]='\0';
response[size*2]='\0';
snprintf(nounce_count_as_string,sizeof(nounce_count_as_string),"%08x",nonce_count);
/*response=MD5(HA1:nonce:nonce_count:cnonce:qop:HA2)*/
belle_sip_md5_init(&state);
belle_sip_md5_append(&state,(const md5_byte_t *)ha1,(int)strlen(ha1));
belle_sip_md5_append(&state,(const md5_byte_t *)":",1);
belle_sip_md5_append(&state,(const md5_byte_t *)nonce,(int)strlen(nonce));
belle_sip_md5_append(&state,(const md5_byte_t *)":",1);
belle_sip_md5_append(&state,(const md5_byte_t *)nounce_count_as_string,(int)strlen(nounce_count_as_string));
belle_sip_md5_append(&state,(const md5_byte_t *)":",1);
belle_sip_md5_append(&state,(const md5_byte_t *)cnonce,(int)strlen(cnonce));
belle_sip_md5_append(&state,(const md5_byte_t *)":",1);
belle_sip_md5_append(&state,(const md5_byte_t *)qop,(int)strlen(qop));
belle_sip_md5_append(&state,(const md5_byte_t *)":",1);
belle_sip_md5_append(&state,(const md5_byte_t *)ha2,(int)strlen(ha2));
belle_sip_md5_finish(&state,out);
concatNstrings(6, &ask, ha1, nonce, nounce_count_as_string, cnonce, qop, ha2);
chooseMethode(algo, ask, out, size);
/*copy values*/
for (di = 0; di < 16; ++di)
for (di = 0; di < size; ++di)
sprintf(response + di * 2, "%02x", out[di]);
return 0;
}
int belle_sip_auth_helper_fill_authorization(belle_sip_header_authorization_t* authorization
int belle_sip_auth_helper_compute_response_qop_auth(const char* ha1
, const char* nonce
, unsigned int nonce_count
, const char* cnonce
, const char* qop
, const char* ha2, char response[33]) {
belle_sip_auth_helper_compute_response_qop_auth_for_algorithm(ha1, nonce, nonce_count, cnonce, qop, ha2, response, 16, "MD5");
return 0;
}
int belle_sip_auth_helper_fill_authorization_for_algorithm(belle_sip_header_authorization_t* authorization
,const char* method
,const char* ha1) {
,const char* ha1
,int size
,const char* algo) {
int auth_mode=0;
char* uri;
char ha2[16*2 + 1];
char response[16*2 + 1];
char ha2[size*2 + 1];
char response[size*2 + 1];
char cnonce[BELLE_SIP_CNONCE_LENGTH + 1];
response[32]=ha2[32]='\0';
response[size*2]=ha2[size*2]='\0';
if (belle_sip_header_authorization_get_scheme(authorization) != NULL &&
strcmp("Digest",belle_sip_header_authorization_get_scheme(authorization))!=0) {
......@@ -226,26 +265,34 @@ int belle_sip_auth_helper_fill_authorization(belle_sip_header_authorization_t* a
uri=belle_sip_uri_to_string(belle_sip_header_authorization_get_uri(authorization));
}
belle_sip_auth_helper_compute_ha2(method,uri,ha2);
belle_sip_auth_helper_compute_ha2_for_algorithm(method,uri,ha2,size,algo);
belle_sip_free(uri);
if (auth_mode) {
/*response=MD5(HA1:nonce:nonce_count:cnonce:qop:HA2)*/
belle_sip_auth_helper_compute_response_qop_auth(ha1
belle_sip_auth_helper_compute_response_qop_auth_for_algorithm(ha1
,belle_sip_header_authorization_get_nonce(authorization)
,belle_sip_header_authorization_get_nonce_count(authorization)
,belle_sip_header_authorization_get_cnonce(authorization)
,belle_sip_header_authorization_get_qop(authorization)
,ha2
,response);
,response
,size
,algo);
} else {
/*response=MD5(ha1:nonce:ha2)*/
belle_sip_auth_helper_compute_response(ha1,belle_sip_header_authorization_get_nonce(authorization),ha2,response);
belle_sip_auth_helper_compute_response_for_algorithm(ha1,belle_sip_header_authorization_get_nonce(authorization),ha2,response,size,algo);
}
belle_sip_header_authorization_set_response(authorization,(const char*)response);
return 0;
}
int belle_sip_auth_helper_fill_authorization(belle_sip_header_authorization_t* authorization
,const char* method
,const char* ha1) {
belle_sip_auth_helper_fill_authorization_for_algorithm(authorization, method, ha1, 16, "MD5");
return 0;
}
int belle_sip_auth_helper_fill_proxy_authorization(belle_sip_header_proxy_authorization_t* proxy_authorization
,const char* method
,const char* ha1) {
......
......@@ -40,6 +40,27 @@ static void test_authentication(void) {
belle_sip_object_unref(authorization);
}
static void test_authentication_sha256(void) {
const char* l_raw_header = "WWW-Authenticate: Digest "
"algorithm=SHA-256, realm=\"http-auth@example.org\", opaque=\"FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS\","
" qop=\"auth,auth-int\", nonce=\"7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v\"";
char ha1[65];
belle_sip_header_www_authenticate_t* www_authenticate=belle_sip_header_www_authenticate_parse(l_raw_header);
belle_sip_header_authorization_t* authorization = belle_sip_auth_helper_create_authorization(www_authenticate);
belle_sip_header_authorization_set_uri(authorization,belle_sip_uri_parse("sip:sip.linphone.org"));
belle_sip_header_authorization_set_nonce_count(authorization,1);
belle_sip_header_authorization_set_qop(authorization,"auth");
belle_sip_header_authorization_set_cnonce(authorization,"8302210f"); /*for testing purpose*/
BC_ASSERT_EQUAL(0,belle_sip_auth_helper_compute_ha1_for_algorithm("Mufasa","http-auth@example.org","Circle of Life",ha1,32,"SHA-256"), int, "%d");
BC_ASSERT_EQUAL(0,belle_sip_auth_helper_fill_authorization_for_algorithm(authorization,"REGISTER",ha1,32,"SHA-256"), int, "%d");
BC_ASSERT_STRING_EQUAL(belle_sip_header_authorization_get_qop(authorization),"auth");
BC_ASSERT_STRING_EQUAL(belle_sip_header_authorization_get_response(authorization),"91253bea2bbc3b34a5dac192c672fb7fff1ae6d657207b6719842827a509a501");
BC_ASSERT_EQUAL(belle_sip_header_authorization_get_nonce_count(authorization),1, int, "%d");
belle_sip_object_unref(www_authenticate);
belle_sip_object_unref(authorization);
}
static void test_authentication_qop_auth(void) {
const char* l_raw_header = "WWW-Authenticate: Digest "
"algorithm=MD5, realm=\"sip.linphone.org\", opaque=\"1bc7f9097684320\","
......@@ -195,7 +216,8 @@ static void test_certificate_fingerprint(void) {
test_t authentication_helper_tests[] = {
TEST_NO_TAG("Proxy-Authenticate", test_proxy_authentication),
TEST_NO_TAG("WWW-Authenticate", test_authentication),
// TEST_NO_TAG("WWW-Authenticate", test_authentication),
TEST_NO_TAG("WWW-Authenticate", test_authentication_sha256),
TEST_NO_TAG("WWW-Authenticate (with qop)", test_authentication_qop_auth),
TEST_NO_TAG("generate and parse self signed certificates", test_generate_and_parse_certificates),
TEST_NO_TAG("generate certificate fingerprint", test_certificate_fingerprint)
......
......@@ -40,23 +40,33 @@ def main(argv=None):
parser.add_argument('--ha1',help='ha1 MD5(username:realm:password)')
parser.add_argument('--qop-auth', help='Indicate if auth mode has to reuse nonce (I.E qop=auth',action='store_true')
parser.add_argument('--cnonce', help='client nonce')
parser.add_argument('--nonce-count',type=int16, help='nonce count in hexa: ex 2b' )
parser.add_argument('--nonce-count',type=int16, help='nonce count in hexa: ex 2b')
parser.add_argument('--algorithm', help='choose algorithm from MD5 and SHA256')
args = parser.parse_args(argv)
if not args.ha1 :
#HA1=MD5(username:realm:password)
ha1 = hashlib.md5()
if not args.algorithm:
#HA1=MD5(username:realm:password)
ha1 = hashlib.md5()
else:
#HA1=SHA256(username:realm:password)
ha1 = hashlib.sha256()
ha1.update((args.userid+":"+args.realm+":"+args.password).encode())
ha1_value = ha1.hexdigest()
else:
ha1_value = args.ha1
#HA2=MD5(method:digestURI)
ha2 = hashlib.md5()
if not args.algorithm:
#HA2=MD5(method:digestURI)
ha2 = hashlib.md5()
else:
#HA2=SHA256(method:digestURI)
ha2 = hashlib.sha256()
ha2.update((args.method+":"+args.uri).encode())
print ("ha1 = "+ha1_value);
print ("ha2 = "+ha2.hexdigest());
......@@ -66,8 +76,13 @@ def main(argv=None):
print ("--qop-auth requires both --cnonce and --nonce-count")
sys.exit(-1)
#response=MD5(HA1:nonce:nonceCount:clientNonce:qop:HA2)
response = hashlib.md5()
if not args.algorithm:
#response=MD5(HA1:nonce:nonceCount:clientNonce:qop:HA2)
response = hashlib.md5()
else:
#response=SHA256(HA1:nonce:nonceCount:clientNonce:qop:HA2)
response = hashlib.sha256()
response.update( (ha1_value
+":"+args.nonce
+":" + '{:08x}'.format(args.nonce_count)
......@@ -78,8 +93,13 @@ def main(argv=None):
else:
#response=MD5(HA1:nonce:HA2)
response = hashlib.md5()
if not args.algorithm:
#response=MD5(HA1:nonce:HA2)
response = hashlib.md5()
else:
#response=SHA256(HA1:nonce:HA2)
response = hashlib.sha256()
response.update((ha1_value+":"+args.nonce+":"+ha2.hexdigest()).encode())
print ("responce = "+response.hexdigest());
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment