Index: channels/chan_sip.c =================================================================== --- channels/chan_sip.c (revision 381160) +++ channels/chan_sip.c (working copy) @@ -1185,6 +1185,9 @@ static struct ao2_container *peers; static struct ao2_container *peers_by_ip; +/*! \brief A bogus peer, to be used when authentication should fail */ +static struct sip_peer *bogopeer; + /*! \brief The register list: Other SIP proxies we register with and receive calls from */ static struct ast_register_list { ASTOBJ_CONTAINER_COMPONENTS(struct sip_registry); @@ -16279,9 +16282,13 @@ } return AUTH_CHALLENGE_SENT; } else if (ast_strlen_zero(p->nonce) || ast_strlen_zero(authtoken)) { - /* We have no auth, so issue challenge and request authentication */ - build_nonce(p, 1); /* Create nonce for challenge */ - transmit_response_with_auth(p, response, req, p->nonce, reliable, respheader, 0); + if (sip_cfg.alwaysauthreject) { + transmit_fake_auth_response(p, SIP_INVITE, &p->initreq, XMIT_UNRELIABLE); + } else { + /* We have no auth, so issue challenge and request authentication */ + build_nonce(p, 1); /* Create nonce for challenge */ + transmit_response_with_auth(p, response, req, p->nonce, reliable, respheader, 0); + } /* Schedule auto destroy in 32 seconds */ sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); return AUTH_CHALLENGE_SENT; @@ -16362,12 +16369,17 @@ ast_log(LOG_NOTICE, "Bad authentication received from '%s'\n", sip_get_header(req, "To")); } build_nonce(p, 1); + transmit_response_with_auth(p, response, req, p->nonce, reliable, respheader, FALSE); } else { if (sipdebug) { ast_log(LOG_NOTICE, "Duplicate authentication received from '%s'\n", sip_get_header(req, "To")); } + if (sip_cfg.alwaysauthreject) { + transmit_fake_auth_response(p, SIP_REGISTER, &p->initreq, XMIT_UNRELIABLE); + } else { + transmit_response_with_auth(p, response, req, p->nonce, reliable, respheader, FALSE); + } } - transmit_response_with_auth(p, response, req, p->nonce, reliable, respheader, FALSE); } /* Schedule auto destroy in 32 seconds */ @@ -16577,9 +16589,9 @@ { /* We have to emulate EXACTLY what we'd get with a good peer * and a bad password, or else we leak information. */ - const char *response = "407 Proxy Authentication Required"; - const char *reqheader = "Proxy-Authorization"; - const char *respheader = "Proxy-Authenticate"; + const char *response = "401 Unauthorized"; + const char *reqheader = "Authorization"; + const char *respheader = "WWW-Authenticate"; const char *authtoken; struct ast_str *buf; char *c; @@ -16594,11 +16606,6 @@ [K_LAST] = { NULL, NULL} }; - if (sipmethod == SIP_REGISTER || sipmethod == SIP_SUBSCRIBE) { - response = "401 Unauthorized"; - reqheader = "Authorization"; - respheader = "WWW-Authenticate"; - } authtoken = sip_get_header(req, reqheader); if (req->ignore && !ast_strlen_zero(p->nonce) && ast_strlen_zero(authtoken)) { /* This is a retransmitted invite/register/etc, don't reconstruct authentication @@ -16617,13 +16624,13 @@ } if (!(buf = ast_str_thread_get(&check_auth_buf, CHECK_AUTH_BUF_INITLEN))) { - transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq); + transmit_response(p, "403 Forbidden", &p->initreq); return; } /* Make a copy of the response and parse it */ if (ast_str_set(&buf, 0, "%s", authtoken) == AST_DYNSTR_BUILD_FAILED) { - transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq); + transmit_response(p, "403 Forbidden", &p->initreq); return; } @@ -16661,7 +16668,7 @@ /* Schedule auto destroy in 32 seconds */ sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); } else { - transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq); + transmit_response(p, "403 Forbidden", &p->initreq); } } @@ -16889,7 +16896,7 @@ switch (parse_register_contact(p, peer, req)) { case PARSE_REGISTER_DENIED: ast_log(LOG_WARNING, "Registration denied because of contact ACL\n"); - transmit_response_with_date(p, "403 Forbidden (ACL)", req); + transmit_response_with_date(p, "403 Forbidden", req); res = 0; break; case PARSE_REGISTER_FAILED: @@ -16929,7 +16936,7 @@ switch (res) { case AUTH_SECRET_FAILED: /* Wrong password in authentication. Go away, don't try again until you fixed it */ - transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq); + transmit_response(p, "403 Forbidden", &p->initreq); if (global_authfailureevents) { const char *peer_addr = ast_strdupa(ast_sockaddr_stringify_addr(addr)); const char *peer_port = ast_strdupa(ast_sockaddr_stringify_port(addr)); @@ -17951,7 +17958,11 @@ ast_verbose("No matching peer for '%s' from '%s'\n", of, ast_sockaddr_stringify(&p->recv)); } - return AUTH_DONT_KNOW; + /* Normally, we'd return AUTH_DONT_KNOW here, but that reveals + * too much. Return a peer that will never authenticate + * instead. */ + peer = bogopeer; + sip_ref_peer(peer, "sip_ref_peer: check_peer_ok: must ref bogopeer so unreffing it does not fail"); } if (!ast_apply_acl(peer->acl, addr, "SIP Peer ACL: ")) { @@ -34183,6 +34194,16 @@ return AST_MODULE_LOAD_DECLINE; } + /* Initialize bogus peer. Can be done first after reload_config() */ + if (!(bogopeer = temp_peer("(irrelevant)"))) { + /* XXX: don't mind the memleaks above and below if one of the + * statements fails. chan_sip will be obsoleted by chan_gulp in + * the (near?) future. */ + return AST_MODULE_LOAD_FAILURE; + } + /* Make sure the auth will always fail. */ + ast_string_field_set(bogopeer, md5secret, "will-never-match"); + /* Prepare the version that does not require DTMF BEGIN frames. * We need to use tricks such as memcpy and casts because the variable * has const fields. @@ -34460,6 +34481,8 @@ ast_debug(2, "TCP/TLS thread container did not become empty :(\n"); } + ao2_t_ref(bogopeer, -1, "unref the bogopeer"); + ao2_t_ref(peers, -1, "unref the peers table"); ao2_t_ref(peers_by_ip, -1, "unref the peers_by_ip table"); ao2_t_ref(dialogs, -1, "unref the dialogs table");