Hmmm...
Thank you very much for support
I use subst('/^From:(.*)sip:[^@]*@[a-zA-Z0-9.]+(.*)$/From:\1sip:$avp(i:21)@$avp(i:24)\2/i');
now replace work strange i can see first time it said correct to: From: sip:andres.moya4@sipdiscount.com;transport=UDP;tag=19790648. for both - first INVITE and second with auth header
Second time i am sending to provider: From: sip:andres.moya4@sipdiscount.com;transport=UDP;tag=19790648.From: sip:21100036838@terrasip.net;transport=UDP;tag=19790648. and then with auth header: From: sip:andres.moya4@sipdiscount.com;transport=UDP;tag=19790648.
something is wrong again :( You can see i used flags to split first subst call from second one. Second time it is not doing substitution, it is adding to From header :) But then looks like uac_auth removes one :)
I don't care to restore From field, i need it just work.
uac_replace_from do nothing then caller in failure_route via sub route second time. maybe it set From for first branch?
I want it go on list of providers and authenticate then asked.
I have branch_route, i tried to arm t_on_branch , but xlog in this route never write anything in log. I don't know how to use branches. I just know that if i want to call t_relay(), i should always say - append_branch() ;) Any one can explain briefly how branches supposed to work? Especially how to use branch_route. I feel i am nearly there. I guess author of auc module can maybe be interested to add loading of authentication data from database.
my number is sip:andres.moya@riki.ru (not email), anyone welcome to call... testing
ok my logic is
if (number PSTN) { route (PSTN_RELAY); }
route[PSTN_RELAY]{
do first stage cr_route.....
route(LOAD_AUTH);
t_relay();
}
##### LOAD_AUTH ########## # loading authentication information from carrierauth table # set From field according to carrierauth information # arguments: # $rd - request uri doamin, sip provider carrier # returns: # avp(i:20) - rewrited host = $rd # avp(i:21) - auth user # avp(i:22) - auth pass # avp(i:23) - auth realm # avp(i:24) - auth domain
route[LOAD_AUTH]{ xlog ("L_INFO","LOAD_AUTH: searching authentication for host host: $rd"); $avp(i:20)=$rd;
if ( avp_db_query( "SELECT username, password, realm, domain FROM carrierauth WHERE hostname='$rd'", "$avp(i:21);$avp(i:22);$avp(i:23);$avp(i:24)") > 0 ) { xlog ("L_INFO","LOAD_AUTH: for $rd loaded data user: $avp(i:21) pass: $avp(i:22) realm: $avp(i:23) domain: $avp(i:24)");
# replace from_user@from_domain xlog("L_INFO","LOAD_AUTH: changing From: -> sip:$avp(i:21)@$avp(i:24)");
#uac_replace_from("sip:$avp(i:21)@$avp(i:24)"); #uac_replace_from doesnt work in failure route. if (!isflagset(30)) {
subst('/^From:(.*)sip:[^@]*@[a-zA-Z0-9.]+(.*)$/From:\1sip:$avp(i:21)@$avp(i:24)\2/i');
} else {
subst('/^From:(.*)sip:[^@]*@[a-zA-Z0-9.]+(.*)$/From:\1sip:$avp(i:21)@$avp(i:24)\2/i'); } setflag(30); }
# we are not relaying authentications :) remove_hf("Authorization"); # remove client authentication
# reset flag to mark no authentication yet performed resetflag(10); # let's use 10 to know uac authentication was not sent yet
xlog("L_INFO","LOAD_AUTH: flag 10 reset and Authorization header clered. returning\n");
return(1);
}
failure_route[FAIL_ONE] { xlog("L_INFO","entering failure route with code: $T_reply_code \n"); #if (t_grep_status("415")) xlog("L_INFO","415! \n");
if ( t_check_status("401|407") ) # Unathorised reply { xlog("L_INFO","Authentication required \n"); # have we already tried to authenticate? do we have auth information loaded? if (isflagset(10) || $avp(i:21)==$null ) # auth was already sent or we don't have auth info { xlog("Authentication to $avp(i:20) provider as $avp(i:21)@$avp(i:24) failed\n"); t_reply("503","Authentication failed"); avp_delete("$avp(i:20)"); avp_delete("$avp(i:21)"); avp_delete("$avp(i:22)"); avp_delete("$avp(i:23)"); avp_delete("$avp(i:24)"); exit(); # :(
}
# if call from here LOAD_AUTH will look for original uri, not rewriten before if( !is_avp_set("$avp(i:20)") || $avp(i:20)=='') { # if LAOD_AUTH was not done yet route (LOAD_AUTH); # loads auth avps and rewrite 'from' field }
# this avps loaded before by LOAD_AUTH # avp(i:20) - rewrited host # avp(i:21) - auth user # avp(i:22) - auth pass # avp(i:23) - auth realm # avp(i:24) - auth domain
xlog ("L_INFO","for $rd using: $avp(i:21) pass: $avp(i:22) realm: $avp(i:23) domain: $avp(i:24)");
remove_hf("Authorization"); # remove client authentication if (uac_auth()) # adding auth header {xlog ("\nMessage:\n$mb\n\n"); xlog("L_INFO","Authorization header set, sending...\n"); # mark that auth was performed setflag(10);
# next time i want t_check_status look at some other errstatus t_drop_replies();
t_on_failure("FAIL_ONE"); # repeat the request with auth response this time append_branch(); # ??? t_relay();
exit; } }
# In case of failure on PSTN provider, send it to an alternative route: # if ( t_check_status("415|480|408|5[0-9][0-9]")) { if ( isflagset(11) && t_check_status("415|480|408|5[0-9][0-9]")) {
# next time i want t_check_status look at some other errstatus t_drop_replies();
xlog("L_INFO", "FAIL_ONE: got code $T_reply_code will try next carrier domain\n"); revert_uri(); if (!cr_next_domain("$avp(s:carrier)", "$avp(s:domain)", "$avp(s:rc_pstn_num)", "$avp(s:rc_host)", "$T_reply_code", "$avp(s:domain)")) { xlog("L_ERR", "cr_next_domain failed\n"); exit; } if (!cr_route("$avp(s:carrier)", "$avp(s:domain)", "$avp(s:rc_pstn_num)", "$avp(s:rc_pstn_num)", "call_id")) { xlog("L_ERR", "cr_route failed\n"); exit; }
route(LOAD_AUTH);
xlog("L_INFO", "FAIL_ONE: done LOAD_AUTH, relaying to next provider: $rd\n"); t_on_failure("FAIL_ONE"); append_branch(); if (!t_relay()) { xlog("L_ERR", "t_relay to $rd failed\n"); exit; } exit;
}
#!ifdef WITH_NAT if (is_method("INVITE") && (isbflagset("6") || isflagset(5))) { unforce_rtp_proxy(); } #!endif
if (t_is_canceled()) { exit; }
t_reply("404","Not found");
}
Miklos Tirpak wrote:
[please keep the list CC-d because others may also be interested in the solution or may know the answer better.]
On 11/20/2009 07:06 PM, Andres Moya wrote:
Can i ask one more question here. It is complicated, i am using uac_replace_from and uac_auth. I am using failure route to process authentication if necessary and redirect on next carrier.
If i authenticated with one provider, then fot let say 415 ( i set only speex in UAC to get it ;) ). Ok SER send request to second provider, i use uac_replace_from once again in my LOAD_AUTH route then uac_auth again.
Ok. now i see from ngrep that uac_replace_from did nothing in from field and use user@domain for first provider, authentication failed :(
Which authentication fails? The first or the second one? The first should work, at least the from header should be rewritten by the function.
The second authentication will not work this way (if it requires a different from header) because the proxy "remembers" for the header changes done before the first t_relay() function call and applies the same header modifications also for any other branch added from failure route. Hence, the outgoing SIP request to the second provider will contain the same from HF as the request to the first provider.
The easiest way is to apply the header modifications in branch route if you do not need to reuse them later from failure route. Modifications done in branch routes are valid only within that branch.
I moved uac_replace_from to my failure route to call once again before uac_auth, but got config error as i can't use uac_replace_from in failure_route.
I think you already use this function from failure route because it is in a route block that is included from failure route. The only difference is that the syntax checker does not recognize the issue. I am not familiar with uac_replace_from() but after having a quick look at the function I think it is safe to use it from here.
Ok i will use textops to rewrite, but it is ugly?
The main difference is that uac_replace_from() restores the original From HF when the response if forwarded. If you use textops module then you need to restore the header manually.
no. Maybe i should call uac_replace_from in branch route?
I would suggest this way. Both for the first and for the second provider.
Miklos
Thanks