mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 10:47:18 +00:00 
			
		
		
		
	Provide authentication for BYE and CANCEL requests
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@764 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		| @@ -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")) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user