xref: /titanic_52/usr/src/lib/libsip/common/sip_gids.c (revision 2c2c41837e330b002c4220a39638150db504fe0e)
140cb5e5dSvi117747 /*
240cb5e5dSvi117747  * CDDL HEADER START
340cb5e5dSvi117747  *
440cb5e5dSvi117747  * The contents of this file are subject to the terms of the
540cb5e5dSvi117747  * Common Development and Distribution License (the "License").
640cb5e5dSvi117747  * You may not use this file except in compliance with the License.
740cb5e5dSvi117747  *
840cb5e5dSvi117747  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
940cb5e5dSvi117747  * or http://www.opensolaris.org/os/licensing.
1040cb5e5dSvi117747  * See the License for the specific language governing permissions
1140cb5e5dSvi117747  * and limitations under the License.
1240cb5e5dSvi117747  *
1340cb5e5dSvi117747  * When distributing Covered Code, include this CDDL HEADER in each
1440cb5e5dSvi117747  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1540cb5e5dSvi117747  * If applicable, add the following below this CDDL HEADER, with the
1640cb5e5dSvi117747  * fields enclosed by brackets "[]" replaced with your own identifying
1740cb5e5dSvi117747  * information: Portions Copyright [yyyy] [name of copyright owner]
1840cb5e5dSvi117747  *
1940cb5e5dSvi117747  * CDDL HEADER END
2040cb5e5dSvi117747  */
2140cb5e5dSvi117747 
2240cb5e5dSvi117747 /*
23*2c2c4183Svi117747  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
2440cb5e5dSvi117747  * Use is subject to license terms.
2540cb5e5dSvi117747  */
2640cb5e5dSvi117747 
2740cb5e5dSvi117747 #pragma ident	"%Z%%M%	%I%	%E% SMI"
2840cb5e5dSvi117747 
2940cb5e5dSvi117747 #include <stdio.h>
3040cb5e5dSvi117747 #include <stdlib.h>
3140cb5e5dSvi117747 #include <string.h>
3240cb5e5dSvi117747 #include <fcntl.h>
33*2c2c4183Svi117747 #include <pthread.h>
3440cb5e5dSvi117747 #include <unistd.h>
35*2c2c4183Svi117747 #include <sip.h>
3640cb5e5dSvi117747 #ifdef	__linux__
3740cb5e5dSvi117747 #include <sasl/sasl.h>
3840cb5e5dSvi117747 #include <sasl/saslplug.h>
3940cb5e5dSvi117747 #else
4040cb5e5dSvi117747 #include <sys/md5.h>
4140cb5e5dSvi117747 #endif
4240cb5e5dSvi117747 
4340cb5e5dSvi117747 #include "sip_miscdefs.h"
44*2c2c4183Svi117747 #include "sip_msg.h"
4540cb5e5dSvi117747 
4640cb5e5dSvi117747 void	sip_md5_hash(char *, int, char *, int, char *, int,  char *, int,
4740cb5e5dSvi117747 	    char *, int, char *, int, uchar_t *);
4840cb5e5dSvi117747 
4940cb5e5dSvi117747 #define	SIP_RANDOM_LEN	20
5040cb5e5dSvi117747 
5140cb5e5dSvi117747 /*
5240cb5e5dSvi117747  * Wrapper around /dev/urandom
5340cb5e5dSvi117747  */
5440cb5e5dSvi117747 static int
5540cb5e5dSvi117747 sip_get_random(char *buf, int buflen)
5640cb5e5dSvi117747 {
5740cb5e5dSvi117747 	static int devrandom = -1;
5840cb5e5dSvi117747 
5940cb5e5dSvi117747 	if (devrandom == -1 &&
6040cb5e5dSvi117747 	    (devrandom = open("/dev/urandom", O_RDONLY)) == -1) {
6140cb5e5dSvi117747 		return (-1);
6240cb5e5dSvi117747 	}
6340cb5e5dSvi117747 
6440cb5e5dSvi117747 	if (read(devrandom, buf, buflen) == -1)
6540cb5e5dSvi117747 		return (-1);
6640cb5e5dSvi117747 	return (0);
6740cb5e5dSvi117747 }
6840cb5e5dSvi117747 
6940cb5e5dSvi117747 /*
7040cb5e5dSvi117747  * Get MD5 hash of call_id, from_tag, to_tag using key
7140cb5e5dSvi117747  */
7240cb5e5dSvi117747 void
7340cb5e5dSvi117747 sip_md5_hash(char *str1, int lstr1, char *str2, int lstr2, char *str3,
7440cb5e5dSvi117747     int lstr3, char *str4, int lstr4, char *str5, int lstr5,
7540cb5e5dSvi117747     char *str6, int lstr6, uchar_t *digest)
7640cb5e5dSvi117747 {
7740cb5e5dSvi117747 	MD5_CTX	ctx;
7840cb5e5dSvi117747 
7940cb5e5dSvi117747 #ifdef	__linux__
8040cb5e5dSvi117747 	_sasl_MD5Init(&ctx);
8140cb5e5dSvi117747 
8240cb5e5dSvi117747 	_sasl_MD5Update(&ctx, (uchar_t *)&sip_hash_salt, sizeof (uint64_t));
8340cb5e5dSvi117747 
8440cb5e5dSvi117747 	if (str1 != NULL)
8540cb5e5dSvi117747 		_sasl_MD5Update(&ctx, (uchar_t *)str1, lstr1);
8640cb5e5dSvi117747 
8740cb5e5dSvi117747 	if (str2 != NULL)
8840cb5e5dSvi117747 		_sasl_MD5Update(&ctx, (uchar_t *)str2, lstr2);
8940cb5e5dSvi117747 
9040cb5e5dSvi117747 	if (str3 != NULL)
9140cb5e5dSvi117747 		_sasl_MD5Update(&ctx, (uchar_t *)str3, lstr3);
9240cb5e5dSvi117747 
9340cb5e5dSvi117747 	if (str4 != NULL)
9440cb5e5dSvi117747 		_sasl_MD5Update(&ctx, (uchar_t *)str4, lstr4);
9540cb5e5dSvi117747 
9640cb5e5dSvi117747 	if (str5 != NULL)
9740cb5e5dSvi117747 		_sasl_MD5Update(&ctx, (uchar_t *)str5, lstr5);
9840cb5e5dSvi117747 
9940cb5e5dSvi117747 	if (str6 != NULL)
10040cb5e5dSvi117747 		_sasl_MD5Update(&ctx, (uchar_t *)str6, lstr6);
10140cb5e5dSvi117747 
10240cb5e5dSvi117747 	_sasl_MD5Final(digest, &ctx);
10340cb5e5dSvi117747 #else	/* solaris */
10440cb5e5dSvi117747 	MD5Init(&ctx);
10540cb5e5dSvi117747 
10640cb5e5dSvi117747 	MD5Update(&ctx, (uchar_t *)&sip_hash_salt, sizeof (uint64_t));
10740cb5e5dSvi117747 
10840cb5e5dSvi117747 	if (str1 != NULL)
10940cb5e5dSvi117747 		MD5Update(&ctx, (uchar_t *)str1, lstr1);
11040cb5e5dSvi117747 
11140cb5e5dSvi117747 	if (str2 != NULL)
11240cb5e5dSvi117747 		MD5Update(&ctx, (uchar_t *)str2, lstr2);
11340cb5e5dSvi117747 
11440cb5e5dSvi117747 	if (str3 != NULL)
11540cb5e5dSvi117747 		MD5Update(&ctx, (uchar_t *)str3, lstr3);
11640cb5e5dSvi117747 
11740cb5e5dSvi117747 	if (str4 != NULL)
11840cb5e5dSvi117747 		MD5Update(&ctx, (uchar_t *)str4, lstr4);
11940cb5e5dSvi117747 
12040cb5e5dSvi117747 	if (str5 != NULL)
12140cb5e5dSvi117747 		MD5Update(&ctx, (uchar_t *)str5, lstr5);
12240cb5e5dSvi117747 
12340cb5e5dSvi117747 	if (str6 != NULL)
12440cb5e5dSvi117747 		MD5Update(&ctx, (uchar_t *)str6, lstr6);
12540cb5e5dSvi117747 
12640cb5e5dSvi117747 	MD5Final(digest, &ctx);
12740cb5e5dSvi117747 #endif
12840cb5e5dSvi117747 }
12940cb5e5dSvi117747 
13040cb5e5dSvi117747 /*
13140cb5e5dSvi117747  * generate a guid (globally unique id)
13240cb5e5dSvi117747  */
13340cb5e5dSvi117747 char *
13440cb5e5dSvi117747 sip_guid()
13540cb5e5dSvi117747 {
13640cb5e5dSvi117747 	int		i;
13740cb5e5dSvi117747 	uint8_t		*r;
13840cb5e5dSvi117747 	uint32_t 	random;
13940cb5e5dSvi117747 	uint32_t	time;
14040cb5e5dSvi117747 	char		*guid;
14140cb5e5dSvi117747 	int		guidlen;
14240cb5e5dSvi117747 #ifdef	__linux__
14340cb5e5dSvi117747 	struct timespec	tspec;
14440cb5e5dSvi117747 #endif
14540cb5e5dSvi117747 
14640cb5e5dSvi117747 	guid = (char *)malloc(SIP_RANDOM_LEN + 1);
14740cb5e5dSvi117747 	if (guid == NULL)
14840cb5e5dSvi117747 		return (NULL);
14940cb5e5dSvi117747 	/*
15040cb5e5dSvi117747 	 * Get a 32-bit random #
15140cb5e5dSvi117747 	 */
15240cb5e5dSvi117747 	if (sip_get_random((char *)&random, sizeof (random)) != 0)
15340cb5e5dSvi117747 		return (NULL);
15440cb5e5dSvi117747 #ifdef	__linux__
15540cb5e5dSvi117747 	if (clock_gettime(CLOCK_REALTIME, &tspec) != 0)
15640cb5e5dSvi117747 		return (NULL);
15740cb5e5dSvi117747 	time = (uint32_t)tspec.tv_nsec;
15840cb5e5dSvi117747 #else
15940cb5e5dSvi117747 	/*
16040cb5e5dSvi117747 	 * Get 32-bits from gethrtime()
16140cb5e5dSvi117747 	 */
16240cb5e5dSvi117747 	time = (uint32_t)gethrtime();
16340cb5e5dSvi117747 #endif
16440cb5e5dSvi117747 	(void) snprintf(guid, SIP_RANDOM_LEN + 1, "%u%u", random, time);
16540cb5e5dSvi117747 	guidlen = strlen(guid);
16640cb5e5dSvi117747 
16740cb5e5dSvi117747 	/*
16840cb5e5dSvi117747 	 * just throw in some alphabets too
16940cb5e5dSvi117747 	 */
17040cb5e5dSvi117747 	r = (uint8_t *)malloc(guidlen);
17140cb5e5dSvi117747 	if (sip_get_random((char *)r, guidlen) != 0) {
17240cb5e5dSvi117747 		free(guid);
17340cb5e5dSvi117747 		return (NULL);
17440cb5e5dSvi117747 	}
17540cb5e5dSvi117747 	for (i = 0; i < guidlen; i++) {
17640cb5e5dSvi117747 		if ((r[i] >= 65 && r[i] <= 90) ||
17740cb5e5dSvi117747 		    (r[i] >= 97 && r[i] <= 122)) {
17840cb5e5dSvi117747 			guid[i] = r[i];
17940cb5e5dSvi117747 		}
18040cb5e5dSvi117747 	}
18140cb5e5dSvi117747 	free(r);
18240cb5e5dSvi117747 	return (guid);
18340cb5e5dSvi117747 }
18440cb5e5dSvi117747 
18540cb5e5dSvi117747 /*
18640cb5e5dSvi117747  * Generate  branchid for a transaction
18740cb5e5dSvi117747  */
18840cb5e5dSvi117747 char *
18940cb5e5dSvi117747 sip_branchid(sip_msg_t sip_msg)
19040cb5e5dSvi117747 {
19140cb5e5dSvi117747 	char		*guid;
19240cb5e5dSvi117747 	char		*branchid;
19340cb5e5dSvi117747 	_sip_header_t	*via;
19440cb5e5dSvi117747 	unsigned char 	md5_hash[16];
19540cb5e5dSvi117747 	_sip_header_t	*to;
19640cb5e5dSvi117747 	_sip_header_t	*from;
19740cb5e5dSvi117747 	_sip_header_t	*callid;
19840cb5e5dSvi117747 	_sip_msg_t	*_sip_msg;
19940cb5e5dSvi117747 	int		cseq;
20040cb5e5dSvi117747 	MD5_CTX		ctx;
20140cb5e5dSvi117747 	size_t		len;
20240cb5e5dSvi117747 	int		hdrlen;
20340cb5e5dSvi117747 	int		i;
20440cb5e5dSvi117747 
20540cb5e5dSvi117747 	if (sip_msg == NULL) {
20640cb5e5dSvi117747 generate_bid:
20740cb5e5dSvi117747 		if ((branchid = (char *)malloc(SIP_BRANCHID_LEN + 1)) == NULL)
20840cb5e5dSvi117747 			return (NULL);
20940cb5e5dSvi117747 		guid = sip_guid();
21040cb5e5dSvi117747 		if (guid == NULL) {
21140cb5e5dSvi117747 			free(branchid);
21240cb5e5dSvi117747 			return (NULL);
21340cb5e5dSvi117747 		}
21440cb5e5dSvi117747 		(void) snprintf(branchid, SIP_BRANCHID_LEN + 1, "z9hG4bK%s",
21540cb5e5dSvi117747 		    guid);
21640cb5e5dSvi117747 		free(guid);
21740cb5e5dSvi117747 		return (branchid);
21840cb5e5dSvi117747 	}
21940cb5e5dSvi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
22040cb5e5dSvi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
22140cb5e5dSvi117747 	via = sip_search_for_header(_sip_msg, SIP_VIA, NULL);
22240cb5e5dSvi117747 	if (via == NULL) {
22340cb5e5dSvi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
22440cb5e5dSvi117747 		goto generate_bid;
22540cb5e5dSvi117747 	}
22640cb5e5dSvi117747 	to = sip_search_for_header(_sip_msg, SIP_TO, NULL);
22740cb5e5dSvi117747 	from = sip_search_for_header(_sip_msg, SIP_FROM, NULL);
22840cb5e5dSvi117747 	callid = sip_search_for_header(_sip_msg, SIP_CALL_ID, NULL);
22940cb5e5dSvi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
23040cb5e5dSvi117747 	cseq = sip_get_callseq_num(_sip_msg, NULL);
23140cb5e5dSvi117747 	if (to == NULL || from == NULL || callid == NULL || cseq == -1)
23240cb5e5dSvi117747 		return (NULL);
23340cb5e5dSvi117747 	if (_sip_msg->sip_msg_req_res == NULL ||
23440cb5e5dSvi117747 	    _sip_msg->sip_msg_req_res->U.sip_request.sip_request_uri.
23540cb5e5dSvi117747 	    sip_str_ptr == NULL) {
23640cb5e5dSvi117747 		return (NULL);
23740cb5e5dSvi117747 	}
23840cb5e5dSvi117747 	len = 2 * sizeof (md5_hash) + 1;
23940cb5e5dSvi117747 	if ((branchid = malloc(len)) == NULL)
24040cb5e5dSvi117747 		return (NULL);
24140cb5e5dSvi117747 #ifdef	__linux__
24240cb5e5dSvi117747 	_sasl_MD5Init(&ctx);
24340cb5e5dSvi117747 	hdrlen = via->sip_hdr_end - via->sip_hdr_start;
24440cb5e5dSvi117747 	_sasl_MD5Update(&ctx, (uchar_t *)via->sip_hdr_start, hdrlen);
24540cb5e5dSvi117747 	hdrlen = to->sip_hdr_end - to->sip_hdr_start;
24640cb5e5dSvi117747 	_sasl_MD5Update(&ctx, (uchar_t *)to->sip_hdr_start, hdrlen);
24740cb5e5dSvi117747 	hdrlen = from->sip_hdr_end - from->sip_hdr_start;
24840cb5e5dSvi117747 	_sasl_MD5Update(&ctx, (uchar_t *)from->sip_hdr_start, hdrlen);
24940cb5e5dSvi117747 	hdrlen = callid->sip_hdr_end - callid->sip_hdr_start;
25040cb5e5dSvi117747 	_sasl_MD5Update(&ctx, (uchar_t *)callid->sip_hdr_start, hdrlen);
25140cb5e5dSvi117747 	_sasl_MD5Update(&ctx, (uchar_t *)_sip_msg->sip_msg_req_res->
25240cb5e5dSvi117747 	    U.sip_request.sip_request_uri.sip_str_ptr,
25340cb5e5dSvi117747 	    _sip_msg->sip_msg_req_res->U.sip_request.
25440cb5e5dSvi117747 	    sip_request_uri.sip_str_len);
25540cb5e5dSvi117747 	_sasl_MD5Update(&ctx, (uchar_t *)&cseq, sizeof (int));
25640cb5e5dSvi117747 	_sasl_MD5Final(md5_hash, &ctx);
25740cb5e5dSvi117747 #else	/* solaris */
25840cb5e5dSvi117747 	MD5Init(&ctx);
25940cb5e5dSvi117747 	hdrlen = via->sip_hdr_end - via->sip_hdr_start;
26040cb5e5dSvi117747 	MD5Update(&ctx, (uchar_t *)via->sip_hdr_start, hdrlen);
26140cb5e5dSvi117747 	hdrlen = to->sip_hdr_end - to->sip_hdr_start;
26240cb5e5dSvi117747 	MD5Update(&ctx, (uchar_t *)to->sip_hdr_start, hdrlen);
26340cb5e5dSvi117747 	hdrlen = from->sip_hdr_end - from->sip_hdr_start;
26440cb5e5dSvi117747 	MD5Update(&ctx, (uchar_t *)from->sip_hdr_start, hdrlen);
26540cb5e5dSvi117747 	hdrlen = callid->sip_hdr_end - callid->sip_hdr_start;
26640cb5e5dSvi117747 	MD5Update(&ctx, (uchar_t *)callid->sip_hdr_start, hdrlen);
26740cb5e5dSvi117747 	MD5Update(&ctx, (uchar_t *)_sip_msg->sip_msg_req_res->
26840cb5e5dSvi117747 	    U.sip_request.sip_request_uri.sip_str_ptr,
26940cb5e5dSvi117747 	    _sip_msg->sip_msg_req_res->U.sip_request.
27040cb5e5dSvi117747 	    sip_request_uri.sip_str_len);
27140cb5e5dSvi117747 	MD5Update(&ctx, (uchar_t *)&cseq, sizeof (int));
27240cb5e5dSvi117747 	MD5Final(md5_hash, &ctx);
27340cb5e5dSvi117747 #endif
27440cb5e5dSvi117747 	for (i = 0; i < sizeof (md5_hash); i++) {
27540cb5e5dSvi117747 		(void) snprintf(&branchid[2 * i], len - (2 * i), "%02x",
27640cb5e5dSvi117747 		    md5_hash[i]);
27740cb5e5dSvi117747 	}
27840cb5e5dSvi117747 	return (branchid);
27940cb5e5dSvi117747 }
28040cb5e5dSvi117747 
28140cb5e5dSvi117747 uint32_t
28240cb5e5dSvi117747 sip_get_cseq()
28340cb5e5dSvi117747 {
28440cb5e5dSvi117747 	time_t	tval;
28540cb5e5dSvi117747 
28640cb5e5dSvi117747 	tval = time(NULL);
28740cb5e5dSvi117747 
28840cb5e5dSvi117747 	return ((uint32_t)tval);
28940cb5e5dSvi117747 }
29040cb5e5dSvi117747 
29140cb5e5dSvi117747 uint32_t
29240cb5e5dSvi117747 sip_get_rseq()
29340cb5e5dSvi117747 {
29440cb5e5dSvi117747 	time_t	tval;
29540cb5e5dSvi117747 
29640cb5e5dSvi117747 	tval = time(NULL);
29740cb5e5dSvi117747 
29840cb5e5dSvi117747 	return ((uint32_t)tval);
29940cb5e5dSvi117747 }
300