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