1*2882Svi117747 /* 2*2882Svi117747 * CDDL HEADER START 3*2882Svi117747 * 4*2882Svi117747 * The contents of this file are subject to the terms of the 5*2882Svi117747 * Common Development and Distribution License (the "License"). 6*2882Svi117747 * You may not use this file except in compliance with the License. 7*2882Svi117747 * 8*2882Svi117747 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*2882Svi117747 * or http://www.opensolaris.org/os/licensing. 10*2882Svi117747 * See the License for the specific language governing permissions 11*2882Svi117747 * and limitations under the License. 12*2882Svi117747 * 13*2882Svi117747 * When distributing Covered Code, include this CDDL HEADER in each 14*2882Svi117747 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*2882Svi117747 * If applicable, add the following below this CDDL HEADER, with the 16*2882Svi117747 * fields enclosed by brackets "[]" replaced with your own identifying 17*2882Svi117747 * information: Portions Copyright [yyyy] [name of copyright owner] 18*2882Svi117747 * 19*2882Svi117747 * CDDL HEADER END 20*2882Svi117747 */ 21*2882Svi117747 22*2882Svi117747 /* 23*2882Svi117747 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*2882Svi117747 * Use is subject to license terms. 25*2882Svi117747 */ 26*2882Svi117747 27*2882Svi117747 #pragma ident "%Z%%M% %I% %E% SMI" 28*2882Svi117747 29*2882Svi117747 #include <stdio.h> 30*2882Svi117747 #include <stdlib.h> 31*2882Svi117747 #include <string.h> 32*2882Svi117747 #include <fcntl.h> 33*2882Svi117747 #include <unistd.h> 34*2882Svi117747 #include <errno.h> 35*2882Svi117747 #include <sys/types.h> 36*2882Svi117747 #include <time.h> 37*2882Svi117747 #include <sys/errno.h> 38*2882Svi117747 #ifdef __linux__ 39*2882Svi117747 #include <sasl/sasl.h> 40*2882Svi117747 #include <sasl/saslplug.h> 41*2882Svi117747 #else 42*2882Svi117747 #include <sys/md5.h> 43*2882Svi117747 #endif 44*2882Svi117747 45*2882Svi117747 #include "sip_parse_uri.h" 46*2882Svi117747 #include "sip_msg.h" 47*2882Svi117747 #include "sip_miscdefs.h" 48*2882Svi117747 49*2882Svi117747 void sip_md5_hash(char *, int, char *, int, char *, int, char *, int, 50*2882Svi117747 char *, int, char *, int, uchar_t *); 51*2882Svi117747 52*2882Svi117747 #define SIP_RANDOM_LEN 20 53*2882Svi117747 54*2882Svi117747 /* 55*2882Svi117747 * Wrapper around /dev/urandom 56*2882Svi117747 */ 57*2882Svi117747 static int 58*2882Svi117747 sip_get_random(char *buf, int buflen) 59*2882Svi117747 { 60*2882Svi117747 static int devrandom = -1; 61*2882Svi117747 62*2882Svi117747 if (devrandom == -1 && 63*2882Svi117747 (devrandom = open("/dev/urandom", O_RDONLY)) == -1) { 64*2882Svi117747 return (-1); 65*2882Svi117747 } 66*2882Svi117747 67*2882Svi117747 if (read(devrandom, buf, buflen) == -1) 68*2882Svi117747 return (-1); 69*2882Svi117747 return (0); 70*2882Svi117747 } 71*2882Svi117747 72*2882Svi117747 /* 73*2882Svi117747 * Get MD5 hash of call_id, from_tag, to_tag using key 74*2882Svi117747 */ 75*2882Svi117747 void 76*2882Svi117747 sip_md5_hash(char *str1, int lstr1, char *str2, int lstr2, char *str3, 77*2882Svi117747 int lstr3, char *str4, int lstr4, char *str5, int lstr5, 78*2882Svi117747 char *str6, int lstr6, uchar_t *digest) 79*2882Svi117747 { 80*2882Svi117747 MD5_CTX ctx; 81*2882Svi117747 82*2882Svi117747 #ifdef __linux__ 83*2882Svi117747 _sasl_MD5Init(&ctx); 84*2882Svi117747 85*2882Svi117747 _sasl_MD5Update(&ctx, (uchar_t *)&sip_hash_salt, sizeof (uint64_t)); 86*2882Svi117747 87*2882Svi117747 if (str1 != NULL) 88*2882Svi117747 _sasl_MD5Update(&ctx, (uchar_t *)str1, lstr1); 89*2882Svi117747 90*2882Svi117747 if (str2 != NULL) 91*2882Svi117747 _sasl_MD5Update(&ctx, (uchar_t *)str2, lstr2); 92*2882Svi117747 93*2882Svi117747 if (str3 != NULL) 94*2882Svi117747 _sasl_MD5Update(&ctx, (uchar_t *)str3, lstr3); 95*2882Svi117747 96*2882Svi117747 if (str4 != NULL) 97*2882Svi117747 _sasl_MD5Update(&ctx, (uchar_t *)str4, lstr4); 98*2882Svi117747 99*2882Svi117747 if (str5 != NULL) 100*2882Svi117747 _sasl_MD5Update(&ctx, (uchar_t *)str5, lstr5); 101*2882Svi117747 102*2882Svi117747 if (str6 != NULL) 103*2882Svi117747 _sasl_MD5Update(&ctx, (uchar_t *)str6, lstr6); 104*2882Svi117747 105*2882Svi117747 _sasl_MD5Final(digest, &ctx); 106*2882Svi117747 #else /* solaris */ 107*2882Svi117747 MD5Init(&ctx); 108*2882Svi117747 109*2882Svi117747 MD5Update(&ctx, (uchar_t *)&sip_hash_salt, sizeof (uint64_t)); 110*2882Svi117747 111*2882Svi117747 if (str1 != NULL) 112*2882Svi117747 MD5Update(&ctx, (uchar_t *)str1, lstr1); 113*2882Svi117747 114*2882Svi117747 if (str2 != NULL) 115*2882Svi117747 MD5Update(&ctx, (uchar_t *)str2, lstr2); 116*2882Svi117747 117*2882Svi117747 if (str3 != NULL) 118*2882Svi117747 MD5Update(&ctx, (uchar_t *)str3, lstr3); 119*2882Svi117747 120*2882Svi117747 if (str4 != NULL) 121*2882Svi117747 MD5Update(&ctx, (uchar_t *)str4, lstr4); 122*2882Svi117747 123*2882Svi117747 if (str5 != NULL) 124*2882Svi117747 MD5Update(&ctx, (uchar_t *)str5, lstr5); 125*2882Svi117747 126*2882Svi117747 if (str6 != NULL) 127*2882Svi117747 MD5Update(&ctx, (uchar_t *)str6, lstr6); 128*2882Svi117747 129*2882Svi117747 MD5Final(digest, &ctx); 130*2882Svi117747 #endif 131*2882Svi117747 } 132*2882Svi117747 133*2882Svi117747 /* 134*2882Svi117747 * generate a guid (globally unique id) 135*2882Svi117747 */ 136*2882Svi117747 char * 137*2882Svi117747 sip_guid() 138*2882Svi117747 { 139*2882Svi117747 int i; 140*2882Svi117747 uint8_t *r; 141*2882Svi117747 uint32_t random; 142*2882Svi117747 uint32_t time; 143*2882Svi117747 char *guid; 144*2882Svi117747 int guidlen; 145*2882Svi117747 #ifdef __linux__ 146*2882Svi117747 struct timespec tspec; 147*2882Svi117747 #endif 148*2882Svi117747 149*2882Svi117747 guid = (char *)malloc(SIP_RANDOM_LEN + 1); 150*2882Svi117747 if (guid == NULL) 151*2882Svi117747 return (NULL); 152*2882Svi117747 /* 153*2882Svi117747 * Get a 32-bit random # 154*2882Svi117747 */ 155*2882Svi117747 if (sip_get_random((char *)&random, sizeof (random)) != 0) 156*2882Svi117747 return (NULL); 157*2882Svi117747 #ifdef __linux__ 158*2882Svi117747 if (clock_gettime(CLOCK_REALTIME, &tspec) != 0) 159*2882Svi117747 return (NULL); 160*2882Svi117747 time = (uint32_t)tspec.tv_nsec; 161*2882Svi117747 #else 162*2882Svi117747 /* 163*2882Svi117747 * Get 32-bits from gethrtime() 164*2882Svi117747 */ 165*2882Svi117747 time = (uint32_t)gethrtime(); 166*2882Svi117747 #endif 167*2882Svi117747 (void) snprintf(guid, SIP_RANDOM_LEN + 1, "%u%u", random, time); 168*2882Svi117747 guidlen = strlen(guid); 169*2882Svi117747 170*2882Svi117747 /* 171*2882Svi117747 * just throw in some alphabets too 172*2882Svi117747 */ 173*2882Svi117747 r = (uint8_t *)malloc(guidlen); 174*2882Svi117747 if (sip_get_random((char *)r, guidlen) != 0) { 175*2882Svi117747 free(guid); 176*2882Svi117747 return (NULL); 177*2882Svi117747 } 178*2882Svi117747 for (i = 0; i < guidlen; i++) { 179*2882Svi117747 if ((r[i] >= 65 && r[i] <= 90) || 180*2882Svi117747 (r[i] >= 97 && r[i] <= 122)) { 181*2882Svi117747 guid[i] = r[i]; 182*2882Svi117747 } 183*2882Svi117747 } 184*2882Svi117747 free(r); 185*2882Svi117747 return (guid); 186*2882Svi117747 } 187*2882Svi117747 188*2882Svi117747 /* 189*2882Svi117747 * Generate branchid for a transaction 190*2882Svi117747 */ 191*2882Svi117747 char * 192*2882Svi117747 sip_branchid(sip_msg_t sip_msg) 193*2882Svi117747 { 194*2882Svi117747 char *guid; 195*2882Svi117747 char *branchid; 196*2882Svi117747 _sip_header_t *via; 197*2882Svi117747 unsigned char md5_hash[16]; 198*2882Svi117747 _sip_header_t *to; 199*2882Svi117747 _sip_header_t *from; 200*2882Svi117747 _sip_header_t *callid; 201*2882Svi117747 _sip_msg_t *_sip_msg; 202*2882Svi117747 int cseq; 203*2882Svi117747 MD5_CTX ctx; 204*2882Svi117747 size_t len; 205*2882Svi117747 int hdrlen; 206*2882Svi117747 int i; 207*2882Svi117747 208*2882Svi117747 if (sip_msg == NULL) { 209*2882Svi117747 generate_bid: 210*2882Svi117747 if ((branchid = (char *)malloc(SIP_BRANCHID_LEN + 1)) == NULL) 211*2882Svi117747 return (NULL); 212*2882Svi117747 guid = sip_guid(); 213*2882Svi117747 if (guid == NULL) { 214*2882Svi117747 free(branchid); 215*2882Svi117747 return (NULL); 216*2882Svi117747 } 217*2882Svi117747 (void) snprintf(branchid, SIP_BRANCHID_LEN + 1, "z9hG4bK%s", 218*2882Svi117747 guid); 219*2882Svi117747 free(guid); 220*2882Svi117747 return (branchid); 221*2882Svi117747 } 222*2882Svi117747 _sip_msg = (_sip_msg_t *)sip_msg; 223*2882Svi117747 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); 224*2882Svi117747 via = sip_search_for_header(_sip_msg, SIP_VIA, NULL); 225*2882Svi117747 if (via == NULL) { 226*2882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 227*2882Svi117747 goto generate_bid; 228*2882Svi117747 } 229*2882Svi117747 to = sip_search_for_header(_sip_msg, SIP_TO, NULL); 230*2882Svi117747 from = sip_search_for_header(_sip_msg, SIP_FROM, NULL); 231*2882Svi117747 callid = sip_search_for_header(_sip_msg, SIP_CALL_ID, NULL); 232*2882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 233*2882Svi117747 cseq = sip_get_callseq_num(_sip_msg, NULL); 234*2882Svi117747 if (to == NULL || from == NULL || callid == NULL || cseq == -1) 235*2882Svi117747 return (NULL); 236*2882Svi117747 if (_sip_msg->sip_msg_req_res == NULL || 237*2882Svi117747 _sip_msg->sip_msg_req_res->U.sip_request.sip_request_uri. 238*2882Svi117747 sip_str_ptr == NULL) { 239*2882Svi117747 return (NULL); 240*2882Svi117747 } 241*2882Svi117747 len = 2 * sizeof (md5_hash) + 1; 242*2882Svi117747 if ((branchid = malloc(len)) == NULL) 243*2882Svi117747 return (NULL); 244*2882Svi117747 #ifdef __linux__ 245*2882Svi117747 _sasl_MD5Init(&ctx); 246*2882Svi117747 hdrlen = via->sip_hdr_end - via->sip_hdr_start; 247*2882Svi117747 _sasl_MD5Update(&ctx, (uchar_t *)via->sip_hdr_start, hdrlen); 248*2882Svi117747 hdrlen = to->sip_hdr_end - to->sip_hdr_start; 249*2882Svi117747 _sasl_MD5Update(&ctx, (uchar_t *)to->sip_hdr_start, hdrlen); 250*2882Svi117747 hdrlen = from->sip_hdr_end - from->sip_hdr_start; 251*2882Svi117747 _sasl_MD5Update(&ctx, (uchar_t *)from->sip_hdr_start, hdrlen); 252*2882Svi117747 hdrlen = callid->sip_hdr_end - callid->sip_hdr_start; 253*2882Svi117747 _sasl_MD5Update(&ctx, (uchar_t *)callid->sip_hdr_start, hdrlen); 254*2882Svi117747 _sasl_MD5Update(&ctx, (uchar_t *)_sip_msg->sip_msg_req_res-> 255*2882Svi117747 U.sip_request.sip_request_uri.sip_str_ptr, 256*2882Svi117747 _sip_msg->sip_msg_req_res->U.sip_request. 257*2882Svi117747 sip_request_uri.sip_str_len); 258*2882Svi117747 _sasl_MD5Update(&ctx, (uchar_t *)&cseq, sizeof (int)); 259*2882Svi117747 _sasl_MD5Final(md5_hash, &ctx); 260*2882Svi117747 #else /* solaris */ 261*2882Svi117747 MD5Init(&ctx); 262*2882Svi117747 hdrlen = via->sip_hdr_end - via->sip_hdr_start; 263*2882Svi117747 MD5Update(&ctx, (uchar_t *)via->sip_hdr_start, hdrlen); 264*2882Svi117747 hdrlen = to->sip_hdr_end - to->sip_hdr_start; 265*2882Svi117747 MD5Update(&ctx, (uchar_t *)to->sip_hdr_start, hdrlen); 266*2882Svi117747 hdrlen = from->sip_hdr_end - from->sip_hdr_start; 267*2882Svi117747 MD5Update(&ctx, (uchar_t *)from->sip_hdr_start, hdrlen); 268*2882Svi117747 hdrlen = callid->sip_hdr_end - callid->sip_hdr_start; 269*2882Svi117747 MD5Update(&ctx, (uchar_t *)callid->sip_hdr_start, hdrlen); 270*2882Svi117747 MD5Update(&ctx, (uchar_t *)_sip_msg->sip_msg_req_res-> 271*2882Svi117747 U.sip_request.sip_request_uri.sip_str_ptr, 272*2882Svi117747 _sip_msg->sip_msg_req_res->U.sip_request. 273*2882Svi117747 sip_request_uri.sip_str_len); 274*2882Svi117747 MD5Update(&ctx, (uchar_t *)&cseq, sizeof (int)); 275*2882Svi117747 MD5Final(md5_hash, &ctx); 276*2882Svi117747 #endif 277*2882Svi117747 for (i = 0; i < sizeof (md5_hash); i++) { 278*2882Svi117747 (void) snprintf(&branchid[2 * i], len - (2 * i), "%02x", 279*2882Svi117747 md5_hash[i]); 280*2882Svi117747 } 281*2882Svi117747 return (branchid); 282*2882Svi117747 } 283*2882Svi117747 284*2882Svi117747 uint32_t 285*2882Svi117747 sip_get_cseq() 286*2882Svi117747 { 287*2882Svi117747 time_t tval; 288*2882Svi117747 289*2882Svi117747 tval = time(NULL); 290*2882Svi117747 291*2882Svi117747 return ((uint32_t)tval); 292*2882Svi117747 } 293*2882Svi117747 294*2882Svi117747 uint32_t 295*2882Svi117747 sip_get_rseq() 296*2882Svi117747 { 297*2882Svi117747 time_t tval; 298*2882Svi117747 299*2882Svi117747 tval = time(NULL); 300*2882Svi117747 301*2882Svi117747 return ((uint32_t)tval); 302*2882Svi117747 } 303