|
|
|
@ -0,0 +1,242 @@ |
|
|
|
|
|
|
|
modparam("statistics","variable", "auth:amqp_not_available") |
|
|
|
modparam("statistics","variable", "auth:new_tran") |
|
|
|
modparam("statistics","variable", "auth:challenge") |
|
|
|
modparam("statistics","variable", "auth:amqp_async_error") |
|
|
|
modparam("statistics","variable", "auth:amqp_returned") |
|
|
|
modparam("statistics","variable", "auth:amqp_timeout") |
|
|
|
modparam("statistics","variable", "auth:authn_perm_err") |
|
|
|
modparam("statistics","variable", "auth:authn_err") |
|
|
|
modparam("statistics","variable", "auth:authn_resp") |
|
|
|
modparam("statistics","variable", "auth:authn_unknown") |
|
|
|
|
|
|
|
|
|
|
|
route[AUTHORIZATION] |
|
|
|
{ |
|
|
|
if (isflagset(FLAG_INTERNALLY_SOURCED)) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (isflagset(FLAG_AUTHORIZED)) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (!is_method("INVITE|REFER|MESSAGE|NOTIFY|SUBSCRIBE|PUBLISH")) { |
|
|
|
setflag(FLAG_AUTHORIZED); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
route(AUTHORIZATION_CHECK); |
|
|
|
|
|
|
|
if (!isflagset(FLAG_AUTHORIZED)) { |
|
|
|
xlog("L_INFO", "$ci|auth|challenging $rm from $Au $si:$sp\n"); |
|
|
|
$var(auth) = auth_challenge("$fd", "4"); |
|
|
|
update_stat("auth:challenge", "+1"); |
|
|
|
if($var(auth) != 1) { |
|
|
|
xlog("L_ERROR", "$ci|register|error creating or sending challenge to $rm attempt for $fu from $si:$sp\n"); |
|
|
|
send_reply("403", "Forbidden"); |
|
|
|
} |
|
|
|
exit; |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
route[AUTHORIZATION_CHECK] |
|
|
|
{ |
|
|
|
|
|
|
|
route(AUTHORIZATION_CHECK_TRUSTED); |
|
|
|
route(AUTHORIZATION_CHECK_REGISTERED); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
route[AUTHORIZATION_CHECK_TRUSTED] |
|
|
|
{ |
|
|
|
if (isflagset(FLAG_AUTHORIZED)) return; |
|
|
|
|
|
|
|
if (isflagset(FLAG_TRUSTED_SOURCE)) { |
|
|
|
route(SETUP_AUTH_ORIGIN); |
|
|
|
route(SETUP_AUTH_TRUSTED); |
|
|
|
setflag(FLAG_AUTHORIZED); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
route[AUTHORIZATION_CHECK_REGISTERED] |
|
|
|
{ |
|
|
|
if (isflagset(FLAG_AUTHORIZED)) return; |
|
|
|
|
|
|
|
#!ifdef REGISTRAR_ROLE |
|
|
|
$xavp(regcfg=>match_received) = $su; |
|
|
|
if (registered("location","sip:$Au", 2, 1) == 1) { |
|
|
|
route(SETUP_AUTH_ORIGIN); |
|
|
|
$xavp(hf[0]=>X-AUTH-Token) = $xavp(ulattrs=>token); |
|
|
|
setflag(FLAG_AUTHORIZED); |
|
|
|
} |
|
|
|
#!endif |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
route[HANDLE_AUTHORIZATION] |
|
|
|
{ |
|
|
|
|
|
|
|
if(!is_present_hf("Proxy-Authorization")) { |
|
|
|
route(MAIN); |
|
|
|
exit; |
|
|
|
} |
|
|
|
|
|
|
|
$var(amqp_payload_request) = $_s({"Event-Category" : "directory" , "Event-Name" : "authn_req", "Method" : "REGISTER", "Auth-Nonce" : "$adn", "Auth-Realm" : "$fd", "Auth-User" : "$fU", "From" : "$fu", "To" : "$tu", "Orig-IP" : "$si", "Orig-Port" : "$sp", "User-Agent" : "$(ua{s.escape.common}{s.replace,\','}{s.replace,$$,})", "Contact" : "$(ct{s.escape.common}{s.replace,\','}{s.replace,$$,})", "Call-ID" : "$ci" }); |
|
|
|
$var(amqp_routing_key) = $_s($def(REGISTRAR_AMQP_RK_PREFIX)$(fd{kz.encode})); |
|
|
|
$avp(kz_timeout) = $sel(cfg_get.kazoo.registrar_query_timeout_ms); |
|
|
|
$xavp(deltas=>query) = $(TV(Sn){s.replace,.,}); |
|
|
|
|
|
|
|
xlog("L_DEBUG", "$ci|amqp|publishing to $def(REGISTRAR_AMQP_EXCHANGE) => $var(amqp_routing_key) : $def(REGISTRAR_AMQP_FLAGS) : $var(amqp_payload_request)\n"); |
|
|
|
if(kazoo_async_query("$def(REGISTRAR_AMQP_EXCHANGE)", $var(amqp_routing_key), $var(amqp_payload_request), "KZ_AUTHORIZATION_CHECK_REPLY", "KZ_AUTHORIZATION_CHECK_TIMEOUT", "$def(REGISTRAR_AMQP_FLAGS)") != 1) { |
|
|
|
xlog("L_INFO", "$ci|log|failed to send registrar query for authentication credentials for $Au $si:$sp\n"); |
|
|
|
update_stat("auth:amqp_async_error", "+1"); |
|
|
|
send_reply("403", "Forbidden"); |
|
|
|
exit; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
failure_route[KZ_AUTHORIZATION_CHECK_TIMEOUT] |
|
|
|
{ |
|
|
|
if($(kzR{kz.json,Event-Name}) == "message_returned" ) { |
|
|
|
xlog("L_WARNING", "$ci|amqp|message was returned by broker $(kzR{kz.json,Error-Code}) $(kzR{kz.json,Error-Reason})\n"); |
|
|
|
update_stat("auth:amqp_returned", "+1"); |
|
|
|
} else { |
|
|
|
xlog("L_WARNING", "$ci|end|failed $T_reply_code $T_reply_reason [$T(id_index):$T(id_label)] querying directory for authentication credentials for $Au $si:$sp\n"); |
|
|
|
update_stat("auth:amqp_timeout", "+1"); |
|
|
|
} |
|
|
|
t_reply("403", "Forbidden"); |
|
|
|
exit; |
|
|
|
} |
|
|
|
|
|
|
|
onreply_route[KZ_AUTHORIZATION_CHECK_REPLY] |
|
|
|
{ |
|
|
|
$var(StartRoute) = $(TV(Sn){s.replace,.,}); |
|
|
|
$var(delta_to_start) = $var(StartRoute) - $(kzR{kz.json,AMQP-Received}); |
|
|
|
$var(delta_from_query) = $(kzR{kz.json,AMQP-Received}) - $xavp(deltas=>query); |
|
|
|
xlog("L_INFO", "$ci|log|received $(kzR{kz.json,Event-Category}) $(kzR{kz.json,Event-Name}) reply from $(kzR{kz.json,App-Name})-$(kzR{kz.json,App-Version}) (Δ1 $(kzR{kz.json,AMQP-Elapsed-Micro}) μs , Δ2 $var(delta_to_start) μs, Δ3 $var(delta_from_query) μs)\n"); |
|
|
|
$var(password) = $(kzR{kz.json,Auth-Password}); |
|
|
|
if( $(kzR{kz.json,Event-Name}) == "authn_err" ) { |
|
|
|
update_stat("auth:authn_err", "+1"); |
|
|
|
t_reply("403", "Forbidden"); |
|
|
|
exit; |
|
|
|
} else if( $(kzR{kz.json,Event-Name}) == "authn_resp" ) { |
|
|
|
update_stat("auth:authn_resp", "+1"); |
|
|
|
route(KZ_AUTHORIZATION_CHECK_RESPONSE); |
|
|
|
} else { |
|
|
|
update_stat("auth:authn_unknown", "+1"); |
|
|
|
xlog("L_INFO", "$ci|log|unhandle response from directory $Au via $(kzR{kz.json,App-Name})-$(kzR{kz.json,App-Version})\n"); |
|
|
|
t_reply("403", "Forbidden"); |
|
|
|
exit; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
route[KZ_AUTHORIZATION_CHECK_RESPONSE] |
|
|
|
{ |
|
|
|
if (!pv_auth_check("$fd", "$var(password)", "0", "0")) { |
|
|
|
#!ifdef ANTIFLOOD_ROLE |
|
|
|
route(ANITFLOOD_FAILED_AUTH); |
|
|
|
#!endif |
|
|
|
xlog("L_WARNING", "$ci|end|auth|$mbu\n"); |
|
|
|
|
|
|
|
send_reply("403", "Forbidden"); |
|
|
|
exit; |
|
|
|
} |
|
|
|
|
|
|
|
consume_credentials(); |
|
|
|
route(SETUP_AUTH_ORIGIN); |
|
|
|
$xavp(ulattrs=>custom_channel_vars) = $(kzR{kz.json,Custom-Channel-Vars}); |
|
|
|
$xavp(ulattrs[0]=>token) = $_s($(kzR{kz.json,Custom-Channel-Vars.Authorizing-ID})@$(kzR{kz.json,Custom-Channel-Vars.Account-ID})); |
|
|
|
setflag(FLAG_AUTHORIZED); |
|
|
|
route(MAIN); |
|
|
|
exit; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
route[SETUP_AUTH_ORIGIN] |
|
|
|
{ |
|
|
|
$xavp(hf=>X-AUTH-IP) = $si; |
|
|
|
$xavp(hf[0]=>X-AUTH-PORT) = $sp; |
|
|
|
} |
|
|
|
|
|
|
|
route[SETUP_AUTH_AOR] |
|
|
|
{ |
|
|
|
if ($avp(is_registered) == "true") return; |
|
|
|
|
|
|
|
#!ifdef REGISTRAR_ROLE |
|
|
|
$xavp(regcfg=>match_received) = $su; |
|
|
|
if (registered("location","sip:$Au", 2, 1) == 1) { |
|
|
|
$avp(is_registered) = "true"; |
|
|
|
} |
|
|
|
#!endif |
|
|
|
} |
|
|
|
|
|
|
|
route[SETUP_AUTH_TRUSTED] |
|
|
|
{ |
|
|
|
|
|
|
|
if (isflagset(FLAG_TRUSTED_SOURCE)) { |
|
|
|
$xavp(hf[0]=>X-AUTH-Token) = $avp(trusted_x_header); |
|
|
|
$xavp(hf[0]=>X-AUTH-URI-User) = $rU; |
|
|
|
$xavp(hf[0]=>X-AUTH-URI-Realm) = $rd; |
|
|
|
if(is_present_hf("P-Asserted-Identity") && $(ai{uri.user}) != "") { |
|
|
|
$xavp(hf[0]=>X-AUTH-From-User) = $(ai{uri.user}); |
|
|
|
} else if(is_present_hf("P-Preferred-Identity") && $pU != "") { |
|
|
|
$xavp(hf[0]=>X-AUTH-From-User) = $pU; |
|
|
|
} else if(is_present_hf("Remote-Party-ID") && $(re{uri.user}) != "") { |
|
|
|
$xavp(hf[0]=>X-AUTH-From-User) = $(re{uri.user}); |
|
|
|
} else { |
|
|
|
$xavp(hf[0]=>X-AUTH-From-User) = $fU; |
|
|
|
} |
|
|
|
if($xavp(hf=>X-AUTH-From-User) =~ "^\+?00+$") { |
|
|
|
$xavp(hf[0]=>X-AUTH-From-Is-Anonymous) = "true"; |
|
|
|
$xavp(hf[0]=>X-AUTH-From-User) = $null; |
|
|
|
} else if($(xavp(hf=>X-AUTH-From-User){s.tolower}) =~ "^anonymous$") { |
|
|
|
$xavp(hf[0]=>X-AUTH-From-Is-Anonymous) = "true"; |
|
|
|
$xavp(hf[0]=>X-AUTH-From-User) = $null; |
|
|
|
} |
|
|
|
setflag(FLAG_AUTHORIZED); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
route[AUTH_HEADERS_JSON] |
|
|
|
{ |
|
|
|
xavp_params_implode("hf", "$var(outx)"); |
|
|
|
$var(out) = $(var(outx){re.subst,/^(.*);$$/\1/}); |
|
|
|
$var(c) = $(var(out){param.count}); |
|
|
|
$var(headers_json) = ""; |
|
|
|
$var(sep) = ""; |
|
|
|
xlog("L_DEBUG", "$ci|auth|headers $var(c) => $var(out) => $var(outx)\n"); |
|
|
|
while($var(c) > 0) { |
|
|
|
$var(idx) = $var(c) - 1; |
|
|
|
xlog("L_DEBUG", "$ci|auth|adding $(var(out){param.name,$var(idx)}): $(var(out){param.valueat,$var(idx)}{s.unescape.param})\n"); |
|
|
|
append_hf("$(var(out){param.name,$var(idx)}): $(var(out){param.valueat,$var(idx)}{s.unescape.param})\r\n"); |
|
|
|
$var(headers_json) = $_s($var(headers_json)$var(sep)"$(var(out){param.name,$var(idx)})" : "$(var(out){param.valueat,$var(idx)}{s.unescape.param})"); |
|
|
|
$var(c) = $var(c) - 1; |
|
|
|
$var(sep) = " , "; |
|
|
|
} |
|
|
|
$var(headers_json) = $_s({ $var(headers_json) }); |
|
|
|
} |
|
|
|
|
|
|
|
route[AUTH_HEADERS] |
|
|
|
{ |
|
|
|
remove_hf_re("^X-"); |
|
|
|
|
|
|
|
if (!is_method("INVITE|MESSAGE|REFER")) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
xavp_params_implode("hf", "$var(outx)"); |
|
|
|
$var(out) = $(var(outx){re.subst,/^(.*);$$/\1/}); |
|
|
|
$var(c) = $(var(out){param.count}); |
|
|
|
xlog("L_DEBUG", "$ci|auth|headers $var(c) => $var(out) => $var(outx)\n"); |
|
|
|
while($var(c) > 0) { |
|
|
|
$var(idx) = $var(c) - 1; |
|
|
|
xlog("L_DEBUG", "$ci|auth|adding $(var(out){param.name,$var(idx)}): $(var(out){param.valueat,$var(idx)}{s.unescape.param})\n"); |
|
|
|
append_hf("$(var(out){param.name,$var(idx)}): $(var(out){param.valueat,$var(idx)}{s.unescape.param})\r\n"); |
|
|
|
$var(c) = $var(c) - 1; |
|
|
|
} |
|
|
|
|
|
|
|
} |