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.
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.
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]
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
37 #include <sasl/sasl.h>
38 #include <sasl/saslplug.h>
43 #include "sip_miscdefs.h"
46 void sip_md5_hash(char *, int, char *, int, char *, int, char *, int,
47 char *, int, char *, int, uchar_t
*);
49 #define SIP_RANDOM_LEN 20
52 * Wrapper around /dev/urandom
55 sip_get_random(char *buf
, int buflen
)
57 static int devrandom
= -1;
59 if (devrandom
== -1 &&
60 (devrandom
= open("/dev/urandom", O_RDONLY
)) == -1) {
64 if (read(devrandom
, buf
, buflen
) == -1)
70 * Get MD5 hash of call_id, from_tag, to_tag using key
73 sip_md5_hash(char *str1
, int lstr1
, char *str2
, int lstr2
, char *str3
,
74 int lstr3
, char *str4
, int lstr4
, char *str5
, int lstr5
,
75 char *str6
, int lstr6
, uchar_t
*digest
)
82 _sasl_MD5Update(&ctx
, (uchar_t
*)&sip_hash_salt
, sizeof (uint64_t));
85 _sasl_MD5Update(&ctx
, (uchar_t
*)str1
, lstr1
);
88 _sasl_MD5Update(&ctx
, (uchar_t
*)str2
, lstr2
);
91 _sasl_MD5Update(&ctx
, (uchar_t
*)str3
, lstr3
);
94 _sasl_MD5Update(&ctx
, (uchar_t
*)str4
, lstr4
);
97 _sasl_MD5Update(&ctx
, (uchar_t
*)str5
, lstr5
);
100 _sasl_MD5Update(&ctx
, (uchar_t
*)str6
, lstr6
);
102 _sasl_MD5Final(digest
, &ctx
);
106 MD5Update(&ctx
, (uchar_t
*)&sip_hash_salt
, sizeof (uint64_t));
109 MD5Update(&ctx
, (uchar_t
*)str1
, lstr1
);
112 MD5Update(&ctx
, (uchar_t
*)str2
, lstr2
);
115 MD5Update(&ctx
, (uchar_t
*)str3
, lstr3
);
118 MD5Update(&ctx
, (uchar_t
*)str4
, lstr4
);
121 MD5Update(&ctx
, (uchar_t
*)str5
, lstr5
);
124 MD5Update(&ctx
, (uchar_t
*)str6
, lstr6
);
126 MD5Final(digest
, &ctx
);
131 * generate a guid (globally unique id)
143 struct timespec tspec
;
146 guid
= (char *)malloc(SIP_RANDOM_LEN
+ 1);
150 * Get a 32-bit random #
152 if (sip_get_random((char *)&random
, sizeof (random
)) != 0)
155 if (clock_gettime(CLOCK_REALTIME
, &tspec
) != 0)
157 time
= (uint32_t)tspec
.tv_nsec
;
160 * Get 32-bits from gethrtime()
162 time
= (uint32_t)gethrtime();
164 (void) snprintf(guid
, SIP_RANDOM_LEN
+ 1, "%u%u", random
, time
);
165 guidlen
= strlen(guid
);
168 * just throw in some alphabets too
170 r
= (uint8_t *)malloc(guidlen
);
171 if (sip_get_random((char *)r
, guidlen
) != 0) {
175 for (i
= 0; i
< guidlen
; i
++) {
176 if ((r
[i
] >= 65 && r
[i
] <= 90) ||
177 (r
[i
] >= 97 && r
[i
] <= 122)) {
186 * Generate branchid for a transaction
189 sip_branchid(sip_msg_t sip_msg
)
194 unsigned char md5_hash
[16];
197 _sip_header_t
*callid
;
198 _sip_msg_t
*_sip_msg
;
205 if (sip_msg
== NULL
) {
207 if ((branchid
= (char *)malloc(SIP_BRANCHID_LEN
+ 1)) == NULL
)
214 (void) snprintf(branchid
, SIP_BRANCHID_LEN
+ 1, "z9hG4bK%s",
219 _sip_msg
= (_sip_msg_t
*)sip_msg
;
220 (void) pthread_mutex_lock(&_sip_msg
->sip_msg_mutex
);
221 via
= sip_search_for_header(_sip_msg
, SIP_VIA
, NULL
);
223 (void) pthread_mutex_unlock(&_sip_msg
->sip_msg_mutex
);
226 to
= sip_search_for_header(_sip_msg
, SIP_TO
, NULL
);
227 from
= sip_search_for_header(_sip_msg
, SIP_FROM
, NULL
);
228 callid
= sip_search_for_header(_sip_msg
, SIP_CALL_ID
, NULL
);
229 (void) pthread_mutex_unlock(&_sip_msg
->sip_msg_mutex
);
230 cseq
= sip_get_callseq_num(_sip_msg
, NULL
);
231 if (to
== NULL
|| from
== NULL
|| callid
== NULL
|| cseq
== -1)
233 if (_sip_msg
->sip_msg_req_res
== NULL
||
234 _sip_msg
->sip_msg_req_res
->U
.sip_request
.sip_request_uri
.
235 sip_str_ptr
== NULL
) {
238 len
= 2 * sizeof (md5_hash
) + 1;
239 if ((branchid
= malloc(len
)) == NULL
)
243 hdrlen
= via
->sip_hdr_end
- via
->sip_hdr_start
;
244 _sasl_MD5Update(&ctx
, (uchar_t
*)via
->sip_hdr_start
, hdrlen
);
245 hdrlen
= to
->sip_hdr_end
- to
->sip_hdr_start
;
246 _sasl_MD5Update(&ctx
, (uchar_t
*)to
->sip_hdr_start
, hdrlen
);
247 hdrlen
= from
->sip_hdr_end
- from
->sip_hdr_start
;
248 _sasl_MD5Update(&ctx
, (uchar_t
*)from
->sip_hdr_start
, hdrlen
);
249 hdrlen
= callid
->sip_hdr_end
- callid
->sip_hdr_start
;
250 _sasl_MD5Update(&ctx
, (uchar_t
*)callid
->sip_hdr_start
, hdrlen
);
251 _sasl_MD5Update(&ctx
, (uchar_t
*)_sip_msg
->sip_msg_req_res
->
252 U
.sip_request
.sip_request_uri
.sip_str_ptr
,
253 _sip_msg
->sip_msg_req_res
->U
.sip_request
.
254 sip_request_uri
.sip_str_len
);
255 _sasl_MD5Update(&ctx
, (uchar_t
*)&cseq
, sizeof (int));
256 _sasl_MD5Final(md5_hash
, &ctx
);
259 hdrlen
= via
->sip_hdr_end
- via
->sip_hdr_start
;
260 MD5Update(&ctx
, (uchar_t
*)via
->sip_hdr_start
, hdrlen
);
261 hdrlen
= to
->sip_hdr_end
- to
->sip_hdr_start
;
262 MD5Update(&ctx
, (uchar_t
*)to
->sip_hdr_start
, hdrlen
);
263 hdrlen
= from
->sip_hdr_end
- from
->sip_hdr_start
;
264 MD5Update(&ctx
, (uchar_t
*)from
->sip_hdr_start
, hdrlen
);
265 hdrlen
= callid
->sip_hdr_end
- callid
->sip_hdr_start
;
266 MD5Update(&ctx
, (uchar_t
*)callid
->sip_hdr_start
, hdrlen
);
267 MD5Update(&ctx
, (uchar_t
*)_sip_msg
->sip_msg_req_res
->
268 U
.sip_request
.sip_request_uri
.sip_str_ptr
,
269 _sip_msg
->sip_msg_req_res
->U
.sip_request
.
270 sip_request_uri
.sip_str_len
);
271 MD5Update(&ctx
, (uchar_t
*)&cseq
, sizeof (int));
272 MD5Final(md5_hash
, &ctx
);
274 for (i
= 0; i
< sizeof (md5_hash
); i
++) {
275 (void) snprintf(&branchid
[2 * i
], len
- (2 * i
), "%02x",
288 return ((uint32_t)tval
);
298 return ((uint32_t)tval
);