- Formatting
authorOlle Johansson <oej@edvina.net>
Mon, 19 Jun 2006 21:09:24 +0000 (21:09 +0000)
committerOlle Johansson <oej@edvina.net>
Mon, 19 Jun 2006 21:09:24 +0000 (21:09 +0000)
- Create larger buffer for managing long auth headers from clients (adviced by SNOM)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@34951 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_sip.c

index 8bee7bc..94c4068 100644 (file)
@@ -7604,6 +7604,26 @@ static enum check_auth_result check_auth(struct sip_pvt *p, struct sip_request *
        const char *reqheader = "Proxy-Authorization";
        const char *respheader = "Proxy-Authenticate";
        const char *authtoken;
+       char a1_hash[256];
+       char resp_hash[256]="";
+       char tmp[BUFSIZ * 2];                /* Make a large enough buffer */
+       char *c;
+       int  wrongnonce = FALSE;
+       int  good_response;
+       const char *usednonce = p->randdata;
+
+       /* table of recognised keywords, and their value in the digest */
+       enum keys { K_RESP, K_URI, K_USER, K_NONCE, K_LAST };
+       struct x {
+               const char *key;
+               const char *s;
+       } *i, keys[] = {
+               [K_RESP] = { "response=", "" },
+               [K_URI] = { "uri=", "" },
+               [K_USER] = { "username=", "" },
+               [K_NONCE] = { "nonce=", "" },
+               [K_LAST] = { NULL, NULL}
+       };
 
        /* Always OK if no secret */
        if (ast_strlen_zero(secret) && ast_strlen_zero(md5secret))
@@ -7635,120 +7655,102 @@ static enum check_auth_result check_auth(struct sip_pvt *p, struct sip_request *
                /* Schedule auto destroy in 32 seconds */
                sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
                return AUTH_CHALLENGE_SENT;
-       } else {        /* We have auth, so check it */
+       } 
 
-               /* XXX reduce nesting here */
+       /* --- We have auth, so check it */
 
-               /* Whoever came up with the authentication section of SIP can suck my %&#$&* for not putting
-               an example in the spec of just what it is you're doing a hash on. */
-               char a1_hash[256];
-               char resp_hash[256]="";
-               char tmp[256];
-               char *c;
-               int  wrongnonce = FALSE;
-               int  good_response;
-               const char *usednonce = p->randdata; /* XXX check */
-
-               /* table of recognised keywords, and their value in the digest */
-               enum keys { K_RESP, K_URI, K_USER, K_NONCE, K_LAST };
-               struct x {
-                       const char *key;
-                       const char *s;
-               } *i, keys[] = {
-                       [K_RESP] = { "response=", "" },
-                       [K_URI] = { "uri=", "" },
-                       [K_USER] = { "username=", "" },
-                       [K_NONCE] = { "nonce=", "" },
-                       [K_LAST] = { NULL, NULL}
-               };
-
-               /* Make a copy of the response and parse it */
-               ast_copy_string(tmp, authtoken, sizeof(tmp));
-               c = tmp;
-
-               while(c && *(c = ast_skip_blanks(c)) ) { /* lookup for keys */
-                       for (i = keys; i->key != NULL; i++) {
-                               const char *separator = ",";    /* default */
-
-                               if (strncasecmp(c, i->key, strlen(i->key)) != 0)
-                                       continue;
-                               /* Found. Skip keyword, take text in quotes or up to the separator. */
-                               c += strlen(i->key);
-                               if (*c == '"') { /* in quotes. Skip first and look for last */
-                                       c++;
-                                       separator = "\"";
-                               }
-                               i->s = c;
-                               strsep(&c, separator);
-                               break;
+       /* Whoever came up with the authentication section of SIP can suck my %&#$&* for not putting
+          an example in the spec of just what it is you're doing a hash on. */
+
+
+       /* Make a copy of the response and parse it */
+       ast_copy_string(tmp, authtoken, sizeof(tmp));
+       c = tmp;
+
+       while(c && *(c = ast_skip_blanks(c)) ) { /* lookup for keys */
+               for (i = keys; i->key != NULL; i++) {
+                       const char *separator = ",";    /* default */
+
+                       if (strncasecmp(c, i->key, strlen(i->key)) != 0)
+                               continue;
+                       /* Found. Skip keyword, take text in quotes or up to the separator. */
+                       c += strlen(i->key);
+                       if (*c == '"') { /* in quotes. Skip first and look for last */
+                               c++;
+                               separator = "\"";
                        }
-                       if (i->key == NULL) /* not found, jump after space or comma */
-                               strsep(&c, " ,");
-               }
-               /* Verify that digest username matches  the username we auth as */
-               if (strcmp(username, keys[K_USER].s)) {
-                       ast_log(LOG_WARNING, "username mismatch, have <%s>, digest has <%s>\n",
-                               username, keys[K_USER].s);
-                       /* Oops, we're trying something here */
-                       return AUTH_USERNAME_MISMATCH;
+                       i->s = c;
+                       strsep(&c, separator);
+                       break;
                }
+               if (i->key == NULL) /* not found, jump after space or comma */
+                       strsep(&c, " ,");
+       }
 
-               /* Verify nonce from request matches our nonce.  If not, send 401 with new nonce */
-               if (strcasecmp(p->randdata, keys[K_NONCE].s)) { /* XXX it was 'n'casecmp ? */
-                       wrongnonce = TRUE;
-                       usednonce = keys[K_NONCE].s;
-               }
+       /* Verify that digest username matches  the username we auth as */
+       if (strcmp(username, keys[K_USER].s)) {
+               ast_log(LOG_WARNING, "username mismatch, have <%s>, digest has <%s>\n",
+                       username, keys[K_USER].s);
+               /* Oops, we're trying something here */
+               return AUTH_USERNAME_MISMATCH;
+       }
 
-               if (!ast_strlen_zero(md5secret))
-                       ast_copy_string(a1_hash, md5secret, sizeof(a1_hash));
-               else {
-                       char a1[256];
-                       snprintf(a1, sizeof(a1), "%s:%s:%s", username, global_realm, secret);
-                       ast_md5_hash(a1_hash, a1);
-               }
+       /* Verify nonce from request matches our nonce.  If not, send 401 with new nonce */
+       if (strcasecmp(p->randdata, keys[K_NONCE].s)) { /* XXX it was 'n'casecmp ? */
+               wrongnonce = TRUE;
+               usednonce = keys[K_NONCE].s;
+       }
 
-               /* compute the expected response to compare with what we received */
-               {
-                       char a2[256];
-                       char a2_hash[256];
-                       char resp[256];
-
-                       snprintf(a2, sizeof(a2), "%s:%s", sip_methods[sipmethod].text,
-                                       S_OR(keys[K_URI].s, uri));
-                       ast_md5_hash(a2_hash, a2);
-                       snprintf(resp, sizeof(resp), "%s:%s:%s", a1_hash, usednonce, a2_hash);
-                       ast_md5_hash(resp_hash, resp);
-               }
+       if (!ast_strlen_zero(md5secret))
+               ast_copy_string(a1_hash, md5secret, sizeof(a1_hash));
+       else {
+               char a1[256];
+               snprintf(a1, sizeof(a1), "%s:%s:%s", username, global_realm, secret);
+               ast_md5_hash(a1_hash, a1);
+       }
 
-               good_response = keys[K_RESP].s &&
-                               !strncasecmp(keys[K_RESP].s, resp_hash, strlen(resp_hash));
-               if (wrongnonce) {
-                       ast_string_field_build(p, randdata, "%08lx", ast_random());
-                       if (good_response) {
-                               if (sipdebug)
-                                       ast_log(LOG_NOTICE, "stale nonce received from '%s'\n", get_header(req, "To"));
-                               /* We got working auth token, based on stale nonce . */
-                               transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 1);
-                       } else {
-                               /* Everything was wrong, so give the device one more try with a new challenge */
-                               if (sipdebug)
-                                       ast_log(LOG_NOTICE, "Bad authentication received from '%s'\n", get_header(req, "To"));
-                               transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0);
-                       }
+       /* compute the expected response to compare with what we received */
+       {
+               char a2[256];
+               char a2_hash[256];
+               char resp[256];
 
-                       /* Schedule auto destroy in 32 seconds */
-                       sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
-                       return AUTH_CHALLENGE_SENT;
-               } 
-               if (good_response)
-                       return AUTH_SUCCESSFUL;
+               snprintf(a2, sizeof(a2), "%s:%s", sip_methods[sipmethod].text,
+                               S_OR(keys[K_URI].s, uri));
+               ast_md5_hash(a2_hash, a2);
+               snprintf(resp, sizeof(resp), "%s:%s:%s", a1_hash, usednonce, a2_hash);
+               ast_md5_hash(resp_hash, resp);
+       }
 
-               /* Ok, we have a bad username/secret pair */
-               /* Challenge again, and again, and again */
-               transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0);
+       good_response = keys[K_RESP].s &&
+                       !strncasecmp(keys[K_RESP].s, resp_hash, strlen(resp_hash));
+       if (wrongnonce) {
+               ast_string_field_build(p, randdata, "%08lx", ast_random());
+               if (good_response) {
+                       if (sipdebug)
+                               ast_log(LOG_NOTICE, "Correct auth, but based on stale nonce received from '%s'\n", get_header(req, "To"));
+                       /* We got working auth token, based on stale nonce . */
+                       transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 1);
+               } else {
+                       /* Everything was wrong, so give the device one more try with a new challenge */
+                       if (sipdebug)
+                               ast_log(LOG_NOTICE, "Bad authentication received from '%s'\n", get_header(req, "To"));
+                       transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0);
+               }
+
+               /* Schedule auto destroy in 32 seconds */
                sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
                return AUTH_CHALLENGE_SENT;
-       }
+       } 
+       if (good_response)
+               return AUTH_SUCCESSFUL;
+
+       /* Ok, we have a bad username/secret pair */
+       /* Challenge again, and again, and again */
+       transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0);
+       sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
+
+       return AUTH_CHALLENGE_SENT;
 }
 
 /*! \brief Callback for the devicestate notification (SUBSCRIBE) support subsystem