Coverage Report

Created: 2025-03-06 06:58

/src/gnutls/lib/str.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2002-2012 Free Software Foundation, Inc.
3
 * Copyright (C) 2016-2017 Red Hat, Inc.
4
 *
5
 * Author: Nikos Mavrogiannopoulos
6
 *
7
 * This file is part of GnuTLS.
8
 *
9
 * The GnuTLS is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public License
11
 * as published by the Free Software Foundation; either version 2.1 of
12
 * the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful, but
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
21
 *
22
 */
23
24
#include "gnutls_int.h"
25
#include "errors.h"
26
#include "num.h"
27
#include "str.h"
28
#include <stdarg.h>
29
#include <c-ctype.h>
30
#include <intprops.h>
31
#include <nettle/base64.h>
32
#include "extras/hex.h"
33
34
/* These functions are like strcat, strcpy. They only
35
 * do bound checking (they shouldn't cause buffer overruns),
36
 * and they always produce null terminated strings.
37
 *
38
 * They should be used only with null terminated strings.
39
 */
40
void _gnutls_str_cat(char *dest, size_t dest_tot_size, const char *src)
41
0
{
42
0
  size_t str_size = strlen(src);
43
0
  size_t dest_size = strlen(dest);
44
45
0
  if (dest_tot_size - dest_size > str_size) {
46
0
    strcat(dest, src);
47
0
  } else {
48
0
    if (dest_tot_size - dest_size > 0) {
49
0
      strncat(dest, src, (dest_tot_size - dest_size) - 1);
50
0
      dest[dest_tot_size - 1] = 0;
51
0
    }
52
0
  }
53
0
}
54
55
void _gnutls_str_cpy(char *dest, size_t dest_tot_size, const char *src)
56
0
{
57
0
  size_t str_size = strlen(src);
58
59
0
  if (dest_tot_size > str_size) {
60
0
    strcpy(dest, src);
61
0
  } else {
62
0
    if (dest_tot_size > 0) {
63
0
      memcpy(dest, src, (dest_tot_size)-1);
64
0
      dest[dest_tot_size - 1] = 0;
65
0
    }
66
0
  }
67
0
}
68
69
void _gnutls_buffer_init(gnutls_buffer_st *str)
70
0
{
71
0
  str->data = str->allocd = NULL;
72
0
  str->max_length = 0;
73
0
  str->length = 0;
74
0
}
75
76
void _gnutls_buffer_clear(gnutls_buffer_st *str)
77
0
{
78
0
  if (str == NULL || str->allocd == NULL)
79
0
    return;
80
0
  gnutls_free(str->allocd);
81
82
0
  str->data = NULL;
83
0
  str->max_length = 0;
84
0
  str->length = 0;
85
0
}
86
87
#define MIN_CHUNK 1024
88
89
/**
90
 * gnutls_buffer_append_data:
91
 * @dest: the buffer to append to
92
 * @data: the data
93
 * @data_size: the size of @data
94
 *
95
 * Appends the provided @data to the destination buffer.
96
 *
97
 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
98
 *
99
 * Since: 3.4.0
100
 **/
101
int gnutls_buffer_append_data(gnutls_buffer_t dest, const void *data,
102
            size_t data_size)
103
0
{
104
0
  size_t const tot_len = data_size + dest->length;
105
0
  int ret;
106
107
0
  if (unlikely(dest->data != NULL && dest->allocd == NULL))
108
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
109
110
0
  if (data_size == 0)
111
0
    return 0;
112
113
0
  if (unlikely(sizeof(size_t) == 4 &&
114
0
         INT_ADD_OVERFLOW(((ssize_t)MAX(data_size, MIN_CHUNK)),
115
0
              ((ssize_t)dest->length)))) {
116
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
117
0
  }
118
119
0
  ret = _gnutls_buffer_resize(dest, tot_len);
120
0
  if (ret < 0) {
121
0
    return ret;
122
0
  }
123
0
  assert(dest->data != NULL);
124
125
0
  memcpy(&dest->data[dest->length], data, data_size);
126
0
  dest->length = tot_len;
127
128
0
  return 0;
129
0
}
130
131
#ifdef AGGRESSIVE_REALLOC
132
133
/* Use a simpler logic for reallocation; i.e., always call
134
 * gnutls_realloc_fast() and do not reclaim the no-longer-used
135
 * area which has been removed from the beginning of buffer
136
 * with _gnutls_buffer_pop_datum().  This helps hit more
137
 * issues when running under valgrind.
138
 */
