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