Index: channels/chan_sip.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v retrieving revision 1.812 diff -u -r1.812 chan_sip.c --- channels/chan_sip.c 23 Aug 2005 01:50:11 -0000 1.812 +++ channels/chan_sip.c 23 Aug 2005 09:22:08 -0000 @@ -114,6 +114,7 @@ #define DEFAULT_RETRANS 1000 /* How frequently to retransmit */ /* 2 * 500 ms in RFC 3261 */ #define MAX_RETRANS 7 /* Try only 7 times for retransmissions */ +#define MAX_AUTHTRIES 3 /* Try authentication three times, then fail */ #define DEBUG_READ 0 /* Recieved data */ @@ -4971,8 +4972,10 @@ ast_copy_string(p->qop, r->qop, sizeof(p->qop)); memset(digest,0,sizeof(digest)); - build_reply_digest(p, sipmethod, digest, sizeof(digest)); - add_header(&req, "Authorization", digest); + if(!build_reply_digest(p, sipmethod, digest, sizeof(digest))) + add_header(&req, "Authorization", digest); + else + ast_log(LOG_NOTICE, "No authorization available for authentication of registration to %s@%s\n", r->username, r->hostname); } @@ -5089,8 +5092,10 @@ char digest[1024]; memset(digest, 0, sizeof(digest)); - build_reply_digest(p, sipmethod, digest, sizeof(digest)); - add_header(&resp, "Proxy-Authorization", digest); + if(!build_reply_digest(p, sipmethod, digest, sizeof(digest))) + add_header(&resp, "Proxy-Authorization", digest); + else + ast_log(LOG_WARNING, "No authentication available for call %s\n", p->callid); } /* If we are hanging up and know a cause for that, send it in clear text to make debugging easier. */ @@ -8116,6 +8121,8 @@ memset(&options, 0, sizeof(struct sip_invite_param)); p->authtries++; + if (option_debug > 1) + ast_log(LOG_DEBUG, "Auth attempt %d on %s\n", p->authtries, sip_methods[sipmethod].text); memset(digest,0,sizeof(digest)); if (reply_digest(p, req, header, sipmethod, digest, sizeof(digest) )) { /* No way to authenticate */ @@ -8130,6 +8137,7 @@ /*--- reply_digest: reply to authentication for outbound registrations ---*/ /* This is used for register= servers in sip.conf, SIP proxies we register with for receiving calls from. */ +/* Returns -1 if we have no auth */ static int reply_digest(struct sip_pvt *p, struct sip_request *req, char *header, int sipmethod, char *digest, int digest_len) { @@ -8192,13 +8200,13 @@ ast_copy_string(r->opaque, p->opaque, sizeof(r->opaque)); ast_copy_string(r->qop, p->qop, sizeof(r->qop)); } - build_reply_digest(p, sipmethod, digest, digest_len); - return 0; + return build_reply_digest(p, sipmethod, digest, digest_len); } /*--- build_reply_digest: Build reply digest ---*/ /* Build digest challenge for authentication of peers (for registration) and users (for calls). Also used for authentication of CANCEL and BYE */ +/* Returns -1 if we have no auth */ static int build_reply_digest(struct sip_pvt *p, int method, char* digest, int digest_len) { char a1[256]; @@ -8236,10 +8244,12 @@ secret = p->peersecret; md5secret = p->peermd5secret; } + if (ast_strlen_zero(username)) /* We have no authentication */ + return -1; /* Calculate SIP digest response */ - snprintf(a1,sizeof(a1),"%s:%s:%s",username,p->realm,secret); + snprintf(a1,sizeof(a1),"%s:%s:%s", username, p->realm, secret); snprintf(a2,sizeof(a2),"%s:%s", sip_methods[method].text, uri); if (!ast_strlen_zero(md5secret)) ast_copy_string(a1_hash, md5secret, sizeof(a1_hash)); @@ -8249,10 +8259,10 @@ /* XXX We hard code the nonce-number to 1... What are the odds? Are we seriously going to keep track of every nonce we've seen? Also we hard code to "auth"... XXX */ if (!ast_strlen_zero(p->qop)) - snprintf(resp,sizeof(resp),"%s:%s:%s:%s:%s:%s",a1_hash,p->nonce, "00000001", cnonce, "auth", a2_hash); + snprintf(resp,sizeof(resp),"%s:%s:%s:%s:%s:%s", a1_hash, p->nonce, "00000001", cnonce, "auth", a2_hash); else - snprintf(resp,sizeof(resp),"%s:%s:%s",a1_hash,p->nonce,a2_hash); - ast_md5_hash(resp_hash,resp); + snprintf(resp,sizeof(resp),"%s:%s:%s", a1_hash, p->nonce, a2_hash); + ast_md5_hash(resp_hash, resp); /* XXX We hard code our qop to "auth" for now. XXX */ if (!ast_strlen_zero(p->qop)) snprintf(digest, digest_len, "Digest username=\"%s\", realm=\"%s\", algorithm=MD5, uri=\"%s\", nonce=\"%s\", response=\"%s\", opaque=\"%s\", qop=auth, cnonce=\"%s\", nc=00000001", username, p->realm, uri, p->nonce, resp_hash, p->opaque, cnonce); @@ -8626,7 +8636,7 @@ switch (resp) { case 401: /* Unauthorized */ - if ((p->authtries > 1) || do_register_auth(p, req, "WWW-Authenticate", "Authorization")) { + if ((p->authtries == MAX_AUTHTRIES) || do_register_auth(p, req, "WWW-Authenticate", "Authorization")) { ast_log(LOG_NOTICE, "Failed to authenticate on REGISTER to '%s@%s' (Tries %d)\n", p->registry->username, p->registry->hostname, p->authtries); ast_set_flag(p, SIP_NEEDDESTROY); } @@ -8645,7 +8655,7 @@ ast_sched_del(sched, r->timeout); break; case 407: /* Proxy auth */ - if ((p->authtries > 1) || do_register_auth(p, req, "Proxy-Authenticate", "Proxy-Authorization")) { + if ((p->authtries == MAX_AUTHTRIES) || do_register_auth(p, req, "Proxy-Authenticate", "Proxy-Authorization")) { ast_log(LOG_NOTICE, "Failed to authenticate on REGISTER to '%s' (tries '%d')\n", get_header(&p->initreq, "From"), p->authtries); ast_set_flag(p, SIP_NEEDDESTROY); } @@ -8866,6 +8876,7 @@ } break; case 200: /* 200 OK */ + p->authtries = 0; /* Reset authentication counter */ if (sipmethod == SIP_MESSAGE) { /* We successfully transmitted a message */ ast_set_flag(p, SIP_NEEDDESTROY); @@ -8904,13 +8915,12 @@ } else /* It's possible we're getting an ACK after we've tried to disconnect by sending CANCEL */ ast_set_flag(p, SIP_PENDINGBYE); - p->authtries = 0; /* If I understand this right, the branch is different for a non-200 ACK only */ transmit_request(p, SIP_ACK, seqno, 0, 1); check_pendings(p); } else if (sipmethod == SIP_REGISTER) { res = handle_response_register(p, resp, rest, req, ignore, seqno); - } + } break; case 401: /* Not www-authorized on SIP method */ if (sipmethod == SIP_INVITE) { @@ -8918,9 +8928,12 @@ transmit_request(p, SIP_ACK, seqno, 0, 0); /* Then we AUTH */ p->theirtag[0]='\0'; /* forget their old tag, so we don't match tags when getting response */ - if ((p->authtries > 1) || do_proxy_auth(p, req, "WWW-Authenticate", "Authorization", SIP_INVITE, 1)) { + if ((p->authtries == MAX_AUTHTRIES) || do_proxy_auth(p, req, "WWW-Authenticate", "Authorization", SIP_INVITE, 1)) { ast_log(LOG_NOTICE, "Failed to authenticate on INVITE to '%s'\n", get_header(&p->initreq, "From")); ast_set_flag(p, SIP_NEEDDESTROY); + ast_set_flag(p, SIP_ALREADYGONE); + if (p->owner) + ast_queue_control(p->owner, AST_CONTROL_CONGESTION); } } else if (p->registry && sipmethod == SIP_REGISTER) { res = handle_response_register(p, resp, rest, req, ignore, seqno); @@ -8957,9 +8970,12 @@ /* But only if the packet wasn't marked as ignore in handle_request */ if (!ignore){ p->theirtag[0]='\0'; /* forget their old tag, so we don't match tags when getting response */ - if ((p->authtries > 1) || do_proxy_auth(p, req, "Proxy-Authenticate", "Proxy-Authorization", SIP_INVITE, 1)) { + if ((p->authtries == MAX_AUTHTRIES) || do_proxy_auth(p, req, "Proxy-Authenticate", "Proxy-Authorization", SIP_INVITE, 1)) { ast_log(LOG_NOTICE, "Failed to authenticate on INVITE to '%s'\n", get_header(&p->initreq, "From")); ast_set_flag(p, SIP_NEEDDESTROY); + if (p->owner) + ast_queue_control(p->owner, AST_CONTROL_CONGESTION); + ast_set_flag(p, SIP_ALREADYGONE); } } } else if (sipmethod == SIP_BYE || sipmethod == SIP_REFER) { @@ -8967,7 +8983,7 @@ ast_log(LOG_WARNING, "Asked to authenticate %s, to %s:%d but we have no matching peer!\n", msg, ast_inet_ntoa(iabuf, sizeof(iabuf), p->recv.sin_addr), ntohs(p->recv.sin_port)); ast_set_flag(p, SIP_NEEDDESTROY); - if ((p->authtries > 1) || do_proxy_auth(p, req, "Proxy-Authenticate", "Proxy-Authorization", sipmethod, 0)) { + if ((p->authtries == MAX_AUTHTRIES) || do_proxy_auth(p, req, "Proxy-Authenticate", "Proxy-Authorization", sipmethod, 0)) { ast_log(LOG_NOTICE, "Failed to authenticate on %s to '%s'\n", msg, get_header(&p->initreq, "From")); ast_set_flag(p, SIP_NEEDDESTROY); } @@ -9072,9 +9088,10 @@ switch(resp) { case 200: /* Change branch since this is a 200 response */ - if (sipmethod == SIP_INVITE) + if (sipmethod == SIP_INVITE) { transmit_request(p, SIP_ACK, seqno, 0, 1); - else if (sipmethod == SIP_MESSAGE) + p->authtries = 0; + } else if (sipmethod == SIP_MESSAGE) /* We successfully transmitted a message */ ast_set_flag(p, SIP_NEEDDESTROY); break; @@ -9083,7 +9100,7 @@ if (ast_strlen_zero(p->authname)) ast_log(LOG_WARNING, "Asked to authenticate %s, to %s:%d but we have no matching peer!\n", msg, ast_inet_ntoa(iabuf, sizeof(iabuf), p->recv.sin_addr), ntohs(p->recv.sin_port)); - if ((p->authtries > 1) || do_proxy_auth(p, req, "Proxy-Authenticate", "Proxy-Authorization", sipmethod, 0)) { + if ((p->authtries == MAX_AUTHTRIES) || do_proxy_auth(p, req, "Proxy-Authenticate", "Proxy-Authorization", sipmethod, 0)) { ast_log(LOG_NOTICE, "Failed to authenticate on %s to '%s'\n", msg, get_header(&p->initreq, "From")); ast_set_flag(p, SIP_NEEDDESTROY); }