139
int _gnutls_buffer_resize(gnutls_buffer_st *dest, size_t new_size)
140
{
141
  size_t unused;
142
143
  if (unlikely(dest->data != NULL && dest->allocd == NULL))
144
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
145
146
  unused = MEMSUB(dest->data, dest->allocd);
147
  dest->allocd = gnutls_realloc_fast(dest->allocd, new_size + unused);
148
  if (dest->allocd == NULL) {
149
    gnutls_assert();
150
    return GNUTLS_E_MEMORY_ERROR;
151
  }
152
  dest->max_length = new_size + unused;
153
  dest->data = dest->allocd + unused;
154
155
  return 0;
156
}
157
158
#else
159
160
static void align_allocd_with_data(gnutls_buffer_st *dest)
161
0
{
162
0
  assert(dest->allocd != NULL);
163
0
  assert(dest->data != NULL);
164
0
  if (dest->length)
165
0
    memmove(dest->allocd, dest->data, dest->length);
166
0
  dest->data = dest->allocd;
167
0
}
168
169
int _gnutls_buffer_resize(gnutls_buffer_st *dest, size_t new_size)
170
0
{
171
0
  if (unlikely(dest->data != NULL && dest->allocd == NULL))
172
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
173
174
0
  if (dest->max_length >= new_size) {
175
0
    size_t unused = MEMSUB(dest->data, dest->allocd);
176
0
    if (dest->max_length - unused <= new_size) {
177
0
      align_allocd_with_data(dest);
178
0
    }
179
180
0
    return 0;
181
0
  } else {
182
0
    size_t unused = MEMSUB(dest->data, dest->allocd);
183
0
    size_t alloc_len = MAX(new_size, MIN_CHUNK) +
184
0
           MAX(dest->max_length, MIN_CHUNK);
185
186
0
    dest->allocd = gnutls_realloc_fast(dest->allocd, alloc_len);
187
0
    if (dest->allocd == NULL) {
188
0
      gnutls_assert();
189
0
      return GNUTLS_E_MEMORY_ERROR;
190
0
    }
191
0
    dest->max_length = alloc_len;
192
0
    dest->data = dest->allocd + unused;
193
194
0
    align_allocd_with_data(dest);
195
196
0
    return 0;
197
0
  }
198
0
}
199
200
#endif
201
202
/* Appends the provided string. The null termination byte is appended
203
 * but not included in length.
204
 */
205
int _gnutls_buffer_append_str(gnutls_buffer_st *dest, const char *src)
206
0
{
207
0
  int ret;
208
0
  ret = _gnutls_buffer_append_data(dest, src, strlen(src) + 1);
209
0
  if (ret >= 0)
210
0
    dest->length--;
211
212
0
  return ret;
213
0
}
214
215
/* returns data from a string in a constant buffer.
216
 * The data will NOT be valid if buffer is released or
217
 * data are appended in the buffer.
218
 */
219
void _gnutls_buffer_pop_datum(gnutls_buffer_st *str, gnutls_datum_t *data,
220
            size_t req_size)
221
0
{
222
0
  if (str->length == 0) {
223
0
    data->data = NULL;
224
0
    data->size = 0;
225
0
    return;
226
0
  }
227
228
0
  if (req_size > str->length)
229
0
    req_size = str->length;
230
231
0
  data->data = str->data;
232
0
  data->size = req_size;
233
234
0
  str->data += req_size;
235
0
  str->length -= req_size;
236
237
  /* if string becomes empty start from beginning */
238
0
  if (str->length == 0) {
239
0
    str->data = str->allocd;
240
0
  }
241
242
0
  return;
243
0
}
244
245
/* converts the buffer to a datum if possible. After this call
246
 * (failed or not) the buffer should be considered deinitialized.
247
 */
248
int _gnutls_buffer_to_datum(gnutls_buffer_st *str, gnutls_datum_t *data,
249
          unsigned is_str)
250
0
{
251
0
  int ret;
252
253
0
  if (str->length == 0) {
254
0
    data->data = NULL;
255
0
    data->size = 0;
256
0
    ret = 0;
257
0
    goto fail;
258
0
  }
259
260
0
  if (is_str) {
261
0
    ret = _gnutls_buffer_append_data(str, "\x00", 1);
262
0
    if (ret < 0) {
263
0
      gnutls_assert();
264
0
      goto fail;
265
0
    }
266
0
  }
267
268
0
  if (str->allocd != str->data) {
269
0
    data->data = gnutls_malloc(str->length);
270
0
    if (data->data == NULL) {
271
0
      gnutls_assert();
272
0
      ret = GNUTLS_E_MEMORY_ERROR;
273
0
      goto fail;
274
0
    }
275
0
    memcpy(data->data, str->data, str->length);
276
0
    data->size = str->length;
277
0
    _gnutls_buffer_clear(str);
278
0
  } else {
279
0
    data->data = str->data;
280
0
    data->size = str->length;
281
0
    _gnutls_buffer_init(str);
282
0
  }
283
284
0
  if (is_str) {
285
0
    data->size--;
286
0
  }
287
288
0
  return 0;
289
0
fail:
290
0
  _gnutls_buffer_clear(str);
291
0
  return ret;
292
0
}
293
294
/* returns data from a string in a constant buffer. Will
295
 * fail with GNUTLS_E_PARSING_ERROR, if the string has not enough data.
296
 */
