Index: chan_sip.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v retrieving revision 1.46 diff -u -r1.46 chan_sip.c --- chan_sip.c 6 Apr 2003 23:39:57 -0000 1.46 +++ chan_sip.c 7 Apr 2003 01:11:07 -0000 @@ -190,6 +190,8 @@ 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 */ @@ -327,7 +329,7 @@ static int transmit_response(struct sip_pvt *p, char *msg, struct sip_request *req); 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(struct sip_pvt *p, char *msg, int inc, int reliable, char *auth); 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 +337,7 @@ 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) { @@ -899,9 +902,16 @@ p->needdestroy = 1; /* Start the process if it's not already started */ if (!p->alreadygone && strlen(p->initreq.data)) { + char digest[256]; + char *auth = NULL; if (needcancel) { if (p->outgoing) { - transmit_request(p, "CANCEL", 0, 1); + if (*p->realm) { + auth = digest; + memset(digest,0,sizeof(digest)); + build_reply_digest(p, "CANCEL", digest, sizeof(digest)); + } + transmit_request(p, "CANCEL", 0, 1, auth); /* 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 +920,12 @@ transmit_response_reliable(p, "403 Forbidden", &p->initreq); } else { /* Send a hangup */ - transmit_request(p, "BYE", 1, 1); + if (*p->realm) { + auth = digest; + memset(digest,0,sizeof(digest)); + build_reply_digest(p, "BYE", digest, sizeof(digest)); + } + transmit_request(p, "BYE", 1, 1, auth); } } ast_pthread_mutex_unlock(&p->lock); @@ -2534,10 +2549,13 @@ return send_request(p, &req, 1, p->ocseq); } -static int transmit_request(struct sip_pvt *p, char *msg, int inc, int reliable) +static int transmit_request(struct sip_pvt *p, char *msg, int inc, int reliable, char *auth) { struct sip_request resp; reqprep(&resp, p, msg, inc); + if (auth) + add_header(&resp, "Proxy-Authorization", auth); + add_header(&resp, "Content-Length", "0"); add_blank_header(&resp); return send_request(p, &resp, reliable, p->ocseq); @@ -3495,13 +3513,6 @@ 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); @@ -3540,24 +3551,38 @@ c++; } - /* Okay. We've got the realm and nonce from the server. Now lets build the MD5 digest. */ + /* 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); +} + +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] = ""; + 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[] = @@ -3677,7 +3702,7 @@ if (peer->pokeexpire > -1) ast_sched_del(sched, peer->pokeexpire); if (!strcasecmp(msg, "INVITE")) - transmit_request(p, "ACK", 0, 0); + transmit_request(p, "ACK", 0, 0, NULL); p->needdestroy = 1; /* Try again eventually */ if ((peer->lastms < 0) || (peer->lastms > peer->maxms)) @@ -3744,7 +3769,7 @@ ast_queue_control(p->owner, AST_CONTROL_ANSWER, 0); } } - transmit_request(p, "ACK", 0, 0); + transmit_request(p, "ACK", 0, 0, NULL); } else if (!strcasecmp(msg, "REGISTER")) { /* char *exp; */ int expires; @@ -3768,13 +3793,13 @@ break; case 401: /* Not authorized on REGISTER */ /* XXX: Do I need to ACK the 401? - transmit_request(p, "ACK", 0); + transmit_request(p, "ACK", 0, NULL); */ do_register_auth(p, req); break; case 407: /* First we ACK */ - transmit_request(p, "ACK", 0, 0); + transmit_request(p, "ACK", 0, 0, NULL); /* Then we AUTH */ do_proxy_auth(p, req); /* This is just a hack to kill the channel while testing */ @@ -3787,7 +3812,7 @@ } if (p->owner) ast_queue_hangup(p->owner,0); - transmit_request(p,"ACK",0); + transmit_request(p,"ACK",0, NULL); sip_destroy(p); p = NULL; */ @@ -3827,7 +3852,7 @@ ast_queue_hangup(p->owner, 0); break; } - transmit_request(p, "ACK", 0, 0); + transmit_request(p, "ACK", 0, 0, NULL); p->alreadygone = 1; if (!p->owner) p->needdestroy = 1; @@ -3844,7 +3869,7 @@ switch(resp) { case 200: if (!strcasecmp(msg, "INVITE") || !strcasecmp(msg, "REGISTER") ) - transmit_request(p, "ACK", 0, 0); + transmit_request(p, "ACK", 0, 0, NULL); break; } } @@ -4158,8 +4183,15 @@ ast_async_goto(transfer_to,"", p->refer_to,1, 1); } } - /* Always increment on a BYE */ - transmit_request(p, "BYE", 1, 1); + { + char digest[256]; + if (*p->realm) { + memset(digest,0,sizeof(digest)); + build_reply_digest(p, "BYE", digest, sizeof(digest)); + } + /* Always increment on a BYE */ + transmit_request(p, "BYE", 1, 1, (*p->realm) ? digest : NULL); + } p->alreadygone = 1; } } else if (!strcasecmp(cmd, "CANCEL")) {