diff options
author | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2003-04-07 03:46:20 +0000 |
---|---|---|
committer | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2003-04-07 03:46:20 +0000 |
commit | 750ec83ae6a81c31cefdc7b6ea62d3ce2eb801c1 (patch) | |
tree | fd2a394e9895a84bbcc4ac5032303235cd87ab3e /channels | |
parent | b37b4edbaf917034fbc4ff6e7ddabe07d9e8207c (diff) |
Provide authentication for BYE and CANCEL requests
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@764 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rwxr-xr-x | channels/chan_sip.c | 114 |
1 files changed, 71 insertions, 43 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c index bb57ad5f5..e924d3aac 100755 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -190,6 +190,8 @@ static struct sip_pvt { char callerid[256]; /* Caller*ID */ char via[256]; char accountcode[256]; /* Account code */ + char realm[256]; /* Authorization realm */ + char nonce[256]; /* Authorization nonce */ int amaflags; /* AMA Flags */ struct sip_request initreq; /* Initial request */ @@ -328,6 +330,7 @@ static int transmit_response(struct sip_pvt *p, char *msg, struct sip_request *r static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_request *req, int retrans); static int transmit_response_with_auth(struct sip_pvt *p, char *msg, struct sip_request *req, char *rand, int reliable); static int transmit_request(struct sip_pvt *p, char *msg, int inc, int reliable); +static int transmit_request_with_auth(struct sip_pvt *p, char *msg, int inc, int reliable); static int transmit_invite(struct sip_pvt *p, char *msg, int sendsdp, char *auth, char *vxml_url); static int transmit_reinvite_with_sdp(struct sip_pvt *p, struct ast_rtp *rtp); static int transmit_info_with_digit(struct sip_pvt *p, char digit); @@ -335,6 +338,7 @@ static int transmit_message_with_text(struct sip_pvt *p, char *text); static int do_proxy_auth(struct sip_pvt *p, struct sip_request *req); char *getsipuri(char *header); static void free_old_route(struct sip_route *route); +static int build_reply_digest(struct sip_pvt *p, char *orig_header, char *digest, int digest_len); static int __sip_xmit(struct sip_pvt *p, char *data, int len) { @@ -901,7 +905,7 @@ static int sip_hangup(struct ast_channel *ast) if (!p->alreadygone && strlen(p->initreq.data)) { if (needcancel) { if (p->outgoing) { - transmit_request(p, "CANCEL", 0, 1); + transmit_request_with_auth(p, "CANCEL", 0, 1); /* Actually don't destroy us yet, wait for the 487 on our original INVITE, but do set an autodestruct just in case. */ p->needdestroy = 0; @@ -910,7 +914,7 @@ static int sip_hangup(struct ast_channel *ast) transmit_response_reliable(p, "403 Forbidden", &p->initreq); } else { /* Send a hangup */ - transmit_request(p, "BYE", 1, 1); + transmit_request_with_auth(p, "BYE", 1, 1); } } ast_pthread_mutex_unlock(&p->lock); @@ -2543,6 +2547,23 @@ static int transmit_request(struct sip_pvt *p, char *msg, int inc, int reliable) return send_request(p, &resp, reliable, p->ocseq); } +static int transmit_request_with_auth(struct sip_pvt *p, char *msg, int inc, int reliable) +{ + struct sip_request resp; + reqprep(&resp, p, msg, inc); + if (*p->realm) + { + char digest[256]; + memset(digest,0,sizeof(digest)); + build_reply_digest(p, msg, digest, sizeof(digest)); + add_header(&resp, "Proxy-Authorization", digest); + } + + add_header(&resp, "Content-Length", "0"); + add_blank_header(&resp); + return send_request(p, &resp, reliable, p->ocseq); +} + static int expire_register(void *data) { struct sip_peer *p = data; @@ -3495,13 +3516,6 @@ static int reply_digest(struct sip_pvt *p, struct sip_request *req, char *header char *realm = ""; char *nonce = ""; char *c; - char a1[256]; - char a2[256]; - char a1_hash[256]; - char a2_hash[256]; - char resp[256]; - char resp_hash[256]; - char uri[256] = ""; strncpy(tmp, get_header(req, header),sizeof(tmp) - 1); @@ -3511,53 +3525,67 @@ static int reply_digest(struct sip_pvt *p, struct sip_request *req, char *header while (*c && (*c < 33)) c++; if (!*c) break; - if (!strncasecmp(c,"realm=", strlen("realm="))) { - c+=strlen("realm="); - if ((*c == '\"')) { - realm=++c; - if ((c = strchr(c,'\"'))) - *c = '\0'; - } else { - realm = c; - if ((c = strchr(c,','))) - *c = '\0'; - } - - } else if (!strncasecmp(c, "nonce=", strlen("nonce="))) { - c+=strlen("nonce="); - if ((*c == '\"')) { - nonce=++c; - if ((c = strchr(c,'\"'))) - *c = '\0'; - } else { - nonce = c; - if ((c = strchr(c,','))) - *c = '\0'; - } - } else - c = strchr(c,','); - if (c) - c++; + if (!strncasecmp(c,"realm=", strlen("realm="))) { + c+=strlen("realm="); + if ((*c == '\"')) { + realm=++c; + if ((c = strchr(c,'\"'))) + *c = '\0'; + } else { + realm = c; + if ((c = strchr(c,','))) + *c = '\0'; } + } else if (!strncasecmp(c, "nonce=", strlen("nonce="))) { + c+=strlen("nonce="); + if ((*c == '\"')) { + nonce=++c; + if ((c = strchr(c,'\"'))) + *c = '\0'; + } else { + nonce = c; + if ((c = strchr(c,','))) + *c = '\0'; + } + } else + c = strchr(c,','); + if (c) + c++; + } + + /* copy realm and nonce for later authorization of CANCELs and BYEs */ + strncpy(p->realm, realm, sizeof(p->realm)-1); + strncpy(p->nonce, nonce, sizeof(p->nonce)-1); + + build_reply_digest(p, orig_header, digest, digest_len); + return 0; +} + +static int build_reply_digest(struct sip_pvt *p, char* orig_header, char* digest, int digest_len) +{ + char a1[256]; + char a2[256]; + char a1_hash[256]; + char a2_hash[256]; + char resp[256]; + char resp_hash[256]; + char uri[256] = ""; - /* Okay. We've got the realm and nonce from the server. Now lets build the MD5 digest. */ snprintf(uri, sizeof(uri), "sip:%s@%s",p->username, inet_ntoa(p->sa.sin_addr)); - snprintf(a1,sizeof(a1),"%s:%s:%s",p->peername,realm,p->peersecret); + snprintf(a1,sizeof(a1),"%s:%s:%s",p->peername,p->realm,p->peersecret); snprintf(a2,sizeof(a2),"%s:%s",orig_header,uri); md5_hash(a1_hash,a1); md5_hash(a2_hash,a2); - snprintf(resp,sizeof(resp),"%s:%s:%s",a1_hash,nonce,a2_hash); + snprintf(resp,sizeof(resp),"%s:%s:%s",a1_hash,p->nonce,a2_hash); md5_hash(resp_hash,resp); - snprintf(digest,digest_len,"Digest username=\"%s\", realm=\"%s\", algorithm=\"MD5\", uri=\"%s\", nonce=\"%s\", response=\"%s\"",p->peername,realm,uri,nonce,resp_hash); + snprintf(digest,digest_len,"Digest username=\"%s\", realm=\"%s\", algorithm=\"MD5\", uri=\"%s\", nonce=\"%s\", response=\"%s\"",p->peername,p->realm,uri,p->nonce,resp_hash); return 0; } - - static char show_users_usage[] = @@ -4159,7 +4187,7 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc } } /* Always increment on a BYE */ - transmit_request(p, "BYE", 1, 1); + transmit_request_with_auth(p, "BYE", 1, 1); p->alreadygone = 1; } } else if (!strcasecmp(cmd, "CANCEL")) { |