297
int _gnutls_buffer_pop_data(gnutls_buffer_st *str, void *data, size_t req_size)
298
0
{
299
0
  gnutls_datum_t tdata;
300
301
0
  _gnutls_buffer_pop_datum(str, &tdata, req_size);
302
0
  if (tdata.data == NULL || tdata.size != req_size) {
303
0
    return GNUTLS_E_PARSING_ERROR;
304
0
  }
305
306
0
  memcpy(data, tdata.data, tdata.size);
307
308
0
  return 0;
309
0
}
310
311
int _gnutls_buffer_append_printf(gnutls_buffer_st *dest, const char *fmt, ...)
312
0
{
313
0
  va_list args;
314
0
  int len;
315
0
  char *str = NULL;
316
317
0
  va_start(args, fmt);
318
0
  len = vasprintf(&str, fmt, args);
319
0
  va_end(args);
320
321
0
  if (len < 0 || !str)
322
0
    return -1;
323
324
0
  len = _gnutls_buffer_append_str(dest, str);
325
326
0
  free(str);
327
328
0
  return len;
329
0
}
330
331
static int _gnutls_buffer_insert_data(gnutls_buffer_st *dest, int pos,
332
              const void *str, size_t str_size)
333
0
{
334
0
  size_t orig_length = dest->length;
335
0
  int ret;
336
337
0
  ret = _gnutls_buffer_resize(
338
0
    dest, dest->length + str_size); /* resize to make space */
339
0
  if (ret < 0)
340
0
    return ret;
341
342
0
  assert(dest->data != NULL);
343
344
0
  memmove(&dest->data[pos + str_size], &dest->data[pos],
345
0
    orig_length - pos);
346
347
0
  memcpy(&dest->data[pos], str, str_size);
348
0
  dest->length += str_size;
349
350
0
  return 0;
351
0
}
352
353
static void _gnutls_buffer_delete_data(gnutls_buffer_st *dest, int pos,
354
               size_t str_size)
355
0
{
356
0
  memmove(&dest->data[pos], &dest->data[pos + str_size],
357
0
    dest->length - pos - str_size);
358
359
0
  dest->length -= str_size;
360
361
0
  return;
362
0
}
363
364
int _gnutls_buffer_append_escape(gnutls_buffer_st *dest, const void *data,
365
         size_t data_size, const char *invalid_chars)
366
0
{
367
0
  int rv = -1;
368
0
  char t[5];
369
0
  unsigned int pos = dest->length;
370
371
0
  rv = _gnutls_buffer_append_data(dest, data, data_size);
372
0
  if (rv < 0)
373
0
    return gnutls_assert_val(rv);
374
375
0
  while (pos < dest->length) {
376
0
    if (dest->data[pos] == '\\' ||
377
0
        strchr(invalid_chars, dest->data[pos]) ||
378
0
        !c_isgraph(dest->data[pos])) {
379
0
      snprintf(t, sizeof(t), "%%%.2X",
380
0
         (unsigned int)dest->data[pos]);
381
382
0
      _gnutls_buffer_delete_data(dest, pos, 1);
383
384
0
      if (_gnutls_buffer_insert_data(dest, pos, t, 3) < 0) {
385
0
        rv = -1;
386
0
        goto cleanup;
387
0
      }
388
0
      pos += 3;
389
0
    } else
390
0
      pos++;
391
0
  }
392
393
0
  rv = 0;
394
395
0
cleanup:
396
0
  return rv;
397
0
}
398
399
int _gnutls_buffer_unescape(gnutls_buffer_st *dest)
400
0
{
401
0
  int rv = -1;
402
0
  unsigned int pos = 0;
403
404
0
  while (pos < dest->length) {
405
0
    if (dest->data[pos] == '%') {
406
0
      if (pos + 1 < dest->length &&
407
0
          dest->data[pos + 1] == '%') {
408
        // %% -> %
409
0
        _gnutls_buffer_delete_data(dest, pos, 1);
410
0
      } else if (pos + 2 < dest->length &&
411
0
           c_isxdigit(dest->data[pos + 1]) &&
412
0
           c_isxdigit(dest->data[pos + 2])) {
413
0
        unsigned char x;
414
415
0
        hex_decode((char *)dest->data + pos + 1, 2, &x,
416
0
             1);
417
418
0
        _gnutls_buffer_delete_data(dest, pos, 3);
419
0
        _gnutls_buffer_insert_data(dest, pos, &x, 1);
420
0
      }
421
0
    }
422
0
    pos++;
423
0
  }
424
425
0
  rv = 0;
426
427
0
  return rv;
428
0
}
429
430
/* Converts the given string (old) to hex. A buffer must be provided
431
 * to hold the new hex string. The new string will be null terminated.
432
 * If the buffer does not have enough space to hold the string, a
433
 * truncated hex string is returned (always null terminated).
434
 */
