Hello every one, I change modules/auth_db/authorize.c to check pre-payed user's mount.Itworks,But I Get Memory leak. I check the source many times,but I can't find the ploblem. Can anyone else help me. The following is my authorize,c file
##########################################################
#include <string.h> #include <stdlib.h> #include "../../ut.h" #include "../../str.h" #include "../../db/db.h" #include "../../dprint.h" #include "../../parser/digest/digest.h" #include "../../parser/parse_from.h" #include "../../parser/parse_uri.h" #include "../../parser/hf.h" #include "../../parser/parser_f.h" #include "../../usr_avp.h" #include "../../mem/mem.h" #include "authdb_mod.h" #include "rfc2617.h"
#define MESSAGE_500 "Server Internal Error" #define MOUNT_COL "Amount" #define MOUNT_COL_LEN (sizeof(MOUNT_COL)-1) #define STATUS_COL "Status" #define STATUS_COL_LEN (sizeof(STATUS_COL)-1) #define ACCT_CODE_COL "ACCT_CODE" #define ACCT_CODE_COL_LEN (sizeof(ACCT_CODE_COL)-1) #define AGENT_CODE "Agent_Code" #define AGENT_CODE_LEN (sizeof(AGENT_CODE)-1) #define ROOT_AGENT "Agent_Code_Root" #define ROOT_AGENT_LEN (sizeof(ROOT_AGENT)-1) #define CARDNO "Card_No" #define CARDNOLEN (sizeof(CARDNO)-1) #define DOMAIN "domain" #define DOMAINLEN (sizeof(DOMAIN)-1) #define LOCALDOMAIN " xtox.org"
static db_con_t* db_handle=0; /* database connection handle */ static db_func_t auth_dbf;
/************************************************************ get user agent a mount from CASH_ACCT_INTO table
select Amount,Status from CASH_ACCT_INFO where acct_code = '10agent'; select Amount,Status from CASH_ACCT_INFO where acct_code_root = '10agentroor'
**********************************************************/
static inline int getagentmount(str agent) { db_key_t key[1]; db_val_t val[1]; db_key_t* col; db_res_t* res;
double mount=0.0; int status=3; int n,nc;
str acct_code = {ACCT_CODE_COL,ACCT_CODE_COL_LEN}; //CASH_ACCT_INFO.ACCT_CODE str mount_col = {MOUNT_COL,MOUNT_COL_LEN};//CASH_ACCT_INFO.Amount str status_col = {STATUS_COL,STATUS_COL_LEN};//CASH_ACCT_INFO.Status col = pkg_malloc(sizeof(*col)*2); if(col == NULL) { return -1; } col[0] = mount_col.s; col[1] = status_col.s;
key[0] = acct_code.s;
char agentcode[2000]; bzero(agentcode,sizeof(agentcode)); strcpy(agentcode,"1000"); strncat(agentcode,agent.s,agent.len);
VAL_TYPE(val) = DB_STR; VAL_NULL(val) = 0; VAL_STR(val).s = (char*)agentcode; VAL_STR(val).len = strlen(agentcode); n=1; nc=2; if (auth_dbf.use_table(db_handle, "CASH_ACCT_INFO") < 0) { pkg_free(col); return -1; } if (auth_dbf.query(db_handle, key, 0, val, col, n, nc, 0, &res) < 0) { pkg_free(col); auth_dbf.free_result(db_handle,res); return -1; } if ((RES_ROW_N(res) == 0)) { pkg_free(col); auth_dbf.free_result(db_handle,res); return 1; } pkg_free(col); mount = ROW_VALUES(RES_ROWS(res))[0].val.double_val; status = ROW_VALUES(RES_ROWS(res))[1].val.int_val;
if((mount > 1)&&(status>0)) { auth_dbf.free_result(db_handle,res); return 2; } auth_dbf.free_result(db_handle,res); return 0; }
/************************************************************* get username from tblDOMAIN_ACCT Function name:getusername Parameters: str domain[in]; char* acct[in/out]:if get acct ,stored in this field Return Value: if find domain from tblDOMAIN_ACCT AND GetAccount return 1; if find no acct return 0; IF SOME ERROR OCCORS RETURN -1;
***********************************************************/
static inline int getusername(char* domain,char* acct) { db_key_t key[1]; db_val_t val[1]; db_key_t *col; db_res_t *res;
str cardnocol = {CARDNO,CARDNOLEN}; str domaincol = {DOMAIN,DOMAINLEN}; col = pkg_malloc(sizeof(*col) * 1);//only one column (Card_No) to select from tblDOMAIN_ACCT if(col == NULL) { return -1; } col[0] = cardnocol.s; key[0] = domaincol.s; VAL_TYPE(val) = DB_STR; VAL_NULL(val) = 0; VAL_STR(val).s = domain; VAL_STR(val).len = strlen(domain);
if (auth_dbf.use_table(db_handle, "tblDOMAIN_ACCT") < 0) { pkg_free(col); return -1; } if (auth_dbf.query(db_handle, key, 0, val, col, 1, 1, 0, &res) < 0) { pkg_free(col); return -1; } if ((RES_ROW_N(res) == 0)) { pkg_free(col); auth_dbf.free_result(db_handle,res); return 0; } pkg_free(col);
strcpy(acct,(char*)ROW_VALUES(RES_ROWS(res))[0].val.string_val); auth_dbf.free_result(db_handle,res); return 1; }
/************************************************************** get user amount from CASH_ACCT_INFO table it's sql is select amount,status,Agent_Code,Agent_Code_Root from CASH_ACCT_INFO where acct_code = '20user' ************************************************************/ static inline int getmount(/*str username*/char* username,char* agent,char* agentroot) { db_key_t key[1]; db_val_t val[1]; db_key_t* col; db_res_t* res;
double mount; int n,nc; int status;
str mount_col = {MOUNT_COL,MOUNT_COL_LEN};//CASH_ACCT_INFO.AMOUNT str status_col = {STATUS_COL,STATUS_COL_LEN};//CASH_ACCT_INFO.Status str acct_code = {ACCT_CODE_COL,ACCT_CODE_COL_LEN}; //CASH_ACCT_INFO.ACCT_CODE str agent_code = {AGENT_CODE,AGENT_CODE_LEN};//CASH_ACCT_INFO.Agent_Code str root_agent = {ROOT_AGENT,ROOT_AGENT_LEN};//CASH_ACCT_INFO.Agent_Code_Root
col = pkg_malloc(sizeof(*col) * 4 );//4 column to select Amout,Status,Agent_Code,Agent_Code_Root if (col == NULL) { LOG(L_ERR, "getmount: Error while allocating memory\n"); return -1; } col[0] = mount_col.s; col[1] = status_col.s; col[2] = agent_code.s; col[3] = root_agent.s;
key[0] = acct_code.s;
char user[2500]; bzero(user,sizeof(user)); strcpy(user,"2000"); strcat(user,username); VAL_TYPE(val) = DB_STR; VAL_NULL(val) = 0; VAL_STR(val).s = (char*)user; VAL_STR(val).len = strlen(user); n = 1; //nc = credentials_n + 1; nc = 4; if (auth_dbf.use_table(db_handle, "CASH_ACCT_INFO") < 0) { pkg_free(col); return -1; } if (auth_dbf.query(db_handle, key, 0, val, col, n, nc, 0, &res) < 0) { pkg_free(col); return -1; } if ((RES_ROW_N(res) == 0)) { pkg_free(col); auth_dbf.free_result(db_handle,res); return 1; }
pkg_free(col); mount = ROW_VALUES(RES_ROWS(res))[0].val.double_val; status = ROW_VALUES(RES_ROWS(res))[1].val.int_val;
if((mount > 1)&&(status>0)) { str agent1,agentroot1; agent1.s = (char*)ROW_VALUES(RES_ROWS(res))[2].val.string_val; agent1.len = strlen(agent1.s); agentroot1.s = (char*)ROW_VALUES(RES_ROWS(res))[3].val.string_val; agentroot1.len = strlen(agentroot1.s); strncpy(agent,agent1.s,agent1.len); strncpy(agentroot,agentroot1.s,agentroot1.len); auth_dbf.free_result(db_handle,res); return 2; } else { auth_dbf.free_result(db_handle,res); return 0; } }
/* * Calculate the response and compare with the given response string * Authorization is successful if this two strings are same */ static inline int check_response(dig_cred_t* _cred, str* _method, char* _ha1) { HASHHEX resp, hent;
/* * First, we have to verify that the response received has * the same length as responses created by us */ if (_cred->response.len != 32) { DBG("check_response(): Receive response len != 32\n"); return 1; }
/* * Now, calculate our response from parameters received * from the user agent */ calc_response(_ha1, &(_cred->nonce), &(_cred->nc), &(_cred->cnonce), &(_cred-> qop.qop_str), _cred->qop.qop_parsed == QOP_AUTHINT, _method, &(_cred->uri), hent, resp);
DBG("check_response(): Our result = '%s'\n", resp);
/* * And simply compare the strings, the user is * authorized if they match */ if (!memcmp(resp, _cred->response.s, 32)) { DBG("check_response(): Authorization is OK\n"); return 0; } else { DBG("check_response(): Authorization failed\n"); return 2; } }
/* * Authorize digest credentials */ static inline int authorize(struct sip_msg* _m, str* _realm, char* _table, int _hftype) { char ha1[256]; int res, i; struct hdr_field* h; auth_body_t* cred; auth_result_t ret; str domain, value; int_str iname, ivalue; db_res_t* result; str rpid; domain = *_realm;
ret = pre_auth_func(_m, &domain, _hftype, &h);
switch(ret) { case ERROR: return 0; case NOT_AUTHORIZED: return -1; case DO_AUTHORIZATION: break; case AUTHORIZED: return 1; } str furi; struct sip_uri puri; if(parse_from_header(_m)<0) { return -1; } furi = get_from(_m)->uri; if(parse_uri(furi.s,furi.len,&puri) < 0) { return -1; }
char msgdomain[2055]; bzero(msgdomain,sizeof(msgdomain)); strncpy(msgdomain,puri.host.s,puri.host.len); int m,len; int p=0; len=strlen(msgdomain); for(m=0;m<len;m++) { if(msgdomain[m]!='@') msgdomain[p++]=msgdomain[m]; } msgdomain[p]='\0';
cred = (auth_body_t*)h->parsed; char acct[2000]; bzero(acct,sizeof(acct)); struct username* tmp = &cred->digest.username; if(strncmp(msgdomain,domain.s,strlen(msgdomain)))//domain is not local domain { if((res = getusername(msgdomain,acct)) == 1) { tmp->user.s = (char*)acct; tmp->user.len = strlen(acct); } else { return -1; } } else { strncpy(acct,tmp-> user.s,tmp->user.len); }
res = get_ha1(tmp, &domain, _table, ha1, &result); //res = get_ha1(&cred->digest.username, &domain, _table, ha1, &result); if (res < 0) { /* Error while accessing the database */ if (sl_reply(_m, (char*)500, MESSAGE_500) == -1) { LOG(L_ERR, "authorize(): Error while sending 500 reply\n"); } return 0; } if (res > 0) { /* Username not found in the database */ auth_dbf.free_result(db_handle, result); return -1; }
char agent[2000],agentroot[2000]; bzero(agent,sizeof(agent)); bzero(agentroot,sizeof(agentroot));
res = getmount(acct,agent,agentroot); if(res < 0) { auth_dbf.free_result(db_handle, result); return 0; } if(res == 0) { auth_dbf.free_result(db_handle, result); return -1; } if(res == 1) { auth_dbf.free_result(db_handle, result); return -1; }
if(res == 2) { str ll,ss; ll.s = (char*)agent; ll.len = strlen(ll.s); ss.s = (char*)agentroot; ss.len = strlen(ss.s); if(getagentmount(ll) != 2) { auth_dbf.free_result(db_handle, result); return -1; } if(strcmp(agent,agentroot)) { if(getagentmount(ss) != 2) { auth_dbf.free_result(db_handle, result); return -1; } } }
/* Recalculate response, it must be same to authorize successfully */ if (!check_response(&(cred->digest), &_m->first_line.u.request.method, ha1)) { rpid.s = NULL; rpid.len = 0; for (i = 0; i < avps_str_n; i++) { if (avps_str[i].len != 4 || VAL_NULL(&(result->rows[0].values[1 + avps_int_n + i])) || memcmp(avps_str[i].s, "rpid", 4) != 0) continue; rpid.s = (char*)VAL_STRING(&(result->rows[0].values[1 + avps_int_n + i])); if(rpid.s!=NULL) rpid.len = strlen(rpid.s); } ret = post_auth_func(_m, h, &rpid); switch(ret) { case ERROR: auth_dbf.free_result(db_handle, result); return 0; case NOT_AUTHORIZED: auth_dbf.free_result(db_handle, result); return -1; case AUTHORIZED: for (i = 0; i < avps_int_n; i++) { if(VAL_NULL(&(result->rows[0].values[1 + i]))) continue; iname.s = &(avps_int[i]); ivalue.n = VAL_INT(&(result->rows[0].values[1 + i])); add_avp(AVP_NAME_STR, iname, ivalue); DBG("authorize(): set integer AVP '%.*s = %d'\n", iname.s->len, ZSW(iname.s->s), ivalue.n); } for (i = 0; i < avps_str_n; i++) { value.s = (char*)VAL_STRING(&(result->rows[0].values[1 + avps_int_n + i])); if(VAL_NULL(&(result->rows[0].values[1 + avps_int_n + i])) || value.s==NULL) continue; iname.s = &(avps_str[i]); value.len = strlen(value.s); ivalue.s = &value; add_avp(AVP_NAME_STR | AVP_VAL_STR, iname, ivalue); DBG("authorize(): set string AVP '%.*s = %.*s'\n", iname.s->len, ZSW(iname.s->s), value.len, ZSW(value.s)); } auth_dbf.free_result(db_handle, result); return 1; default: auth_dbf.free_result(db_handle, result); return -1; } }
auth_dbf.free_result(db_handle, result); return -1; }
/* * Authorize using Proxy-Authorize header field */ int proxy_authorize(struct sip_msg* _m, char* _realm, char* _table) { /* realm parameter is converted to str* in str_fixup */ return authorize(_m, (str*)_realm, _table, HDR_PROXYAUTH); }
/* * Authorize using WWW-Authorize header field */ int www_authorize(struct sip_msg* _m, char* _realm, char* _table) { return authorize(_m, (str*)_realm, _table, HDR_AUTHORIZATION); }
int auth_db_init(char* db_url) { if (auth_dbf.init==0){ LOG(L_CRIT, "BUG: auth_db_bind: null dbf\n"); goto error; } db_handle=auth_dbf.init(db_url); if (db_handle==0){ LOG(L_ERR, "ERROR: auth_db_bind: unable to connect to the database\n"); goto error; } return 0; error: return -1; }
int auth_db_bind(char* db_url) { if (bind_dbmod(db_url, &auth_dbf)<0){ LOG(L_ERR, "ERROR: auth_db_bind: unable to bind to the database" " module\n"); return -1; } return 0; }
void auth_db_close() { if (db_handle && auth_dbf.close){ auth_dbf.close(db_handle); db_handle=0; } }
int auth_db_ver(char* db_url, str* name) { db_con_t* dbh; int ver;
if (auth_dbf.init==0){ LOG(L_CRIT, "BUG: auth_db_ver: unbound database\n"); return -1; } dbh=auth_dbf.init(db_url); if (dbh==0){ LOG(L_ERR, "ERROR: auth_db_ver: unable to open database connection\n"); return -1; } ver=table_version(&auth_dbf, dbh, name); auth_dbf.close(dbh); return ver; } ##########################################################