diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index bb57ad5f563fa4b51d4804074c878942c3f6c07a..e924d3aac2a8f927421353fb49e7b791cde5f4dc 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")) {