435
char *_gnutls_bin2hex(const void *_old, size_t oldlen, char *buffer,
436
          size_t buffer_size, const char *separator)
437
0
{
438
0
  unsigned int i, j;
439
0
  const uint8_t *old = _old;
440
0
  int step = 2;
441
0
  const char empty[] = "";
442
443
0
  if (separator != NULL && separator[0] != 0)
444
0
    step = 3;
445
0
  else
446
0
    separator = empty;
447
448
0
  if (buffer_size < 3) {
449
0
    gnutls_assert();
450
0
    return NULL;
451
0
  }
452
453
0
  i = j = 0;
454
0
  sprintf(&buffer[j], "%.2x", old[i]);
455
0
  j += 2;
456
0
  i++;
457
458
0
  for (; i < oldlen && j + step < buffer_size; j += step) {
459
0
    sprintf(&buffer[j], "%s%.2x", separator, old[i]);
460
0
    i++;
461
0
  }
462
0
  buffer[j] = '\0';
463
464
0
  return buffer;
465
0
}
466
467
/**
468
 * gnutls_hex2bin:
469
 * @hex_data: string with data in hex format
470
 * @hex_size: size of hex data
471
 * @bin_data: output array with binary data
472
 * @bin_size: when calling should hold maximum size of @bin_data,
473
 *      on return will hold actual length of @bin_data.
474
 *
475
 * Convert a buffer with hex data to binary data. This function
476
 * unlike gnutls_hex_decode() can parse hex data with separators
477
 * between numbers. That is, it ignores any non-hex characters.
478
 *
479
 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
480
 *
481
 * Since: 2.4.0
482
 **/
483
int gnutls_hex2bin(const char *hex_data, size_t hex_size, void *bin_data,
484
       size_t *bin_size)
485
0
{
486
0
  return _gnutls_hex2bin(hex_data, hex_size, (void *)bin_data, bin_size);
487
0
}
488
489
int _gnutls_hex2bin(const char *hex_data, size_t hex_size, uint8_t *bin_data,
490
        size_t *bin_size)
491
0
{
492
0
  unsigned int i, j;
493
0
  uint8_t hex2_data[3];
494
0
  unsigned long val;
495
496
0
  hex2_data[2] = 0;
497
498
0
  for (i = j = 0; i < hex_size;) {
499
0
    if (!isxdigit(
500
0
          hex_data[i])) { /* skip non-hex such as the ':' in 00:FF */
501
0
      i++;
502
0
      continue;
503
0
    }
504
0
    if (j >= *bin_size) {
505
0
      gnutls_assert();
506
0
      return GNUTLS_E_SHORT_MEMORY_BUFFER;
507
0
    }
508
509
0
    if (i + 1 >= hex_size)
510
0
      return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
511
512
0
    hex2_data[0] = hex_data[i];
513
0
    hex2_data[1] = hex_data[i + 1];
514
0
    i += 2;
515
516
0
    val = strtoul((char *)hex2_data, NULL, 16);
517
0
    if (val == ULONG_MAX) {
518
0
      gnutls_assert();
519
0
      return GNUTLS_E_PARSING_ERROR;
520
0
    }
521
0
    bin_data[j] = val;
522
0
    j++;
523
0
  }
524
0
  *bin_size = j;
525
526
0
  return 0;
527
0
}
528
529
/**
530
 * gnutls_hex_decode2:
531
 * @hex_data: contain the encoded data
532
 * @result: the result in an allocated string
533
 *
534
 * This function will decode the given encoded data, using the hex
535
 * encoding used by PSK password files.
536
 *
537
 * Returns: %GNUTLS_E_PARSING_ERROR on invalid hex data, or 0 on success.
538
 **/
539
int gnutls_hex_decode2(const gnutls_datum_t *hex_data, gnutls_datum_t *result)
540
0
{
541
0
  int ret;
542
0
  int size = hex_data_size(hex_data->size);
543
544
0
  result->data = gnutls_malloc(size);
545
0
  if (result->data == NULL) {
546
0
    gnutls_assert();
547
0
    return GNUTLS_E_MEMORY_ERROR;
548
0
  }
549
550
0
  result->size = size;
551
0
  ret = hex_decode((char *)hex_data->data, hex_data->size, result->data,
552
0
       result->size);
553
0
  if (ret == 0) {
554
0
    gnutls_assert();
555
0
    gnutls_free(result->data);
556
0
    return GNUTLS_E_PARSING_ERROR;
557
0
  }
558
559
0
  return 0;
560
0
}
561
562
/**
563
 * gnutls_hex_decode:
564
 * @hex_data: contain the encoded data
565
 * @result: the place where decoded data will be copied
566
 * @result_size: holds the size of the result
567
 *
568
 * This function will decode the given encoded data, using the hex
569
 * encoding used by PSK password files.
570
 *
571
 * Initially @result_size must hold the maximum size available in
572
 * @result, and on return it will contain the number of bytes written.
573
 *
574
 * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
575
 *   long enough, %GNUTLS_E_PARSING_ERROR on invalid hex data, or 0 on success.
576
 **/
