Hello every one,
I change modules/auth_db/authorize.c to check pre-payed user's mount.It works,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;
}
##########################################################