|
|
|
@ -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,32 +7655,13 @@ 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));
|
|
|
|
@ -7685,6 +7686,7 @@ static enum check_auth_result check_auth(struct sip_pvt *p, struct sip_request *
|
|
|
|
|
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",
|
|
|
|
@ -7726,7 +7728,7 @@ static enum check_auth_result check_auth(struct sip_pvt *p, struct sip_request *
|
|
|
|
|
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"));
|
|
|
|
|
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 {
|
|
|
|
@ -7747,8 +7749,8 @@ static enum check_auth_result check_auth(struct sip_pvt *p, struct sip_request *
|
|
|
|
|
/* 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
|
|
|
|
|