1 /*
2 * Copyright (C) 2011, 2012, 2013 Citrix Systems
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the project nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 #include "ns_turn_msg.h"
32 #include "ns_turn_msg_addr.h"
33
34 ///////////// Security functions implementation from ns_turn_msg.h ///////////
35
36 #include "ns_turn_openssl.h"
37
38 ///////////
39
40 #include <stdlib.h>
41
42 ///////////
43
44 static void generate_random_nonce(unsigned char *nonce, size_t sz);
45
46 ///////////
47
stun_method_str(uint16_t method,char * smethod)48 int stun_method_str(uint16_t method, char *smethod)
49 {
50 int ret = 0;
51
52 const char* s = "UNKNOWN";
53
54 switch(method) {
55 case STUN_METHOD_BINDING:
56 s = "BINDING";
57 break;
58 case STUN_METHOD_ALLOCATE:
59 s = "ALLOCATE";
60 break;
61 case STUN_METHOD_REFRESH:
62 s = "REFRESH";
63 break;
64 case STUN_METHOD_SEND:
65 s = "SEND";
66 break;
67 case STUN_METHOD_DATA:
68 s = "DATA";
69 break;
70 case STUN_METHOD_CREATE_PERMISSION:
71 s = "CREATE_PERMISSION";
72 break;
73 case STUN_METHOD_CHANNEL_BIND:
74 s = "CHANNEL_BIND";
75 break;
76 case STUN_METHOD_CONNECT:
77 s = "CONNECT";
78 break;
79 case STUN_METHOD_CONNECTION_BIND:
80 s = "CONNECTION_BIND";
81 break;
82 case STUN_METHOD_CONNECTION_ATTEMPT:
83 s = "CONNECTION_ATTEMPT";
84 break;
85 default:
86 ret = -1;
87 };
88
89 if(smethod) {
90 bcopy(s,smethod,strlen(s)+1);
91 }
92
93 return ret;
94 }
95
turn_random(void)96 long turn_random(void)
97 {
98 long ret = 0;
99 if(!RAND_bytes((unsigned char *)&ret,sizeof(ret)))
100 ret = random();
101 return ret;
102 }
103
turn_random_tid_size(void * id)104 static void turn_random_tid_size(void *id)
105 {
106 uint32_t *ar=(uint32_t*)id;
107 if(!RAND_pseudo_bytes((unsigned char *)ar,12)) {
108 size_t i;
109 for(i=0;i<3;++i) {
110 ar[i] = (uint32_t)random();
111 }
112 }
113 }
114
stun_calculate_hmac(const uint8_t * buf,size_t len,const uint8_t * key,size_t keylen,uint8_t * hmac,unsigned int * hmac_len,SHATYPE shatype)115 int stun_calculate_hmac(const uint8_t *buf, size_t len, const uint8_t *key, size_t keylen, uint8_t *hmac, unsigned int *hmac_len, SHATYPE shatype)
116 {
117 ERR_clear_error();
118 UNUSED_ARG(shatype);
119
120 if(shatype == SHATYPE_SHA256) {
121 #if !defined(OPENSSL_NO_SHA256) && defined(SHA256_DIGEST_LENGTH)
122 if (!HMAC(EVP_sha256(), key, (int)keylen, buf, len, hmac, hmac_len)) {
123 return -1;
124 }
125 #else
126 fprintf(stderr,"SHA256 is not supported\n");
127 return -1;
128 #endif
129 } else if(shatype == SHATYPE_SHA384) {
130 #if !defined(OPENSSL_NO_SHA384) && defined(SHA384_DIGEST_LENGTH)
131 if (!HMAC(EVP_sha384(), key, (int)keylen, buf, len, hmac, hmac_len)) {
132 return -1;
133 }
134 #else
135 fprintf(stderr,"SHA384 is not supported\n");
136 return -1;
137 #endif
138 } else if(shatype == SHATYPE_SHA512) {
139 #if !defined(OPENSSL_NO_SHA512) && defined(SHA512_DIGEST_LENGTH)
140 if (!HMAC(EVP_sha512(), key, (int)keylen, buf, len, hmac, hmac_len)) {
141 return -1;
142 }
143 #else
144 fprintf(stderr,"SHA512 is not supported\n");
145 return -1;
146 #endif
147 } else
148 if (!HMAC(EVP_sha1(), key, (int)keylen, buf, len, hmac, hmac_len)) {
149 return -1;
150 }
151
152 return 0;
153 }
154
stun_produce_integrity_key_str(const uint8_t * uname,const uint8_t * realm,const uint8_t * upwd,hmackey_t key,SHATYPE shatype)155 int stun_produce_integrity_key_str(const uint8_t *uname, const uint8_t *realm, const uint8_t *upwd, hmackey_t key, SHATYPE shatype)
156 {
157 int ret;
158
159 ERR_clear_error();
160 UNUSED_ARG(shatype);
161
162 size_t ulen = strlen((const char*)uname);
163 size_t rlen = strlen((const char*)realm);
164 size_t plen = strlen((const char*)upwd);
165 size_t sz = ulen+1+rlen+1+plen+1+10;
166 size_t strl = ulen+1+rlen+1+plen;
167 uint8_t *str = (uint8_t*)malloc(sz+1);
168
169 strncpy((char*)str,(const char*)uname,sz);
170 str[ulen]=':';
171 strncpy((char*)str+ulen+1,(const char*)realm,sz-ulen-1);
172 str[ulen+1+rlen]=':';
173 strncpy((char*)str+ulen+1+rlen+1,(const char*)upwd,sz-ulen-1-rlen-1);
174 str[strl]=0;
175
176 if(shatype == SHATYPE_SHA256) {
177 #if !defined(OPENSSL_NO_SHA256) && defined(SHA256_DIGEST_LENGTH)
178 #if OPENSSL_VERSION_NUMBER < 0x10100000L
179 unsigned int keylen = 0;
180 EVP_MD_CTX ctx;
181 EVP_DigestInit(&ctx,EVP_sha256());
182 EVP_DigestUpdate(&ctx,str,strl);
183 EVP_DigestFinal(&ctx,key,&keylen);
184 EVP_MD_CTX_cleanup(&ctx);
185 #else
186 unsigned int keylen = 0;
187 EVP_MD_CTX *ctx = EVP_MD_CTX_new();
188 EVP_DigestInit(ctx,EVP_sha256());
189 EVP_DigestUpdate(ctx,str,strl);
190 EVP_DigestFinal(ctx,key,&keylen);
191 EVP_MD_CTX_free(ctx);
192 #endif
193 ret = 0;
194 #else
195 fprintf(stderr,"SHA256 is not supported\n");
196 ret = -1;
197 #endif
198 } else if(shatype == SHATYPE_SHA384) {
199 #if !defined(OPENSSL_NO_SHA384) && defined(SHA384_DIGEST_LENGTH)
200 #if OPENSSL_VERSION_NUMBER < 0x10100000L
201 unsigned int keylen = 0;
202 EVP_MD_CTX ctx;
203 EVP_DigestInit(&ctx,EVP_sha384());
204 EVP_DigestUpdate(&ctx,str,strl);
205 EVP_DigestFinal(&ctx,key,&keylen);
206 EVP_MD_CTX_cleanup(&ctx);
207 #else
208 unsigned int keylen = 0;
209 EVP_MD_CTX *ctx = EVP_MD_CTX_new();
210 EVP_DigestInit(ctx,EVP_sha384());
211 EVP_DigestUpdate(ctx,str,strl);
212 EVP_DigestFinal(ctx,key,&keylen);
213 EVP_MD_CTX_free(ctx);
214 #endif
215 ret = 0;
216 #else
217 fprintf(stderr,"SHA384 is not supported\n");
218 ret = -1;
219 #endif
220 } else if(shatype == SHATYPE_SHA512) {
221 #if !defined(OPENSSL_NO_SHA512) && defined(SHA512_DIGEST_LENGTH)
222 #if OPENSSL_VERSION_NUMBER < 0x10100000L
223 unsigned int keylen = 0;
224 EVP_MD_CTX ctx;
225 EVP_DigestInit(&ctx,EVP_sha512());
226 EVP_DigestUpdate(&ctx,str,strl);
227 EVP_DigestFinal(&ctx,key,&keylen);
228 EVP_MD_CTX_cleanup(&ctx);
229 #else
230 unsigned int keylen = 0;
231 EVP_MD_CTX *ctx = EVP_MD_CTX_new();
232 EVP_DigestInit(ctx,EVP_sha512());
233 EVP_DigestUpdate(ctx,str,strl);
234 EVP_DigestFinal(ctx,key,&keylen);
235 EVP_MD_CTX_free(ctx);
236 #endif
237 ret = 0;
238 #else
239 fprintf(stderr,"SHA512 is not supported\n");
240 ret = -1;
241 #endif
242 } else {
243 #if OPENSSL_VERSION_NUMBER < 0x10100000L
244 unsigned int keylen = 0;
245 EVP_MD_CTX ctx;
246 EVP_MD_CTX_init(&ctx);
247 #if defined EVP_MD_CTX_FLAG_NON_FIPS_ALLOW && !defined(LIBRESSL_VERSION_NUMBER)
248 if (FIPS_mode()) {
249 EVP_MD_CTX_set_flags(&ctx,EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
250 }
251 #endif
252 EVP_DigestInit_ex(&ctx,EVP_md5(), NULL);
253 EVP_DigestUpdate(&ctx,str,strl);
254 EVP_DigestFinal(&ctx,key,&keylen);
255 EVP_MD_CTX_cleanup(&ctx);
256 #else
257 unsigned int keylen = 0;
258 EVP_MD_CTX *ctx = EVP_MD_CTX_new();
259 #if defined EVP_MD_CTX_FLAG_NON_FIPS_ALLOW && ! defined(LIBRESSL_VERSION_NUMBER)
260 if (FIPS_mode()) {
261 EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
262 }
263 #endif
264 EVP_DigestInit_ex(ctx,EVP_md5(), NULL);
265 EVP_DigestUpdate(ctx,str,strl);
266 EVP_DigestFinal(ctx,key,&keylen);
267 EVP_MD_CTX_free(ctx);
268 #endif
269 ret = 0;
270 }
271
272 free(str);
273
274 return ret;
275 }
276
277 #define PWD_SALT_SIZE (8)
278
readable_string(unsigned char * orig,unsigned char * out,size_t sz)279 static void readable_string(unsigned char *orig, unsigned char *out, size_t sz)
280 {
281 size_t i = 0;
282 out[0]=0;
283
284 for(i = 0; i < sz; ++i) {
285 snprintf((char*)(out + (i * 2)), 4, "%02x", (unsigned int)orig[i]);
286 }
287 }
288
generate_enc_password(const char * pwd,char * result,const unsigned char * orig_salt)289 static void generate_enc_password(const char* pwd, char *result, const unsigned char *orig_salt)
290 {
291 unsigned char salt[PWD_SALT_SIZE+1];
292 if(!orig_salt) {
293 generate_random_nonce(salt, PWD_SALT_SIZE);
294 } else {
295 bcopy(orig_salt,salt,PWD_SALT_SIZE);
296 salt[PWD_SALT_SIZE]=0;
297 }
298 unsigned char rsalt[PWD_SALT_SIZE*2+1];
299 readable_string(salt,rsalt,PWD_SALT_SIZE);
300 result[0]='$';
301 result[1]='5';
302 result[2]='$';
303 bcopy((char*)rsalt,result+3,PWD_SALT_SIZE+PWD_SALT_SIZE);
304 result[3+PWD_SALT_SIZE+PWD_SALT_SIZE]='$';
305 unsigned char* out = (unsigned char*)(result+3+PWD_SALT_SIZE+PWD_SALT_SIZE+1);
306 {
307 #if OPENSSL_VERSION_NUMBER < 0x10100000L
308 EVP_MD_CTX ctx;
309 #if !defined(OPENSSL_NO_SHA256) && defined(SHA256_DIGEST_LENGTH)
310 EVP_DigestInit(&ctx,EVP_sha256());
311 #else
312 EVP_DigestInit(&ctx,EVP_sha1());
313 #endif
314 EVP_DigestUpdate(&ctx,salt,PWD_SALT_SIZE);
315 EVP_DigestUpdate(&ctx,pwd,strlen(pwd));
316 {
317 unsigned char hash[129];
318 unsigned int keylen = 0;
319 EVP_DigestFinal(&ctx,hash,&keylen);
320 readable_string(hash,out,keylen);
321 }
322 EVP_MD_CTX_cleanup(&ctx);
323 #else
324 EVP_MD_CTX *ctx = EVP_MD_CTX_new();
325 #if !defined(OPENSSL_NO_SHA256) && defined(SHA256_DIGEST_LENGTH)
326 EVP_DigestInit(ctx,EVP_sha256());
327 #else
328 EVP_DigestInit(ctx,EVP_sha1());
329 #endif
330 EVP_DigestUpdate(ctx,salt,PWD_SALT_SIZE);
331 EVP_DigestUpdate(ctx,pwd,strlen(pwd));
332 {
333 unsigned char hash[129];
334 unsigned int keylen = 0;
335 EVP_DigestFinal(ctx,hash,&keylen);
336 readable_string(hash,out,keylen);
337 }
338 EVP_MD_CTX_free(ctx);
339 #endif
340 }
341 }
342
generate_new_enc_password(const char * pwd,char * result)343 void generate_new_enc_password(const char* pwd, char *result)
344 {
345 generate_enc_password(pwd, result, NULL);
346 }
347
encrypted_password(const char * pin,unsigned char * salt)348 static int encrypted_password(const char* pin, unsigned char* salt)
349 {
350 size_t min_len = 3+PWD_SALT_SIZE+PWD_SALT_SIZE+1+32;
351 if(strlen(pin)>=min_len) {
352 if((pin[0]=='$') && (pin[1]=='5') && (pin[2]=='$') && (pin[3+PWD_SALT_SIZE+PWD_SALT_SIZE]=='$')) {
353 size_t i = 0;
354 for(i=0;i<PWD_SALT_SIZE;++i) {
355 const char* c = pin+3+i+i;
356 char sc[3];
357 sc[0]=c[0];
358 sc[1]=c[1];
359 sc[2]=0;
360 salt[i] = (unsigned char)strtoul(sc,NULL,16);
361 }
362 return 1;
363 }
364 }
365 return 0;
366 }
367
check_password(const char * pin,const char * pwd)368 int check_password(const char* pin, const char* pwd)
369 {
370 unsigned char salt[PWD_SALT_SIZE];
371 if(!encrypted_password(pwd,salt)) {
372 return strcmp(pin,pwd);
373 }
374 char enc_pin[257];
375 generate_enc_password(pin, enc_pin, salt);
376 return strcmp(enc_pin,pwd);
377 }
378
379 /////////////////////////////////////////////////////////////////
380
381 static uint32_t ns_crc32(const uint8_t *buffer, uint32_t len);
382
383 void print_hmac(const char *name, const void *s, size_t len);
384
385 /////////////////////////////////////////////////////////////////
386
stun_get_command_message_len_str(const uint8_t * buf,size_t len)387 int stun_get_command_message_len_str(const uint8_t* buf, size_t len)
388 {
389 if (len < STUN_HEADER_LENGTH)
390 return -1;
391
392 /* Validate the size the buffer claims to be */
393 size_t bufLen = (size_t) (nswap16(((const uint16_t*)(buf))[1]) + STUN_HEADER_LENGTH);
394 if (bufLen > len) {
395 return -1;
396 }
397
398 return bufLen;
399 }
400
stun_set_command_message_len_str(uint8_t * buf,int len)401 static int stun_set_command_message_len_str(uint8_t* buf, int len) {
402 if(len<STUN_HEADER_LENGTH) return -1;
403 ((uint16_t*)buf)[1]=nswap16((uint16_t)(len-STUN_HEADER_LENGTH));
404 return 0;
405 }
406
407 /////////// Low-level binary //////////////////////////////////////////////
408
stun_make_type(uint16_t method)409 uint16_t stun_make_type(uint16_t method) {
410 method = method & 0x0FFF;
411 return ((method & 0x000F) | ((method & 0x0070)<<1) |
412 ((method & 0x0380)<<2) | ((method & 0x0C00)<<2));
413 }
414
stun_get_method_str(const uint8_t * buf,size_t len)415 uint16_t stun_get_method_str(const uint8_t *buf, size_t len) {
416 if(!buf || len<2) return (uint16_t)-1;
417
418 uint16_t tt = nswap16(((const uint16_t*)buf)[0]);
419
420 return (tt & 0x000F) | ((tt & 0x00E0)>>1) |
421 ((tt & 0x0E00)>>2) | ((tt & 0x3000)>>2);
422 }
423
stun_get_msg_type_str(const uint8_t * buf,size_t len)424 uint16_t stun_get_msg_type_str(const uint8_t *buf, size_t len) {
425 if(!buf || len<2) return (uint16_t)-1;
426 return ((nswap16(((const uint16_t*)buf)[0])) & 0x3FFF);
427 }
428
is_channel_msg_str(const uint8_t * buf,size_t blen)429 int is_channel_msg_str(const uint8_t* buf, size_t blen) {
430 return (buf && blen>=4 && STUN_VALID_CHANNEL(nswap16(((const uint16_t*)buf)[0])));
431 }
432
433 /////////////// message types /////////////////////////////////
434
stun_is_command_message_str(const uint8_t * buf,size_t blen)435 int stun_is_command_message_str(const uint8_t* buf, size_t blen)
436 {
437 if (buf && blen >= STUN_HEADER_LENGTH) {
438 if (!STUN_VALID_CHANNEL(nswap16(((const uint16_t*)buf)[0]))) {
439 if ((((uint8_t) buf[0]) & ((uint8_t) (0xC0))) == 0) {
440 if (nswap32(((const uint32_t*)(buf))[1])
441 == STUN_MAGIC_COOKIE) {
442 uint16_t len = nswap16(((const uint16_t*)(buf))[1]);
443 if ((len & 0x0003) == 0) {
444 if ((size_t) (len + STUN_HEADER_LENGTH) == blen) {
445 return 1;
446 }
447 }
448 }
449 }
450 }
451 }
452 return 0;
453 }
454
old_stun_is_command_message_str(const uint8_t * buf,size_t blen,uint32_t * cookie)455 int old_stun_is_command_message_str(const uint8_t* buf, size_t blen, uint32_t *cookie)
456 {
457 if (buf && blen >= STUN_HEADER_LENGTH) {
458 if (!STUN_VALID_CHANNEL(nswap16(((const uint16_t*)buf)[0]))) {
459 if ((((uint8_t) buf[0]) & ((uint8_t) (0xC0))) == 0) {
460 if (nswap32(((const uint32_t*)(buf))[1])
461 != STUN_MAGIC_COOKIE) {
462 uint16_t len = nswap16(((const uint16_t*)(buf))[1]);
463 if ((len & 0x0003) == 0) {
464 if ((size_t) (len + STUN_HEADER_LENGTH) == blen) {
465 *cookie = nswap32(((const uint32_t*)(buf))[1]);
466 return 1;
467 }
468 }
469 }
470 }
471 }
472 }
473 return 0;
474 }
475
stun_is_command_message_full_check_str(const uint8_t * buf,size_t blen,int must_check_fingerprint,int * fingerprint_present)476 int stun_is_command_message_full_check_str(const uint8_t* buf, size_t blen, int must_check_fingerprint, int *fingerprint_present) {
477 if(!stun_is_command_message_str(buf,blen))
478 return 0;
479 stun_attr_ref sar = stun_attr_get_first_by_type_str(buf, blen, STUN_ATTRIBUTE_FINGERPRINT);
480 if(!sar) {
481 if(fingerprint_present)
482 *fingerprint_present = 0;
483 if(stun_get_method_str(buf,blen) == STUN_METHOD_BINDING) {
484 return 1;
485 }
486 return !must_check_fingerprint;
487 }
488 if(stun_attr_get_len(sar) != 4)
489 return 0;
490 const uint32_t* fingerprint = (const uint32_t*)stun_attr_get_value(sar);
491 if(!fingerprint)
492 return !must_check_fingerprint;
493 uint32_t crc32len = (uint32_t)((((const uint8_t*)fingerprint)-buf)-4);
494 int ret = (*fingerprint == nswap32(ns_crc32(buf,crc32len) ^ ((uint32_t)0x5354554e)));
495 if(ret && fingerprint_present)
496 *fingerprint_present = ret;
497 return ret;
498 }
499
stun_is_command_message_offset_str(const uint8_t * buf,size_t blen,int offset)500 int stun_is_command_message_offset_str(const uint8_t* buf, size_t blen, int offset) {
501 return stun_is_command_message_str(buf + offset, blen);
502 }
503
stun_is_request_str(const uint8_t * buf,size_t len)504 int stun_is_request_str(const uint8_t* buf, size_t len) {
505 if(is_channel_msg_str(buf,len)) return 0;
506 return IS_STUN_REQUEST(stun_get_msg_type_str(buf,len));
507 }
508
stun_is_success_response_str(const uint8_t * buf,size_t len)509 int stun_is_success_response_str(const uint8_t* buf, size_t len) {
510 if(is_channel_msg_str(buf,len)) return 0;
511 return IS_STUN_SUCCESS_RESP(stun_get_msg_type_str(buf,len));
512 }
513
stun_is_error_response_str(const uint8_t * buf,size_t len,int * err_code,uint8_t * err_msg,size_t err_msg_size)514 int stun_is_error_response_str(const uint8_t* buf, size_t len, int *err_code, uint8_t *err_msg, size_t err_msg_size) {
515 if(is_channel_msg_str(buf,len)) return 0;
516 if(IS_STUN_ERR_RESP(stun_get_msg_type_str(buf,len))) {
517 if(err_code) {
518 stun_attr_ref sar = stun_attr_get_first_by_type_str(buf, len, STUN_ATTRIBUTE_ERROR_CODE);
519 if(sar) {
520 if(stun_attr_get_len(sar)>=4) {
521 const uint8_t* val = (const uint8_t*)stun_attr_get_value(sar);
522 *err_code=(int)(val[2]*100 + val[3]);
523 if(err_msg && err_msg_size>0) {
524 err_msg[0]=0;
525 if(stun_attr_get_len(sar)>4) {
526 size_t msg_len = stun_attr_get_len(sar) - 4;
527 if(msg_len>(err_msg_size-1))
528 msg_len=err_msg_size - 1;
529 bcopy(val+4, err_msg, msg_len);
530 err_msg[msg_len]=0;
531 }
532 }
533 }
534 }
535 }
536 return 1;
537 }
538 return 0;
539 }
540
stun_is_challenge_response_str(const uint8_t * buf,size_t len,int * err_code,uint8_t * err_msg,size_t err_msg_size,uint8_t * realm,uint8_t * nonce,uint8_t * server_name,int * oauth)541 int stun_is_challenge_response_str(const uint8_t* buf, size_t len, int *err_code, uint8_t *err_msg, size_t err_msg_size,
542 uint8_t *realm, uint8_t *nonce, uint8_t *server_name, int *oauth)
543 {
544 int ret = stun_is_error_response_str(buf, len, err_code, err_msg, err_msg_size);
545
546 if(ret && (((*err_code) == 401) || ((*err_code) == 438) )) {
547
548 stun_attr_ref sar = stun_attr_get_first_by_type_str(buf,len,STUN_ATTRIBUTE_REALM);
549 if(sar) {
550
551 int found_oauth = 0;
552
553 const uint8_t *value = stun_attr_get_value(sar);
554 if(value) {
555 size_t vlen = (size_t)stun_attr_get_len(sar);
556 bcopy(value,realm,vlen);
557 realm[vlen]=0;
558
559 {
560 sar = stun_attr_get_first_by_type_str(buf,len,STUN_ATTRIBUTE_THIRD_PARTY_AUTHORIZATION);
561 if(sar) {
562 value = stun_attr_get_value(sar);
563 if(value) {
564 vlen = (size_t)stun_attr_get_len(sar);
565 if(vlen>0) {
566 if(server_name) {
567 bcopy(value,server_name,vlen);
568 }
569 found_oauth = 1;
570 }
571 }
572 }
573 }
574
575 sar = stun_attr_get_first_by_type_str(buf,len,STUN_ATTRIBUTE_NONCE);
576 if(sar) {
577 value = stun_attr_get_value(sar);
578 if(value) {
579 vlen = (size_t)stun_attr_get_len(sar);
580 bcopy(value,nonce,vlen);
581 nonce[vlen]=0;
582 if(oauth) {
583 *oauth = found_oauth;
584 }
585 return 1;
586 }
587 }
588 }
589 }
590 }
591
592 return 0;
593 }
594
stun_is_response_str(const uint8_t * buf,size_t len)595 int stun_is_response_str(const uint8_t* buf, size_t len) {
596 if(is_channel_msg_str(buf,len)) return 0;
597 if(IS_STUN_SUCCESS_RESP(stun_get_msg_type_str(buf,len))) return 1;
598 if(IS_STUN_ERR_RESP(stun_get_msg_type_str(buf,len))) return 1;
599 return 0;
600 }
601
stun_is_indication_str(const uint8_t * buf,size_t len)602 int stun_is_indication_str(const uint8_t* buf, size_t len) {
603 if(is_channel_msg_str(buf,len)) return 0;
604 return IS_STUN_INDICATION(stun_get_msg_type_str(buf,len));
605 }
606
stun_make_request(uint16_t method)607 uint16_t stun_make_request(uint16_t method) {
608 return GET_STUN_REQUEST(stun_make_type(method));
609 }
610
stun_make_indication(uint16_t method)611 uint16_t stun_make_indication(uint16_t method) {
612 return GET_STUN_INDICATION(stun_make_type(method));
613 }
614
stun_make_success_response(uint16_t method)615 uint16_t stun_make_success_response(uint16_t method) {
616 return GET_STUN_SUCCESS_RESP(stun_make_type(method));
617 }
618
stun_make_error_response(uint16_t method)619 uint16_t stun_make_error_response(uint16_t method) {
620 return GET_STUN_ERR_RESP(stun_make_type(method));
621 }
622
623 //////////////// INIT ////////////////////////////////////////////
624
stun_init_buffer_str(uint8_t * buf,size_t * len)625 void stun_init_buffer_str(uint8_t *buf, size_t *len) {
626 *len=STUN_HEADER_LENGTH;
627 bzero(buf,*len);
628 }
629
stun_init_command_str(uint16_t message_type,uint8_t * buf,size_t * len)630 void stun_init_command_str(uint16_t message_type, uint8_t* buf, size_t *len) {
631 stun_init_buffer_str(buf,len);
632 message_type &= (uint16_t)(0x3FFF);
633 ((uint16_t*)buf)[0]=nswap16(message_type);
634 ((uint16_t*)buf)[1]=0;
635 ((uint32_t*)buf)[1]=nswap32(STUN_MAGIC_COOKIE);
636 stun_tid_generate_in_message_str(buf,NULL);
637 }
638
old_stun_init_command_str(uint16_t message_type,uint8_t * buf,size_t * len,uint32_t cookie)639 void old_stun_init_command_str(uint16_t message_type, uint8_t* buf, size_t *len, uint32_t cookie) {
640 stun_init_buffer_str(buf,len);
641 message_type &= (uint16_t)(0x3FFF);
642 ((uint16_t*)buf)[0]=nswap16(message_type);
643 ((uint16_t*)buf)[1]=0;
644 ((uint32_t*)buf)[1]=nswap32(cookie);
645 stun_tid_generate_in_message_str(buf,NULL);
646 }
647
stun_init_request_str(uint16_t method,uint8_t * buf,size_t * len)648 void stun_init_request_str(uint16_t method, uint8_t* buf, size_t *len) {
649 stun_init_command_str(stun_make_request(method), buf, len);
650 }
651
stun_init_indication_str(uint16_t method,uint8_t * buf,size_t * len)652 void stun_init_indication_str(uint16_t method, uint8_t* buf, size_t *len) {
653 stun_init_command_str(stun_make_indication(method), buf, len);
654 }
655
stun_init_success_response_str(uint16_t method,uint8_t * buf,size_t * len,stun_tid * id)656 void stun_init_success_response_str(uint16_t method, uint8_t* buf, size_t *len, stun_tid* id) {
657 stun_init_command_str(stun_make_success_response(method), buf, len);
658 if(id) {
659 stun_tid_message_cpy(buf, id);
660 }
661 }
662
old_stun_init_success_response_str(uint16_t method,uint8_t * buf,size_t * len,stun_tid * id,uint32_t cookie)663 void old_stun_init_success_response_str(uint16_t method, uint8_t* buf, size_t *len, stun_tid* id, uint32_t cookie) {
664 old_stun_init_command_str(stun_make_success_response(method), buf, len, cookie);
665 if(id) {
666 stun_tid_message_cpy(buf, id);
667 }
668 }
669
get_default_reason(int error_code)670 const uint8_t* get_default_reason(int error_code)
671 {
672 const uint8_t* reason = (const uint8_t *) "Unknown error";
673
674 switch (error_code){
675 case 300:
676 reason = (const uint8_t *) "Try Alternate";
677 break;
678 case 400:
679 reason = (const uint8_t *) "Bad Request";
680 break;
681 case 401:
682 reason = (const uint8_t *) "Unauthorized";
683 break;
684 case 403:
685 reason = (const uint8_t *) "Forbidden";
686 break;
687 case 404:
688 reason = (const uint8_t *) "Not Found";
689 break;
690 case 420:
691 reason = (const uint8_t *) "Unknown Attribute";
692 break;
693 case 437:
694 reason = (const uint8_t *) "Allocation Mismatch";
695 break;
696 case 438:
697 reason = (const uint8_t *) "Stale Nonce";
698 break;
699 case 440:
700 reason = (const uint8_t *) "Address Family not Supported";
701 break;
702 case 441:
703 reason = (const uint8_t *) "Wrong Credentials";
704 break;
705 case 442:
706 reason = (const uint8_t *) "Unsupported Transport Protocol";
707 break;
708 case 443:
709 reason = (const uint8_t *) "Peer Address Family Mismatch";
710 break;
711 case 446:
712 reason = (const uint8_t *) "Connection Already Exists";
713 break;
714 case 447:
715 reason = (const uint8_t *) "Connection Timeout or Failure";
716 break;
717 case 486:
718 reason = (const uint8_t *) "Allocation Quota Reached";
719 break;
720 case 487:
721 reason = (const uint8_t *) "Role Conflict";
722 break;
723 case 500:
724 reason = (const uint8_t *) "Server Error";
725 break;
726 case 508:
727 reason = (const uint8_t *) "Insufficient Capacity";
728 break;
729 default:
730 ;
731 };
732
733 return reason;
734 }
735
stun_init_error_response_common_str(uint8_t * buf,size_t * len,uint16_t error_code,const uint8_t * reason,stun_tid * id)736 static void stun_init_error_response_common_str(uint8_t* buf, size_t *len,
737 uint16_t error_code, const uint8_t *reason,
738 stun_tid* id)
739 {
740
741 if (!reason || !strcmp((const char*)reason,"Unknown error")) {
742 reason = get_default_reason(error_code);
743 }
744
745 uint8_t avalue[513];
746 avalue[0] = 0;
747 avalue[1] = 0;
748 avalue[2] = (uint8_t) (error_code / 100);
749 avalue[3] = (uint8_t) (error_code % 100);
750 strncpy((char*) (avalue + 4), (const char*) reason, sizeof(avalue)-4);
751 avalue[sizeof(avalue)-1]=0;
752 int alen = 4 + (int)strlen((const char*) (avalue+4));
753
754 //"Manual" padding for compatibility with classic old stun:
755 {
756 int rem = alen % 4;
757 if(rem) {
758 alen +=(4-rem);
759 }
760 }
761
762 stun_attr_add_str(buf, len, STUN_ATTRIBUTE_ERROR_CODE, (uint8_t*) avalue, alen);
763 if (id) {
764 stun_tid_message_cpy(buf, id);
765 }
766 }
767
old_stun_init_error_response_str(uint16_t method,uint8_t * buf,size_t * len,uint16_t error_code,const uint8_t * reason,stun_tid * id,uint32_t cookie)768 void old_stun_init_error_response_str(uint16_t method, uint8_t* buf, size_t *len,
769 uint16_t error_code, const uint8_t *reason,
770 stun_tid* id, uint32_t cookie)
771 {
772
773 old_stun_init_command_str(stun_make_error_response(method), buf, len, cookie);
774
775 stun_init_error_response_common_str(buf, len,
776 error_code, reason,
777 id);
778 }
779
stun_init_error_response_str(uint16_t method,uint8_t * buf,size_t * len,uint16_t error_code,const uint8_t * reason,stun_tid * id)780 void stun_init_error_response_str(uint16_t method, uint8_t* buf, size_t *len,
781 uint16_t error_code, const uint8_t *reason,
782 stun_tid* id)
783 {
784
785 stun_init_command_str(stun_make_error_response(method), buf, len);
786
787 stun_init_error_response_common_str(buf, len,
788 error_code, reason,
789 id);
790 }
791
792 /////////// CHANNEL ////////////////////////////////////////////////
793
stun_init_channel_message_str(uint16_t chnumber,uint8_t * buf,size_t * len,int length,int do_padding)794 int stun_init_channel_message_str(uint16_t chnumber, uint8_t* buf, size_t *len, int length, int do_padding)
795 {
796 uint16_t rlen = (uint16_t)length;
797
798 if(length<0 || (MAX_STUN_MESSAGE_SIZE<(4+length))) return -1;
799 ((uint16_t*)(buf))[0]=nswap16(chnumber);
800 ((uint16_t*)(buf))[1]=nswap16((uint16_t)length);
801
802 if(do_padding && (rlen & 0x0003))
803 rlen = ((rlen>>2)+1)<<2;
804
805 *len=4+rlen;
806
807 return 0;
808 }
809
stun_is_channel_message_str(const uint8_t * buf,size_t * blen,uint16_t * chnumber,int mandatory_padding)810 int stun_is_channel_message_str(const uint8_t *buf, size_t *blen, uint16_t* chnumber, int mandatory_padding)
811 {
812 uint16_t datalen_header;
813 uint16_t datalen_actual;
814
815 if (!blen || (*blen < 4))
816 return 0;
817
818 uint16_t chn = nswap16(((const uint16_t*)(buf))[0]);
819 if (!STUN_VALID_CHANNEL(chn))
820 return 0;
821
822 if(*blen>(uint16_t)-1)
823 *blen=(uint16_t)-1;
824
825 datalen_actual = (uint16_t)(*blen) - 4;
826 datalen_header = ((const uint16_t*)buf)[1];
827 datalen_header = nswap16(datalen_header);
828
829 if (datalen_header > datalen_actual)
830 return 0;
831
832 if (datalen_header != datalen_actual) {
833
834 /* maybe there are padding bytes for 32-bit alignment. Mandatory for TCP. Optional for UDP */
835
836 if(datalen_actual & 0x0003) {
837
838 if(mandatory_padding) {
839 return 0;
840 } else if ((datalen_actual < datalen_header) || (datalen_header == 0)) {
841 return 0;
842 } else {
843 uint16_t diff = datalen_actual - datalen_header;
844 if (diff > 3)
845 return 0;
846 }
847 }
848 }
849
850 *blen = datalen_header + 4;
851
852 if (chnumber)
853 *chnumber = chn;
854
855 return 1;
856 }
857
858 ////////// STUN message ///////////////////////////////
859
sheadof(const char * head,const char * full,int ignore_case)860 static inline int sheadof(const char *head, const char* full, int ignore_case)
861 {
862 while(*head) {
863 if(*head != *full) {
864 if(ignore_case && (tolower((int)*head)==tolower((int)*full))) {
865 //OK
866 } else {
867 return 0;
868 }
869 }
870 ++head;++full;
871 }
872 return 1;
873 }
874
findstr(const char * hay,size_t slen,const char * needle,int ignore_case)875 static inline const char* findstr(const char *hay, size_t slen, const char *needle, int ignore_case)
876 {
877 const char *ret = NULL;
878
879 if(hay && slen && needle) {
880 size_t nlen=strlen(needle);
881 if(nlen<=slen) {
882 size_t smax = slen-nlen+1;
883 size_t i;
884 const char *sp = hay;
885 for(i=0;i<smax;++i) {
886 if(sheadof(needle,sp+i,ignore_case)) {
887 ret = sp+i;
888 break;
889 }
890 }
891 }
892 }
893
894 return ret;
895 }
896
is_http_inline(const char * s,size_t blen)897 static inline int is_http_inline(const char *s, size_t blen) {
898 if(s && blen>=12) {
899 if((strstr(s,"GET ")==s) ||(strstr(s,"POST ")==s) || (strstr(s,"DELETE ")==s) || (strstr(s,"PUT ")==s)) {
900 const char *sp=findstr(s+4,blen-4," HTTP/",0);
901 if(sp) {
902 sp += 6;
903 size_t diff_blen = sp-s;
904 if(diff_blen+4 <= blen) {
905 sp=findstr(sp,blen-diff_blen,"\r\n\r\n",0);
906 if(sp) {
907 int ret_len = (int)(sp-s+4);
908 const char* clheader = "content-length: ";
909 const char* cl = findstr(s,sp-s,clheader,1);
910 if(cl) {
911 unsigned long clen = strtoul(cl+strlen(clheader),NULL,10);
912 if(clen>0 && clen<(0x0FFFFFFF)) {
913 ret_len += (int)clen;
914 }
915 }
916 return ret_len;
917 }
918 }
919 }
920 }
921 }
922 return 0;
923 }
924
is_http(const char * s,size_t blen)925 int is_http(const char *s, size_t blen) {
926 return is_http_inline(s, blen);
927 }
928
stun_get_message_len_str(uint8_t * buf,size_t blen,int padding,size_t * app_len)929 int stun_get_message_len_str(uint8_t *buf, size_t blen, int padding, size_t *app_len) {
930 if (buf && blen) {
931 /* STUN request/response ? */
932 if (buf && blen >= STUN_HEADER_LENGTH) {
933 if (!STUN_VALID_CHANNEL(nswap16(((const uint16_t*)buf)[0]))) {
934 if ((((uint8_t) buf[0]) & ((uint8_t) (0xC0))) == 0) {
935 if (nswap32(((const uint32_t*)(buf))[1])
936 == STUN_MAGIC_COOKIE) {
937 uint16_t len = nswap16(((const uint16_t*)(buf))[1]);
938 if ((len & 0x0003) == 0) {
939 len += STUN_HEADER_LENGTH;
940 if ((size_t) len <= blen) {
941 *app_len = (size_t)len;
942 return (int)len;
943 }
944 }
945 }
946 }
947 }
948 }
949
950 //HTTP request ?
951 {
952 int http_len = is_http_inline(((char*)buf), blen);
953 if((http_len>0) && ((size_t)http_len<=blen)) {
954 *app_len = (size_t)http_len;
955 return http_len;
956 }
957 }
958
959 /* STUN channel ? */
960 if(blen>=4) {
961 uint16_t chn=nswap16(((const uint16_t*)(buf))[0]);
962 if(STUN_VALID_CHANNEL(chn)) {
963
964 uint16_t bret = (4+(nswap16(((const uint16_t*)(buf))[1])));
965
966 *app_len = bret;
967
968 if(padding && (bret & 0x0003)) {
969 bret = ((bret>>2)+1)<<2;
970 }
971
972 if(bret<=blen) {
973 return bret;
974 }
975 }
976 }
977
978 }
979
980 return -1;
981 }
982
983 ////////// ALLOCATE ///////////////////////////////////
984
stun_set_allocate_request_str(uint8_t * buf,size_t * len,uint32_t lifetime,int af4,int af6,uint8_t transport,int mobile,const char * rt,int ep)985 int stun_set_allocate_request_str(uint8_t* buf, size_t *len, uint32_t lifetime, int af4, int af6,
986 uint8_t transport, int mobile, const char* rt, int ep) {
987
988 stun_init_request_str(STUN_METHOD_ALLOCATE, buf, len);
989
990 //REQUESTED-TRANSPORT
991 {
992 uint8_t field[4];
993 field[0]=transport;
994 field[1]=0;
995 field[2]=0;
996 field[3]=0;
997 if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_REQUESTED_TRANSPORT,field,sizeof(field))<0) return -1;
998 }
999
1000 //LIFETIME
1001 {
1002 if(lifetime<1) lifetime=STUN_DEFAULT_ALLOCATE_LIFETIME;
1003 uint32_t field=nswap32(lifetime);
1004 if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_LIFETIME,(uint8_t*)(&field),sizeof(field))<0) return -1;
1005 }
1006
1007 //MICE
1008 if(mobile) {
1009 if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_MOBILITY_TICKET,(const uint8_t*)"",0)<0) return -1;
1010 }
1011
1012 if(ep>-1) {
1013 uint8_t value = ep ? 0x80 : 0x00;
1014 if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_EVEN_PORT,(const uint8_t*)&value,1)<0) return -1;
1015 }
1016
1017 //RESERVATION-TOKEN, EVEN-PORT and DUAL-ALLOCATION are mutually exclusive:
1018 if(rt) {
1019
1020 stun_attr_add_str(buf,len, STUN_ATTRIBUTE_RESERVATION_TOKEN, (const uint8_t*) rt, 8);
1021
1022 } else {
1023
1024 //ADRESS-FAMILY
1025 if (af4 && !af6) {
1026 uint8_t field[4];
1027 field[0] = (uint8_t)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4;
1028 field[1]=0;
1029 field[2]=0;
1030 field[3]=0;
1031 if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY,field,sizeof(field))<0) return -1;
1032 }
1033
1034 if (af6 && !af4) {
1035 uint8_t field[4];
1036 field[0] = (uint8_t)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6;
1037 field[1]=0;
1038 field[2]=0;
1039 field[3]=0;
1040 if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY,field,sizeof(field))<0) return -1;
1041 }
1042
1043 if (af4 && af6) {
1044 uint8_t field[4];
1045 field[0] = (uint8_t)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6;
1046 field[1]=0;
1047 field[2]=0;
1048 field[3]=0;
1049 if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_ADDITIONAL_ADDRESS_FAMILY,field,sizeof(field))<0) return -1;
1050 }
1051 }
1052
1053 return 0;
1054 }
1055
stun_set_allocate_response_str(uint8_t * buf,size_t * len,stun_tid * tid,const ioa_addr * relayed_addr1,const ioa_addr * relayed_addr2,const ioa_addr * reflexive_addr,uint32_t lifetime,uint32_t max_lifetime,int error_code,const uint8_t * reason,uint64_t reservation_token,char * mobile_id)1056 int stun_set_allocate_response_str(uint8_t* buf, size_t *len, stun_tid* tid,
1057 const ioa_addr *relayed_addr1, const ioa_addr *relayed_addr2,
1058 const ioa_addr *reflexive_addr,
1059 uint32_t lifetime, uint32_t max_lifetime, int error_code, const uint8_t *reason,
1060 uint64_t reservation_token, char* mobile_id) {
1061
1062 if(!error_code) {
1063
1064 stun_init_success_response_str(STUN_METHOD_ALLOCATE, buf, len, tid);
1065
1066 if(relayed_addr1) {
1067 if(stun_attr_add_addr_str(buf,len,STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS,relayed_addr1)<0) return -1;
1068 }
1069
1070 if(relayed_addr2) {
1071 if(stun_attr_add_addr_str(buf,len,STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS,relayed_addr2)<0) return -1;
1072 }
1073
1074 if(reflexive_addr) {
1075 if(stun_attr_add_addr_str(buf,len,STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,reflexive_addr)<0) return -1;
1076 }
1077
1078 if(reservation_token) {
1079 reservation_token=nswap64(reservation_token);
1080 stun_attr_add_str(buf,len,STUN_ATTRIBUTE_RESERVATION_TOKEN,(uint8_t*)(&reservation_token),8);
1081 }
1082
1083 {
1084 if(lifetime<1) lifetime=STUN_DEFAULT_ALLOCATE_LIFETIME;
1085 else if(lifetime>max_lifetime) lifetime = max_lifetime;
1086
1087 uint32_t field=nswap32(lifetime);
1088 if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_LIFETIME,(uint8_t*)(&field),sizeof(field))<0) return -1;
1089 }
1090
1091 if(mobile_id && *mobile_id) {
1092 if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_MOBILITY_TICKET,(uint8_t*)mobile_id,(int)strlen(mobile_id))<0) return -1;
1093 }
1094
1095 } else {
1096 stun_init_error_response_str(STUN_METHOD_ALLOCATE, buf, len, error_code, reason, tid);
1097 }
1098
1099 return 0;
1100 }
1101
1102 /////////////// CHANNEL BIND ///////////////////////////////////////
1103
stun_set_channel_bind_request_str(uint8_t * buf,size_t * len,const ioa_addr * peer_addr,uint16_t channel_number)1104 uint16_t stun_set_channel_bind_request_str(uint8_t* buf, size_t *len,
1105 const ioa_addr* peer_addr, uint16_t channel_number) {
1106
1107 if(!STUN_VALID_CHANNEL(channel_number)) {
1108 channel_number = 0x4000 + ((uint16_t)(((uint32_t)turn_random())%(0x7FFF-0x4000+1)));
1109 }
1110
1111 stun_init_request_str(STUN_METHOD_CHANNEL_BIND, buf, len);
1112
1113 if(stun_attr_add_channel_number_str(buf, len, channel_number)<0) return 0;
1114
1115 if(!peer_addr) {
1116 ioa_addr ca;
1117 bzero(&ca,sizeof(ioa_addr));
1118
1119 if(stun_attr_add_addr_str(buf,len,STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &ca)<0) return 0;
1120 } else {
1121 if(stun_attr_add_addr_str(buf,len,STUN_ATTRIBUTE_XOR_PEER_ADDRESS, peer_addr)<0) return 0;
1122 }
1123
1124 return channel_number;
1125 }
1126
stun_set_channel_bind_response_str(uint8_t * buf,size_t * len,stun_tid * tid,int error_code,const uint8_t * reason)1127 void stun_set_channel_bind_response_str(uint8_t* buf, size_t *len, stun_tid* tid, int error_code, const uint8_t *reason) {
1128 if(!error_code) {
1129 stun_init_success_response_str(STUN_METHOD_CHANNEL_BIND, buf, len, tid);
1130 } else {
1131 stun_init_error_response_str(STUN_METHOD_CHANNEL_BIND, buf, len, error_code, reason, tid);
1132 }
1133 }
1134
1135 /////////////// BINDING ///////////////////////////////////////
1136
stun_set_binding_request_str(uint8_t * buf,size_t * len)1137 void stun_set_binding_request_str(uint8_t* buf, size_t *len) {
1138 stun_init_request_str(STUN_METHOD_BINDING, buf, len);
1139 }
1140
stun_set_binding_response_str(uint8_t * buf,size_t * len,stun_tid * tid,const ioa_addr * reflexive_addr,int error_code,const uint8_t * reason,uint32_t cookie,int old_stun)1141 int stun_set_binding_response_str(uint8_t* buf, size_t *len, stun_tid* tid,
1142 const ioa_addr *reflexive_addr, int error_code, const uint8_t *reason,
1143 uint32_t cookie, int old_stun)
1144
1145 {
1146 if (!error_code) {
1147 if (!old_stun) {
1148 stun_init_success_response_str(STUN_METHOD_BINDING, buf, len, tid);
1149 } else {
1150 old_stun_init_success_response_str(STUN_METHOD_BINDING, buf, len, tid, cookie);
1151 }
1152 if(!old_stun && reflexive_addr) {
1153 if (stun_attr_add_addr_str(buf, len, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, reflexive_addr) < 0)
1154 return -1;
1155 }
1156 if(reflexive_addr) {
1157 if (stun_attr_add_addr_str(buf, len, STUN_ATTRIBUTE_MAPPED_ADDRESS, reflexive_addr) < 0)
1158 return -1;
1159 }
1160 } else if (!old_stun) {
1161 stun_init_error_response_str(STUN_METHOD_BINDING, buf, len, error_code, reason, tid);
1162 } else {
1163 old_stun_init_error_response_str(STUN_METHOD_BINDING, buf, len, error_code, reason, tid, cookie);
1164 }
1165
1166 return 0;
1167 }
1168
stun_is_binding_request_str(const uint8_t * buf,size_t len,size_t offset)1169 int stun_is_binding_request_str(const uint8_t* buf, size_t len, size_t offset)
1170 {
1171 if(offset < len) {
1172 buf += offset;
1173 len -= offset;
1174 if (stun_is_command_message_str(buf, len)) {
1175 if (stun_is_request_str(buf, len) && (stun_get_method_str(buf, len) == STUN_METHOD_BINDING)) {
1176 return 1;
1177 }
1178 }
1179 }
1180 return 0;
1181 }
1182
stun_is_binding_response_str(const uint8_t * buf,size_t len)1183 int stun_is_binding_response_str(const uint8_t* buf, size_t len) {
1184 if(stun_is_command_message_str(buf,len) &&
1185 (stun_get_method_str(buf,len)==STUN_METHOD_BINDING)) {
1186 if(stun_is_response_str(buf,len)) {
1187 return 1;
1188 }
1189 }
1190 return 0;
1191 }
1192
1193 /////////////////////////////// TID ///////////////////////////////
1194
1195
stun_tid_equals(const stun_tid * id1,const stun_tid * id2)1196 int stun_tid_equals(const stun_tid *id1, const stun_tid *id2) {
1197 if(id1==id2) return 1;
1198 if(!id1) return 0;
1199 if(!id2) return 0;
1200 {
1201 unsigned int i=0;
1202 for(i=0;i<STUN_TID_SIZE;++i) {
1203 if(id1->tsx_id[i]!=id2->tsx_id[i]) return 0;
1204 }
1205 }
1206 return 1;
1207 }
1208
stun_tid_cpy(stun_tid * id1,const stun_tid * id2)1209 void stun_tid_cpy(stun_tid *id1, const stun_tid *id2) {
1210 if(!id1) return;
1211 if(!id2) return;
1212 bcopy((const void*)(id2->tsx_id),(void*)(id1->tsx_id),STUN_TID_SIZE);
1213 }
1214
stun_tid_string_cpy(uint8_t * s,const stun_tid * id)1215 static void stun_tid_string_cpy(uint8_t* s, const stun_tid* id) {
1216 if(s && id) {
1217 bcopy((const void*)(id->tsx_id),s,STUN_TID_SIZE);
1218 }
1219 }
1220
stun_tid_from_string(const uint8_t * s,stun_tid * id)1221 static void stun_tid_from_string(const uint8_t* s, stun_tid* id) {
1222 if(s && id) {
1223 bcopy(s,(void*)(id->tsx_id),STUN_TID_SIZE);
1224 }
1225 }
1226
stun_tid_from_message_str(const uint8_t * buf,size_t len,stun_tid * id)1227 void stun_tid_from_message_str(const uint8_t* buf, size_t len, stun_tid* id) {
1228 UNUSED_ARG(len);
1229 stun_tid_from_string(buf+8, id);
1230 }
1231
stun_tid_message_cpy(uint8_t * buf,const stun_tid * id)1232 void stun_tid_message_cpy(uint8_t* buf, const stun_tid* id) {
1233 if(buf && id) {
1234 stun_tid_string_cpy(buf+8, id);
1235 }
1236 }
1237
stun_tid_generate(stun_tid * id)1238 void stun_tid_generate(stun_tid* id) {
1239 if(id) {
1240 turn_random_tid_size(id->tsx_id);
1241 }
1242 }
1243
stun_tid_generate_in_message_str(uint8_t * buf,stun_tid * id)1244 void stun_tid_generate_in_message_str(uint8_t* buf, stun_tid* id) {
1245 stun_tid tmp;
1246 if(!id) id=&tmp;
1247 stun_tid_generate(id);
1248 stun_tid_message_cpy(buf, id);
1249 }
1250
1251 /////////////////// TIME ////////////////////////////////////////////////////////
1252
stun_adjust_allocate_lifetime(turn_time_t lifetime,turn_time_t max_allowed_lifetime,turn_time_t max_lifetime)1253 turn_time_t stun_adjust_allocate_lifetime(turn_time_t lifetime, turn_time_t max_allowed_lifetime, turn_time_t max_lifetime) {
1254
1255 if(!lifetime) lifetime = STUN_DEFAULT_ALLOCATE_LIFETIME;
1256 else if(lifetime<STUN_MIN_ALLOCATE_LIFETIME) lifetime = STUN_MIN_ALLOCATE_LIFETIME;
1257 else if(lifetime>max_allowed_lifetime) lifetime = max_allowed_lifetime;
1258
1259 if(max_lifetime && (max_lifetime < lifetime)) {
1260 lifetime = max_lifetime;
1261 }
1262
1263 return lifetime;
1264 }
1265
1266 ////////////// ATTR /////////////////////////////////////////////////////////////
1267
stun_attr_get_type(stun_attr_ref attr)1268 int stun_attr_get_type(stun_attr_ref attr) {
1269 if(attr)
1270 return (int)(nswap16(((const uint16_t*)attr)[0]));
1271 return -1;
1272 }
1273
stun_attr_get_len(stun_attr_ref attr)1274 int stun_attr_get_len(stun_attr_ref attr) {
1275 if(attr)
1276 return (int)(nswap16(((const uint16_t*)attr)[1]));
1277 return -1;
1278 }
1279
stun_attr_get_value(stun_attr_ref attr)1280 const uint8_t* stun_attr_get_value(stun_attr_ref attr) {
1281 if(attr) {
1282 int len = (int)(nswap16(((const uint16_t*)attr)[1]));
1283 if(len<1) return NULL;
1284 return ((const uint8_t*)attr)+4;
1285 }
1286 return NULL;
1287 }
1288
stun_get_requested_address_family(stun_attr_ref attr)1289 int stun_get_requested_address_family(stun_attr_ref attr)
1290 {
1291 if (attr) {
1292 int len = (int) (nswap16(((const uint16_t*)attr)[1]));
1293 if (len != 4)
1294 return STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_INVALID;
1295 int val = ((const uint8_t*) attr)[4];
1296 switch (val){
1297 case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4:
1298 return val;
1299 case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6:
1300 return val;
1301 default:
1302 return STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_INVALID;
1303 };
1304 }
1305 return STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT;
1306 }
1307
stun_attr_get_channel_number(stun_attr_ref attr)1308 uint16_t stun_attr_get_channel_number(stun_attr_ref attr) {
1309 if(attr) {
1310 const uint8_t* value = stun_attr_get_value(attr);
1311 if(value && (stun_attr_get_len(attr) >= 2)) {
1312 uint16_t cn=nswap16(((const uint16_t*)value)[0]);
1313 if(STUN_VALID_CHANNEL(cn)) return cn;
1314 }
1315 }
1316 return 0;
1317 }
1318
stun_attr_get_bandwidth(stun_attr_ref attr)1319 band_limit_t stun_attr_get_bandwidth(stun_attr_ref attr) {
1320 if(attr) {
1321 const uint8_t* value = stun_attr_get_value(attr);
1322 if(value && (stun_attr_get_len(attr) >= 4)) {
1323 uint32_t bps=nswap32(((const uint32_t*)value)[0]);
1324 return (band_limit_t)(bps << 7);
1325 }
1326 }
1327 return 0;
1328 }
1329
stun_attr_get_reservation_token_value(stun_attr_ref attr)1330 uint64_t stun_attr_get_reservation_token_value(stun_attr_ref attr) {
1331 if(attr) {
1332 const uint8_t* value = stun_attr_get_value(attr);
1333 if(value && (stun_attr_get_len(attr) == 8)) {
1334 uint64_t token;
1335 bcopy(value, &token, sizeof(uint64_t));
1336 return nswap64(token);
1337 }
1338 }
1339 return 0;
1340 }
1341
stun_attr_is_addr(stun_attr_ref attr)1342 int stun_attr_is_addr(stun_attr_ref attr) {
1343
1344 if(attr) {
1345 switch(stun_attr_get_type(attr)) {
1346 case STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS:
1347 case STUN_ATTRIBUTE_XOR_PEER_ADDRESS:
1348 case STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS:
1349 case STUN_ATTRIBUTE_MAPPED_ADDRESS:
1350 case STUN_ATTRIBUTE_ALTERNATE_SERVER:
1351 case OLD_STUN_ATTRIBUTE_RESPONSE_ADDRESS:
1352 case OLD_STUN_ATTRIBUTE_SOURCE_ADDRESS:
1353 case OLD_STUN_ATTRIBUTE_CHANGED_ADDRESS:
1354 case OLD_STUN_ATTRIBUTE_REFLECTED_FROM:
1355 case STUN_ATTRIBUTE_RESPONSE_ORIGIN:
1356 case STUN_ATTRIBUTE_OTHER_ADDRESS:
1357 return 1;
1358 break;
1359 default:
1360 ;
1361 };
1362 }
1363 return 0;
1364 }
1365
stun_attr_get_even_port(stun_attr_ref attr)1366 uint8_t stun_attr_get_even_port(stun_attr_ref attr) {
1367 if(attr) {
1368 const uint8_t* value=stun_attr_get_value(attr);
1369 if(value) {
1370 if((uint8_t)(value[0]) > 0x7F) return 1;
1371 }
1372 }
1373 return 0;
1374 }
1375
stun_attr_get_first_by_type_str(const uint8_t * buf,size_t len,uint16_t attr_type)1376 stun_attr_ref stun_attr_get_first_by_type_str(const uint8_t* buf, size_t len, uint16_t attr_type) {
1377
1378 stun_attr_ref attr=stun_attr_get_first_str(buf,len);
1379 while(attr) {
1380 if(stun_attr_get_type(attr) == attr_type) {
1381 return attr;
1382 }
1383 attr=stun_attr_get_next_str(buf,len,attr);
1384 }
1385
1386 return NULL;
1387 }
1388
stun_attr_check_valid(stun_attr_ref attr,size_t remaining)1389 static stun_attr_ref stun_attr_check_valid(stun_attr_ref attr, size_t remaining) {
1390
1391 if(remaining >= 4) {
1392 /* Read the size of the attribute */
1393 size_t attrlen = stun_attr_get_len(attr);
1394 remaining -= 4;
1395
1396 /* Round to boundary */
1397 uint16_t rem4 = ((uint16_t)attrlen) & 0x0003;
1398 if(rem4) {
1399 attrlen = attrlen+4-(int)rem4;
1400 }
1401
1402 /* Check that there's enough space remaining */
1403 if(attrlen <= remaining) {
1404 return attr;
1405 }
1406 }
1407
1408 return NULL;
1409 }
1410
stun_attr_get_first_str(const uint8_t * buf,size_t len)1411 stun_attr_ref stun_attr_get_first_str(const uint8_t* buf, size_t len) {
1412
1413 int bufLen = stun_get_command_message_len_str(buf,len);
1414 if(bufLen > STUN_HEADER_LENGTH) {
1415 stun_attr_ref attr = (stun_attr_ref)(buf+STUN_HEADER_LENGTH);
1416 return stun_attr_check_valid(attr, bufLen - STUN_HEADER_LENGTH);
1417 }
1418
1419 return NULL;
1420 }
1421
stun_attr_get_next_str(const uint8_t * buf,size_t len,stun_attr_ref prev)1422 stun_attr_ref stun_attr_get_next_str(const uint8_t* buf, size_t len, stun_attr_ref prev) {
1423
1424 if(!prev) return stun_attr_get_first_str(buf,len);
1425 else {
1426 const uint8_t* end = buf + stun_get_command_message_len_str(buf,len);
1427 int attrlen=stun_attr_get_len(prev);
1428 uint16_t rem4 = ((uint16_t)attrlen) & 0x0003;
1429 if(rem4) {
1430 attrlen = attrlen+4-(int)rem4;
1431 }
1432 /* Note the order here: operations on attrlen are untrusted as they may overflow */
1433 if(attrlen < end - (const uint8_t*)prev - 4) {
1434 const uint8_t* attr_end=(const uint8_t*)prev+4+attrlen;
1435 return stun_attr_check_valid(attr_end, end - attr_end);
1436 }
1437 return NULL;
1438 }
1439 }
1440
stun_attr_add_str(uint8_t * buf,size_t * len,uint16_t attr,const uint8_t * avalue,int alen)1441 int stun_attr_add_str(uint8_t* buf, size_t *len, uint16_t attr, const uint8_t* avalue, int alen) {
1442 if(alen<0) alen=0;
1443 uint8_t tmp[1];
1444 if(!avalue) {
1445 alen=0;
1446 avalue=tmp;
1447 }
1448 int clen = stun_get_command_message_len_str(buf,*len);
1449 int newlen = clen + 4 + alen;
1450 int newlenrem4=newlen & 0x00000003;
1451 if(newlenrem4) {
1452 newlen=newlen+(4-newlenrem4);
1453 }
1454 if(newlen>=MAX_STUN_MESSAGE_SIZE) return -1;
1455 else {
1456 uint8_t* attr_start=buf+clen;
1457
1458 uint16_t *attr_start_16t=(uint16_t*)attr_start;
1459
1460 stun_set_command_message_len_str(buf,newlen);
1461 *len = newlen;
1462
1463 attr_start_16t[0]=nswap16(attr);
1464 attr_start_16t[1]=nswap16(alen);
1465 if(alen>0) bcopy(avalue,attr_start+4,alen);
1466 return 0;
1467 }
1468 }
1469
stun_attr_add_addr_str(uint8_t * buf,size_t * len,uint16_t attr_type,const ioa_addr * ca)1470 int stun_attr_add_addr_str(uint8_t *buf, size_t *len, uint16_t attr_type, const ioa_addr* ca) {
1471
1472 stun_tid tid;
1473 stun_tid_from_message_str(buf, *len, &tid);
1474
1475 int xor_ed=0;
1476 switch(attr_type) {
1477 case STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS:
1478 case STUN_ATTRIBUTE_XOR_PEER_ADDRESS:
1479 case STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS:
1480 xor_ed=1;
1481 break;
1482 default:
1483 ;
1484 };
1485
1486 ioa_addr public_addr;
1487 map_addr_from_private_to_public(ca,&public_addr);
1488
1489 uint8_t cfield[64];
1490 int clen=0;
1491 if(stun_addr_encode(&public_addr, cfield, &clen, xor_ed, STUN_MAGIC_COOKIE, tid.tsx_id)<0) {
1492 return -1;
1493 }
1494
1495 if(stun_attr_add_str(buf,len,attr_type,(uint8_t*)(&cfield),clen)<0) return -1;
1496
1497 return 0;
1498 }
1499
stun_attr_get_addr_str(const uint8_t * buf,size_t len,stun_attr_ref attr,ioa_addr * ca,const ioa_addr * default_addr)1500 int stun_attr_get_addr_str(const uint8_t *buf, size_t len, stun_attr_ref attr, ioa_addr* ca, const ioa_addr *default_addr) {
1501
1502 stun_tid tid;
1503 stun_tid_from_message_str(buf, len, &tid);
1504 ioa_addr public_addr;
1505
1506 addr_set_any(ca);
1507 addr_set_any(&public_addr);
1508
1509 int attr_type = stun_attr_get_type(attr);
1510 if(attr_type<0) return -1;
1511
1512 int xor_ed=0;
1513 switch(attr_type) {
1514 case STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS:
1515 case STUN_ATTRIBUTE_XOR_PEER_ADDRESS:
1516 case STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS:
1517 xor_ed=1;
1518 break;
1519 default:
1520 ;
1521 };
1522
1523 const uint8_t *cfield=stun_attr_get_value(attr);
1524 if(!cfield) return -1;
1525
1526 if(stun_addr_decode(&public_addr, cfield, stun_attr_get_len(attr), xor_ed, STUN_MAGIC_COOKIE, tid.tsx_id)<0) {
1527 return -1;
1528 }
1529
1530 map_addr_from_public_to_private(&public_addr, ca);
1531
1532 if(default_addr && addr_any_no_port(ca) && !addr_any_no_port(default_addr)) {
1533 int port = addr_get_port(ca);
1534 addr_cpy(ca,default_addr);
1535 addr_set_port(ca,port);
1536 }
1537
1538 return 0;
1539 }
1540
stun_attr_get_first_addr_str(const uint8_t * buf,size_t len,uint16_t attr_type,ioa_addr * ca,const ioa_addr * default_addr)1541 int stun_attr_get_first_addr_str(const uint8_t *buf, size_t len, uint16_t attr_type, ioa_addr* ca, const ioa_addr *default_addr) {
1542
1543 stun_attr_ref attr=stun_attr_get_first_str(buf,len);
1544
1545 while(attr) {
1546 if(stun_attr_is_addr(attr) && (attr_type == stun_attr_get_type(attr))) {
1547 if(stun_attr_get_addr_str(buf,len,attr,ca,default_addr)==0) {
1548 return 0;
1549 }
1550 }
1551 attr=stun_attr_get_next_str(buf,len,attr);
1552 }
1553
1554 return -1;
1555 }
1556
stun_attr_add_channel_number_str(uint8_t * buf,size_t * len,uint16_t chnumber)1557 int stun_attr_add_channel_number_str(uint8_t* buf, size_t *len, uint16_t chnumber) {
1558
1559 uint16_t field[2];
1560 field[0]=nswap16(chnumber);
1561 field[1]=0;
1562
1563 return stun_attr_add_str(buf,len,STUN_ATTRIBUTE_CHANNEL_NUMBER,(uint8_t*)(field),sizeof(field));
1564 }
1565
stun_attr_add_bandwidth_str(uint8_t * buf,size_t * len,band_limit_t bps0)1566 int stun_attr_add_bandwidth_str(uint8_t* buf, size_t *len, band_limit_t bps0) {
1567
1568 uint32_t bps = (uint32_t)(band_limit_t)(bps0 >> 7);
1569
1570 uint32_t field=nswap32(bps);
1571
1572 return stun_attr_add_str(buf,len,STUN_ATTRIBUTE_NEW_BANDWIDTH,(uint8_t*)(&field),sizeof(field));
1573 }
1574
stun_attr_add_address_error_code(uint8_t * buf,size_t * len,int requested_address_family,int error_code)1575 int stun_attr_add_address_error_code(uint8_t* buf, size_t *len, int requested_address_family, int error_code)
1576 {
1577 const uint8_t *reason = get_default_reason(error_code);
1578
1579 uint8_t avalue[513];
1580 avalue[0] = (uint8_t)requested_address_family;
1581 avalue[1] = 0;
1582 avalue[2] = (uint8_t) (error_code / 100);
1583 avalue[3] = (uint8_t) (error_code % 100);
1584 strncpy((char*) (avalue + 4), (const char*) reason, sizeof(avalue)-4);
1585 avalue[sizeof(avalue)-1]=0;
1586 int alen = 4 + (int)strlen((const char*) (avalue+4));
1587
1588 //"Manual" padding for compatibility with classic old stun:
1589 {
1590 int rem = alen % 4;
1591 if(rem) {
1592 alen +=(4-rem);
1593 }
1594 }
1595
1596 stun_attr_add_str(buf, len, STUN_ATTRIBUTE_ADDRESS_ERROR_CODE, (uint8_t*) avalue, alen);
1597
1598 return 0;
1599 }
1600
stun_attr_get_address_error_code(uint8_t * buf,size_t len,int * requested_address_family,int * error_code)1601 int stun_attr_get_address_error_code(uint8_t* buf, size_t len, int *requested_address_family, int *error_code)
1602 {
1603 if(requested_address_family) {
1604 *requested_address_family = 0;
1605 }
1606 if(error_code) {
1607 *error_code = 0;
1608 }
1609 if(buf && len) {
1610 stun_attr_ref sar = stun_attr_get_first_by_type_str(buf, len, STUN_ATTRIBUTE_ADDRESS_ERROR_CODE);
1611 if(sar) {
1612 const uint8_t* value = stun_attr_get_value(sar);
1613 if(!value) {
1614 return -1;
1615 } else {
1616 int alen = stun_attr_get_len(sar);
1617 if(alen != 4) {
1618 return -1;
1619 }
1620 if(requested_address_family) {
1621 *requested_address_family = value[0];
1622 }
1623 if(error_code) {
1624 *error_code = (int)(value[2]*100+value[3]);
1625 }
1626 return 0;
1627 }
1628 }
1629 }
1630 return 0;
1631 }
1632
stun_attr_get_first_channel_number_str(const uint8_t * buf,size_t len)1633 uint16_t stun_attr_get_first_channel_number_str(const uint8_t *buf, size_t len) {
1634
1635 stun_attr_ref attr=stun_attr_get_first_str(buf,len);
1636 while(attr) {
1637 if(stun_attr_get_type(attr) == STUN_ATTRIBUTE_CHANNEL_NUMBER) {
1638 uint16_t ret = stun_attr_get_channel_number(attr);
1639 if(STUN_VALID_CHANNEL(ret)) {
1640 return ret;
1641 }
1642 }
1643 attr=stun_attr_get_next_str(buf,len,attr);
1644 }
1645
1646 return 0;
1647 }
1648
1649 ////////////// FINGERPRINT ////////////////////////////
1650
stun_attr_add_fingerprint_str(uint8_t * buf,size_t * len)1651 int stun_attr_add_fingerprint_str(uint8_t *buf, size_t *len)
1652 {
1653 uint32_t crc32 = 0;
1654 stun_attr_add_str(buf, len, STUN_ATTRIBUTE_FINGERPRINT, (uint8_t*)&crc32, 4);
1655 crc32 = ns_crc32(buf,(int)*len-8);
1656 *((uint32_t*)(buf+*len-4)) = nswap32(crc32 ^ ((uint32_t)0x5354554e));
1657 return 0;
1658 }
1659 ////////////// CRC ///////////////////////////////////////////////
1660
1661 #define CRC_MASK 0xFFFFFFFFUL
1662
1663 #define UPDATE_CRC(crc, c) crc = crctable[(uint8_t)crc ^ (uint8_t)(c)] ^ (crc >> 8)
1664
1665 static const uint32_t crctable[256] = {
1666 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
1667 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
1668 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
1669 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
1670 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
1671 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
1672 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
1673 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
1674 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
1675 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
1676 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
1677 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
1678 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
1679 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
1680 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
1681 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
1682 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
1683 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
1684 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
1685 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
1686 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
1687 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
1688 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
1689 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
1690 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
1691 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
1692 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
1693 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
1694 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
1695 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
1696 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
1697 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
1698 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
1699 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
1700 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
1701 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
1702 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
1703 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
1704 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
1705 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
1706 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
1707 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
1708 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
1709 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
1710 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
1711 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
1712 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
1713 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
1714 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
1715 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
1716 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
1717 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
1718 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
1719 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
1720 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
1721 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
1722 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
1723 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
1724 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
1725 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
1726 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
1727 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
1728 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
1729 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
1730 };
1731
1732 /*
1733
1734 #define CRCPOLY 0xEDB88320UL
1735 reversed 0x04C11DB7
1736 1110 1101 1001 1000 1000 0011 0010 0000
1737
1738 static void make_crctable(void)
1739 {
1740 uint i, j;
1741 uint32_t r;
1742
1743 for (i = 0; i < 256; ++i) {
1744 r = i;
1745 for (j = 8; j > 0; --j) {
1746 if (r & 1)
1747 r = (r >> 1) ^ CRCPOLY;
1748 else
1749 r >>= 1;
1750 }
1751 crctable[i] = r;
1752 }
1753 }
1754 */
1755
ns_crc32(const uint8_t * buffer,uint32_t len)1756 static uint32_t ns_crc32(const uint8_t *buffer, uint32_t len)
1757 {
1758 uint32_t crc = CRC_MASK;
1759 while ( len-- ) UPDATE_CRC( crc, *buffer++ );
1760 return (~crc);
1761 }
1762
1763 //////////// SASLprep RFC 4013 /////////////////////////////////////////
1764
1765 /* We support only basic ASCII table */
1766
SASLprep(uint8_t * s)1767 int SASLprep(uint8_t *s)
1768 {
1769 if(s) {
1770 uint8_t *strin = s;
1771 uint8_t *strout = s;
1772 for(;;) {
1773 uint8_t c = *strin;
1774 if(!c) {
1775 *strout=0;
1776 break;
1777 }
1778
1779 switch(c) {
1780 case 0xAD:
1781 ++strin;
1782 break;
1783 case 0xA0:
1784 case 0x20:
1785 *strout=0x20;
1786 ++strout;
1787 ++strin;
1788 break;
1789 case 0x7F:
1790 return -1;
1791 default:
1792 if(c<0x1F)
1793 return -1;
1794 if(c>=0x80 && c<=0x9F)
1795 return -1;
1796 *strout=c;
1797 ++strout;
1798 ++strin;
1799 };
1800 }
1801 }
1802
1803 return 0;
1804 }
1805
1806 //////////////// Message Integrity ////////////////////////////
1807
get_hmackey_size(SHATYPE shatype)1808 size_t get_hmackey_size(SHATYPE shatype)
1809 {
1810 if(shatype == SHATYPE_SHA256)
1811 return 32;
1812 if(shatype == SHATYPE_SHA384)
1813 return 48;
1814 if(shatype == SHATYPE_SHA512)
1815 return 64;
1816 return 16;
1817 }
1818
print_bin_func(const char * name,size_t len,const void * s,const char * func)1819 void print_bin_func(const char *name, size_t len, const void *s, const char *func)
1820 {
1821 printf("<%s>:<%s>:len=%d:[",func,name,(int)len);
1822 size_t i;
1823 for(i=0;i<len;i++) {
1824 printf("%02x",(int)((const uint8_t*)s)[i]);
1825 }
1826 printf("]\n");
1827 }
1828
stun_attr_add_integrity_str(turn_credential_type ct,uint8_t * buf,size_t * len,hmackey_t key,password_t pwd,SHATYPE shatype)1829 int stun_attr_add_integrity_str(turn_credential_type ct, uint8_t *buf, size_t *len, hmackey_t key, password_t pwd, SHATYPE shatype)
1830 {
1831 uint8_t hmac[MAXSHASIZE];
1832
1833 unsigned int shasize;
1834
1835 switch(shatype) {
1836 case SHATYPE_SHA256:
1837 shasize = SHA256SIZEBYTES;
1838 break;
1839 case SHATYPE_SHA384:
1840 shasize = SHA384SIZEBYTES;
1841 break;
1842 case SHATYPE_SHA512:
1843 shasize = SHA512SIZEBYTES;
1844 break;
1845 default:
1846 shasize = SHA1SIZEBYTES;
1847 };
1848
1849 if(stun_attr_add_str(buf, len, STUN_ATTRIBUTE_MESSAGE_INTEGRITY, hmac, shasize)<0)
1850 return -1;
1851
1852 if(ct == TURN_CREDENTIALS_SHORT_TERM) {
1853 if(stun_calculate_hmac(buf, *len-4-shasize, pwd, strlen((char*)pwd), buf+*len-shasize, &shasize, shatype)<0)
1854 return -1;
1855 } else {
1856 if(stun_calculate_hmac(buf, *len-4-shasize, key, get_hmackey_size(shatype), buf+*len-shasize, &shasize, shatype)<0)
1857 return -1;
1858 }
1859
1860 return 0;
1861 }
1862
stun_attr_add_integrity_by_key_str(uint8_t * buf,size_t * len,const uint8_t * uname,const uint8_t * realm,hmackey_t key,const uint8_t * nonce,SHATYPE shatype)1863 int stun_attr_add_integrity_by_key_str(uint8_t *buf, size_t *len, const uint8_t *uname, const uint8_t *realm, hmackey_t key, const uint8_t *nonce, SHATYPE shatype)
1864 {
1865 if(stun_attr_add_str(buf, len, STUN_ATTRIBUTE_USERNAME, uname, (int)strlen((const char*)uname))<0)
1866 return -1;
1867
1868 if(stun_attr_add_str(buf, len, STUN_ATTRIBUTE_NONCE, nonce, (int)strlen((const char*)nonce))<0)
1869 return -1;
1870
1871 if(stun_attr_add_str(buf, len, STUN_ATTRIBUTE_REALM, realm, (int)strlen((const char*)realm))<0)
1872 return -1;
1873
1874 password_t p;
1875 return stun_attr_add_integrity_str(TURN_CREDENTIALS_LONG_TERM, buf, len, key, p, shatype);
1876 }
1877
stun_attr_add_integrity_by_user_str(uint8_t * buf,size_t * len,const uint8_t * uname,const uint8_t * realm,const uint8_t * upwd,const uint8_t * nonce,SHATYPE shatype)1878 int stun_attr_add_integrity_by_user_str(uint8_t *buf, size_t *len, const uint8_t *uname, const uint8_t *realm, const uint8_t *upwd, const uint8_t *nonce, SHATYPE shatype)
1879 {
1880 hmackey_t key;
1881
1882 if(stun_produce_integrity_key_str(uname, realm, upwd, key, shatype)<0)
1883 return -1;
1884
1885 return stun_attr_add_integrity_by_key_str(buf, len, uname, realm, key, nonce, shatype);
1886 }
1887
stun_attr_add_integrity_by_user_short_term_str(uint8_t * buf,size_t * len,const uint8_t * uname,password_t pwd,SHATYPE shatype)1888 int stun_attr_add_integrity_by_user_short_term_str(uint8_t *buf, size_t *len, const uint8_t *uname, password_t pwd, SHATYPE shatype)
1889 {
1890 if(stun_attr_add_str(buf, len, STUN_ATTRIBUTE_USERNAME, uname, (int)strlen((const char*)uname))<0)
1891 return -1;
1892
1893 hmackey_t key;
1894 return stun_attr_add_integrity_str(TURN_CREDENTIALS_SHORT_TERM, buf, len, key, pwd, shatype);
1895 }
1896
print_hmac(const char * name,const void * s,size_t len)1897 void print_hmac(const char *name, const void *s, size_t len)
1898 {
1899 printf("%s:len=%d:[",name,(int)len);
1900 size_t i;
1901 for(i=0;i<len;i++) {
1902 printf("%02x",(int)((const uint8_t*)s)[i]);
1903 }
1904 printf("]\n");
1905 }
1906
1907 /*
1908 * Return -1 if failure, 0 if the integrity is not correct, 1 if OK
1909 */
stun_check_message_integrity_by_key_str(turn_credential_type ct,uint8_t * buf,size_t len,hmackey_t key,password_t pwd,SHATYPE shatype)1910 int stun_check_message_integrity_by_key_str(turn_credential_type ct, uint8_t *buf, size_t len, hmackey_t key, password_t pwd, SHATYPE shatype)
1911 {
1912 int res = 0;
1913 uint8_t new_hmac[MAXSHASIZE];
1914 unsigned int shasize;
1915 const uint8_t *old_hmac = NULL;
1916
1917 stun_attr_ref sar = stun_attr_get_first_by_type_str(buf, len, STUN_ATTRIBUTE_MESSAGE_INTEGRITY);
1918 if (!sar)
1919 return -1;
1920
1921 int sarlen = stun_attr_get_len(sar);
1922
1923 switch(sarlen) {
1924 case SHA256SIZEBYTES:
1925 shasize = SHA256SIZEBYTES;
1926 if(shatype != SHATYPE_SHA256)
1927 return -1;
1928 break;
1929 case SHA384SIZEBYTES:
1930 shasize = SHA384SIZEBYTES;
1931 if(shatype != SHATYPE_SHA384)
1932 return -1;
1933 break;
1934 case SHA512SIZEBYTES:
1935 shasize = SHA512SIZEBYTES;
1936 if(shatype != SHATYPE_SHA512)
1937 return -1;
1938 break;
1939 case SHA1SIZEBYTES:
1940 shasize = SHA1SIZEBYTES;
1941 if(shatype != SHATYPE_SHA1)
1942 return -1;
1943 break;
1944 default:
1945 return -1;
1946 };
1947
1948 int orig_len = stun_get_command_message_len_str(buf, len);
1949 if (orig_len < 0)
1950 return -1;
1951
1952 int new_len = (int)((const uint8_t*) sar - buf) + 4 + shasize;
1953 if (new_len > orig_len)
1954 return -1;
1955
1956 if (stun_set_command_message_len_str(buf, new_len) < 0)
1957 return -1;
1958
1959 if(ct == TURN_CREDENTIALS_SHORT_TERM) {
1960 res = stun_calculate_hmac(buf, (size_t) new_len - 4 - shasize, pwd, strlen((char*)pwd), new_hmac, &shasize, shatype);
1961 } else {
1962 res = stun_calculate_hmac(buf, (size_t) new_len - 4 - shasize, key, get_hmackey_size(shatype), new_hmac, &shasize, shatype);
1963 }
1964
1965 stun_set_command_message_len_str(buf, orig_len);
1966 if(res<0)
1967 return -1;
1968
1969 old_hmac = stun_attr_get_value(sar);
1970 if(!old_hmac)
1971 return -1;
1972
1973 if(bcmp(old_hmac,new_hmac,shasize))
1974 return 0;
1975
1976 return +1;
1977 }
1978
1979 /*
1980 * Return -1 if failure, 0 if the integrity is not correct, 1 if OK
1981 */
stun_check_message_integrity_str(turn_credential_type ct,uint8_t * buf,size_t len,const uint8_t * uname,const uint8_t * realm,const uint8_t * upwd,SHATYPE shatype)1982 int stun_check_message_integrity_str(turn_credential_type ct, uint8_t *buf, size_t len, const uint8_t *uname, const uint8_t *realm, const uint8_t *upwd, SHATYPE shatype)
1983 {
1984 hmackey_t key;
1985 password_t pwd;
1986
1987 if(ct == TURN_CREDENTIALS_SHORT_TERM)
1988 strncpy((char*)pwd,(const char*)upwd,sizeof(password_t));
1989 else if (stun_produce_integrity_key_str(uname, realm, upwd, key, shatype) < 0)
1990 return -1;
1991
1992 return stun_check_message_integrity_by_key_str(ct, buf, len, key, pwd, shatype);
1993 }
1994
1995 /* RFC 5780 */
1996
stun_attr_get_change_request_str(stun_attr_ref attr,int * change_ip,int * change_port)1997 int stun_attr_get_change_request_str(stun_attr_ref attr, int *change_ip, int *change_port)
1998 {
1999 if(stun_attr_get_len(attr) == 4) {
2000 const uint8_t* value = stun_attr_get_value(attr);
2001 if(value) {
2002 *change_ip = (value[3] & (uint8_t)0x04);
2003 *change_port = (value[3] & (uint8_t)0x02);
2004 return 0;
2005 }
2006 }
2007 return -1;
2008 }
2009
stun_attr_add_change_request_str(uint8_t * buf,size_t * len,int change_ip,int change_port)2010 int stun_attr_add_change_request_str(uint8_t *buf, size_t *len, int change_ip, int change_port)
2011 {
2012 uint8_t avalue[4]={0,0,0,0};
2013
2014 if(change_ip) {
2015 if(change_port) {
2016 avalue[3] = 0x06;
2017 } else {
2018 avalue[3] = 0x04;
2019 }
2020 } else if(change_port) {
2021 avalue[3]=0x02;
2022 }
2023
2024 return stun_attr_add_str(buf, len, STUN_ATTRIBUTE_CHANGE_REQUEST, avalue, 4);
2025 }
2026
stun_attr_get_response_port_str(stun_attr_ref attr)2027 int stun_attr_get_response_port_str(stun_attr_ref attr)
2028 {
2029 if(stun_attr_get_len(attr) >= 2) {
2030 const uint8_t* value = stun_attr_get_value(attr);
2031 if(value) {
2032 return nswap16(((const uint16_t*)value)[0]);
2033 }
2034 }
2035 return -1;
2036 }
2037
stun_attr_add_response_port_str(uint8_t * buf,size_t * len,uint16_t port)2038 int stun_attr_add_response_port_str(uint8_t *buf, size_t *len, uint16_t port)
2039 {
2040 uint8_t avalue[4]={0,0,0,0};
2041 uint16_t *port_ptr = (uint16_t*)avalue;
2042
2043 *port_ptr = nswap16(port);
2044
2045 return stun_attr_add_str(buf, len, STUN_ATTRIBUTE_RESPONSE_PORT, avalue, 4);
2046 }
2047
stun_attr_get_padding_len_str(stun_attr_ref attr)2048 int stun_attr_get_padding_len_str(stun_attr_ref attr) {
2049 int len = stun_attr_get_len(attr);
2050 if(len<0)
2051 return -1;
2052 return (uint16_t)len;
2053 }
2054
stun_attr_add_padding_str(uint8_t * buf,size_t * len,uint16_t padding_len)2055 int stun_attr_add_padding_str(uint8_t *buf, size_t *len, uint16_t padding_len)
2056 {
2057 uint8_t avalue[0xFFFF];
2058 bzero(avalue,padding_len);
2059
2060 return stun_attr_add_str(buf, len, STUN_ATTRIBUTE_PADDING, avalue, padding_len);
2061 }
2062
2063 /* OAUTH */
2064
2065 #define OAUTH_ERROR(...) fprintf(stderr,__VA_ARGS__)
2066
remove_spaces(char * s)2067 static void remove_spaces(char *s)
2068 {
2069 char *sfns = s;
2070 while(*sfns) {
2071 if(*sfns != ' ')
2072 break;
2073 ++sfns;
2074 }
2075 if(*sfns) {
2076 if(sfns != s) {
2077 while(*sfns && (*sfns != ' ')) {
2078 *s = *sfns;
2079 ++s;
2080 ++sfns;
2081 };
2082 *s = 0;
2083 } else {
2084 while(*s) {
2085 if(*s == ' ') {
2086 *s = 0;
2087 break;
2088 }
2089 ++s;
2090 }
2091 }
2092 }
2093 }
2094
normalize_algorithm(char * s)2095 static void normalize_algorithm(char *s)
2096 {
2097 char c = *s;
2098 while(c) {
2099 if(c=='_') *s='-';
2100 else if((c>='a')&&(c<='z')) {
2101 *s = c - 'a' + 'A';
2102 }
2103 ++s;
2104 c = *s;
2105 }
2106 }
2107
2108 size_t calculate_enc_key_length(ENC_ALG a);
calculate_enc_key_length(ENC_ALG a)2109 size_t calculate_enc_key_length(ENC_ALG a)
2110 {
2111 switch(a) {
2112 #if !defined(TURN_NO_GCM)
2113 case A128GCM:
2114 return 16;
2115 #endif
2116 default:
2117 break;
2118 };
2119
2120 return 32;
2121 }
2122
2123 size_t calculate_auth_key_length(ENC_ALG a);
calculate_auth_key_length(ENC_ALG a)2124 size_t calculate_auth_key_length(ENC_ALG a)
2125 {
2126 switch(a) {
2127 #if !defined(TURN_NO_GCM)
2128 case A256GCM:
2129 case A128GCM:
2130 return 0;
2131 #endif
2132 default:
2133 break;
2134 };
2135
2136 return 0;
2137 }
2138
2139 int calculate_key(char *key, size_t key_size,
2140 char *new_key, size_t new_key_size);
calculate_key(char * key,size_t key_size,char * new_key,size_t new_key_size)2141 int calculate_key(char *key, size_t key_size,
2142 char *new_key, size_t new_key_size)
2143 {
2144 UNUSED_ARG(key_size);
2145
2146 bcopy(key,new_key,new_key_size);
2147
2148 return 0;
2149 }
2150
convert_oauth_key_data(const oauth_key_data * oakd0,oauth_key * key,char * err_msg,size_t err_msg_size)2151 int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *err_msg, size_t err_msg_size)
2152 {
2153 if(oakd0 && key) {
2154
2155 oauth_key_data oakd_obj;
2156 bcopy(oakd0,&oakd_obj,sizeof(oauth_key_data));
2157 oauth_key_data *oakd = &oakd_obj;
2158
2159 if(!(oakd->ikm_key_size)) {
2160 if(err_msg) {
2161 snprintf(err_msg,err_msg_size,"key is not defined");
2162 }
2163 }
2164
2165 remove_spaces(oakd->kid);
2166
2167 remove_spaces(oakd->as_rs_alg);
2168
2169 normalize_algorithm(oakd->as_rs_alg);
2170
2171 if(!(oakd->kid[0])) {
2172 if(err_msg) {
2173 snprintf(err_msg,err_msg_size,"KID is not defined");
2174 }
2175 OAUTH_ERROR("KID is not defined\n");
2176 return -1;
2177 }
2178
2179 bzero(key,sizeof(oauth_key));
2180
2181 STRCPY(key->kid,oakd->kid);
2182
2183 bcopy(oakd->ikm_key,key->ikm_key,sizeof(key->ikm_key));
2184 key->ikm_key_size = oakd->ikm_key_size;
2185
2186 key->timestamp = oakd->timestamp;
2187 key->lifetime = oakd->lifetime;
2188
2189 if(!(key->timestamp)) key->timestamp = OAUTH_DEFAULT_TIMESTAMP;
2190 if(!(key->lifetime)) key->lifetime = OAUTH_DEFAULT_LIFETIME;
2191
2192 key->as_rs_alg = ENC_ALG_ERROR;
2193 #if !defined(TURN_NO_GCM)
2194 key->as_rs_alg = ENC_ALG_DEFAULT;
2195 if(!strcmp(oakd->as_rs_alg,"A128GCM")) {
2196 key->as_rs_alg = A128GCM;
2197 key->auth_key_size = 0;
2198 key->auth_key[0] = 0;
2199 } else if(!strcmp(oakd->as_rs_alg,"A256GCM")) {
2200 key->as_rs_alg = A256GCM;
2201 key->auth_key_size = 0;
2202 key->auth_key[0] = 0;
2203 } else
2204 #endif
2205 {
2206 if(err_msg) {
2207 snprintf(err_msg,err_msg_size,"Wrong oAuth token encryption algorithm: %s (2)\n",oakd->as_rs_alg);
2208 }
2209 OAUTH_ERROR("Wrong oAuth token encryption algorithm: %s (3)\n",oakd->as_rs_alg);
2210 return -1;
2211 }
2212
2213 #if !defined(TURN_NO_GCM)
2214
2215 key->auth_key_size = calculate_auth_key_length(key->as_rs_alg);
2216 if(key->auth_key_size) {
2217 if(calculate_key(key->ikm_key,key->ikm_key_size,key->auth_key,key->auth_key_size)<0) {
2218 return -1;
2219 }
2220 }
2221
2222 key->as_rs_key_size = calculate_enc_key_length(key->as_rs_alg);
2223 if(calculate_key(key->ikm_key,key->ikm_key_size,key->as_rs_key,key->as_rs_key_size)<0) {
2224 return -1;
2225 }
2226 #endif
2227 }
2228
2229 return 0;
2230 }
2231
2232 const EVP_CIPHER *get_cipher_type(ENC_ALG enc_alg);
get_cipher_type(ENC_ALG enc_alg)2233 const EVP_CIPHER *get_cipher_type(ENC_ALG enc_alg)
2234 {
2235 switch(enc_alg) {
2236 #if !defined(TURN_NO_GCM)
2237 case A128GCM:
2238 return EVP_aes_128_gcm();
2239 case A256GCM:
2240 return EVP_aes_256_gcm();
2241 #endif
2242 default:
2243 break;
2244 }
2245 OAUTH_ERROR("%s: Unsupported enc algorithm: %d\n",__FUNCTION__,(int)enc_alg);
2246 return NULL;
2247 }
2248
2249 int my_EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
2250 int *outl, const unsigned char *in, int inl);
my_EVP_EncryptUpdate(EVP_CIPHER_CTX * ctx,unsigned char * out,int * outl,const unsigned char * in,int inl)2251 int my_EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
2252 int *outl, const unsigned char *in, int inl)
2253 {
2254 int cycle = 0;
2255 int out_len = 0;
2256 while((out_len<inl)&&(++cycle<128)) {
2257 int tmp_outl=0;
2258 unsigned char *ptr = NULL;
2259 if(out)
2260 ptr = out+out_len;
2261 int ret = EVP_EncryptUpdate(ctx, ptr, &tmp_outl, in+out_len, inl-out_len);
2262 out_len += tmp_outl;
2263 if(ret<1)
2264 return ret;
2265 }
2266 *outl = out_len;
2267 return 1;
2268 }
2269
2270 int my_EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
2271 int *outl, const unsigned char *in, int inl);
my_EVP_DecryptUpdate(EVP_CIPHER_CTX * ctx,unsigned char * out,int * outl,const unsigned char * in,int inl)2272 int my_EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
2273 int *outl, const unsigned char *in, int inl)
2274 {
2275 int cycle = 0;
2276 int out_len = 0;
2277 while((out_len<inl)&&(++cycle<128)) {
2278 int tmp_outl=0;
2279 unsigned char *ptr = NULL;
2280 if(out)
2281 ptr = out+out_len;
2282 int ret = EVP_DecryptUpdate(ctx, ptr, &tmp_outl, in+out_len, inl-out_len);
2283 out_len += tmp_outl;
2284 if(ret<1)
2285 return ret;
2286 }
2287 *outl = out_len;
2288 return 1;
2289 }
2290
2291 void print_field(const char* name, const unsigned char* f, size_t len);
print_field(const char * name,const unsigned char * f,size_t len)2292 void print_field(const char* name, const unsigned char* f, size_t len) {
2293 printf("\nfield %s==>>\n",name);
2294 size_t i;
2295 for(i = 0;i<len;++i) {
2296 printf("<0x%x>",(unsigned int)f[i]);
2297 }
2298 printf("\n<<==field %s\n",name);
2299 }
2300
2301 int encode_oauth_token_normal(const uint8_t *server_name, encoded_oauth_token *etoken, const oauth_key *key, const oauth_token *dtoken);
encode_oauth_token_normal(const uint8_t * server_name,encoded_oauth_token * etoken,const oauth_key * key,const oauth_token * dtoken)2302 int encode_oauth_token_normal(const uint8_t *server_name, encoded_oauth_token *etoken, const oauth_key *key, const oauth_token *dtoken)
2303 {
2304 UNUSED_ARG(server_name);
2305 UNUSED_ARG(etoken);
2306 UNUSED_ARG(key);
2307 UNUSED_ARG(dtoken);
2308
2309 /*
2310 if(server_name && etoken && key && dtoken && (dtoken->enc_block.key_length<=128)) {
2311
2312 unsigned char orig_field[MAX_ENCODED_OAUTH_TOKEN_SIZE];
2313 bzero(orig_field,sizeof(orig_field));
2314
2315 size_t len = 0;
2316 *((uint16_t*)(orig_field+len)) = nswap16(dtoken->enc_block.key_length);
2317 len +=2;
2318
2319 bcopy(dtoken->enc_block.mac_key,orig_field+len,dtoken->enc_block.key_length);
2320 len += dtoken->enc_block.key_length;
2321
2322 *((uint64_t*)(orig_field+len)) = nswap64(dtoken->enc_block.timestamp);
2323 len += 8;
2324
2325 *((uint32_t*)(orig_field+len)) = nswap32(dtoken->enc_block.lifetime);
2326 len += 4;
2327
2328 const EVP_CIPHER * cipher = get_cipher_type(key->as_rs_alg);
2329 if(!cipher)
2330 return -1;
2331
2332 unsigned char *encoded_field = (unsigned char*)etoken->token;
2333
2334 EVP_CIPHER_CTX ctx;
2335 EVP_CIPHER_CTX_init(&ctx);
2336 EVP_EncryptInit_ex(&ctx, cipher, NULL, (const unsigned char *)key->as_rs_key, NULL);
2337 EVP_CIPHER_CTX_set_padding(&ctx,1);
2338 int outl=0;
2339 my_EVP_EncryptUpdate(&ctx, encoded_field, &outl, orig_field, (int)len);
2340 if(outl % OAUTH_ENC_ALG_BLOCK_SIZE) {
2341 int tmp_outl = 0;
2342 EVP_EncryptFinal_ex(&ctx, encoded_field + outl, &tmp_outl);
2343 outl += tmp_outl;
2344 }
2345
2346 EVP_CIPHER_CTX_cleanup(&ctx);
2347
2348 size_t sn_len = strlen((const char*)server_name);
2349 bcopy(server_name,encoded_field+outl,sn_len);
2350 outl += sn_len;
2351
2352 const EVP_MD *md = get_auth_type(key->auth_alg);
2353 if(!md)
2354 return -1;
2355
2356 unsigned int hmac_len = EVP_MD_size(md);
2357 if (!HMAC(md, key->auth_key, key->auth_key_size, encoded_field, outl, encoded_field + outl, &hmac_len)) {
2358 return -1;
2359 }
2360
2361 update_hmac_len(key->auth_alg, &hmac_len);
2362
2363 bcopy(encoded_field + outl, encoded_field + outl - sn_len, hmac_len);
2364 outl -= sn_len;
2365 outl += hmac_len; //encoded+hmac
2366
2367 etoken->size = outl;
2368
2369 return 0;
2370 }
2371 */
2372 return -1;
2373 }
2374
2375 int decode_oauth_token_normal(const uint8_t *server_name, const encoded_oauth_token *etoken, const oauth_key *key, oauth_token *dtoken);
decode_oauth_token_normal(const uint8_t * server_name,const encoded_oauth_token * etoken,const oauth_key * key,oauth_token * dtoken)2376 int decode_oauth_token_normal(const uint8_t *server_name, const encoded_oauth_token *etoken, const oauth_key *key, oauth_token *dtoken)
2377 {
2378 UNUSED_ARG(server_name);
2379 UNUSED_ARG(etoken);
2380 UNUSED_ARG(key);
2381 UNUSED_ARG(dtoken);
2382
2383 /*
2384 if(server_name && etoken && key && dtoken) {
2385
2386 size_t mac_size = calculate_auth_output_length(key->auth_alg);
2387 size_t min_encoded_field_size = 2+4+8+1;
2388 if(etoken->size < mac_size+min_encoded_field_size) {
2389 OAUTH_ERROR("%s: token size too small: %d, mac_size=%d, min_encoded_field_size=%d\n",__FUNCTION__,(int)etoken->size,(int)mac_size,(int)min_encoded_field_size);
2390 return -1;
2391 }
2392
2393 const unsigned char* encoded_field = (const unsigned char*)etoken->token;
2394 unsigned int encoded_field_size = (unsigned int)etoken->size-mac_size;
2395 const unsigned char* mac = ((const unsigned char*)etoken->token) + etoken->size - mac_size;
2396
2397 {
2398 const EVP_MD *md = get_auth_type(key->auth_alg);
2399 if(!md)
2400 return -1;
2401 unsigned int hmac_len = EVP_MD_size(md);
2402 update_hmac_len(key->auth_alg,&hmac_len);
2403 if(hmac_len != mac_size) {
2404 OAUTH_ERROR("%s: mac size is wrong: %d, must be %d\n",__FUNCTION__,(int)mac_size,(int)hmac_len);
2405 return -1;
2406 }
2407 unsigned char efield[MAX_ENCODED_OAUTH_TOKEN_SIZE];
2408 unsigned char check_mac[MAXSHASIZE];
2409 bcopy(encoded_field,efield,encoded_field_size);
2410 size_t sn_len = strlen((const char*)server_name);
2411 bcopy(server_name,efield+encoded_field_size,sn_len);
2412 if (!HMAC(md, key->auth_key, key->auth_key_size, efield, encoded_field_size+sn_len, check_mac, &hmac_len)) {
2413 return -1;
2414 }
2415
2416 if(bcmp(check_mac,mac,mac_size)) {
2417 OAUTH_ERROR("%s: token integrity check failed\n",__FUNCTION__);
2418 return -1;
2419 }
2420 }
2421
2422 unsigned char decoded_field[MAX_ENCODED_OAUTH_TOKEN_SIZE];
2423
2424 const EVP_CIPHER * cipher = get_cipher_type(key->as_rs_alg);
2425 if(!cipher)
2426 return -1;
2427
2428 EVP_CIPHER_CTX ctx;
2429 EVP_CIPHER_CTX_init(&ctx);
2430 EVP_DecryptInit_ex(&ctx, cipher, NULL, (const unsigned char *)key->as_rs_key, NULL);
2431 EVP_CIPHER_CTX_set_padding(&ctx,1);
2432 int outl=0;
2433 my_EVP_DecryptUpdate(&ctx, decoded_field, &outl, encoded_field, (int)encoded_field_size);
2434
2435 int tmp_outl = 0;
2436 EVP_DecryptFinal_ex(&ctx, decoded_field + outl, &tmp_outl);
2437 outl += tmp_outl;
2438
2439 EVP_CIPHER_CTX_cleanup(&ctx);
2440
2441 size_t len = 0;
2442
2443 dtoken->enc_block.key_length = nswap16(*((uint16_t*)(decoded_field+len)));
2444 len += 2;
2445
2446 bcopy(decoded_field+len,dtoken->enc_block.mac_key,dtoken->enc_block.key_length);
2447 len += dtoken->enc_block.key_length;
2448
2449 dtoken->enc_block.timestamp = nswap64(*((uint64_t*)(decoded_field+len)));
2450 len += 8;
2451
2452 dtoken->enc_block.lifetime = nswap32(*((uint32_t*)(decoded_field+len)));
2453 len += 4;
2454
2455 return 0;
2456 }
2457 */
2458 return -1;
2459 }
2460
generate_random_nonce(unsigned char * nonce,size_t sz)2461 static void generate_random_nonce(unsigned char *nonce, size_t sz) {
2462 if(!RAND_bytes(nonce, (int)sz)) {
2463 size_t i;
2464 for(i=0;i<sz;++i) {
2465 nonce[i] = (unsigned char)random();
2466 }
2467 }
2468 }
2469
2470 #if !defined(TURN_NO_GCM)
2471
encode_oauth_token_gcm(const uint8_t * server_name,encoded_oauth_token * etoken,const oauth_key * key,const oauth_token * dtoken,const uint8_t * nonce0)2472 static int encode_oauth_token_gcm(const uint8_t *server_name, encoded_oauth_token *etoken, const oauth_key *key, const oauth_token *dtoken, const uint8_t* nonce0) {
2473 if(server_name && etoken && key && dtoken && (dtoken->enc_block.key_length<=MAXSHASIZE)) {
2474
2475 unsigned char orig_field[MAX_ENCODED_OAUTH_TOKEN_SIZE];
2476 bzero(orig_field,sizeof(orig_field));
2477
2478 unsigned char nonce[OAUTH_GCM_NONCE_SIZE];
2479 if(nonce0) {
2480 bcopy(nonce0,nonce,sizeof(nonce));
2481 } else {
2482 generate_random_nonce(nonce, sizeof(nonce));
2483 }
2484
2485 size_t len = 0;
2486
2487 *((uint16_t*)(orig_field+len)) = nswap16(OAUTH_GCM_NONCE_SIZE);
2488 len +=2;
2489
2490 bcopy(nonce,orig_field+len,OAUTH_GCM_NONCE_SIZE);
2491 len += OAUTH_GCM_NONCE_SIZE;
2492
2493 *((uint16_t*)(orig_field+len)) = nswap16(dtoken->enc_block.key_length);
2494 len +=2;
2495
2496 bcopy(dtoken->enc_block.mac_key,orig_field+len,dtoken->enc_block.key_length);
2497 len += dtoken->enc_block.key_length;
2498
2499 uint64_t ts = nswap64(dtoken->enc_block.timestamp);
2500 bcopy( &ts, (orig_field+len), sizeof(ts));
2501 len += sizeof(ts);
2502
2503 *((uint32_t*)(orig_field+len)) = nswap32(dtoken->enc_block.lifetime);
2504 len += 4;
2505
2506 const EVP_CIPHER * cipher = get_cipher_type(key->as_rs_alg);
2507 if(!cipher)
2508 return -1;
2509
2510 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2511 EVP_CIPHER_CTX ctx;
2512 EVP_CIPHER_CTX *ctxp = &ctx;
2513 #else
2514 EVP_CIPHER_CTX *ctxp = EVP_CIPHER_CTX_new();
2515 #endif
2516 EVP_CIPHER_CTX_init(ctxp);
2517
2518 /* Initialize the encryption operation. */
2519 if(1 != EVP_EncryptInit_ex(ctxp, cipher, NULL, NULL, NULL))
2520 return -1;
2521
2522 EVP_CIPHER_CTX_set_padding(ctxp,1);
2523
2524 /* Set IV length if default 12 bytes (96 bits) is not appropriate */
2525 if(1 != EVP_CIPHER_CTX_ctrl(ctxp, EVP_CTRL_GCM_SET_IVLEN, OAUTH_GCM_NONCE_SIZE, NULL))
2526 return -1;
2527
2528 /* Initialize key and IV */
2529 if(1 != EVP_EncryptInit_ex(ctxp, NULL, NULL, (const unsigned char *)key->as_rs_key, nonce))
2530 return -1;
2531
2532 int outl=0;
2533 size_t sn_len = strlen((const char*)server_name);
2534
2535 /* Provide any AAD data. This can be called zero or more times as
2536 * required
2537 */
2538 if(1 != my_EVP_EncryptUpdate(ctxp, NULL, &outl, server_name, (int)sn_len))
2539 return -1;
2540
2541 outl=0;
2542 unsigned char *encoded_field = (unsigned char*)etoken->token;
2543 bcopy(orig_field,encoded_field,OAUTH_GCM_NONCE_SIZE + 2);
2544 encoded_field += OAUTH_GCM_NONCE_SIZE + 2;
2545 unsigned char *start_field = orig_field + OAUTH_GCM_NONCE_SIZE + 2;
2546 len -= OAUTH_GCM_NONCE_SIZE + 2;
2547
2548 if(1 != my_EVP_EncryptUpdate(ctxp, encoded_field, &outl, start_field, (int)len))
2549 return -1;
2550
2551 int tmp_outl = 0;
2552 EVP_EncryptFinal_ex(ctxp, encoded_field + outl, &tmp_outl);
2553 outl += tmp_outl;
2554
2555 EVP_CIPHER_CTX_ctrl(ctxp, EVP_CTRL_GCM_GET_TAG, OAUTH_GCM_TAG_SIZE, encoded_field + outl);
2556 outl += OAUTH_GCM_TAG_SIZE;
2557
2558 etoken->size = 2 + OAUTH_GCM_NONCE_SIZE + outl;
2559
2560 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2561 EVP_CIPHER_CTX_cleanup(ctxp);
2562 #else
2563 EVP_CIPHER_CTX_free(ctxp);
2564 #endif
2565
2566 return 0;
2567 }
2568 return -1;
2569 }
2570
decode_oauth_token_gcm(const uint8_t * server_name,const encoded_oauth_token * etoken,const oauth_key * key,oauth_token * dtoken)2571 static int decode_oauth_token_gcm(const uint8_t *server_name, const encoded_oauth_token *etoken, const oauth_key *key, oauth_token *dtoken)
2572 {
2573 if(server_name && etoken && key && dtoken) {
2574
2575 unsigned char snl[2];
2576 bcopy((const unsigned char*)(etoken->token),snl,2);
2577 const unsigned char *csnl = snl;
2578
2579 uint16_t nonce_len = nswap16(*((const uint16_t*)csnl));
2580 dtoken->enc_block.nonce_length = nonce_len;
2581
2582 size_t min_encoded_field_size = 2+4+8+nonce_len+2+OAUTH_GCM_TAG_SIZE+1;
2583 if(etoken->size < min_encoded_field_size) {
2584 OAUTH_ERROR("%s: token size too small: %d\n",__FUNCTION__,(int)etoken->size);
2585 return -1;
2586 }
2587
2588 const unsigned char* encoded_field = (const unsigned char*)(etoken->token + nonce_len + 2);
2589 unsigned int encoded_field_size = (unsigned int)etoken->size - nonce_len - 2 - OAUTH_GCM_TAG_SIZE;
2590 const unsigned char* nonce = ((const unsigned char*)etoken->token + 2);
2591 bcopy(nonce,dtoken->enc_block.nonce,nonce_len);
2592
2593 unsigned char tag[OAUTH_GCM_TAG_SIZE];
2594 bcopy(((const unsigned char*)etoken->token) + nonce_len + 2 + encoded_field_size, tag ,sizeof(tag));
2595
2596 unsigned char decoded_field[MAX_ENCODED_OAUTH_TOKEN_SIZE];
2597
2598 const EVP_CIPHER * cipher = get_cipher_type(key->as_rs_alg);
2599 if(!cipher) {
2600 OAUTH_ERROR("%s: Cannot find cipher for algorithm: %d\n",__FUNCTION__,(int)key->as_rs_alg);
2601 return -1;
2602 }
2603
2604 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2605 EVP_CIPHER_CTX ctx;
2606 EVP_CIPHER_CTX *ctxp = &ctx;
2607 #else
2608 EVP_CIPHER_CTX *ctxp = EVP_CIPHER_CTX_new();
2609 #endif
2610 EVP_CIPHER_CTX_init(ctxp);
2611 /* Initialize the decryption operation. */
2612 if(1 != EVP_DecryptInit_ex(ctxp, cipher, NULL, NULL, NULL)) {
2613 OAUTH_ERROR("%s: Cannot initialize decryption\n",__FUNCTION__);
2614 return -1;
2615 }
2616
2617 //EVP_CIPHER_CTX_set_padding(&ctx,1);
2618
2619 /* Set IV length if default 12 bytes (96 bits) is not appropriate */
2620 if(1 != EVP_CIPHER_CTX_ctrl(ctxp, EVP_CTRL_GCM_SET_IVLEN, nonce_len, NULL)) {
2621 OAUTH_ERROR("%s: Cannot set nonce length\n",__FUNCTION__);
2622 return -1;
2623 }
2624
2625 /* Initialize key and IV */
2626 if(1 != EVP_DecryptInit_ex(ctxp, NULL, NULL, (const unsigned char *)key->as_rs_key, nonce)) {
2627 OAUTH_ERROR("%s: Cannot set nonce\n",__FUNCTION__);
2628 return -1;
2629 }
2630
2631 /* Set expected tag value. A restriction in OpenSSL 1.0.1c and earlier
2632 + * required the tag before any AAD or ciphertext */
2633 EVP_CIPHER_CTX_ctrl (ctxp, EVP_CTRL_GCM_SET_TAG, OAUTH_GCM_TAG_SIZE, tag);
2634
2635 int outl=0;
2636 size_t sn_len = strlen((const char*)server_name);
2637
2638 /* Provide any AAD data. This can be called zero or more times as
2639 * required
2640 */
2641 if(1 != my_EVP_DecryptUpdate(ctxp, NULL, &outl, server_name, (int)sn_len)) {
2642 OAUTH_ERROR("%s: Cannot decrypt update server_name: %s, len=%d\n",__FUNCTION__,server_name,(int)sn_len);
2643 return -1;
2644 }
2645 if(1 != my_EVP_DecryptUpdate(ctxp, decoded_field, &outl, encoded_field, (int)encoded_field_size)) {
2646 OAUTH_ERROR("%s: Cannot decrypt update\n",__FUNCTION__);
2647 return -1;
2648 }
2649
2650 int tmp_outl = 0;
2651 if(EVP_DecryptFinal_ex(ctxp, decoded_field + outl, &tmp_outl)<1) {
2652 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2653 EVP_CIPHER_CTX_cleanup(ctxp);
2654 #else
2655 EVP_CIPHER_CTX_free(ctxp);
2656 #endif
2657 OAUTH_ERROR("%s: token integrity check failed\n",__FUNCTION__);
2658 return -1;
2659 }
2660 outl += tmp_outl;
2661
2662 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2663 EVP_CIPHER_CTX_cleanup(ctxp);
2664 #else
2665 EVP_CIPHER_CTX_free(ctxp);
2666 #endif
2667
2668 size_t len = 0;
2669
2670 dtoken->enc_block.key_length = nswap16(*((uint16_t*)(decoded_field+len)));
2671 len += 2;
2672
2673 bcopy(decoded_field+len,dtoken->enc_block.mac_key,dtoken->enc_block.key_length);
2674 len += dtoken->enc_block.key_length;
2675
2676 uint64_t ts;
2677 bcopy((decoded_field+len),&ts,sizeof(ts));
2678 dtoken->enc_block.timestamp = nswap64(ts);
2679 len += sizeof(ts);
2680
2681 uint32_t lt;
2682 bcopy((decoded_field+len),<,sizeof(lt));
2683 dtoken->enc_block.lifetime = nswap32(lt);
2684 len += sizeof(lt);
2685
2686 return 0;
2687 }
2688 return -1;
2689 }
2690
2691 #endif
2692
encode_oauth_token(const uint8_t * server_name,encoded_oauth_token * etoken,const oauth_key * key,const oauth_token * dtoken,const uint8_t * nonce)2693 int encode_oauth_token(const uint8_t *server_name, encoded_oauth_token *etoken, const oauth_key *key, const oauth_token *dtoken, const uint8_t *nonce)
2694 {
2695 UNUSED_ARG(nonce);
2696 if(server_name && etoken && key && dtoken) {
2697 switch(key->as_rs_alg) {
2698 #if !defined(TURN_NO_GCM)
2699 case A256GCM:
2700 case A128GCM:
2701 return encode_oauth_token_gcm(server_name, etoken,key,dtoken,nonce);
2702 #endif
2703 default:
2704 fprintf(stderr,"Unsupported AS_RS algorithm: %d\n",(int)key->as_rs_alg);
2705 break;
2706 };
2707 }
2708 return -1;
2709 }
2710
decode_oauth_token(const uint8_t * server_name,const encoded_oauth_token * etoken,const oauth_key * key,oauth_token * dtoken)2711 int decode_oauth_token(const uint8_t *server_name, const encoded_oauth_token *etoken, const oauth_key *key, oauth_token *dtoken)
2712 {
2713 if(server_name && etoken && key && dtoken) {
2714 switch(key->as_rs_alg) {
2715 #if !defined(TURN_NO_GCM)
2716 case A256GCM:
2717 case A128GCM:
2718 return decode_oauth_token_gcm(server_name, etoken,key,dtoken);
2719 #endif
2720 default:
2721 fprintf(stderr,"Unsupported AS_RS algorithm: %d\n",(int)key->as_rs_alg);
2722 break;
2723 };
2724 }
2725 return -1;
2726 }
2727
2728 ///////////////////////////////////////////////////////////////
2729