577
int gnutls_hex_decode(const gnutls_datum_t *hex_data, void *result,
578
          size_t *result_size)
579
0
{
580
0
  int ret;
581
0
  size_t size = hex_data_size(hex_data->size);
582
583
0
  if (*result_size < size) {
584
0
    gnutls_assert();
585
0
    return GNUTLS_E_SHORT_MEMORY_BUFFER;
586
0
  }
587
588
0
  ret = hex_decode((char *)hex_data->data, hex_data->size, result, size);
589
0
  if (ret == 0) {
590
0
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
591
0
  }
592
0
  *result_size = size;
593
594
0
  return 0;
595
0
}
596
597
/**
598
 * gnutls_hex_encode:
599
 * @data: contain the raw data
600
 * @result: the place where hex data will be copied
601
 * @result_size: holds the size of the result
602
 *
603
 * This function will convert the given data to printable data, using
604
 * the hex encoding, as used in the PSK password files.
605
 *
606
 * Note that the size of the result includes the null terminator.
607
 *
608
 * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
609
 * long enough, or 0 on success.
610
 **/
611
int gnutls_hex_encode(const gnutls_datum_t *data, char *result,
612
          size_t *result_size)
613
0
{
614
0
  int ret;
615
0
  size_t size = hex_str_size(data->size);
616
617
0
  if (*result_size < size) {
618
0
    gnutls_assert();
619
0
    return GNUTLS_E_SHORT_MEMORY_BUFFER;
620
0
  }
621
622
0
  ret = hex_encode(data->data, data->size, result, *result_size);
623
0
  if (ret == 0) {
624
0
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
625
0
  }
626
627
0
  *result_size = size;
628
629
0
  return 0;
630
0
}
631
632
/**
633
 * gnutls_hex_encode2:
634
 * @data: contain the raw data
635
 * @result: the result in an allocated string
636
 *
637
 * This function will convert the given data to printable data, using
638
 * the hex encoding, as used in the PSK password files.
639
 *
640
 * Note that the size of the result does NOT include the null terminator.
641
 *
642
 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
643
 **/
644
int gnutls_hex_encode2(const gnutls_datum_t *data, gnutls_datum_t *result)
645
0
{
646
0
  int ret;
647
0
  int size = hex_str_size(data->size);
648
649
0
  result->data = gnutls_malloc(size);
650
0
  if (result->data == NULL) {
651
0
    gnutls_assert();
652
0
    return GNUTLS_E_MEMORY_ERROR;
653
0
  }
654
655
0
  ret = hex_encode((char *)data->data, data->size, (char *)result->data,
656
0
       size);
657
0
  if (ret == 0) {
658
0
    gnutls_free(result->data);
659
0
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
660
0
  }
661
662
0
  result->size = size - 1;
663
664
0
  return 0;
665
0
}
666
667
static int hostname_compare_raw(const char *certname, size_t certnamesize,
668
        const char *hostname)
669
0
{
670
0
  if (certnamesize == strlen(hostname) &&
671
0
      memcmp(hostname, certname, certnamesize) == 0)
672
0
    return 1;
673
0
  return 0;
674
0
}
675
676
static int hostname_compare_ascii(const char *certname, size_t certnamesize,
677
          const char *hostname)
678
0
{
679
0
  for (; *certname && *hostname &&
680
0
         c_toupper(*certname) == c_toupper(*hostname);
681
0
       certname++, hostname++, certnamesize--)
682
0
    ;
683
684
  /* the strings are the same */
685
0
  if (certnamesize == 0 && *hostname == '\0')
686
0
    return 1;
687
688
0
  return 0;
689
0
}
690
691
/* compare hostname against certificate, taking account of wildcards
692
 * return 1 on success or 0 on error
693
 *
694
 * note: certnamesize is required as X509 certs can contain embedded NULs in
695
 * the strings such as CN or subjectAltName.
696
 *
697
 * Wildcards are taken into account only if they are the leftmost
698
 * component, and if the string is ascii only (partial advice from rfc6125)
699
 *
700
 */
701
int _gnutls_hostname_compare(const char *certname, size_t certnamesize,
702
           const char *hostname, unsigned vflags)
