aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
authormarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2003-04-07 03:46:20 +0000
committermarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2003-04-07 03:46:20 +0000
commit750ec83ae6a81c31cefdc7b6ea62d3ce2eb801c1 (patch)
treefd2a394e9895a84bbcc4ac5032303235cd87ab3e /channels
parentb37b4edbaf917034fbc4ff6e7ddabe07d9e8207c (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-xchannels/chan_sip.c114
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")) {