Coverage Report

Created: 2026-02-14 07:17

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