703
0
{
704
0
  char *p;
705
0
  unsigned i;
706
707
0
  for (i = 0; i < certnamesize; i++) {
708
0
    if (c_isprint(certname[i]) == 0)
709
0
      return hostname_compare_raw(certname, certnamesize,
710
0
                hostname);
711
0
  }
712
713
0
  if (*certname == '*' &&
714
0
      !(vflags & GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS)) {
715
    /* a wildcard certificate */
716
717
    /* ensure that we have at least two domain components after
718
     * the wildcard. */
719
0
    p = strrchr(certname, '.');
720
0
    if (p == NULL || strchr(certname, '.') == p || p[1] == 0) {
721
0
      return 0;
722
0
    }
723
724
0
    certname++;
725
0
    certnamesize--;
726
727
0
    while (1) {
728
0
      if (hostname_compare_ascii(certname, certnamesize,
729
0
               hostname))
730
0
        return 1;
731
732
      /* wildcards are only allowed to match a single domain
733
         component or component fragment */
734
0
      if (*hostname == '\0' || *hostname == '.')
735
0
        break;
736
0
      hostname++;
737
0
    }
738
739
0
    return 0;
740
0
  } else {
741
0
    return hostname_compare_ascii(certname, certnamesize, hostname);
742
0
  }
743
0
}
744
745
int _gnutls_buffer_append_prefix(gnutls_buffer_st *buf, int pfx_size,
746
         size_t data_size)
747
0
{
748
0
  uint8_t ss[4];
749
750
0
  if (pfx_size == 32) {
751
0
    _gnutls_write_uint32(data_size, ss);
752
0
    pfx_size = 4;
753
0
  } else if (pfx_size == 24) {
754
0
    _gnutls_write_uint24(data_size, ss);
755
0
    pfx_size = 3;
756
0
  } else if (pfx_size == 16) {
757
0
    _gnutls_write_uint16(data_size, ss);
758
0
    pfx_size = 2;
759
0
  } else if (pfx_size == 8) {
760
0
    ss[0] = data_size;
761
0
    pfx_size = 1;
762
0
  } else
763
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
764
765
0
  return _gnutls_buffer_append_data(buf, ss, pfx_size);
766
0
}
767
768
int _gnutls_buffer_pop_prefix8(gnutls_buffer_st *buf, uint8_t *data, int check)
769
0
{
770
0
  if (buf->length < 1) {
771
0
    gnutls_assert();
772
0
    return GNUTLS_E_PARSING_ERROR;
773
0
  }
774
775
0
  *data = buf->data[0];
776
777
0
  if (check && *data > buf->length - 1) {
778
0
    gnutls_assert();
779
0
    return GNUTLS_E_PARSING_ERROR;
780
0
  }
781
782
0
  buf->data++;
783
0
  buf->length--;
784
785
0
  return 0;
786
0
}
787
788
int _gnutls_buffer_pop_prefix16(gnutls_buffer_st *buf, size_t *data_size,
789
        int check)
790
0
{
791
0
  size_t size;
792
793
0
  if (buf->length < 2) {
794
0
    gnutls_assert();
795
0
    return GNUTLS_E_PARSING_ERROR;
796
0
  }
797
798
0
  size = _gnutls_read_uint16(buf->data);
799
0
  if (check && size > buf->length - 2) {
800
0
    gnutls_assert();
801
0
    return GNUTLS_E_PARSING_ERROR;
802
0
  }
803
804
0
  buf->data += 2;
805
0
  buf->length -= 2;
806
807
0
  *data_size = size;
808
809
0
  return 0;
810
0
}
811
812
int _gnutls_buffer_pop_prefix24(gnutls_buffer_st *buf, size_t *data_size,
813
        int check)
814
0
{
815
0
  size_t size;
816
817
0
  if (buf->length < 3) {
818
0
    gnutls_assert();
819
0
    return GNUTLS_E_PARSING_ERROR;
820
0
  }
821
822
0
  size = _gnutls_read_uint24(buf->data);
823
0
  if (check && size > buf->length - 3) {
824
0
    gnutls_assert();
825
0
    return GNUTLS_E_PARSING_ERROR;
826
0
  }
827
828
0
  buf->data += 3;
829
0
  buf->length -= 3;
830
831
0
  *data_size = size;
832
833
0
  return 0;
834
0
}
835
836
/* Reads an uint32 number from the buffer. If check is non zero it will also check whether
837
 * the number read, is less than the data in the buffer
838
 */
839
int _gnutls_buffer_pop_prefix32(gnutls_buffer_st *buf, size_t *data_size,
840
        int check)
841
0
{
842
0
  size_t size;
843
844
0
  if (buf->length < 4) {
845
0
    gnutls_assert();
846
0
    return GNUTLS_E_PARSING_ERROR;
847
0
  }
848
849
0
  size = _gnutls_read_uint32(buf->data);
850
0
  if (check && size > buf->length - 4) {
851
0
    gnutls_assert();
852
0
    return GNUTLS_E_PARSING_ERROR;
853
0
  }
854
855
0
  buf->data += 4;
856
0
  buf->length -= 4;
857
858
0
  *data_size = size;
859
860
0
  return 0;
861
0
}
862
863
int _gnutls_buffer_pop_datum_prefix32(gnutls_buffer_st *buf,
864
              gnutls_datum_t *data)
