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