# HG changeset patch # User Alexandre Westfahl # Date 1278573568 -32400 # Node ID c2fb5b26bfcb379c5d8f5c048ec6de7e24804a9b # Parent 9a9a9e1ed4cbc31c2450b87f24120d15d67477a5 Fix for ticket 8 diff -r 9a9a9e1ed4cb -r c2fb5b26bfcb extensions/app_sip/diamsip.c --- a/extensions/app_sip/diamsip.c Thu Jul 08 15:16:11 2010 +0900 +++ b/extensions/app_sip/diamsip.c Thu Jul 08 16:19:28 2010 +0900 @@ -36,6 +36,13 @@ #include "diamsip.h" struct disp_hdl * diamsip_MAR_hdl=NULL; +struct disp_hdl * diamsip_LIR_hdl=NULL; +struct disp_hdl * diamsip_UAR_hdl=NULL; +struct disp_hdl * diamsip_SAR_hdl=NULL; +struct disp_hdl * diamsip_PPA_hdl=NULL; +struct disp_hdl * diamsip_RTA_hdl=NULL; + + struct disp_hdl * diamsip_default_hdl=NULL; struct session_handler * ds_sess_hdl; @@ -136,16 +143,20 @@ //Register Application memset(&data, 0, sizeof(data)); CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Diameter Session Initiation Protocol (SIP) Application", &data.app, ENOENT) ); - CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Multimedia-Auth-Request", &data.command, ENOENT) ); - //Callback for unexpected messages - CHECK_FCT( fd_disp_register( diamsip_MAR_cb, DISP_HOW_APPID, &data, &diamsip_default_hdl ) ); //**Command Codes //MAR + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Multimedia-Auth-Request", &data.command, ENOENT) ); CHECK_FCT( fd_disp_register( diamsip_MAR_cb, DISP_HOW_CC, &data, &diamsip_MAR_hdl ) ); + //RTA + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Registration-Termination-Answer", &data.command, ENOENT) ); + CHECK_FCT( fd_disp_register( diamsip_RTA_cb, DISP_HOW_CC, &data, &diamsip_RTA_hdl ) ); - //TRACE_DEBUG(INFO,"*%s*%s*%s*%s*",DB_SERVER,DB_USERNAME, DB_PASSWORD, DB_DATABASE); + //Callback for unexpected messages + CHECK_FCT( fd_disp_register( diamsip_default_cb, DISP_HOW_APPID, &data, &diamsip_default_hdl ) ); + + //We start database connection if(start_mysql_connection()) return 1; @@ -159,10 +170,10 @@ void fd_ext_fini(void) { - if (diamsip_MAR_cb) { - (void) fd_disp_unregister(&diamsip_MAR_hdl); - CHECK_FCT_DO( fd_sess_handler_destroy(&ds_sess_hdl),return); - } + + (void) fd_disp_unregister(&diamsip_MAR_hdl); + CHECK_FCT_DO( fd_sess_handler_destroy(&ds_sess_hdl),return); + //We close database connection close_mysql_connection(); diff -r 9a9a9e1ed4cb -r c2fb5b26bfcb extensions/app_sip/diamsip.h --- a/extensions/app_sip/diamsip.h Thu Jul 08 15:16:11 2010 +0900 +++ b/extensions/app_sip/diamsip.h Thu Jul 08 16:19:28 2010 +0900 @@ -75,18 +75,23 @@ void calc_md5(char *buffer, char * data); -void clear_digest(char * digest, char * readable_digest, int digestlength); +void clear_digest(uint8_t * digest, char * readable_digest, int digestlength); struct avp_hdr * walk_digest(struct avp *avp, int avp_code); int start_mysql_connection(); void request_mysql(char *query); void close_mysql_connection(); +void DigestCalcHA1(char * pszAlg,char * pszUserName,char * pszRealm,char * pszPassword,char * pszNonce,char * pszCNonce,HASHHEX SessionKey); +void DigestCalcResponse(HASHHEX HA1,char * pszNonce,char * pszNonceCount,char * pszCNonce,char * pszQop,char * pszMethod,char * pszDigestUri,HASHHEX HEntity,HASHHEX Response); +void DigestCalcResponseAuth(HASHHEX HA1,char * pszNonce,char * pszNonceCount,char * pszCNonce,char * pszQop,char * pszMethod,char * pszDigestUri,HASHHEX HEntity,HASHHEX Response); +int fd_avp_search_avp ( struct avp * groupedavp, struct dict_object * what, struct avp ** avp ); int ds_entry(); void fd_ext_fini(void); int diamsip_default_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act); int diamsip_MAR_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act); +int diamsip_RTA_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act); #define SQL_GETPASSWORD "SELECT `password` FROM ds_users WHERE `username` ='%s'" #define SQL_GETPASSWORD_LEN 52 diff -r 9a9a9e1ed4cb -r c2fb5b26bfcb extensions/app_sip/libdiamsip.c --- a/extensions/app_sip/libdiamsip.c Thu Jul 08 15:16:11 2010 +0900 +++ b/extensions/app_sip/libdiamsip.c Thu Jul 08 16:19:28 2010 +0900 @@ -37,15 +37,8 @@ #include "diamsip.h" MYSQL *conn; -/* -void calculate_nonce(u8 * nonce) -{ - nonce="lkgbsljhsdjdsgj"; - return; -}*/ - -void clear_digest(char * digest, char * readable_digest, int digestlength) +void clear_digest(uint8_t * digest, char * readable_digest, int digestlength) { int i=0; for(i=0;iavp_code==avp_code) { @@ -148,7 +141,7 @@ } else { - CHECK_FCT_DO(fd_msg_browse ( avp, MSG_BRW_WALK, &avp, NULL),0 ); + CHECK_FCT_DO(fd_msg_browse ( avp, MSG_BRW_WALK, &avp, NULL),return NULL); temphdr=NULL; } diff -r 9a9a9e1ed4cb -r c2fb5b26bfcb extensions/app_sip/md5.c --- a/extensions/app_sip/md5.c Thu Jul 08 15:16:11 2010 +0900 +++ b/extensions/app_sip/md5.c Thu Jul 08 16:19:28 2010 +0900 @@ -52,20 +52,20 @@ HASH HA1; MD5Init(&Md5Ctx); - MD5Update(&Md5Ctx, pszUserName, strlen(pszUserName)); - MD5Update(&Md5Ctx, ":", 1); - MD5Update(&Md5Ctx, pszRealm, strlen(pszRealm)); - MD5Update(&Md5Ctx, ":", 1); - MD5Update(&Md5Ctx, pszPassword, strlen(pszPassword)); - MD5Final(HA1, &Md5Ctx); + MD5Update(&Md5Ctx, (const unsigned char *)pszUserName, strlen(pszUserName)); + MD5Update(&Md5Ctx, (const unsigned char *)":", 1); + MD5Update(&Md5Ctx, (const unsigned char *)pszRealm, strlen(pszRealm)); + MD5Update(&Md5Ctx, (const unsigned char *)":", 1); + MD5Update(&Md5Ctx, (const unsigned char *)pszPassword, strlen(pszPassword)); + MD5Final((unsigned char *)HA1, &Md5Ctx); if (strcmp(pszAlg, "md5-sess") == 0) { MD5Init(&Md5Ctx); - MD5Update(&Md5Ctx, HA1, HASHLEN); - MD5Update(&Md5Ctx, ":", 1); - MD5Update(&Md5Ctx, pszNonce, strlen(pszNonce)); - MD5Update(&Md5Ctx, ":", 1); - MD5Update(&Md5Ctx, pszCNonce, strlen(pszCNonce)); - MD5Final(HA1, &Md5Ctx); + MD5Update(&Md5Ctx, (const unsigned char *)HA1, HASHLEN); + MD5Update(&Md5Ctx, (const unsigned char *)":", 1); + MD5Update(&Md5Ctx, (const unsigned char *)pszNonce, strlen(pszNonce)); + MD5Update(&Md5Ctx, (const unsigned char *)":", 1); + MD5Update(&Md5Ctx, (const unsigned char *)pszCNonce, strlen(pszCNonce)); + MD5Final((unsigned char *)HA1, &Md5Ctx); } CvtHex(HA1, SessionKey); } @@ -80,32 +80,32 @@ // calculate H(A2) MD5Init(&Md5Ctx); - MD5Update(&Md5Ctx, pszMethod, strlen(pszMethod)); - MD5Update(&Md5Ctx, ":", 1); - MD5Update(&Md5Ctx, pszDigestUri, strlen(pszDigestUri)); + MD5Update(&Md5Ctx, (const unsigned char *)pszMethod, strlen(pszMethod)); + MD5Update(&Md5Ctx, (const unsigned char *)":", 1); + MD5Update(&Md5Ctx, (const unsigned char *)pszDigestUri, strlen(pszDigestUri)); if (strcmp(pszQop, "auth-int") == 0) { - MD5Update(&Md5Ctx, ":", 1); - MD5Update(&Md5Ctx, HEntity, HASHHEXLEN); + MD5Update(&Md5Ctx, (const unsigned char *)":", 1); + MD5Update(&Md5Ctx, (const unsigned char *)HEntity, HASHHEXLEN); } - MD5Final(HA2, &Md5Ctx); + MD5Final((unsigned char *)HA2, &Md5Ctx); CvtHex(HA2, HA2Hex); // calculate response MD5Init(&Md5Ctx); - MD5Update(&Md5Ctx, HA1, HASHHEXLEN); - MD5Update(&Md5Ctx, ":", 1); - MD5Update(&Md5Ctx, pszNonce, strlen(pszNonce)); - MD5Update(&Md5Ctx, ":", 1); + MD5Update(&Md5Ctx, (const unsigned char *)HA1, HASHHEXLEN); + MD5Update(&Md5Ctx, (const unsigned char *)":", 1); + MD5Update(&Md5Ctx,(const unsigned char *) pszNonce, strlen(pszNonce)); + MD5Update(&Md5Ctx, (const unsigned char *)":", 1); if (*pszQop) { - MD5Update(&Md5Ctx, pszNonceCount, strlen(pszNonceCount)); - MD5Update(&Md5Ctx, ":", 1); - MD5Update(&Md5Ctx, pszCNonce, strlen(pszCNonce)); - MD5Update(&Md5Ctx, ":", 1); - MD5Update(&Md5Ctx, pszQop, strlen(pszQop)); - MD5Update(&Md5Ctx, ":", 1); + MD5Update(&Md5Ctx, (const unsigned char *)pszNonceCount, strlen(pszNonceCount)); + MD5Update(&Md5Ctx, (const unsigned char *)":", 1); + MD5Update(&Md5Ctx, (const unsigned char *)pszCNonce, strlen(pszCNonce)); + MD5Update(&Md5Ctx, (const unsigned char *)":", 1); + MD5Update(&Md5Ctx, (const unsigned char *)pszQop, strlen(pszQop)); + MD5Update(&Md5Ctx, (const unsigned char *)":", 1); } - MD5Update(&Md5Ctx, HA2Hex, HASHHEXLEN); - MD5Final(RespHash, &Md5Ctx); + MD5Update(&Md5Ctx, (const unsigned char *)HA2Hex, HASHHEXLEN); + MD5Final((unsigned char *)RespHash, &Md5Ctx); CvtHex(RespHash, Response); } // calculate Digest_response_Auth as per SIP Digest spec RFC5090 @@ -118,31 +118,31 @@ // calculate H(A2) MD5Init(&Md5Ctx); - MD5Update(&Md5Ctx, ":", 1); - MD5Update(&Md5Ctx, pszDigestUri, strlen(pszDigestUri)); + MD5Update(&Md5Ctx, (const unsigned char *)":", 1); + MD5Update(&Md5Ctx, (const unsigned char *)pszDigestUri, strlen(pszDigestUri)); if (strcmp(pszQop, "auth-int") == 0) { - MD5Update(&Md5Ctx, ":", 1); - MD5Update(&Md5Ctx, HEntity, HASHHEXLEN); + MD5Update(&Md5Ctx, (const unsigned char *)":", 1); + MD5Update(&Md5Ctx, (const unsigned char *)HEntity, HASHHEXLEN); } - MD5Final(HA2, &Md5Ctx); + MD5Final((unsigned char *)HA2, &Md5Ctx); CvtHex(HA2, HA2Hex); // calculate response MD5Init(&Md5Ctx); - MD5Update(&Md5Ctx, HA1, HASHHEXLEN); - MD5Update(&Md5Ctx, ":", 1); - MD5Update(&Md5Ctx, pszNonce, strlen(pszNonce)); - MD5Update(&Md5Ctx, ":", 1); + MD5Update(&Md5Ctx, (const unsigned char *)HA1, HASHHEXLEN); + MD5Update(&Md5Ctx, (const unsigned char *)":", 1); + MD5Update(&Md5Ctx, (const unsigned char *)pszNonce, strlen(pszNonce)); + MD5Update(&Md5Ctx, (const unsigned char *)":", 1); if (*pszQop) { - MD5Update(&Md5Ctx, pszNonceCount, strlen(pszNonceCount)); - MD5Update(&Md5Ctx, ":", 1); - MD5Update(&Md5Ctx, pszCNonce, strlen(pszCNonce)); - MD5Update(&Md5Ctx, ":", 1); - MD5Update(&Md5Ctx, pszQop, strlen(pszQop)); - MD5Update(&Md5Ctx, ":", 1); + MD5Update(&Md5Ctx, (const unsigned char *)pszNonceCount, strlen(pszNonceCount)); + MD5Update(&Md5Ctx, (const unsigned char *)":", 1); + MD5Update(&Md5Ctx, (const unsigned char *)pszCNonce, strlen(pszCNonce)); + MD5Update(&Md5Ctx, (const unsigned char *)":", 1); + MD5Update(&Md5Ctx, (const unsigned char *)pszQop, strlen(pszQop)); + MD5Update(&Md5Ctx, (const unsigned char *)":", 1); } - MD5Update(&Md5Ctx, HA2Hex, HASHHEXLEN); - MD5Final(RespHash, &Md5Ctx); + MD5Update(&Md5Ctx, (const unsigned char *)HA2Hex, HASHHEXLEN); + MD5Final((unsigned char *)RespHash, &Md5Ctx); CvtHex(RespHash, Response); } diff -r 9a9a9e1ed4cb -r c2fb5b26bfcb extensions/app_sip/multimediaauth.c --- a/extensions/app_sip/multimediaauth.c Thu Jul 08 15:16:11 2010 +0900 +++ b/extensions/app_sip/multimediaauth.c Thu Jul 08 16:19:28 2010 +0900 @@ -40,14 +40,14 @@ { struct msg *ans, *qry; struct avp *avp, *a2, *authdataitem; - struct msg_hdr * header = NULL; + //struct msg_hdr * header = NULL; struct avp_hdr * avphdr=NULL, *avpheader=NULL, *avpheader_auth=NULL,*digestheader=NULL; union avp_value val; int found_cnonce=0; struct avp * tempavp=NULL,*sipAuthentication=NULL,*sipAuthenticate=NULL; char * result; char password[51]; - int idx=0, idx2=0, number_of_auth_items=0,i=0; + int idx=0, number_of_auth_items=0,i=0; //Flags and variables for Database int sipurinotstored=0, authenticationpending=0, querylen=0, usernamelen=0; char *query=NULL,*username=NULL; @@ -69,7 +69,7 @@ - /* Add the appropriate command code & Auth-Application-Id */ + /* Add the appropriate command code & Auth-Application-Id { CHECK_FCT( fd_msg_hdr ( *msg, &header ) ); @@ -78,7 +78,7 @@ header->msg_appl = 6; - /* Add the Auth-Application-Id */ + // Add the Auth-Application-Id { CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Application_Id, 0, &avp ) ); ASSERT(avp); @@ -86,7 +86,7 @@ CHECK_FCT( fd_msg_avp_setvalue ( avp, &val ) ); CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) ); } - } + }*/ /* Add the Auth-Session-State AVP */ @@ -124,10 +124,10 @@ //We allocate the double size of username because at worst it can be all quotes username=malloc(avphdr->avp_value->os.len*2+1); //We purify username not to have forbidden characters - usernamelen=mysql_real_escape_string(conn, username, avphdr->avp_value->os.data, avphdr->avp_value->os.len); + usernamelen=mysql_real_escape_string(conn, username, (const char *)avphdr->avp_value->os.data, avphdr->avp_value->os.len); - if((strncmp(avpheader->avp_value->os.data,"REGISTER",avpheader->avp_value->os.len)==0)) + if((strncmp((const char *)avpheader->avp_value->os.data,"REGISTER",avpheader->avp_value->os.len)==0)) { not_found=1; @@ -152,7 +152,7 @@ while ((row = mysql_fetch_row(res)) != NULL) { - if(row[0]!="") + if(strlen(row[0])>0) { strcpy(password,row[0]); not_found=0; @@ -194,7 +194,7 @@ not_found=1; while ((row = mysql_fetch_row(res)) != NULL) { - if(strncmp(avphdr->avp_value->os.data,row[0],avphdr->avp_value->os.len)==0) + if(strncmp((const char *)avphdr->avp_value->os.data,row[0],avphdr->avp_value->os.len)==0) { not_found=0; break; @@ -224,7 +224,7 @@ //We allocate the double size of SIP-URI because at worst it can be all quotes sipuri=malloc(avphdr->avp_value->os.len*2+1); //We purify SIP-URI not to have forbidden characters - sipurilen=mysql_real_escape_string(conn, sipuri, avphdr->avp_value->os.data, avphdr->avp_value->os.len); + sipurilen=mysql_real_escape_string(conn, sipuri, (const char *)avphdr->avp_value->os.data, avphdr->avp_value->os.len); //We get the SIP-URI assignated to the user @@ -244,7 +244,7 @@ not_found=1; while ((row = mysql_fetch_row(res)) != NULL) { - if(strncmp(avphdr->avp_value->os.data,row[0],avphdr->avp_value->os.len)==0) + if(strncmp((const char *)avphdr->avp_value->os.data,row[0],avphdr->avp_value->os.len)==0) { not_found=0; break; @@ -360,8 +360,8 @@ /* Add the Digest QOP AVP */ { CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_QOP, 0, &a2 ) ); - val.os.data="auth"; - val.os.len=strlen(val.os.data); + val.os.data=(unsigned char *)"auth"; + val.os.len=strlen((const char *)val.os.data); CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) ); CHECK_FCT( fd_msg_avp_add( sipAuthenticate, MSG_BRW_LAST_CHILD, a2 ) ); } @@ -386,7 +386,7 @@ memcpy(storednonce->nonce,(char *)nonce,NONCE_SIZE*2+1); CHECK_FCT( fd_sess_state_store ( ds_sess_hdl, sess, &storednonce )); - val.os.data=nonce; + val.os.data=(unsigned char *)nonce; val.os.len=NONCE_SIZE * 2; CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) ); @@ -395,8 +395,8 @@ /* Add the Digest Algorithm AVP */ { CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_Algorithm, 0, &a2 ) ); - val.os.data="MD5"; - val.os.len=strlen(val.os.data); + val.os.data=(unsigned char *)"MD5"; + val.os.len=strlen((const char *)val.os.data); CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) ); CHECK_FCT( fd_msg_avp_add( sipAuthenticate, MSG_BRW_LAST_CHILD, a2 ) ); @@ -463,7 +463,7 @@ { //uint8_t bufferresp[DIGEST_LEN]; //char response[DIGEST_LEN*2+1]; - int i=0; + //We extract all the data we need tempavp=avp; @@ -639,8 +639,7 @@ DigestCalcHA1(digest_algorithm, digest_username, digest_realm, password, digest_nonce,digest_cnonce, HA1); - - DigestCalcResponse(HA1, digest_nonce, digest_noncecount, digest_cnonce, digest_qop,digest_method, digest_uri, HA2, response); + DigestCalcResponse(HA1, digest_nonce, digest_noncecount, digest_cnonce, digest_qop,digest_method, digest_uri, HA2, response); // We check that the Digest-Response is the same (UA, Diameter) @@ -676,7 +675,7 @@ { //Digest-HA1 MUST be used instead of Digest-Response-Auth if Digest-Qop is 'auth-int'. CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_HA1, 0, &a2 ) ); - val.os.data=HA1; + val.os.data=(unsigned char *)HA1; val.os.len=HASHHEXLEN+1; CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) ); CHECK_FCT( fd_msg_avp_add( sipAuthentication, MSG_BRW_LAST_CHILD, a2 ) ); @@ -685,7 +684,7 @@ { //Digest-Response-Auth MUST be used instead of Digest-HA1 if Digest-Qop is 'auth'. CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_Response_Auth, 0, &a2 ) ); - val.os.data=responseauth; + val.os.data=(unsigned char *)responseauth; val.os.len=DIGEST_LEN*2; CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) ); CHECK_FCT( fd_msg_avp_add( sipAuthentication, MSG_BRW_LAST_CHILD, a2 ) ); diff -r 9a9a9e1ed4cb -r c2fb5b26bfcb extensions/app_sip/registrationtermination.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/app_sip/registrationtermination.c Thu Jul 08 16:19:28 2010 +0900 @@ -0,0 +1,98 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Alexandre Westfahl * +* * +* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. * +* * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the Teraoka Laboratory nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of Teraoka Laboratory * +* * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ +#include "diamsip.h" + + +int diamsip_RTA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, enum disp_action * act) +{ + //TODO:remove unused variables + struct msg *ans, *qry; + struct avp *avp, *a2, *authdataitem; + struct msg_hdr * header = NULL; + struct avp_hdr * avphdr=NULL, *avpheader=NULL, *avpheader_auth=NULL,*digestheader=NULL; + union avp_value val; + int found_cnonce=0; + struct avp * tempavp=NULL,*sipAuthentication=NULL,*sipAuthenticate=NULL; + char * result; + int idx=0, idx2=0, number_of_auth_items=0,i=0; + //Flags and variables for Database + int sipurinotstored=0, authenticationpending=0, querylen=0, usernamelen=0; + char *query=NULL,*username=NULL; + + + + TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act); + + if (msg == NULL) + return EINVAL; + + + /* Create answer header */ + qry = *msg; + CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) ); + ans = *msg; + + + /* Add the Auth-Session-State AVP */ + { + + CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.Auth_Session_State, &avp) ); + CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ) ); + + CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) ); + CHECK_FCT( fd_msg_avp_setvalue( avp, avphdr->avp_value ) ); + CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); + } + + CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Deregistration_Reason, &avp) ); + CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ) ); + + + + + + + + + + + + + + + return 0; +} + diff -r 9a9a9e1ed4cb -r c2fb5b26bfcb extensions/test_sip/multimediaauth.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/test_sip/multimediaauth.c Thu Jul 08 16:19:28 2010 +0900 @@ -0,0 +1,786 @@ +/******************************************************************************************************** +* Software License Agreement (BSD License) * +* Author: Alexandre Westfahl * +* * +* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. * +* * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the Teraoka Laboratory nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of Teraoka Laboratory * +* * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +********************************************************************************************************/ +#include "test_sip.h" + + +int test_sip_MAA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, enum disp_action * act) +{ +/* + struct msg *ans, *qry; + struct avp *avp, *a2, *authdataitem; + struct msg_hdr * header = NULL; + struct avp_hdr * avphdr=NULL, *avpheader=NULL, *avpheader_auth=NULL,*digestheader=NULL; + union avp_value val; + int found_cnonce=0; + struct avp * tempavp=NULL,*sipAuthentication=NULL,*sipAuthenticate=NULL; + char * result; + char password[51]; + int idx=0, idx2=0, number_of_auth_items=0,i=0; + //Flags and variables for Database + int sipurinotstored=0, authenticationpending=0, querylen=0, usernamelen=0; + char *query=NULL,*username=NULL; + + //The nonce we will store and retrieve in session + struct ds_nonce *storednonce=NULL; + + + TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act); + + if (msg == NULL) + return EINVAL; + + + // Create answer header + qry = *msg; + CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) ); + ans = *msg; + + + + // Add the appropriate command code & Auth-Application-Id + { + + CHECK_FCT( fd_msg_hdr ( *msg, &header ) ); + header->msg_flags = CMD_FLAG_PROXIABLE; + header->msg_code = 286; + header->msg_appl = 6; + + + // Add the Auth-Application-Id + { + CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Application_Id, 0, &avp ) ); + ASSERT(avp); + val.i32 = header->msg_appl; + CHECK_FCT( fd_msg_avp_setvalue ( avp, &val ) ); + CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) ); + } + } + + + // Add the Auth-Session-State AVP + { + + CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.Auth_Session_State, &avp) ); + CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ) ); + + CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) ); + CHECK_FCT( fd_msg_avp_setvalue( avp, avphdr->avp_value ) ); + CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); + } + + + + // Check if method is REGISTER then User-Name must be present + { + + CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Method, &avp) ); + CHECK_FCT( fd_msg_avp_hdr( avp, &avpheader )); + + + char *method=NULL; + + CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.User_Name, &avp) ); + if(avp!=NULL) + { + + int not_found=1; + MYSQL_RES *res=NULL; + MYSQL_ROW row; + + CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ) ); + + //We allocate the double size of username because at worst it can be all quotes + username=malloc(avphdr->avp_value->os.len*2+1); + //We purify username not to have forbidden characters + usernamelen=mysql_real_escape_string(conn, username, avphdr->avp_value->os.data, avphdr->avp_value->os.len); + + + if((strncmp(avpheader->avp_value->os.data,"REGISTER",avpheader->avp_value->os.len)==0)) + { + not_found=1; + + //We copy username in query + querylen=SQL_GETPASSWORD_LEN + usernamelen; + query = malloc(querylen+2); + snprintf(query, querylen+1, SQL_GETPASSWORD, username); + + + + //We make the query + request_mysql(query); + res=mysql_use_result(conn); + if(res==NULL) + { + //We couldn't make the request + result="DIAMETER_UNABLE_TO_COMPLY"; + goto out; + } + + + + while ((row = mysql_fetch_row(res)) != NULL) + { + if(row[0]!="") + { + strcpy(password,row[0]); + not_found=0; + break; + } + } + mysql_free_result(res); + free(query); + + if(not_found) + { + TRACE_DEBUG(FULL,"The user %s doesn't exist!",username); + result="DIAMETER_ERROR_USER_UNKNOWN"; + free(username); + goto out; + } + + + + //Now that we know the user exist, we get the list of AOR owned by this user + querylen=SQL_GETSIPAOR_LEN + usernamelen; + query = malloc(querylen+2); + snprintf(query, querylen+1, SQL_GETSIPAOR, username); + + //We make the query + request_mysql(query); + res=mysql_use_result(conn); + if(res==NULL) + { + //We couldn't make the request + result="DIAMETER_UNABLE_TO_COMPLY"; + goto out; + } + + //We retrieve the SIP-AOR from AVP to check if the user can us it + CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_AOR, &avp) ); + CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ) ); + + not_found=1; + while ((row = mysql_fetch_row(res)) != NULL) + { + if(strncmp(avphdr->avp_value->os.data,row[0],avphdr->avp_value->os.len)==0) + { + not_found=0; + break; + } + } + mysql_free_result(res); + free(query); + + if(not_found) + { + TRACE_DEBUG(FULL,"The user %s can't use this SIP-AOR!",username); + result="DIAMETER_ERROR_IDENTITIES_DONT_MATCH"; + free(username); + goto out; + } + + } + + CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Server_URI, &avp) ); + CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )); + + if(avphdr!=NULL) + { + char *sipuri=NULL; + int sipurilen=0; + + //We allocate the double size of SIP-URI because at worst it can be all quotes + sipuri=malloc(avphdr->avp_value->os.len*2+1); + //We purify SIP-URI not to have forbidden characters + sipurilen=mysql_real_escape_string(conn, sipuri, avphdr->avp_value->os.data, avphdr->avp_value->os.len); + + + //We get the SIP-URI assignated to the user + querylen=SQL_GETSIPURI_LEN + usernamelen; + query = malloc(querylen+2); + snprintf(query, querylen+1, SQL_GETSIPURI, username); + + //We make the query + request_mysql(query); + res=mysql_use_result(conn); + if(res==NULL) + { + //We couldn't make the request + result="DIAMETER_UNABLE_TO_COMPLY"; + goto out; + } + not_found=1; + while ((row = mysql_fetch_row(res)) != NULL) + { + if(strncmp(avphdr->avp_value->os.data,row[0],avphdr->avp_value->os.len)==0) + { + not_found=0; + break; + } + } + mysql_free_result(res); + free(query); + + if(not_found) + { + //We update the SIP_URI for the user and we flag "authentication in progress" + querylen=SQL_SETSIPURI_LEN + usernamelen + sipurilen; + query = malloc(querylen+2); + snprintf(query, querylen+1, SQL_SETSIPURI, sipuri, username); + + //We make the query + request_mysql(query); + + free(query); + authenticationpending=1; + } + free(sipuri); + + } + else + sipurinotstored=1; + + } + else + { + result="DIAMETER_USER_NAME_REQUIRED"; + goto out; + } + + + free(method); + + } + + + //TODO: remove loop for authdataitem because RFC say only one (wait for answer from Garcia) + // How many Auth Data Items? + CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Number_Auth_Items, &avp) ); + CHECK_FCT( fd_msg_avp_hdr( avp, &avpheader ) ); + + + if(avp!=NULL) + { + CHECK_FCT(fd_msg_search_avp ( qry, sip_dict.SIP_Auth_Data_Item, &avp)); + CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ) ); + + if(avp!=NULL) + { + //First is Authentication Scheme + CHECK_FCT(fd_msg_browse ( avp, MSG_BRW_FIRST_CHILD, &avp, NULL) ); + CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ) ); + + //Digest-Authentication? + if(avphdr->avp_value->i32==0) + { + + for(idx=0;idxavp_value->i32;idx++) + { + //We look for SIP Auth items + CHECK_FCT(fd_msg_browse ( avp, MSG_BRW_WALK, &avp, NULL) ); + + if(avp!=NULL) + { + + CHECK_FCT( fd_msg_avp_hdr( avp,&avphdr )); + + if(avphdr->avp_code==380) //We only create Auth-Data-Item to answer Auth-Data-Item + { + // Add the Auth-Data-Item AVP + CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Auth_Data_Item, 0, &authdataitem ) ); + + // Add the Authentication Scheme AVP + { + CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Authentication_Scheme, 0, &a2 ) ); + val.i32=0; //We only know Digest Authentication + CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) ); + CHECK_FCT( fd_msg_avp_add( authdataitem, MSG_BRW_LAST_CHILD, a2 ) ); + } + + //We need to know if there is a Cnonce attribute (only in the second MAR request) + + //CHECK_FCT(fd_msg_browse ( avp, MSG_BRW_WALK, &avp, NULL) ); + + + CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_CNonce, &a2 )); + + if(a2!=NULL) + found_cnonce=1; + else + found_cnonce=0; + + if(!found_cnonce) + { + // + We are in the case of first access request so we need to challenge the user. + + TRACE_DEBUG(FULL,"First Authorization in progress..."); + + // Create a new session //this create a new session Id !!! + //CHECK_FCT_DO( fd_sess_new( &sess, fd_g_config->cnf_diamid, "test_sip", 7), goto out ); + + + // Create the SIP-Authenticate AVP + { + CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Authenticate, 0, &sipAuthenticate ) ); + } + + // Add the Digest QOP AVP + { + CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_QOP, 0, &a2 ) ); + val.os.data="auth"; + val.os.len=strlen(val.os.data); + CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) ); + CHECK_FCT( fd_msg_avp_add( sipAuthenticate, MSG_BRW_LAST_CHILD, a2 ) ); + } + // Add the Digest Nonce AVP + { + uint8_t buffer[NONCE_SIZE]; + char nonce[NONCE_SIZE * 2 + 1]; + + + gcry_create_nonce ((uint8_t *)buffer, sizeof(buffer)); + + for(i=0;inonce=malloc(NONCE_SIZE*2+1)); + memcpy(storednonce->nonce,(char *)nonce,NONCE_SIZE*2+1); + CHECK_FCT( fd_sess_state_store ( ds_sess_hdl, sess, &storednonce )); + + val.os.data=nonce; + val.os.len=NONCE_SIZE * 2; + + CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) ); + CHECK_FCT( fd_msg_avp_add( sipAuthenticate, MSG_BRW_LAST_CHILD, a2 ) ); + } + // Add the Digest Algorithm AVP + { + CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_Algorithm, 0, &a2 ) ); + val.os.data="MD5"; + val.os.len=strlen(val.os.data); + CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) ); + CHECK_FCT( fd_msg_avp_add( sipAuthenticate, MSG_BRW_LAST_CHILD, a2 ) ); + + } + // Add the Digest Realm AVP + { + tempavp=avp; + + avpheader_auth=walk_digest(tempavp, 104); + if(avpheader_auth!=NULL) + { + CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_Realm, 0, &a2 ) ); + CHECK_FCT( fd_msg_avp_setvalue( a2, avpheader_auth->avp_value ) ); + CHECK_FCT( fd_msg_avp_add( sipAuthenticate, MSG_BRW_LAST_CHILD, a2 ) ); + + } + } + + + //We add SIP Authenticate to Auth Data Item + CHECK_FCT( fd_msg_avp_add( authdataitem, MSG_BRW_LAST_CHILD, sipAuthenticate ) ); + //We add Auth Data Item to Answer + CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, authdataitem ) ); + + number_of_auth_items++; + if(sipurinotstored) + result="DIAMETER_SUCCESS_AUTH_SENT_SERVER_NOT_STORED"; + else + result="DIAMETER_MULTI_ROUND_AUTH"; + found_cnonce=0; + } + else + { + // + We are in the case of access request after challenge so we need to check credentials. + + TRACE_DEBUG(FULL,"Authentication after challenge"); + + // Search the session, retrieve its data + { + //int new=0; + + //TRACE_DEBUG(FULL,"new: *%d*",new); + //ASSERT( new == 0 ); + CHECK_FCT( fd_sess_state_retrieve( ds_sess_hdl, sess, &storednonce )); + if(storednonce ==NULL) + { + result="DIAMETER_UNABLE_TO_COMPLY"; + + if(username!=NULL) + free(username); + goto out; + } + } + + // Create the SIP-Authentication-Info AVP + { + CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Authentication_Info, 0, &sipAuthentication ) ); + } + + + + // Add the Digest response Auth AVP + { + //uint8_t bufferresp[DIGEST_LEN]; + //char response[DIGEST_LEN*2+1]; + int i=0; + + //We extract all the data we need + tempavp=avp; + + char * digest_username=NULL, *digest_uri=NULL, *digest_response=NULL, *digest_realm=NULL, *digest_nonce=NULL, *digest_method=NULL, *digest_qop=NULL, *digest_algorithm=NULL, *digest_cnonce=NULL, *digest_noncecount=NULL; + + + CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Nonce, &a2 )); + if(a2!=NULL) + { + CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader ) ); + if(digestheader!=NULL) + { + + digest_nonce = malloc(digestheader->avp_value->os.len + 1); + memcpy(digest_nonce, digestheader->avp_value->os.data, + digestheader->avp_value->os.len); + digest_nonce[digestheader->avp_value->os.len]='\0'; + TRACE_DEBUG(FULL,"Element:*%s*",digest_nonce); + TRACE_DEBUG(FULL,"Stored Nonce:*%s*",storednonce->nonce); + + if(strcmp(digest_nonce,storednonce->nonce)!=0) + { + free(digest_nonce); + free(storednonce->nonce); + free(storednonce); + result="DIAMETER_UNABLE_TO_COMPLY"; + + if(username!=NULL) + free(username); + goto out; + } + + } + + } + CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Response, &a2 )); + if(a2!=NULL) + { + CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader ) ); + if(digestheader!=NULL) + { + digest_response = malloc(digestheader->avp_value->os.len + 1); + memcpy(digest_response, digestheader->avp_value->os.data, + digestheader->avp_value->os.len); + digest_response[digestheader->avp_value->os.len]='\0'; + TRACE_DEBUG(FULL,"Element:*%s*",digest_response); + } + + } + CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Realm, &a2 )); + if(a2!=NULL) + { + CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader ) ); + if(digestheader!=NULL) + { + digest_realm = malloc(digestheader->avp_value->os.len + 1); + memcpy(digest_realm, digestheader->avp_value->os.data, + digestheader->avp_value->os.len); + digest_realm[digestheader->avp_value->os.len]='\0'; + TRACE_DEBUG(FULL,"Element:*%s*",digest_realm); + } + } + + CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Method, &a2 )); + if(a2!=NULL) + { + CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader ) ); + if(digestheader!=NULL) + { + digest_method = malloc(digestheader->avp_value->os.len + 1); + memcpy(digest_method, digestheader->avp_value->os.data, + digestheader->avp_value->os.len); + digest_method[digestheader->avp_value->os.len]='\0'; + TRACE_DEBUG(FULL,"Element:*%s*",digest_method); + } + } + else + digest_method=""; + + CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_URI, &a2 )); + if(a2!=NULL) + { + CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader ) ); + if(digestheader!=NULL) + { + digest_uri = malloc(digestheader->avp_value->os.len + 1); + memcpy(digest_uri, digestheader->avp_value->os.data, + digestheader->avp_value->os.len); + digest_uri[digestheader->avp_value->os.len]='\0'; + TRACE_DEBUG(FULL,"Element:*%s*",digest_uri); + } + } + + CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_QOP, &a2 )); + if(a2!=NULL) + { + CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader ) ); + if(digestheader!=NULL) + { + digest_qop = malloc(digestheader->avp_value->os.len + 1); + memcpy(digest_qop, digestheader->avp_value->os.data, + digestheader->avp_value->os.len); + digest_qop[digestheader->avp_value->os.len]='\0'; + TRACE_DEBUG(FULL,"Element:*%s*",digest_qop); + } + } + else + digest_qop=NULL; + CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Algorithm, &a2 )); + if(a2!=NULL) + { + CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader ) ); + if(digestheader!=NULL) + { + digest_algorithm = malloc(digestheader->avp_value->os.len + 1); + memcpy(digest_algorithm, digestheader->avp_value->os.data, + digestheader->avp_value->os.len); + digest_algorithm[digestheader->avp_value->os.len]='\0'; + TRACE_DEBUG(FULL,"Element:*%s*",digest_algorithm); + } + } + else + digest_algorithm=NULL; + CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_CNonce, &a2 )); + if(a2!=NULL) + { + CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader ) ); + if(digestheader!=NULL) + { + digest_cnonce = malloc(digestheader->avp_value->os.len + 1); + memcpy(digest_cnonce, digestheader->avp_value->os.data, + digestheader->avp_value->os.len); + digest_cnonce[digestheader->avp_value->os.len]='\0'; + TRACE_DEBUG(FULL,"Element:*%s*",digest_cnonce); + } + } + else + digest_cnonce=""; + CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Nonce_Count, &a2 )); + if(a2!=NULL) + { + CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader ) ); + if(digestheader!=NULL) + { + digest_noncecount = malloc(digestheader->avp_value->os.len + 1); + memcpy(digest_noncecount, digestheader->avp_value->os.data, + digestheader->avp_value->os.len); + digest_noncecount[digestheader->avp_value->os.len]='\0'; + TRACE_DEBUG(FULL,"Element:*%s*",digest_noncecount); + } + } + else + digest_noncecount=""; + CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Username, &a2 )); + if(a2!=NULL) + { + CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader ) ); + if(digestheader!=NULL) + { + digest_username = malloc(digestheader->avp_value->os.len + 1); + memcpy(digest_username, digestheader->avp_value->os.data, + digestheader->avp_value->os.len); + digest_username[digestheader->avp_value->os.len]='\0'; + TRACE_DEBUG(FULL,"Element:*%s*",digest_username); + } + } + //TODO: replace by authentication function + + HASHHEX HA1; + HASHHEX HA2 = ""; + HASHHEX response, responseauth; + + + DigestCalcHA1(digest_algorithm, digest_username, digest_realm, password, digest_nonce,digest_cnonce, HA1); + + DigestCalcResponse(HA1, digest_nonce, digest_noncecount, digest_cnonce, digest_qop,digest_method, digest_uri, HA2, response); + + + // We check that the Digest-Response is the same (UA, Diameter) + if(strcmp(response,digest_response)!=0) + { + TRACE_DEBUG(FULL,"Response calculated by Diameter server:%s",response); + TRACE_DEBUG(FULL,"Response calculated by UA:%s",digest_response); + TRACE_DEBUG(INFO,"Digest-Response does not match!"); + result="DIAMETER_UNABLE_TO_COMPLY"; + free(digest_algorithm); + free(digest_cnonce); + free(digest_nonce); + free(digest_noncecount); + free(digest_method); + free(digest_username); + free(digest_uri); + free(digest_qop); + free(digest_response); + free(digest_realm); + free(storednonce->nonce); + free(storednonce); + if(username!=NULL) + free(username); + goto out; + + } + //We calculate Digest_Response_Auth + DigestCalcResponseAuth(HA1, digest_nonce, digest_noncecount, digest_cnonce, digest_qop,digest_method, digest_uri, HA2, responseauth); + + TRACE_DEBUG(FULL,"Response calculated by Diameter server:%s",response); + TRACE_DEBUG(FULL,"Response calculated by UA:%s",digest_response); + if(strcmp(digest_qop,"auth-int")==0) + { + //Digest-HA1 MUST be used instead of Digest-Response-Auth if Digest-Qop is 'auth-int'. + CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_HA1, 0, &a2 ) ); + val.os.data=HA1; + val.os.len=HASHHEXLEN+1; + CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) ); + CHECK_FCT( fd_msg_avp_add( sipAuthentication, MSG_BRW_LAST_CHILD, a2 ) ); + } + else + { + //Digest-Response-Auth MUST be used instead of Digest-HA1 if Digest-Qop is 'auth'. + CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_Response_Auth, 0, &a2 ) ); + val.os.data=responseauth; + val.os.len=DIGEST_LEN*2; + CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) ); + CHECK_FCT( fd_msg_avp_add( sipAuthentication, MSG_BRW_LAST_CHILD, a2 ) ); + } + free(digest_algorithm); + free(digest_cnonce); + free(digest_nonce); + free(digest_noncecount); + free(digest_method); + free(digest_username); + free(digest_uri); + free(digest_qop); + free(digest_response); + free(digest_realm); + free(storednonce->nonce); + free(storednonce); + + number_of_auth_items++; + } + + + //We add SIP Authentication-Info to Auth Data Item + CHECK_FCT( fd_msg_avp_add( authdataitem, MSG_BRW_LAST_CHILD, sipAuthentication ) ); + //We add Auth Data Item to Answer + CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, authdataitem ) ); + + + if(username!=NULL && authenticationpending) + { + //We clear the flag "authentication pending" + querylen=SQL_CLEARFLAG_LEN + usernamelen; + query = malloc(querylen+2); + snprintf(query, querylen+1, SQL_CLEARFLAG, username); + + //We make the query + request_mysql(query); + + free(query); + } + + if(sipurinotstored) + result="DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED"; + else + result="DIAMETER_SUCCESS"; + found_cnonce=0; + } + } + } + else + TRACE_DEBUG(INFO,"No auth data items!"); + } + //Add SIP_Number_Auth_Items AVP + { + CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Number_Auth_Items, 0, &avp ) ); + val.i32 = number_of_auth_items; + CHECK_FCT( fd_msg_avp_setvalue ( avp, &val ) ); + CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) ); + } + + + } + else + { + TRACE_DEBUG(INFO,"We only support DIGEST for now, unable to comply"); + result="DIAMETER_ERROR_AUTH_SCHEME_NOT_SUPPORTED"; + if(username!=NULL) + free(username); + goto out; + } + } + } + else + { + //TODO: remove this because Number_Auth_Items is not compulsory + TRACE_DEBUG(FULL,"Number-Auth-Items is not included."); + result="DIAMETER_UNABLE_TO_COMPLY"; + if(username!=NULL) + free(username); + goto out; + } + + if(username!=NULL) + free(username); + + +out: + // Set the Origin-Host, Origin-Realm, Result-Code AVPs + CHECK_FCT( fd_msg_rescode_set( ans, result, NULL, NULL, 1 ) ); + + + // Send the answer + CHECK_FCT( fd_msg_send( msg, NULL, NULL ) ); + +*/ + return 0; +} + diff -r 9a9a9e1ed4cb -r c2fb5b26bfcb extensions/test_sip/registrationtermination.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/test_sip/registrationtermination.c Thu Jul 08 16:19:28 2010 +0900 @@ -0,0 +1,43 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Alexandre Westfahl * +* * +* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. * +* * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the Teraoka Laboratory nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of Teraoka Laboratory * +* * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ +#include "test_sip.h" + + +int test_sip_RTR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, enum disp_action * act) +{ + + return 0; +} diff -r 9a9a9e1ed4cb -r c2fb5b26bfcb extensions/test_sip/test_sip.c --- a/extensions/test_sip/test_sip.c Thu Jul 08 15:16:11 2010 +0900 +++ b/extensions/test_sip/test_sip.c Thu Jul 08 16:19:28 2010 +0900 @@ -39,4 +39,161 @@ +struct disp_hdl * test_sip_MAA_hdl=NULL; +struct disp_hdl * test_sip_LIA_hdl=NULL; +struct disp_hdl * test_sip_UAA_hdl=NULL; +struct disp_hdl * test_sip_SAA_hdl=NULL; +struct disp_hdl * test_sip_PPR_hdl=NULL; +struct disp_hdl * test_sip_RTR_hdl=NULL; + +struct disp_hdl * test_sip_default_hdl=NULL; +struct session_handler * ts_sess_hdl; + +//configuration stucture +struct ts_conf * ts_conf=NULL; +static struct ts_conf app_sip_conf; + +//dictionary of SIP +struct test_sip_dict sip_dict; + +int test_sip_default_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act) +{ + TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act); + + return 0; +} + +username = "awestfahl" +password = "test" +sip_aor = "sip:awestfahl@tera.ics.keio.ac.jp" + +#Destination information +destination_realm = "freediameter.net" +destination_sip = "sip:awestfahl@freediameter.net" + +void dump_config() +{ + TRACE_DEBUG(FULL,"***Configuration of TEST Diameter-SIP extension***"); + TRACE_DEBUG(FULL,"# username: *%s*",ts_conf->username); + TRACE_DEBUG(FULL,"# password: *%s*",ts_conf->password); + TRACE_DEBUG(FULL,"# sip_aor: *%s*",ts_conf->sip_aor); + TRACE_DEBUG(FULL,"# destination_realm: *%s*",ts_conf->destination_realm); + TRACE_DEBUG(FULL,"# destination_sip: *%s*",ts_conf->destination_sip); + TRACE_DEBUG(FULL,"***End of TEST Diameter-SIP configuration extension***"); +} + +static int ts_conf_init(void) +{ + ts_conf=&test_sip_conf; + //memset(app_sip_conf, 0, sizeof(struct ts_conf)); + + + return 0; +} + +/* entry point */ +int as_entry(char * conffile) +{ + TRACE_ENTRY("%p", conffile); + + struct dict_object * app=NULL; + struct disp_when data; + + /* Initialize configuration */ + CHECK_FCT( ts_conf_init() ); + + + //We parse the configuration file + if (conffile != NULL) { + CHECK_FCT( ts_conf_handle(conffile) ); + } + else + { + TRACE_DEBUG(INFO, "We need a configuration file for Diameter-SIP extension. See doc/ for an example."); + } + + //We can dump the configuration extracted from app_sip.conf + dump_config(); + + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Diameter Session Initiation Protocol (SIP) Application", &app, ENOENT) ); + CHECK_FCT( fd_disp_app_support ( app, NULL, 1, 0 ) ); + + + + //We set usefull AVPs + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Session-State", &sip_dict.Auth_Session_State, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Application-Id", &sip_dict.Auth_Application_Id, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Auth-Data-Item", &sip_dict.SIP_Auth_Data_Item, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Authorization", &sip_dict.SIP_Authorization, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Authenticate", &sip_dict.SIP_Authenticate, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Number-Auth-Items", &sip_dict.SIP_Number_Auth_Items, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Authentication-Scheme", &sip_dict.SIP_Authentication_Scheme, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Authentication-Info", &sip_dict.SIP_Authentication_Info, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Server-URI", &sip_dict.SIP_Server_URI, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Method", &sip_dict.SIP_Method, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-AOR", &sip_dict.SIP_AOR, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Realm", &sip_dict.Digest_Realm, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-URI", &sip_dict.Digest_URI, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Nonce", &sip_dict.Digest_Nonce, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-CNonce", &sip_dict.Digest_CNonce, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Method", &sip_dict.Digest_Method, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Nonce-Count", &sip_dict.Digest_Nonce_Count, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Realm", &sip_dict.Digest_Realm, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Response", &sip_dict.Digest_Response, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Response-Auth", &sip_dict.Digest_Response_Auth, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Username", &sip_dict.Digest_Username, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Algorithm", &sip_dict.Digest_Algorithm, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-QoP", &sip_dict.Digest_QOP, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "User-Name", &sip_dict.User_Name, ENOENT) ); + + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-HA1", &sip_dict.Digest_HA1, ENOENT) ); + + + //Register Application + memset(&data, 0, sizeof(data)); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Diameter Session Initiation Protocol (SIP) Application", &data.app, ENOENT) ); + + + //**Command Codes + //MAR + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Multimedia-Auth-Request", &data.command, ENOENT) ); + CHECK_FCT( fd_disp_register( test_sip_MAR_cb, DISP_HOW_CC, &data, &test_sip_MAR_hdl ) ); + //RTR + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Registration-Termination-Request", &data.command, ENOENT) ); + CHECK_FCT( fd_disp_register( test_sip_RTR_cb, DISP_HOW_CC, &data, &test_sip_RTA_hdl ) ); + + + //Callback for unexpected messages + CHECK_FCT( fd_disp_register( test_sip_default_cb, DISP_HOW_APPID, &data, &test_sip_default_hdl ) ); + + + //We start database connection + if(start_mysql_connection()) + return 1; + + CHECK_FCT(fd_sess_handler_create(&ds_sess_hdl, free)); + + return 0; +} + +//Cleanup callback +void fd_ext_fini(void) +{ + + if (test_sip_MAR_cb) { + (void) fd_disp_unregister(&test_sip_MAR_hdl); + CHECK_FCT_DO( fd_sess_handler_destroy(&ds_sess_hdl),return); + } + + //We close database connection + close_mysql_connection(); + + + + TRACE_ENTRY(); + return ; +} + +EXTENSION_ENTRY("test_sip", ts_entry); + diff -r 9a9a9e1ed4cb -r c2fb5b26bfcb extensions/test_sip/test_sip.h --- a/extensions/test_sip/test_sip.h Thu Jul 08 15:16:11 2010 +0900 +++ b/extensions/test_sip/test_sip.h Thu Jul 08 16:19:28 2010 +0900 @@ -37,26 +37,50 @@ /* The module configuration */ struct test_sip_conf { - int mode; /* default MODE_DSSERVER | MODE_SL */ - enum {ASMYSQL} datasource; - char * mysql_login; - char * mysql_password; - char * mysql_database; - char * mysql_server; - uint16_t mysql_port; - + char * destination_sip; + char * destination_realm; + char * username; + char * password; + char * sip_aor; }; extern struct test_sip_conf * test_sip_conf; +//Storage for some usefull AVPs +struct sip_dict{ + struct dict_object * Auth_Session_State; + struct dict_object * Auth_Application_Id; + struct dict_object * User_Name; + struct dict_object * SIP_Auth_Data_Item; + struct dict_object * SIP_Authorization; + struct dict_object * SIP_Authenticate; + struct dict_object * SIP_Number_Auth_Items; + struct dict_object * SIP_Authentication_Scheme; + struct dict_object * SIP_Authentication_Info; + struct dict_object * SIP_Server_URI; + struct dict_object * SIP_Method; + struct dict_object * SIP_AOR; + struct dict_object * Digest_URI; + struct dict_object * Digest_Nonce; + struct dict_object * Digest_Nonce_Count; + struct dict_object * Digest_CNonce; + struct dict_object * Digest_Realm; + struct dict_object * Digest_Response; + struct dict_object * Digest_Response_Auth; + struct dict_object * Digest_Username; + struct dict_object * Digest_Method; + struct dict_object * Digest_QOP; + struct dict_object * Digest_Algorithm; + struct dict_object * Digest_HA1; +}; - +extern struct sip_dict sip_dict; - +int test_sip_default_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act); +int test_sip_MAA_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act); +int test_sip_RTR_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act); - -