865
0
{
866
0
  size_t size;
867
0
  int ret;
868
869
0
  ret = _gnutls_buffer_pop_prefix32(buf, &size, 1);
870
0
  if (ret < 0) {
871
0
    gnutls_assert();
872
0
    return ret;
873
0
  }
874
875
0
  if (size > 0) {
876
0
    size_t osize = size;
877
0
    _gnutls_buffer_pop_datum(buf, data, size);
878
0
    if (osize != data->size) {
879
0
      gnutls_assert();
880
0
      return GNUTLS_E_PARSING_ERROR;
881
0
    }
882
0
  } else {
883
0
    data->size = 0;
884
0
    data->data = NULL;
885
0
  }
886
887
0
  return 0;
888
0
}
889
890
int _gnutls_buffer_pop_datum_prefix24(gnutls_buffer_st *buf,
891
              gnutls_datum_t *data)
892
0
{
893
0
  size_t size;
894
0
  int ret;
895
896
0
  ret = _gnutls_buffer_pop_prefix24(buf, &size, 1);
897
0
  if (ret < 0) {
898
0
    gnutls_assert();
899
0
    return ret;
900
0
  }
901
902
0
  if (size > 0) {
903
0
    size_t osize = size;
904
0
    _gnutls_buffer_pop_datum(buf, data, size);
905
0
    if (osize != data->size) {
906
0
      gnutls_assert();
907
0
      return GNUTLS_E_PARSING_ERROR;
908
0
    }
909
0
  } else {
910
0
    data->size = 0;
911
0
    data->data = NULL;
912
0
  }
913
914
0
  return 0;
915
0
}
916
917
int _gnutls_buffer_pop_datum_prefix16(gnutls_buffer_st *buf,
918
              gnutls_datum_t *data)
919
0
{
920
0
  size_t size;
921
922
0
  if (buf->length < 2) {
923
0
    gnutls_assert();
924
0
    return GNUTLS_E_PARSING_ERROR;
925
0
  }
926
927
0
  size = _gnutls_read_uint16(buf->data);
928
929
0
  buf->data += 2;
930
0
  buf->length -= 2;
931
932
0
  if (size > 0) {
933
0
    size_t osize = size;
934
0
    _gnutls_buffer_pop_datum(buf, data, size);
935
0
    if (osize != data->size) {
936
0
      gnutls_assert();
937
0
      return GNUTLS_E_PARSING_ERROR;
938
0
    }
939
0
  } else {
940
0
    data->size = 0;
941
0
    data->data = NULL;
942
0
  }
943
944
0
  return 0;
945
0
}
946
947
int _gnutls_buffer_pop_datum_prefix8(gnutls_buffer_st *buf,
948
             gnutls_datum_t *data)
949
0
{
950
0
  size_t size;
951
952
0
  if (buf->length < 1) {
953
0
    gnutls_assert();
954
0
    return GNUTLS_E_PARSING_ERROR;
955
0
  }
956
957
0
  size = buf->data[0];
958
959
0
  buf->data++;
960
0
  buf->length--;
961
962
0
  if (size > 0) {
963
0
    size_t osize = size;
964
0
    _gnutls_buffer_pop_datum(buf, data, size);
965
0
    if (osize != data->size) {
966
0
      gnutls_assert();
967
0
      return GNUTLS_E_PARSING_ERROR;
968
0
    }
969
0
  } else {
970
0
    data->size = 0;
971
0
    data->data = NULL;
972
0
  }
973
974
0
  return 0;
975
0
}
976
977
int _gnutls_buffer_append_data_prefix(gnutls_buffer_st *buf, int pfx_size,
978
              const void *data, size_t data_size)
979
0
{
980
0
  int ret;
981
982
0
  ret = _gnutls_buffer_append_prefix(buf, pfx_size, data_size);
983
0
  if (ret < 0)
984
0
    return gnutls_assert_val(ret);
985
986
0
  if (data_size > 0) {
987
0
    ret = _gnutls_buffer_append_data(buf, data, data_size);
988
0
    if (ret < 0)
989
0
      return gnutls_assert_val(ret);
990
0
  }
991
992
0
  return 0;
993
0
}
994
995
int _gnutls_buffer_append_mpi(gnutls_buffer_st *buf, int pfx_size, bigint_t mpi,
996
            int lz)
