diff --git a/conf/default_context.xml b/conf/default_context.xml index 6ad54df5aa..19d65a7d9d 100644 --- a/conf/default_context.xml +++ b/conf/default_context.xml @@ -19,6 +19,25 @@ + + + + + + + + + + + + + + + diff --git a/src/include/switch_types.h b/src/include/switch_types.h index dd4c5c90d3..bcd26773bf 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -957,7 +957,8 @@ typedef enum { SWITCH_CAUSE_MANAGER_REQUEST = 503, SWITCH_CAUSE_BLIND_TRANSFER = 600, SWITCH_CAUSE_ATTENDED_TRANSFER = 601, - SWITCH_CAUSE_ALLOTTED_TIMEOUT = 602 + SWITCH_CAUSE_ALLOTTED_TIMEOUT = 602, + SWITCH_CAUSE_USER_CHALLENGE = 603 } switch_call_cause_t; typedef enum { diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index cd9259fccb..5c6cbd6417 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -806,17 +806,21 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi case SWITCH_MESSAGE_INDICATE_REJECT: if (msg->string_arg) { int code = 0; - char *reason; + char *reason = NULL; if (switch_channel_test_flag(channel, CF_ANSWERED)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Call is already answered, Rejecting with hangup\n"); switch_channel_hangup(channel, SWITCH_CAUSE_CALL_REJECTED); } else { - if ((reason = strchr(msg->string_arg, ' '))) { - reason++; + if (!switch_strlen_zero(msg->string_arg)){ code = atoi(msg->string_arg); - } else { + if ((reason = strchr(msg->string_arg, ' '))) { + reason++; + } + } + + if (!reason && code != 407) { reason = "Call Refused"; } @@ -824,8 +828,20 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi code = 488; } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Rejecting with %d %s\n", code, reason); - nua_respond(tech_pvt->nh, code, reason, TAG_END()); + if (code == 407) { + const char *to_uri = switch_channel_get_variable(channel, "sip_to_uri"); + const char *to_host = reason; + + if (switch_strlen_zero(to_host)) { + to_host = switch_channel_get_variable(channel, "sip_to_host"); + } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Challanging call %s\n", to_uri); + sofia_reg_auth_challange(NULL, tech_pvt->profile, tech_pvt->nh, REG_INVITE, to_host, 0); + switch_channel_hangup(channel, SWITCH_CAUSE_USER_CHALLENGE); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Rejecting with %d %s\n", code, reason); + nua_respond(tech_pvt->nh, code, reason, TAG_END()); + } } } break; diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 3d0a5d1d27..24e52001c0 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -428,6 +428,7 @@ void sofia_presence_event_handler(switch_event_t *event); void sofia_presence_mwi_event_handler(switch_event_t *event); void sofia_presence_cancel(void); switch_status_t config_sofia(int reload, char *profile_name); +void sofia_reg_auth_challange(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_regtype_t regtype, const char *realm, int stale); auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, sip_authorization_t const *authorization, const char *regstr, char *np, size_t nplen, char *ip, switch_event_t **v_event); void sofia_reg_handle_sip_r_challenge(int status, diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index e90b7c7d24..572d9d9f17 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -1756,7 +1756,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ return; } - if ((profile->pflags & PFLAG_AUTH_CALLS)) { + if ((profile->pflags & PFLAG_AUTH_CALLS) || sip->sip_proxy_authorization || sip->sip_authorization) { if (sofia_reg_handle_register(nua, profile, nh, sip, REG_INVITE, key, sizeof(key), &v_event)) { if (v_event) { switch_event_destroy(&v_event); @@ -1786,6 +1786,8 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_addr); channel = switch_core_session_get_channel(session); + switch_channel_set_variable(channel, "sip_authorized", "true"); + if (v_event) { switch_event_header_t *hp; diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index b0dbee7c85..f9b7893b1f 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -272,6 +272,36 @@ char *sofia_reg_find_reg_url(sofia_profile_t *profile, const char *user, const c } } + +void sofia_reg_auth_challange(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_regtype_t regtype, const char *realm, int stale) +{ + switch_uuid_t uuid; + char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; + char *sql, *auth_str; + + switch_uuid_get(&uuid); + switch_uuid_format(uuid_str, &uuid); + + switch_mutex_lock(profile->ireg_mutex); + sql = switch_mprintf("insert into sip_authentication (nonce, expires) values('%q', %ld)", + uuid_str, time(NULL) + profile->nonce_ttl); + assert(sql != NULL); + sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, NULL); + switch_safe_free(sql); + switch_mutex_unlock(profile->ireg_mutex); + + auth_str = + switch_mprintf("Digest realm=\"%q\", nonce=\"%q\",%s algorithm=MD5, qop=\"auth\"", realm, uuid_str, stale ? " stale=\"true\"," : ""); + + if (regtype == REG_REGISTER) { + nua_respond(nh, SIP_401_UNAUTHORIZED, TAG_IF(nua, NUTAG_WITH_THIS(nua)), SIPTAG_WWW_AUTHENTICATE_STR(auth_str), TAG_END()); + } else if (regtype == REG_INVITE) { + nua_respond(nh, SIP_407_PROXY_AUTH_REQUIRED, TAG_IF(nua, NUTAG_WITH_THIS(nua)), SIPTAG_PROXY_AUTHENTICATE_STR(auth_str), TAG_END()); + } + + switch_safe_free(auth_str); +} + uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t *profile, nua_handle_t * nh, sip_t const *sip, sofia_regtype_t regtype, char *key, uint32_t keylen, switch_event_t **v_event) { @@ -396,32 +426,11 @@ uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t *profile, nua_han } if (!authorization || stale) { - switch_uuid_t uuid; - char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; - char *sql, *auth_str; - - switch_uuid_get(&uuid); - switch_uuid_format(uuid_str, &uuid); - - switch_mutex_lock(profile->ireg_mutex); - sql = switch_mprintf("insert into sip_authentication (nonce, expires) values('%q', %ld)", - uuid_str, time(NULL) + profile->nonce_ttl); - assert(sql != NULL); - sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, NULL); - switch_safe_free(sql); - switch_mutex_unlock(profile->ireg_mutex); - - auth_str = - switch_mprintf("Digest realm=\"%q\", nonce=\"%q\",%s algorithm=MD5, qop=\"auth\"", to_host, uuid_str, stale ? " stale=\"true\"," : ""); + sofia_reg_auth_challange(nua, profile, nh, regtype, to_host, stale); if (regtype == REG_REGISTER) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Requesting Registration from: [%s@%s]\n", to_user, to_host); - nua_respond(nh, SIP_401_UNAUTHORIZED, NUTAG_WITH_THIS(nua), SIPTAG_WWW_AUTHENTICATE_STR(auth_str), TAG_END()); - } else if (regtype == REG_INVITE) { - nua_respond(nh, SIP_407_PROXY_AUTH_REQUIRED, NUTAG_WITH_THIS(nua), SIPTAG_PROXY_AUTHENTICATE_STR(auth_str), TAG_END()); } - - switch_safe_free(auth_str); return 1; } reg: diff --git a/src/switch_channel.c b/src/switch_channel.c index 68a1a1b646..e4b41f263f 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -96,6 +96,7 @@ static struct switch_cause_table CAUSE_CHART[] = { {"BLIND_TRANSFER", SWITCH_CAUSE_BLIND_TRANSFER}, {"ATTENDED_TRANSFER", SWITCH_CAUSE_ATTENDED_TRANSFER}, {"ALLOTTED_TIMEOUT", SWITCH_CAUSE_ALLOTTED_TIMEOUT}, + {"USER_CHALLENGE", SWITCH_CAUSE_USER_CHALLENGE}, {NULL, 0} };