Initial commit
Change-Id: I6a4444e3c193dae437cd7929f4c39aba7b749efa
diff --git a/extensions/app_sip/libapp_sip.c b/extensions/app_sip/libapp_sip.c
new file mode 100644
index 0000000..6442ff4
--- /dev/null
+++ b/extensions/app_sip/libapp_sip.c
@@ -0,0 +1,1078 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License) *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net> *
+* *
+* 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 <mysql.h>
+#include "app_sip.h"
+
+MYSQL *conn;
+
+void clear_digest(uint8_t * digest, char * readable_digest, int digestlength)
+{
+ int i=0;
+ for(i=0;i<digestlength * 2;i++)
+ sprintf(&readable_digest[2 * i], "%2.2hhx", digest[i]);
+ readable_digest[2 * digestlength]='\0';
+
+ return;
+}
+
+// You must create a table like this "char clearDigest[DIGEST_LEN*2+1];"
+void calc_md5(char *clearDigest, char * data)
+{
+ gcry_md_hd_t md5;
+ uint8_t * binDigest=NULL;
+
+ CHECK_MALLOC_DO(binDigest=malloc(DIGEST_LEN),return);
+
+ gcry_md_open(&md5,GCRY_MD_MD5, 0);
+ gcry_md_write(md5, (char *)data, sizeof(data));
+ memcpy(binDigest, gcry_md_read(md5, GCRY_MD_MD5),gcry_md_get_algo_dlen(GCRY_MD_MD5));
+ gcry_md_close(md5);
+
+ clear_digest(binDigest, clearDigest, DIGEST_LEN);
+ free(binDigest);
+ return;
+}
+
+
+/* Search a given AVP model in an AVP (extracted from libfreediameter/message.c ) */
+int fd_avp_search_avp ( struct avp * groupedavp, struct dict_object * what, struct avp ** avp )
+{
+ struct avp * nextavp;
+ struct avp_hdr * nextavphdr;
+ struct dict_avp_data dictdata;
+
+
+ TRACE_ENTRY("%p %p %p", groupedavp, what, avp);
+
+ CHECK_FCT( fd_dict_getval(what, &dictdata) );
+
+ // Loop only in the group AVP
+ CHECK_FCT( fd_msg_browse(groupedavp, MSG_BRW_FIRST_CHILD, (void *)&nextavp, NULL) );
+ CHECK_FCT( fd_msg_avp_hdr( nextavp, &nextavphdr ) );
+
+ while (nextavphdr) {
+
+ if ( (nextavphdr->avp_code == dictdata.avp_code) && (nextavphdr->avp_vendor == dictdata.avp_vendor) ) // always 0 if no Vendor flag
+ {
+ break;
+ }
+
+ // Otherwise move to next AVP in the grouped AVP
+ CHECK_FCT( fd_msg_browse(nextavp, MSG_BRW_NEXT, (void *)&nextavp, NULL) );
+
+ if(nextavp!=NULL)
+ {
+ CHECK_FCT( fd_msg_avp_hdr( nextavp, &nextavphdr ) );
+ }
+ else
+ nextavphdr=NULL;
+ }
+ if (avp)
+ *avp = nextavp;
+
+ if (avp && nextavp) {
+ struct dictionary * dict;
+ CHECK_FCT( fd_dict_getdict( what, &dict) );
+ CHECK_FCT_DO( fd_msg_parse_dict( nextavp, dict, NULL ), );
+ }
+
+ if (avp || nextavp)
+ return 0;
+ else
+ return ENOENT;
+}
+struct avp_hdr *walk_digest(struct avp *avp, int avp_code)
+{
+ struct avp_hdr *temphdr=NULL;
+ CHECK_FCT_DO(fd_msg_browse ( avp, MSG_BRW_WALK, &avp, NULL),return NULL);
+
+ while(avp!=NULL)
+ {
+
+ CHECK_FCT_DO( fd_msg_avp_hdr( avp,&temphdr ),return NULL);
+
+ if(temphdr->avp_code==avp_code)
+ {
+ //We found the AVP so we set avp to NULL to exit the loop
+ avp=NULL;
+ return temphdr;
+
+ }
+ else if(temphdr->avp_code==380)//SIP-Authorization AVP
+ {
+ //We didn't found the AVP but we finished browsing the Authentication AVP
+ avp=NULL;
+ temphdr=NULL;
+
+ return temphdr;
+ }
+ else
+ {
+ CHECK_FCT_DO(fd_msg_browse ( avp, MSG_BRW_WALK, &avp, NULL),return NULL);
+ temphdr=NULL;
+
+ }
+ }
+
+ return temphdr;
+}
+
+int start_mysql_connection()
+{
+ conn = mysql_init(NULL);
+
+ mysql_options(conn, MYSQL_OPT_RECONNECT, "true");
+
+ if (!mysql_real_connect(conn, as_conf->mysql_server,as_conf->mysql_login, as_conf->mysql_password, as_conf->mysql_database, as_conf->mysql_port, NULL, 0))
+ {//TODO: display error from mysql
+ TRACE_DEBUG(INFO,"Unable to connect to database (%s) with login:%s",as_conf->mysql_database,as_conf->mysql_login);
+ return 1;
+ }
+ return 0;
+
+}
+
+
+void request_mysql(char *query)
+{
+ //We check if the connection is still up
+ mysql_ping(conn);
+
+ if (mysql_query(conn, query))
+ {
+ TRACE_DEBUG(INFO,"Query %s failed", query);
+
+ }
+
+}
+
+void close_mysql_connection()
+{
+ mysql_close(conn);
+
+}
+
+//If password is null, we just verify this user exist
+//We don't need the password length because it is a table'
+int get_password(const unsigned char *username, const size_t usernamelen, char *password)
+{
+ CHECK_PARAMS(username && usernamelen);
+
+ int not_found=2;
+ size_t querylen, usernamepurelen;
+ char *query, *username_pure;
+
+ switch(as_conf->datasource)
+ {
+ //MySQL
+ case ASMYSQL:
+ //We allocate the double size of username because at worst it can be all quotes
+ username_pure=malloc(usernamelen*2+1);
+ //We purify username not to have forbidden characters
+ usernamepurelen=mysql_real_escape_string(conn, username_pure, (const char *)username, usernamelen);
+
+ //We copy username in query
+ querylen=SQL_GETPASSWORD_LEN + usernamepurelen;
+ query = malloc(querylen+2);
+ snprintf(query, querylen+1, SQL_GETPASSWORD, username_pure);
+
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+
+ //We make the query
+ request_mysql(query);
+ res=mysql_use_result(conn);
+ if(res==NULL)
+ {
+ if(password!=NULL)
+ password[0]='\0';
+ free(query);
+ return 2;
+ }
+
+
+
+ while ((row = mysql_fetch_row(res)) != NULL)
+ {
+ if(strlen(row[0])>0)
+ {
+ if(password!=NULL)
+ strcpy(password,row[0]);
+
+ not_found=0;
+ break;
+ }
+ }
+ mysql_free_result(res);
+ free(query);
+ break;
+ }
+ return not_found;
+}
+
+int check_sipaor(const unsigned char *username, const size_t usernamelen, const char * sip_aor,const size_t sipaorlen)
+{
+ CHECK_PARAMS(username && usernamelen && sip_aor && sipaorlen);
+
+ int not_found=2;
+ size_t querylen, usernamepurelen;
+ char *query, *username_pure;
+
+ switch(as_conf->datasource)
+ {
+ //MySQL
+ case ASMYSQL:
+ //We allocate the double size of username because at worst it can be all quotes
+ username_pure=malloc(usernamelen*2+1);
+ //We purify username not to have forbidden characters
+ usernamepurelen=mysql_real_escape_string(conn, username_pure, (const char *)username, usernamelen);
+
+ //We get the list of AOR owned by this user
+ querylen=SQL_GETSIPAOR_LEN + usernamepurelen;
+ query = malloc(querylen+2);
+ snprintf(query, querylen+1, SQL_GETSIPAOR, username_pure);
+
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+
+ //We make the query
+ request_mysql(query);
+ res=mysql_use_result(conn);
+ if(res==NULL)
+ {
+ free(query);
+ return 2;
+ }
+
+
+ not_found=1;
+ while ((row = mysql_fetch_row(res)) != NULL)
+ {
+ if(strncmp((const char *)sip_aor,row[0],sipaorlen)==0)
+ {
+ not_found=0;
+ break;
+ }
+ }
+ mysql_free_result(res);
+ free(query);
+ break;
+ }
+ return not_found;
+}
+
+int get_diameter_uri(const unsigned char *sip_aor, const size_t sipaorlen, char ** diameter_uri, size_t *diameterurilen)
+{
+ CHECK_PARAMS(sip_aor && sipaorlen);
+
+ size_t querylen, sipaorpurelen;
+ char *query, *sipaor_pure;
+ int not_found=2;
+
+
+
+
+ //a sip aor must begin by "sip:" or "sips:" so it must at least be longer than 4 chars
+ if(sipaorlen<5)
+ return 2;
+
+ //NOTE: each method has to purify sip_aor itself. You must remove quotes or special chars for security
+ switch(as_conf->datasource)
+ {
+ //MySQL
+ case ASMYSQL:
+
+ querylen=SQL_GETDIAMURI_LEN + sipaorlen;
+
+
+ //We allocate the double size of SIP-URI because at worst it can be all quotes
+ CHECK_MALLOC(sipaor_pure=malloc(sipaorlen*2+1));
+ //We purify SIP-URI not to have forbidden characters
+ sipaorpurelen=mysql_real_escape_string(conn, sipaor_pure, (const char *)sip_aor, sipaorlen);
+
+
+ query = malloc(querylen+sipaorpurelen+ 2);
+ snprintf(query, querylen+1, SQL_GETDIAMURI, sipaor_pure);
+
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+
+
+ //We make the query
+ request_mysql(query);
+ res=mysql_use_result(conn);
+ if(res==NULL)
+ {
+ //We couldn't make the request
+ diameter_uri=NULL;
+ return 2;
+ }
+
+ while ((row = mysql_fetch_row(res)) != NULL)
+ {
+ *diameterurilen=strlen(row[0]);
+ if(*diameterurilen>0)
+ {
+ CHECK_MALLOC(*diameter_uri=malloc(*diameterurilen+1));
+ strcpy(*diameter_uri,row[0]);
+ not_found=0;
+ break;
+ }
+ }
+ mysql_free_result(res);
+ free(query);
+ free(sipaor_pure);
+ break;
+
+ default:
+
+ //We must never go here, if so, we must stop diameter_sip
+ diameter_uri=NULL;
+ return 2;
+
+ break;
+ }
+
+ //0 if it was found
+ return not_found;
+
+}
+
+
+int exist_username(const unsigned char *sip_aor, const size_t sipaorlen)
+{
+ CHECK_PARAMS(sip_aor && sipaorlen);
+
+ size_t querylen, sipaorpurelen;
+ char *query, *sipaor_pure;
+ int not_found=1;
+
+ //a sip aor must begin by "sip:" or "sips:" so it must at least be longer than 4 chars
+ if(sipaorlen<5)
+ return 2;
+
+ //NOTE: each method has to purify sip_aor itself. You must remove quotes or special chars for security
+
+ switch(as_conf->datasource)
+ {
+ //MySQL
+ case ASMYSQL:
+
+ querylen=SQL_GETUSERNAME_LEN + sipaorlen;
+
+
+ //We allocate the double size of SIP-URI because at worst it can be all quotes
+ CHECK_MALLOC(sipaor_pure=malloc(sipaorlen*2+1));
+ //We purify SIP-URI not to have forbidden characters
+ sipaorpurelen=mysql_real_escape_string(conn, sipaor_pure, (const char *)sip_aor, sipaorlen);
+
+
+ query = malloc(querylen+sipaorpurelen+ 2);
+ snprintf(query, querylen+1, SQL_GETUSERNAME, sipaor_pure);
+
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+
+
+ //We make the query
+ request_mysql(query);
+ res=mysql_use_result(conn);
+ if(res==NULL)
+ {
+ //We couldn't make the request
+ return 2;
+ }
+
+ while ((row = mysql_fetch_row(res)) != NULL)
+ {
+ if(strlen(row[0])>0)
+ {
+ not_found=0;
+ break;
+ }
+ }
+ mysql_free_result(res);
+ free(query);
+ free(sipaor_pure);
+ break;
+
+ default:
+
+ //We must never go here, if so, we must stop diameter_sip
+ TRACE_DEBUG(INFO,"FATAL ERROR: the datasource is unknown, please check your config file!");
+ return 2;
+
+ break;
+ }
+
+ //0 if it was found
+ return not_found;
+
+}
+
+//We check if this user can go in the given network
+int allow_roaming(const unsigned char *username, const size_t usernamelen, const char * network,const size_t networklen)
+{
+ CHECK_PARAMS(username && usernamelen && network && networklen);
+
+ int not_found=2;
+ size_t querylen, usernamepurelen;
+ char *query, *username_pure;
+
+ switch(as_conf->datasource)
+ {
+ //MySQL
+ case ASMYSQL:
+ //We allocate the double size of username because at worst it can be all quotes
+ username_pure=malloc(usernamelen*2+1);
+ //We purify username not to have forbidden characters
+ usernamepurelen=mysql_real_escape_string(conn, username_pure, (const char *)username, usernamelen);
+
+ //We get the list of AOR owned by this user
+ querylen=SQL_GETUSERNET_LEN + usernamepurelen;
+ query = malloc(querylen+2);
+ snprintf(query, querylen+1, SQL_GETUSERNET, username_pure);
+
+
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+
+
+ //We make the query
+ request_mysql(query);
+ res=mysql_use_result(conn);
+ if(res==NULL)
+ {
+ free(query);
+ return 2;
+ }
+
+
+ not_found=1;
+ while ((row = mysql_fetch_row(res)) != NULL)
+ {
+ if(strncmp((const char *)network,row[0],networklen)==0)
+ {
+ not_found=0;
+ break;
+ }
+ }
+ mysql_free_result(res);
+ free(query);
+ break;
+ }
+ return not_found;
+}
+
+//SIP-Server-Capabilities for the SIP-AOR
+int get_sipserver_cap(const unsigned char *sip_aor, const size_t sipaorlen, struct avp **capabilities)
+{
+ CHECK_PARAMS(sip_aor && sipaorlen && capabilities);
+
+ size_t querylen, sipaorpurelen;
+ char *query, *sipaor_pure;
+ int not_found=2;
+ union avp_value value;
+ struct avp *avp;
+
+ //a sip aor must begin by "sip:" or "sips:" so it must at least be longer than 4 chars
+ if(sipaorlen<5)
+ return 2;
+
+ //NOTE: each method has to purify sip_aor itself. You must remove quotes or special chars for security
+ switch(as_conf->datasource)
+ {
+ //MySQL
+ case ASMYSQL:
+
+ querylen=SQL_GETSIPSERCAP_LEN + sipaorlen;
+
+
+ //We allocate the double size of SIP-URI because at worst it can be all quotes
+ CHECK_MALLOC(sipaor_pure=malloc(sipaorlen*2+1));
+ //We purify SIP-URI not to have forbidden characters
+ sipaorpurelen=mysql_real_escape_string(conn, sipaor_pure, (const char *)sip_aor, sipaorlen);
+
+
+ query = malloc(querylen+sipaorpurelen+ 2);
+ snprintf(query, querylen+1, SQL_GETSIPSERCAP, sipaor_pure);
+
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+
+ //We make the query
+ request_mysql(query);
+ res=mysql_use_result(conn);
+ if(res==NULL)
+ {
+ //We couldn't make the request
+ return 2;
+ }
+ not_found=1;
+ while ((row = mysql_fetch_row(res)) != NULL)
+ {
+ if(atoi(row[0])==1)
+ {//mandatory
+ CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Mandatory_Capability, 0, &avp ) );
+ value.i32=(uint32_t)atoi(row[1]);
+ CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+ CHECK_FCT( fd_msg_avp_add ( *capabilities, MSG_BRW_LAST_CHILD, avp) );
+
+ }
+ else
+ {//optional
+ CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Optional_Capability, 0, &avp ) );
+ value.i32=(uint32_t)atoi(row[1]);
+ CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+ CHECK_FCT( fd_msg_avp_add ( *capabilities, MSG_BRW_LAST_CHILD, avp) );
+ }
+ not_found=0;
+ }
+
+ mysql_free_result(res);
+ free(query);
+ free(sipaor_pure);
+ break;
+
+ default:
+
+ //We must never go here, if so, we must stop diameter_sip
+ TRACE_DEBUG(INFO,"FATAL ERROR: the datasource is unknown, please check your config file!");
+ return 2;
+
+ break;
+ }
+
+ //0 if it was found
+ return not_found;
+
+}
+
+
+//We retrieve datatype
+int add_user_datatype(const unsigned char *sip_aor, const size_t sipaorlen,struct msg *message)
+{
+ CHECK_PARAMS(sip_aor && sipaorlen && message );
+
+ size_t querylen, sipaorpurelen;
+ char *query, *sipaor_pure;
+ int not_found=2;
+ union avp_value value;
+ struct avp *avp, *rootavp;
+ unsigned long *length;
+
+ //a sip aor must begin by "sip:" or "sips:" so it must at least be longer than 4 chars
+ if(sipaorlen<5)
+ return 2;
+
+ //NOTE: each method has to purify sip_aor itself. You must remove quotes or special chars for security
+ switch(as_conf->datasource)
+ {
+ //MySQL
+ case ASMYSQL:
+
+ querylen=SQL_GETSIPDATA_LEN + sipaorlen;
+
+
+ //We allocate the double size of SIP-URI because at worst it can be all quotes
+ CHECK_MALLOC(sipaor_pure=malloc(sipaorlen*2+1));
+ //We purify SIP-URI not to have forbidden characters
+ sipaorpurelen=mysql_real_escape_string(conn, sipaor_pure, (const char *)sip_aor, sipaorlen);
+
+
+ query = malloc(querylen+sipaorpurelen+ 2);
+ snprintf(query, querylen+1, SQL_GETSIPDATA, sipaor_pure);
+
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+
+ //We make the query
+ request_mysql(query);
+ res=mysql_use_result(conn);
+ if(res==NULL)
+ {
+ //We couldn't make the request
+ return 2;
+ }
+ not_found=1;
+ while ((row = mysql_fetch_row(res)) != NULL)
+ {
+ length=mysql_fetch_lengths(res);
+
+ if(strlen(row[0])>1)
+ {
+ CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_User_Data, 0, &rootavp ) );
+
+ CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_User_Data_Type, 0, &avp ) );
+ CHECK_MALLOC(value.os.data=malloc(length[0]*sizeof(unsigned char)));
+ strncpy((char *)value.os.data,(char *)row[0],length[0]);
+ value.os.len=(size_t)length[0];
+ CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+ CHECK_FCT( fd_msg_avp_add ( rootavp, MSG_BRW_LAST_CHILD, avp) );
+
+
+
+ CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_User_Data_Contents, 0, &avp ) );
+ CHECK_MALLOC(value.os.data=malloc(length[1]*sizeof(unsigned char)));
+ memcpy(value.os.data,row[1],length[1]);
+ value.os.len=(size_t)length[1];
+ CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+ CHECK_FCT( fd_msg_avp_add ( rootavp, MSG_BRW_LAST_CHILD, avp) );
+
+ //We add SIP_User_Data to message
+ CHECK_FCT( fd_msg_avp_add ( message, MSG_BRW_LAST_CHILD, rootavp) );
+ not_found=0;
+ }
+
+ }
+
+ mysql_free_result(res);
+ free(query);
+ free(sipaor_pure);
+ break;
+
+ default:
+
+ //We must never go here, if so, we must stop diameter_sip
+ TRACE_DEBUG(INFO,"FATAL ERROR: the datasource is unknown, please check your config file!");
+ return 2;
+
+ break;
+ }
+
+ //0 if it was found
+ return not_found;
+
+
+
+}
+
+int set_pending_flag(const unsigned char *username, const size_t usernamelen)
+{
+ CHECK_PARAMS(username && usernamelen);
+
+
+ size_t querylen, usernamepurelen;
+ char *query, *username_pure;
+
+ switch(as_conf->datasource)
+ {
+ //MySQL
+ case ASMYSQL:
+ //We allocate the double size of username because at worst it can be all quotes
+ username_pure=malloc(usernamelen*2+1);
+ //We purify username not to have forbidden characters
+ usernamepurelen=mysql_real_escape_string(conn, username_pure, (const char *)username, usernamelen);
+
+
+
+ //We clear the flag "authentication pending"
+ querylen=SQL_SETFLAG_LEN + usernamepurelen;
+ query = malloc(querylen+2);
+ snprintf(query, querylen+1, SQL_SETFLAG, username_pure);
+
+ if (mysql_query(conn, query))
+ {
+ TRACE_DEBUG(INFO,"Query %s failed", query);
+ free(query);
+ return 2;
+ }
+
+ free(query);
+ break;
+ }
+ return 0;
+}
+int clear_pending_flag(const unsigned char *username, const size_t usernamelen)
+{
+ CHECK_PARAMS(username && usernamelen);
+
+
+ size_t querylen, usernamepurelen;
+ char *query, *username_pure;
+
+ switch(as_conf->datasource)
+ {
+ //MySQL
+ case ASMYSQL:
+ //We allocate the double size of username because at worst it can be all quotes
+ username_pure=malloc(usernamelen*2+1);
+ //We purify username not to have forbidden characters
+ usernamepurelen=mysql_real_escape_string(conn, username_pure, (const char *)username, usernamelen);
+
+
+
+ //We clear the flag "authentication pending"
+ querylen=SQL_CLEARFLAG_LEN + usernamepurelen;
+ query = malloc(querylen+2);
+ snprintf(query, querylen+1, SQL_CLEARFLAG, username_pure);
+
+ if (mysql_query(conn, query))
+ {
+ TRACE_DEBUG(INFO,"Query %s failed", query);
+ free(query);
+ return 2;
+ }
+
+ free(query);
+ break;
+ }
+ return 0;
+}
+
+
+
+int set_sipserver_uri(const unsigned char *username, const size_t usernamelen, const unsigned char *sipserver_uri,const size_t sipserverurilen)
+{
+ CHECK_PARAMS(username && usernamelen && sipserver_uri && sipserverurilen);
+
+
+ size_t querylen, usernamepurelen, sipserveruripurelen;
+ char *query, *username_pure, *sipserveruri_pure;
+
+ switch(as_conf->datasource)
+ {
+ //MySQL
+ case ASMYSQL:
+ //We allocate the double size of username because at worst it can be all quotes
+ username_pure=malloc(usernamelen*2+1);
+ //We purify username not to have forbidden characters
+ usernamepurelen=mysql_real_escape_string(conn, username_pure, (const char *)username, usernamelen);
+
+ //We allocate the double size of username because at worst it can be all quotes
+ sipserveruri_pure=malloc(sipserverurilen*2+1);
+ //We purify username not to have forbidden characters
+ sipserveruripurelen=mysql_real_escape_string(conn, sipserveruri_pure, (const char *)sipserver_uri, sipserverurilen);
+
+ //We clear the flag "authentication pending"
+ querylen=SQL_SETSIPURI_LEN + usernamepurelen + sipserveruripurelen;
+ query = malloc(querylen+2);
+ snprintf(query, querylen+1, SQL_SETSIPURI, sipserveruri_pure,username_pure);
+
+ if (mysql_query(conn, query))
+ {
+ TRACE_DEBUG(INFO,"Query %s failed", query);
+ free(query);
+ return 2;
+ }
+
+ free(query);
+ break;
+ }
+ return 0;
+}
+int remove_sipserver_uri(const unsigned char *sipserver_uri,const size_t sipserverurilen)
+{
+ CHECK_PARAMS(sipserver_uri && sipserverurilen);
+
+
+ size_t querylen, sipserveruripurelen;
+ char *query, *sipserveruri_pure;
+
+ switch(as_conf->datasource)
+ {
+ //MySQL
+ case ASMYSQL:
+ //We allocate the double size of username because at worst it can be all quotes
+ sipserveruri_pure=malloc(sipserverurilen*2+1);
+ //We purify username not to have forbidden characters
+ sipserveruripurelen=mysql_real_escape_string(conn, sipserveruri_pure, (const char *)sipserver_uri, sipserverurilen);
+
+ //We clear the flag "authentication pending"
+ querylen=SQL_RMSIPURI_LEN + sipserveruripurelen;
+ query = malloc(querylen+2);
+ snprintf(query, querylen+1, SQL_RMSIPURI, sipserveruri_pure);
+
+ if (mysql_query(conn, query))
+ {
+ TRACE_DEBUG(INFO,"Query %s failed", query);
+ free(query);
+ return 2;
+ }
+
+ free(query);
+ break;
+ }
+ return 0;
+}
+int set_real_sipserver_uri(const unsigned char *username, const size_t usernamelen, const unsigned char *sipserver_uri,const size_t sipserverurilen)
+{
+ CHECK_PARAMS(username && usernamelen && sipserver_uri && sipserverurilen);
+
+
+ size_t querylen, usernamepurelen, sipserveruripurelen;
+ char *query, *username_pure, *sipserveruri_pure;
+
+ switch(as_conf->datasource)
+ {
+ //MySQL
+ case ASMYSQL:
+ //We allocate the double size of username because at worst it can be all quotes
+ username_pure=malloc(usernamelen*2+1);
+ //We purify username not to have forbidden characters
+ usernamepurelen=mysql_real_escape_string(conn, username_pure, (const char *)username, usernamelen);
+
+ //We allocate the double size of username because at worst it can be all quotes
+ sipserveruri_pure=malloc(sipserverurilen*2+1);
+ //We purify username not to have forbidden characters
+ sipserveruripurelen=mysql_real_escape_string(conn, sipserveruri_pure, (const char *)sipserver_uri, sipserverurilen);
+
+ //We clear the flag "authentication pending"
+ querylen=SQL_SETREALSIPURI_LEN + usernamepurelen + sipserveruripurelen;
+ query = malloc(querylen+2);
+ snprintf(query, querylen+1, SQL_SETREALSIPURI, sipserveruri_pure,username_pure);
+
+ if (mysql_query(conn, query))
+ {
+ TRACE_DEBUG(INFO,"Query %s failed", query);
+ free(query);
+ return 2;
+ }
+
+ free(query);
+ break;
+ }
+ return 0;
+}
+
+int get_sipserver_uri(const unsigned char *sip_aor, const size_t sipaorlen, unsigned char ** sipserver_uri, size_t *sipserverurilen)
+{
+ CHECK_PARAMS(sip_aor && sipaorlen && sipserver_uri && sipserverurilen );
+
+ size_t querylen, sipaorpurelen;
+ char *query, *sipaor_pure;
+ int not_found=2;
+
+
+
+
+ //a sip aor must begin by "sip:" or "sips:" so it must at least be longer than 4 chars
+ if(sipaorlen<5)
+ return 2;
+
+ //NOTE: each method has to purify sip_aor itself. You must remove quotes or special chars for security
+
+ switch(as_conf->datasource)
+ {
+ //MySQL
+ case ASMYSQL:
+
+ querylen=SQL_GETSIPSERURI_LEN + sipaorlen;
+
+ //We allocate the double size of SIP-URI because at worst it can be all quotes
+ CHECK_MALLOC(sipaor_pure=malloc(sipaorlen*2+1));
+ //We purify SIP-URI not to have forbidden characters
+ sipaorpurelen=mysql_real_escape_string(conn, sipaor_pure, (const char *)sip_aor, sipaorlen);
+
+
+ query = malloc(querylen+sipaorpurelen+ 2);
+ snprintf(query, querylen+1, SQL_GETSIPSERURI, sipaor_pure);
+
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+
+ //We make the query
+ request_mysql(query);
+ res=mysql_use_result(conn);
+ if(res==NULL)
+ {
+ //We couldn't make the request
+ sipserver_uri=NULL;
+ return 2;
+ }
+
+ not_found=1;
+ while ((row = mysql_fetch_row(res)) != NULL)
+ {
+ *sipserverurilen=strlen(row[0]);
+ if(*sipserverurilen>4)
+ {
+ CHECK_MALLOC(*sipserver_uri=malloc(*sipserverurilen+1));
+ strcpy((char *)*sipserver_uri,row[0]);
+ not_found=0;
+ break;
+ }
+ }
+ mysql_free_result(res);
+ free(query);
+ free(sipaor_pure);
+ break;
+
+ default:
+
+ //We must never go here, if so, we must stop diameter_sip
+ TRACE_DEBUG(INFO,"FATAL ERROR: the datasource is unknown, please check your config file!");
+ sipserver_uri=NULL;
+ return 2;
+
+ break;
+ }
+
+ //0 if it was found
+ return not_found;
+
+}
+
+
+int count_avp(struct msg * message, int code, int vendor)
+{
+ CHECK_PARAMS(message);
+
+ struct avp_hdr *temphdr;
+ struct avp *avp;
+ int counter=0;
+
+ CHECK_FCT(fd_msg_browse (message, MSG_BRW_WALK, &avp, NULL));
+
+ while(avp!=NULL)
+ {
+
+ CHECK_FCT( fd_msg_avp_hdr( avp,&temphdr ));
+
+ if(temphdr->avp_code==code && temphdr->avp_vendor==vendor)
+ {
+ counter++;
+ }
+
+ CHECK_FCT(fd_msg_browse (avp, MSG_BRW_WALK, &avp, NULL));
+ }
+ return counter;
+}
+/*
+void nonce_add_element(char * nonce)
+{
+ noncechain *newelt=malloc(sizeof(noncechain));
+
+ newelt->nonce=nonce;
+
+ newelt->timestamp=(int)time(NULL);
+ newelt->next=NULL;
+
+ if(listnonce==NULL)
+ {
+ listnonce=newelt;
+ }
+ else
+ {
+ noncechain* temp=listnonce;
+
+ while(temp->next != NULL)
+ {
+ if(temp->timestamp < ((int)time(NULL)-300))
+ {
+ listnonce=temp->next;
+ free(temp);
+ temp=listnonce;
+ }
+ temp = temp->next;
+ }
+ temp->next = newelt;
+ }
+
+}
+void nonce_del_element(char * nonce)
+{
+ if(listnonce!=NULL)
+ {
+ noncechain *temp=listnonce, *tempbefore=NULL;
+
+ if(listnonce->next==NULL && strcmp(listnonce->nonce,nonce)==0)
+ {
+ free(listnonce);
+ listnonce=NULL;
+ return;
+ }
+ while(temp->next != NULL)
+ {
+ if(strcmp(temp->nonce,nonce)==0)
+ {
+ if(tempbefore==NULL)
+ {
+ listnonce=temp->next;
+ free(temp);
+ return;
+ }
+ tempbefore->next=temp->next;
+ free(temp);
+ break;
+ }
+ tempbefore=temp;
+ temp = temp->next;
+ }
+
+ }
+
+}
+int nonce_check_element(char * nonce)
+{
+ if(listnonce==NULL)
+ {
+ //Not found
+ return 0;
+ }
+ else
+ {
+ noncechain* temp=listnonce;
+
+ while(temp->next != NULL)
+ {
+ if(strcmp(temp->nonce,nonce)==0)
+ return 1;
+ else
+ temp = temp->next;
+ }
+ }
+ return 0;
+}
+
+void nonce_deletelistnonce()
+{
+ if(listnonce !=NULL)
+ {
+ noncechain* temp=listnonce;
+
+ while(listnonce->next != NULL)
+ {
+ temp = listnonce->next;
+
+ free(listnonce);
+
+ listnonce=temp;
+ }
+ free(listnonce);
+ }
+}
+*/