997
0
{
998
0
  gnutls_datum_t dd;
999
0
  int ret;
1000
1001
0
  if (lz)
1002
0
    ret = _gnutls_mpi_dprint_lz(mpi, &dd);
1003
0
  else
1004
0
    ret = _gnutls_mpi_dprint(mpi, &dd);
1005
1006
0
  if (ret < 0)
1007
0
    return gnutls_assert_val(ret);
1008
1009
0
  ret = _gnutls_buffer_append_data_prefix(buf, pfx_size, dd.data,
1010
0
            dd.size);
1011
1012
0
  _gnutls_free_datum(&dd);
1013
1014
0
  return ret;
1015
0
}
1016
1017
/* Appends an MPI of fixed-size in bytes left-padded with zeros if necessary */
1018
int _gnutls_buffer_append_fixed_mpi(gnutls_buffer_st *buf, bigint_t mpi,
1019
            unsigned size)
1020
0
{
1021
0
  gnutls_datum_t dd;
1022
0
  unsigned pad, i;
1023
0
  int ret;
1024
1025
0
  ret = _gnutls_mpi_dprint(mpi, &dd);
1026
0
  if (ret < 0)
1027
0
    return gnutls_assert_val(ret);
1028
1029
0
  if (size < dd.size) {
1030
0
    ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1031
0
    goto cleanup;
1032
0
  }
1033
1034
0
  pad = size - dd.size;
1035
0
  for (i = 0; i < pad; i++) {
1036
0
    ret = _gnutls_buffer_append_data(buf, "\x00", 1);
1037
0
    if (ret < 0) {
1038
0
      gnutls_assert();
1039
0
      goto cleanup;
1040
0
    }
1041
0
  }
1042
1043
  /* append the rest */
1044
0
  ret = _gnutls_buffer_append_data(buf, dd.data, dd.size);
1045
1046
0
cleanup:
1047
0
  _gnutls_free_datum(&dd);
1048
0
  return ret;
1049
0
}
1050
1051
void _gnutls_buffer_hexprint(gnutls_buffer_st *str, const void *_data,
1052
           size_t len)
1053
0
{
1054
0
  size_t j;
1055
0
  const unsigned char *data = _data;
1056
1057
0
  if (len == 0)
1058
0
    _gnutls_buffer_append_str(str, "00");
1059
0
  else {
1060
0
    for (j = 0; j < len; j++)
1061
0
      _gnutls_buffer_append_printf(str, "%.2x",
1062
0
                 (unsigned)data[j]);
1063
0
  }
1064
0
}
1065
1066
int _gnutls_buffer_base64print(gnutls_buffer_st *str, const void *_data,
1067
             size_t len)
1068
0
{
1069
0
  const unsigned char *data = _data;
1070
0
  unsigned b64len = BASE64_ENCODE_RAW_LENGTH(len);
1071
0
  int ret;
1072
1073
0
  ret = _gnutls_buffer_resize(str, str->length + b64len + 1);
1074
0
  if (ret < 0) {
1075
0
    return gnutls_assert_val(ret);
1076
0
  }
1077
1078
0
  base64_encode_raw((void *)&str->data[str->length], len, data);
1079
0
  str->length += b64len;
1080
0
  str->data[str->length] = 0;
1081
1082
0
  return 0;
1083
0
}
1084
1085
void _gnutls_buffer_hexdump(gnutls_buffer_st *str, const void *_data,
1086
          size_t len, const char *spc)
1087
0
{
1088
0
  size_t j;
1089
0
  const unsigned char *data = _data;
1090
1091
0
  if (spc)
1092
0
    _gnutls_buffer_append_str(str, spc);
1093
0
  for (j = 0; j < len; j++) {
1094
0
    if (((j + 1) % 16) == 0) {
1095
0
      _gnutls_buffer_append_printf(str, "%.2x\n",
1096
0
                 (unsigned)data[j]);
1097
0
      if (spc && j != (len - 1))
1098
0
        _gnutls_buffer_append_str(str, spc);
1099
0
    } else if (j == (len - 1))
1100
0
      _gnutls_buffer_append_printf(str, "%.2x",
1101
0
                 (unsigned)data[j]);
1102
0
    else
1103
0
      _gnutls_buffer_append_printf(
1104
0
        str, "%.2x:", (unsigned)data[j]);
1105
0
  }
1106
0
  if ((j % 16) != 0)
1107
0
    _gnutls_buffer_append_str(str, "\n");
1108
0
}
1109
1110
void _gnutls_buffer_asciiprint(gnutls_buffer_st *str, const char *data,
1111
             size_t len)
1112
0
{
1113
0
  size_t j;
1114
1115
0
  for (j = 0; j < len; j++)
1116
0
    if (c_isprint(data[j]))
1117
0
      _gnutls_buffer_append_printf(str, "%c",
1118
0
                 (unsigned char)data[j]);
1119
0
    else
1120
0
      _gnutls_buffer_append_printf(str, ".");
1121
0
}