If someone interesting this is set of routes to make Digest authorization manually(with no uac_auth) I would be grateful if somebody optimizes this workaround or find security troubles.
route[dispatch_out] { #For testing, I used the dispatcher module #You can create your own search method register data for proxy in this cfg is «hardcoded» val $avp(registrant)=6 #Now I use gateway attributes in dr_gateways table #Username and password and aor I get from registrant table $avp(registrant)=6; #dispatcher set 1001 is set contain proxy which need to auth #lets go! if(!ds_select_domain("1001","8")){ send_reply("404", "No destination"); exit; } #clearing auth flag resetflag(7); #get auth data from registrant table avp_db_query("select username, password, aor from registrant where id=$avp(registrant)","$avp(stored_username);$avp(stored_password);$avp(stored_aor)"); #build new From-hdr with registrant data uac_replace_from("$avp(stored_username)", "$avp(stored_aor)"); #build new To-hdr with registrant data $avp(stored_to)="sip:" + $(ru{uri.user}) + "@" + $(avp(stored_to){uri.host}) + ":" + $(ru{uri.port}); uac_replace_to("$avp(stored_to)"); t_on_failure("rtf_dispatch_out"); t_on_reply("auth_reply"); t_relay(); exit; } onreply_route[auth_reply] { if ( t_check_status("401|407") ) { #if is not first "unauthorized" - do nothing (see below) if (isflagset(7)) { return; } #special route to parce WWW-Atuh hdr route(parse_digest); } else if ( t_check_status("200") ) { #special route to decrease cseq(see below) route(dec_cseq); } } route[parse_digest]{ #saving Auth HDR of 401/407 reply $avp(stored_digest)=$hdr(WWW-Authenticate); xlog("L_INFO", "Route PARSE_DIGEST orig WWW-Authenticate header is $hdr(WWW-Authenticate);"); #some transformations for parse avp_subst("$avp(stored_digest)", "/, /;/g"); avp_subst("$avp(stored_digest)", "/Digest //g"); avp_subst("$avp(stored_digest)", "/\"//g"); xlog("L_INFO", "Route PARSE_DIGEST digest params is $avp(stored_digest)"); #use script transformations to get values of HDR and save it in AVPs $avp(stored_realm)=$(avp(stored_digest){param.value,realm}); $avp(stored_nonce)=$(avp(stored_digest){param.value,nonce}); if $(avp(stored_digest){param.exist,algorithm}) { $avp(stored_algorithm)=$(avp(stored_digest){param.value,algorithm}); } else { $avp(stored_algorithm)="MD5"; } if $(avp(stored_digest){param.exist,qop}) { $avp(stored_qop)=$(avp(stored_digest){param.value,qop}); } else { $avp(stored_qop)="none"; } xlog("L_INFO", "Route PARSE_DIGEST digest algorithm is $avp(stored_algorithm)"); xlog("L_INFO", "Route PARSE_DIGEST digest realm is $avp(stored_realm)"); xlog("L_INFO", "Route PARSE_DIGEST digest nonce is $avp(stored_nonce)"); xlog("L_INFO", "Route PARSE_DIGEST digest qop is $avp(stored_qop)"); return; } #failure route - processing 401/407 error and send new invite with Authorization HDR failure_route[rtf_dispatch_out]{ xlog("L_INFO", "DISPATCHER OUTBOUND FILED"); if ( t_check_status("401|407") ) { if (isflagset(7)) { #If its not first «unauthorized» - registration data is wrong t_reply("503","Authentication failed"); exit; } #go to route wich append auth HDR route(append_authorize); #route which increase cseq route(inc_cseq); t_on_failure("rtf_dispatch_out"); t_relay(); exit; } if (t_was_cancelled()) { exit; } #this is standard part of dispatcher failure route xlog("L_INFO", "IAM IN FAILURE ROUTE DISPATCH\n"); ds_mark_dst("p"); xlog("L_INFO", "IAM SELECT NEW DESTINATION\n"); if (ds_next_domain()) { $avp(final_reply_timeout) = 2; t_on_failure("rtf_dispatch_out"); t_relay(); exit; } } #this route to append Authorization HDR to second invite route[append_authorize] { xlog("L_INFO", "Route APPEND_AUTHORIZE orig ruri is $ru"); #saving ruri for use it for build response $avp(stored_ruri)="sip:" + $(ru{uri.user}) + "@" + $(ru{uri.host}); xlog("L_INFO", "Route APPEND_AUTHORIZE parsed ruri is $avp(stored_ruri)"); #calculate ha1 $avp(ha1)=$avp(stored_username) + ":" + $avp(stored_realm) + ":" + $avp(stored_password); xlog("L_INFO", "Route APPEND_AUTHORIZE ha1 is $avp(ha1)"); $avp(ha1)=$(avp(ha1){s.md5}); xlog("L_INFO", "Route APPEND_AUTHORIZE ha1 is $avp(ha1)"); #switch for different types of qop switch($avp(stored_qop)) { case "none": $avp(ha2)=$rm + ":" + $avp(stored_ruri); xlog("L_INFO", "Route APPEND_AUTHORIZE $rm ha2 is $avp(ha2)"); $avp(ha2)=$(avp(ha2){s.md5}); xlog("L_INFO", "Route APPEND_AUTHORIZE $rm ha2 is $avp(ha2)"); $avp(auth_response)=$avp(ha1) + ":" + $avp(stored_nonce) + ":" + $avp(ha2); xlog("L_INFO", "Route APPEND_AUTHORIZE auth_response is $avp(auth_response)"); $avp(auth_response)=$(avp(auth_response){s.md5}); xlog("L_INFO", "Route APPEND_AUTHORIZE auth_response is $avp(auth_response)"); $avp(auth_hdr)="Authorization: Digest username=\"" + $avp(stored_username) + "\", realm=\"" + $avp(stored_realm) + "\", nonce=\"" + $avp(stored_nonce) + "\", uri=\"" + $avp(stored_ruri) + "\", response=\"" + $avp(auth_response) + "\", algorithm=" + $avp(stored_algorithm) + "\r\n"; break; case "auth": $avp(ha2)=$rm + ":" + $avp(stored_ruri); xlog("L_INFO", "Route APPEND_AUTHORIZE $rm ha2 is $avp(ha2)"); $avp(ha2)=$(avp(ha2){s.md5}); xlog("L_INFO", "Route APPEND_AUTHORIZE $rm ha2 is $avp(ha2)"); $avp(stored_cnonce)=$(RANDOM{s.dec2hex}); #xlog("random testing $(RANDOM{s.dec2hex})\n"); $avp(nc)="00000001"; $avp(auth_response)=$avp(ha1) + ":" + $avp(stored_nonce) + ":00000001:" + $avp(stored_cnonce) + ":auth:" + $avp(ha2); xlog("L_INFO", "Route APPEND_AUTHORIZE auth_response is $avp(auth_response)"); $avp(auth_response)=$(avp(auth_response){s.md5}); xlog("L_INFO", "Route APPEND_AUTHORIZE auth_response is $avp(auth_response)"); $avp(auth_hdr)="Authorization: Digest username=\"" + $avp(stored_username) + "\", realm=\"" + $avp(stored_realm) + "\", nonce=\"" + $avp(stored_nonce) + "\", uri=\"" + $avp(stored_ruri) + "\", response=\"" + $avp(auth_response) + "\", algorithm=" + $avp(stored_algorithm) + "\", qop=auth" + ", cnonce=\"" + $avp(stored_cnonce) + "\", nc=00000001" + "\r\n"; break; case "auth-int": #TODO xlog("L_INFO", "Route APPEND_AUTHORIZE not supported qop auth-int"); break; default: xlog("L_INFO", "Route APPEND_AUTHORIZE unexpected qop is $avp(stored_qop)"); } xlog("L_INFO", "Route APPEND_AUTHORIZE auth_hdr is <$avp(auth_hdr)>"); #Append HDR to Invite if (append_hf("$avp(auth_hdr)")) { setflag(7); } return; } #two short routes to inc or dec cseq value #it use dialog module!!!!!! #I need dlg_flag for check manual cseq updating --------------------------------------------------------- …... route[inc_cseq]{ if(remove_hf("CSeq")){ $var(cseq) = $(cs{s.int}) + 1; $var(cseq) = "CSeq: " + $var(cseq) + " " + $rm + "\r\n"; append_hf("$var(cseq)"); if (!is_dlg_flag_set("7")) { set_dlg_flag("7"); } xlog("L_INFO", "INCREASE CSEQ NEW IS <$var(cseq)>"); } return; } route[dec_cseq]{ if(remove_hf("CSeq")){ $var(cseq) = $(cs{s.int}) - 1; $var(cseq) = "CSeq: " + $var(cseq) + " " + $rm + "\r\n"; append_hf("$var(cseq)"); if (!is_dlg_flag_set("7")) { set_dlg_flag("7"); } xlog("L_INFO", "DECREASE CSEQ NEW IS<$var(cseq)>"); } return; } #and in standard part of route logic #that looks like this: if (has_totag()) { if (loose_route() || match_dialog() ) { if (is_method("BYE")) { setflag(ACC_DO); # do accounting ... setflag(ACC_FAILED); # ... even if the transaction fails } else if (is_method("INVITE")) { record_route(); } else if (is_method("ACK")) { #Decreasing cseq back if (is_dlg_flag_set("7")) { route(inc_cseq); } } ………….. } …... --------------------------------------------------------- Thanks! ———————————— Timofeev Dmitry VoIP Engineer Linux, Asterisk, Freeswitch, Cisco solutions Skype: itsroot icq: 227227933
_______________________________________________ Users mailing list Users@lists.opensips.org http://lists.opensips.org/cgi-bin/mailman/listinfo/users