Coverage Report

Created: 2025-08-03 07:00

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