Coverage Report

Created: 2023-03-26 07:33

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