xref: /onnv-gate/usr/src/lib/libsip/common/sip_gids.c (revision 3439:0302bfe973fe)
12882Svi117747 /*
22882Svi117747  * CDDL HEADER START
32882Svi117747  *
42882Svi117747  * The contents of this file are subject to the terms of the
52882Svi117747  * Common Development and Distribution License (the "License").
62882Svi117747  * You may not use this file except in compliance with the License.
72882Svi117747  *
82882Svi117747  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92882Svi117747  * or http://www.opensolaris.org/os/licensing.
102882Svi117747  * See the License for the specific language governing permissions
112882Svi117747  * and limitations under the License.
122882Svi117747  *
132882Svi117747  * When distributing Covered Code, include this CDDL HEADER in each
142882Svi117747  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152882Svi117747  * If applicable, add the following below this CDDL HEADER, with the
162882Svi117747  * fields enclosed by brackets "[]" replaced with your own identifying
172882Svi117747  * information: Portions Copyright [yyyy] [name of copyright owner]
182882Svi117747  *
192882Svi117747  * CDDL HEADER END
202882Svi117747  */
212882Svi117747 
222882Svi117747 /*
23*3439Svi117747  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
242882Svi117747  * Use is subject to license terms.
252882Svi117747  */
262882Svi117747 
272882Svi117747 #pragma ident	"%Z%%M%	%I%	%E% SMI"
282882Svi117747 
292882Svi117747 #include <stdio.h>
302882Svi117747 #include <stdlib.h>
312882Svi117747 #include <string.h>
322882Svi117747 #include <fcntl.h>
33*3439Svi117747 #include <pthread.h>
342882Svi117747 #include <unistd.h>
35*3439Svi117747 #include <sip.h>
362882Svi117747 #ifdef	__linux__
372882Svi117747 #include <sasl/sasl.h>
382882Svi117747 #include <sasl/saslplug.h>
392882Svi117747 #else
402882Svi117747 #include <sys/md5.h>
412882Svi117747 #endif
422882Svi117747 
43*3439Svi117747 #include "sip_miscdefs.h"
442882Svi117747 #include "sip_msg.h"
452882Svi117747 
462882Svi117747 void	sip_md5_hash(char *, int, char *, int, char *, int,  char *, int,
472882Svi117747 	    char *, int, char *, int, uchar_t *);
482882Svi117747 
492882Svi117747 #define	SIP_RANDOM_LEN	20
502882Svi117747 
512882Svi117747 /*
522882Svi117747  * Wrapper around /dev/urandom
532882Svi117747  */
542882Svi117747 static int
sip_get_random(char * buf,int buflen)552882Svi117747 sip_get_random(char *buf, int buflen)
562882Svi117747 {
572882Svi117747 	static int devrandom = -1;
582882Svi117747 
592882Svi117747 	if (devrandom == -1 &&
602882Svi117747 	    (devrandom = open("/dev/urandom", O_RDONLY)) == -1) {
612882Svi117747 		return (-1);
622882Svi117747 	}
632882Svi117747 
642882Svi117747 	if (read(devrandom, buf, buflen) == -1)
652882Svi117747 		return (-1);
662882Svi117747 	return (0);
672882Svi117747 }
682882Svi117747 
692882Svi117747 /*
702882Svi117747  * Get MD5 hash of call_id, from_tag, to_tag using key
712882Svi117747  */
722882Svi117747 void
sip_md5_hash(char * str1,int lstr1,char * str2,int lstr2,char * str3,int lstr3,char * str4,int lstr4,char * str5,int lstr5,char * str6,int lstr6,uchar_t * digest)732882Svi117747 sip_md5_hash(char *str1, int lstr1, char *str2, int lstr2, char *str3,
742882Svi117747     int lstr3, char *str4, int lstr4, char *str5, int lstr5,
752882Svi117747     char *str6, int lstr6, uchar_t *digest)
762882Svi117747 {
772882Svi117747 	MD5_CTX	ctx;
782882Svi117747 
792882Svi117747 #ifdef	__linux__
802882Svi117747 	_sasl_MD5Init(&ctx);
812882Svi117747 
822882Svi117747 	_sasl_MD5Update(&ctx, (uchar_t *)&sip_hash_salt, sizeof (uint64_t));
832882Svi117747 
842882Svi117747 	if (str1 != NULL)
852882Svi117747 		_sasl_MD5Update(&ctx, (uchar_t *)str1, lstr1);
862882Svi117747 
872882Svi117747 	if (str2 != NULL)
882882Svi117747 		_sasl_MD5Update(&ctx, (uchar_t *)str2, lstr2);
892882Svi117747 
902882Svi117747 	if (str3 != NULL)
912882Svi117747 		_sasl_MD5Update(&ctx, (uchar_t *)str3, lstr3);
922882Svi117747 
932882Svi117747 	if (str4 != NULL)
942882Svi117747 		_sasl_MD5Update(&ctx, (uchar_t *)str4, lstr4);
952882Svi117747 
962882Svi117747 	if (str5 != NULL)
972882Svi117747 		_sasl_MD5Update(&ctx, (uchar_t *)str5, lstr5);
982882Svi117747 
992882Svi117747 	if (str6 != NULL)
1002882Svi117747 		_sasl_MD5Update(&ctx, (uchar_t *)str6, lstr6);
1012882Svi117747 
1022882Svi117747 	_sasl_MD5Final(digest, &ctx);
1032882Svi117747 #else	/* solaris */
1042882Svi117747 	MD5Init(&ctx);
1052882Svi117747 
1062882Svi117747 	MD5Update(&ctx, (uchar_t *)&sip_hash_salt, sizeof (uint64_t));
1072882Svi117747 
1082882Svi117747 	if (str1 != NULL)
1092882Svi117747 		MD5Update(&ctx, (uchar_t *)str1, lstr1);
1102882Svi117747 
1112882Svi117747 	if (str2 != NULL)
1122882Svi117747 		MD5Update(&ctx, (uchar_t *)str2, lstr2);
1132882Svi117747 
1142882Svi117747 	if (str3 != NULL)
1152882Svi117747 		MD5Update(&ctx, (uchar_t *)str3, lstr3);
1162882Svi117747 
1172882Svi117747 	if (str4 != NULL)
1182882Svi117747 		MD5Update(&ctx, (uchar_t *)str4, lstr4);
1192882Svi117747 
1202882Svi117747 	if (str5 != NULL)
1212882Svi117747 		MD5Update(&ctx, (uchar_t *)str5, lstr5);
1222882Svi117747 
1232882Svi117747 	if (str6 != NULL)
1242882Svi117747 		MD5Update(&ctx, (uchar_t *)str6, lstr6);
1252882Svi117747 
1262882Svi117747 	MD5Final(digest, &ctx);
1272882Svi117747 #endif
1282882Svi117747 }
1292882Svi117747 
1302882Svi117747 /*
1312882Svi117747  * generate a guid (globally unique id)
1322882Svi117747  */
1332882Svi117747 char *
sip_guid()1342882Svi117747 sip_guid()
1352882Svi117747 {
1362882Svi117747 	int		i;
1372882Svi117747 	uint8_t		*r;
1382882Svi117747 	uint32_t 	random;
1392882Svi117747 	uint32_t	time;
1402882Svi117747 	char		*guid;
1412882Svi117747 	int		guidlen;
1422882Svi117747 #ifdef	__linux__
1432882Svi117747 	struct timespec	tspec;
1442882Svi117747 #endif
1452882Svi117747 
1462882Svi117747 	guid = (char *)malloc(SIP_RANDOM_LEN + 1);
1472882Svi117747 	if (guid == NULL)
1482882Svi117747 		return (NULL);
1492882Svi117747 	/*
1502882Svi117747 	 * Get a 32-bit random #
1512882Svi117747 	 */
1522882Svi117747 	if (sip_get_random((char *)&random, sizeof (random)) != 0)
1532882Svi117747 		return (NULL);
1542882Svi117747 #ifdef	__linux__
1552882Svi117747 	if (clock_gettime(CLOCK_REALTIME, &tspec) != 0)
1562882Svi117747 		return (NULL);
1572882Svi117747 	time = (uint32_t)tspec.tv_nsec;
1582882Svi117747 #else
1592882Svi117747 	/*
1602882Svi117747 	 * Get 32-bits from gethrtime()
1612882Svi117747 	 */
1622882Svi117747 	time = (uint32_t)gethrtime();
1632882Svi117747 #endif
1642882Svi117747 	(void) snprintf(guid, SIP_RANDOM_LEN + 1, "%u%u", random, time);
1652882Svi117747 	guidlen = strlen(guid);
1662882Svi117747 
1672882Svi117747 	/*
1682882Svi117747 	 * just throw in some alphabets too
1692882Svi117747 	 */
1702882Svi117747 	r = (uint8_t *)malloc(guidlen);
1712882Svi117747 	if (sip_get_random((char *)r, guidlen) != 0) {
1722882Svi117747 		free(guid);
1732882Svi117747 		return (NULL);
1742882Svi117747 	}
1752882Svi117747 	for (i = 0; i < guidlen; i++) {
1762882Svi117747 		if ((r[i] >= 65 && r[i] <= 90) ||
1772882Svi117747 		    (r[i] >= 97 && r[i] <= 122)) {
1782882Svi117747 			guid[i] = r[i];
1792882Svi117747 		}
1802882Svi117747 	}
1812882Svi117747 	free(r);
1822882Svi117747 	return (guid);
1832882Svi117747 }
1842882Svi117747 
1852882Svi117747 /*
1862882Svi117747  * Generate  branchid for a transaction
1872882Svi117747  */
1882882Svi117747 char *
sip_branchid(sip_msg_t sip_msg)1892882Svi117747 sip_branchid(sip_msg_t sip_msg)
1902882Svi117747 {
1912882Svi117747 	char		*guid;
1922882Svi117747 	char		*branchid;
1932882Svi117747 	_sip_header_t	*via;
1942882Svi117747 	unsigned char 	md5_hash[16];
1952882Svi117747 	_sip_header_t	*to;
1962882Svi117747 	_sip_header_t	*from;
1972882Svi117747 	_sip_header_t	*callid;
1982882Svi117747 	_sip_msg_t	*_sip_msg;
1992882Svi117747 	int		cseq;
2002882Svi117747 	MD5_CTX		ctx;
2012882Svi117747 	size_t		len;
2022882Svi117747 	int		hdrlen;
2032882Svi117747 	int		i;
2042882Svi117747 
2052882Svi117747 	if (sip_msg == NULL) {
2062882Svi117747 generate_bid:
2072882Svi117747 		if ((branchid = (char *)malloc(SIP_BRANCHID_LEN + 1)) == NULL)
2082882Svi117747 			return (NULL);
2092882Svi117747 		guid = sip_guid();
2102882Svi117747 		if (guid == NULL) {
2112882Svi117747 			free(branchid);
2122882Svi117747 			return (NULL);
2132882Svi117747 		}
2142882Svi117747 		(void) snprintf(branchid, SIP_BRANCHID_LEN + 1, "z9hG4bK%s",
2152882Svi117747 		    guid);
2162882Svi117747 		free(guid);
2172882Svi117747 		return (branchid);
2182882Svi117747 	}
2192882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
2202882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
2212882Svi117747 	via = sip_search_for_header(_sip_msg, SIP_VIA, NULL);
2222882Svi117747 	if (via == NULL) {
2232882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
2242882Svi117747 		goto generate_bid;
2252882Svi117747 	}
2262882Svi117747 	to = sip_search_for_header(_sip_msg, SIP_TO, NULL);
2272882Svi117747 	from = sip_search_for_header(_sip_msg, SIP_FROM, NULL);
2282882Svi117747 	callid = sip_search_for_header(_sip_msg, SIP_CALL_ID, NULL);
2292882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
2302882Svi117747 	cseq = sip_get_callseq_num(_sip_msg, NULL);
2312882Svi117747 	if (to == NULL || from == NULL || callid == NULL || cseq == -1)
2322882Svi117747 		return (NULL);
2332882Svi117747 	if (_sip_msg->sip_msg_req_res == NULL ||
2342882Svi117747 	    _sip_msg->sip_msg_req_res->U.sip_request.sip_request_uri.
2352882Svi117747 	    sip_str_ptr == NULL) {
2362882Svi117747 		return (NULL);
2372882Svi117747 	}
2382882Svi117747 	len = 2 * sizeof (md5_hash) + 1;
2392882Svi117747 	if ((branchid = malloc(len)) == NULL)
2402882Svi117747 		return (NULL);
2412882Svi117747 #ifdef	__linux__
2422882Svi117747 	_sasl_MD5Init(&ctx);
2432882Svi117747 	hdrlen = via->sip_hdr_end - via->sip_hdr_start;
2442882Svi117747 	_sasl_MD5Update(&ctx, (uchar_t *)via->sip_hdr_start, hdrlen);
2452882Svi117747 	hdrlen = to->sip_hdr_end - to->sip_hdr_start;
2462882Svi117747 	_sasl_MD5Update(&ctx, (uchar_t *)to->sip_hdr_start, hdrlen);
2472882Svi117747 	hdrlen = from->sip_hdr_end - from->sip_hdr_start;
2482882Svi117747 	_sasl_MD5Update(&ctx, (uchar_t *)from->sip_hdr_start, hdrlen);
2492882Svi117747 	hdrlen = callid->sip_hdr_end - callid->sip_hdr_start;
2502882Svi117747 	_sasl_MD5Update(&ctx, (uchar_t *)callid->sip_hdr_start, hdrlen);
2512882Svi117747 	_sasl_MD5Update(&ctx, (uchar_t *)_sip_msg->sip_msg_req_res->
2522882Svi117747 	    U.sip_request.sip_request_uri.sip_str_ptr,
2532882Svi117747 	    _sip_msg->sip_msg_req_res->U.sip_request.
2542882Svi117747 	    sip_request_uri.sip_str_len);
2552882Svi117747 	_sasl_MD5Update(&ctx, (uchar_t *)&cseq, sizeof (int));
2562882Svi117747 	_sasl_MD5Final(md5_hash, &ctx);
2572882Svi117747 #else	/* solaris */
2582882Svi117747 	MD5Init(&ctx);
2592882Svi117747 	hdrlen = via->sip_hdr_end - via->sip_hdr_start;
2602882Svi117747 	MD5Update(&ctx, (uchar_t *)via->sip_hdr_start, hdrlen);
2612882Svi117747 	hdrlen = to->sip_hdr_end - to->sip_hdr_start;
2622882Svi117747 	MD5Update(&ctx, (uchar_t *)to->sip_hdr_start, hdrlen);
2632882Svi117747 	hdrlen = from->sip_hdr_end - from->sip_hdr_start;
2642882Svi117747 	MD5Update(&ctx, (uchar_t *)from->sip_hdr_start, hdrlen);
2652882Svi117747 	hdrlen = callid->sip_hdr_end - callid->sip_hdr_start;
2662882Svi117747 	MD5Update(&ctx, (uchar_t *)callid->sip_hdr_start, hdrlen);
2672882Svi117747 	MD5Update(&ctx, (uchar_t *)_sip_msg->sip_msg_req_res->
2682882Svi117747 	    U.sip_request.sip_request_uri.sip_str_ptr,
2692882Svi117747 	    _sip_msg->sip_msg_req_res->U.sip_request.
2702882Svi117747 	    sip_request_uri.sip_str_len);
2712882Svi117747 	MD5Update(&ctx, (uchar_t *)&cseq, sizeof (int));
2722882Svi117747 	MD5Final(md5_hash, &ctx);
2732882Svi117747 #endif
2742882Svi117747 	for (i = 0; i < sizeof (md5_hash); i++) {
2752882Svi117747 		(void) snprintf(&branchid[2 * i], len - (2 * i), "%02x",
2762882Svi117747 		    md5_hash[i]);
2772882Svi117747 	}
2782882Svi117747 	return (branchid);
2792882Svi117747 }
2802882Svi117747 
2812882Svi117747 uint32_t
sip_get_cseq()2822882Svi117747 sip_get_cseq()
2832882Svi117747 {
2842882Svi117747 	time_t	tval;
2852882Svi117747 
2862882Svi117747 	tval = time(NULL);
2872882Svi117747 
2882882Svi117747 	return ((uint32_t)tval);
2892882Svi117747 }
2902882Svi117747 
2912882Svi117747 uint32_t
sip_get_rseq()2922882Svi117747 sip_get_rseq()
2932882Svi117747 {
2942882Svi117747 	time_t	tval;
2952882Svi117747 
2962882Svi117747 	tval = time(NULL);
2972882Svi117747 
2982882Svi117747 	return ((uint32_t)tval);
2992882Svi117747 }
300