~nutznboltz-deactivatedaccount/ubuntu/precise/gnutls26/fix-lp926350

« back to all changes in this revision

Viewing changes to lib/gnutls_str.c

  • Committer: Package Import Robot
  • Author(s): Andreas Metzler
  • Date: 2011-10-01 15:28:13 UTC
  • mfrom: (12.1.20 sid)
  • Revision ID: package-import@ubuntu.com-20111001152813-yygm1c4cxonfxhzy
Tags: 2.12.11-1
* New upstream version.
  + Allow CA importing of 0 certificates to succeed. Closes: #640639
* Add libp11-kit-dev to libgnutls-dev dependencies. (see #643811)
* [20_guiledocstring.diff] guile: Fix docstring extraction with CPP 4.5+.

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
#include <gnutls_num.h>
29
29
#include <gnutls_str.h>
30
30
#include <stdarg.h>
 
31
#include <c-ctype.h>
31
32
 
32
33
/* These function are like strcat, strcpy. They only
33
34
 * do bound checking (they shouldn't cause buffer overruns),
48
49
  else
49
50
    {
50
51
      if (dest_tot_size - dest_size > 0)
51
 
        {
52
 
          strncat (dest, src, (dest_tot_size - dest_size) - 1);
53
 
          dest[dest_tot_size - 1] = 0;
54
 
        }
 
52
        {
 
53
          strncat (dest, src, (dest_tot_size - dest_size) - 1);
 
54
          dest[dest_tot_size - 1] = 0;
 
55
        }
55
56
    }
56
57
}
57
58
 
67
68
  else
68
69
    {
69
70
      if (dest_tot_size > 0)
70
 
        {
71
 
          strncpy (dest, src, (dest_tot_size) - 1);
72
 
          dest[dest_tot_size - 1] = 0;
73
 
        }
 
71
        {
 
72
          strncpy (dest, src, (dest_tot_size) - 1);
 
73
          dest[dest_tot_size - 1] = 0;
 
74
        }
74
75
    }
75
76
}
76
77
 
77
78
void
78
79
_gnutls_mem_cpy (char *dest, size_t dest_tot_size, const char *src,
79
 
                 size_t src_size)
 
80
                 size_t src_size)
80
81
{
81
82
 
82
83
  if (dest_tot_size >= src_size)
86
87
  else
87
88
    {
88
89
      if (dest_tot_size > 0)
89
 
        {
90
 
          memcpy (dest, src, dest_tot_size);
91
 
        }
 
90
        {
 
91
          memcpy (dest, src, dest_tot_size);
 
92
        }
92
93
    }
93
94
}
94
95
 
95
96
void
96
 
_gnutls_string_init (gnutls_string * str,
97
 
                     gnutls_alloc_function alloc_func,
98
 
                     gnutls_realloc_function realloc_func,
99
 
                     gnutls_free_function free_func)
 
97
_gnutls_buffer_init (gnutls_buffer_st * str)
100
98
{
101
99
  str->data = str->allocd = NULL;
102
100
  str->max_length = 0;
103
101
  str->length = 0;
104
 
 
105
 
  str->alloc_func = alloc_func;
106
 
  str->free_func = free_func;
107
 
  str->realloc_func = realloc_func;
108
102
}
109
103
 
110
104
void
111
 
_gnutls_string_clear (gnutls_string * str)
 
105
_gnutls_buffer_clear (gnutls_buffer_st * str)
112
106
{
113
107
  if (str == NULL || str->allocd == NULL)
114
108
    return;
115
 
  str->free_func (str->allocd);
 
109
  gnutls_free (str->allocd);
116
110
 
117
111
  str->data = str->allocd = NULL;
118
112
  str->max_length = 0;
119
113
  str->length = 0;
120
114
}
121
115
 
122
 
#define MIN_CHUNK 256
 
116
#define MIN_CHUNK 1024
123
117
 
124
118
int
125
 
_gnutls_string_append_data (gnutls_string * dest, const void *data,
126
 
                            size_t data_size)
 
119
_gnutls_buffer_append_data (gnutls_buffer_st * dest, const void *data,
 
120
                            size_t data_size)
127
121
{
128
122
  size_t tot_len = data_size + dest->length;
129
123
 
132
126
      size_t unused = MEMSUB (dest->data, dest->allocd);
133
127
 
134
128
      if (dest->max_length - unused <= tot_len)
135
 
        {
136
 
          if (dest->length && dest->data)
137
 
            memmove (dest->allocd, dest->data, dest->length);
 
129
        {
 
130
          if (dest->length && dest->data)
 
131
            memmove (dest->allocd, dest->data, dest->length);
138
132
 
139
 
          dest->data = dest->allocd;
140
 
        }
 
133
          dest->data = dest->allocd;
 
134
        }
141
135
      memmove (&dest->data[dest->length], data, data_size);
142
136
      dest->length = tot_len;
143
137
 
147
141
    {
148
142
      size_t unused = MEMSUB (dest->data, dest->allocd);
149
143
      size_t new_len =
150
 
        MAX (data_size, MIN_CHUNK) + MAX (dest->max_length, MIN_CHUNK);
 
144
        MAX (data_size, MIN_CHUNK) + MAX (dest->max_length, MIN_CHUNK);
151
145
 
152
 
      dest->allocd = dest->realloc_func (dest->allocd, new_len);
 
146
      dest->allocd = gnutls_realloc (dest->allocd, new_len);
153
147
      if (dest->allocd == NULL)
154
 
        {
155
 
          gnutls_assert ();
156
 
          return GNUTLS_E_MEMORY_ERROR;
157
 
        }
 
148
        {
 
149
          gnutls_assert ();
 
150
          return GNUTLS_E_MEMORY_ERROR;
 
151
        }
158
152
      dest->max_length = new_len;
159
153
      dest->data = dest->allocd + unused;
160
154
 
161
155
      if (dest->length && dest->data)
162
 
        memmove (dest->allocd, dest->data, dest->length);
 
156
        memmove (dest->allocd, dest->data, dest->length);
163
157
      dest->data = dest->allocd;
164
158
 
165
159
      memcpy (&dest->data[dest->length], data, data_size);
170
164
}
171
165
 
172
166
int
173
 
_gnutls_string_resize (gnutls_string * dest, size_t new_size)
 
167
_gnutls_buffer_resize (gnutls_buffer_st * dest, size_t new_size)
174
168
{
175
169
  if (dest->max_length >= new_size)
176
170
    {
177
171
      size_t unused = MEMSUB (dest->data, dest->allocd);
178
172
      if (dest->max_length - unused <= new_size)
179
 
        {
180
 
          if (dest->length && dest->data)
181
 
            memmove (dest->allocd, dest->data, dest->length);
182
 
          dest->data = dest->allocd;
183
 
        }
 
173
        {
 
174
          if (dest->length && dest->data)
 
175
            memmove (dest->allocd, dest->data, dest->length);
 
176
          dest->data = dest->allocd;
 
177
        }
184
178
 
185
179
      return 0;
186
180
    }
188
182
    {
189
183
      size_t unused = MEMSUB (dest->data, dest->allocd);
190
184
      size_t alloc_len =
191
 
        MAX (new_size, MIN_CHUNK) + MAX (dest->max_length, MIN_CHUNK);
 
185
        MAX (new_size, MIN_CHUNK) + MAX (dest->max_length, MIN_CHUNK);
192
186
 
193
 
      dest->allocd = dest->realloc_func (dest->allocd, alloc_len);
 
187
      dest->allocd = gnutls_realloc (dest->allocd, alloc_len);
194
188
      if (dest->allocd == NULL)
195
 
        {
196
 
          gnutls_assert ();
197
 
          return GNUTLS_E_MEMORY_ERROR;
198
 
        }
 
189
        {
 
190
          gnutls_assert ();
 
191
          return GNUTLS_E_MEMORY_ERROR;
 
192
        }
199
193
      dest->max_length = alloc_len;
200
194
      dest->data = dest->allocd + unused;
201
195
 
202
196
      if (dest->length && dest->data)
203
 
        memmove (dest->allocd, dest->data, dest->length);
 
197
        memmove (dest->allocd, dest->data, dest->length);
204
198
      dest->data = dest->allocd;
205
199
 
206
200
      return 0;
208
202
}
209
203
 
210
204
int
211
 
_gnutls_string_append_str (gnutls_string * dest, const char *src)
 
205
_gnutls_buffer_append_str (gnutls_buffer_st * dest, const char *src)
212
206
{
213
 
  return _gnutls_string_append_data (dest, src, strlen (src));
 
207
  return _gnutls_buffer_append_data (dest, src, strlen (src));
214
208
}
215
209
 
216
210
/* returns data from a string in a constant buffer.
218
212
 * data are appended in the buffer.
219
213
 */
220
214
void
221
 
_gnutls_string_get_datum (gnutls_string * str, gnutls_datum_t * data,
222
 
                          size_t req_size)
 
215
_gnutls_buffer_pop_datum (gnutls_buffer_st * str, gnutls_datum_t * data,
 
216
                          size_t req_size)
223
217
{
224
218
 
225
219
  if (str->length == 0)
247
241
  return;
248
242
}
249
243
 
 
244
/* converts the buffer to a datum if possible. After this call the buffer
 
245
 * is at an usable state and might not be used or deinitialized */
 
246
int
 
247
_gnutls_buffer_to_datum (gnutls_buffer_st * str, gnutls_datum_t * data)
 
248
{
 
249
 
 
250
  if (str->length == 0)
 
251
    {
 
252
      data->data = NULL;
 
253
      data->size = 0;
 
254
      return 0;
 
255
    }
 
256
 
 
257
  if (str->allocd != str->data)
 
258
    {
 
259
      data->data = gnutls_malloc (str->length);
 
260
      if (data->data == NULL)
 
261
        {
 
262
          gnutls_assert ();
 
263
          return GNUTLS_E_MEMORY_ERROR;
 
264
        }
 
265
      memcpy (data->data, str->data, str->length);
 
266
      data->size = str->length;
 
267
      _gnutls_buffer_clear (str);
 
268
    }
 
269
  else
 
270
    {
 
271
      data->data = str->data;
 
272
      data->size = str->length;
 
273
    }
 
274
 
 
275
  return 0;
 
276
}
 
277
 
250
278
/* returns data from a string in a constant buffer.
251
279
 */
252
280
void
253
 
_gnutls_string_get_data (gnutls_string * str, void *data, size_t * req_size)
 
281
_gnutls_buffer_pop_data (gnutls_buffer_st * str, void *data,
 
282
                         size_t * req_size)
254
283
{
255
284
  gnutls_datum_t tdata;
256
285
 
257
 
  _gnutls_string_get_datum (str, &tdata, *req_size);
 
286
  _gnutls_buffer_pop_datum (str, &tdata, *req_size);
258
287
 
259
288
  *req_size = tdata.size;
260
289
  memcpy (data, tdata.data, tdata.size);
263
292
}
264
293
 
265
294
int
266
 
_gnutls_string_append_printf (gnutls_string * dest, const char *fmt, ...)
 
295
_gnutls_buffer_append_printf (gnutls_buffer_st * dest, const char *fmt, ...)
267
296
{
268
297
  va_list args;
269
298
  int len;
276
305
  if (len < 0 || !str)
277
306
    return -1;
278
307
 
279
 
  len = _gnutls_string_append_str (dest, str);
 
308
  len = _gnutls_buffer_append_str (dest, str);
280
309
 
281
310
  free (str);
282
311
 
283
312
  return len;
284
313
}
285
314
 
 
315
static int
 
316
_gnutls_buffer_insert_data (gnutls_buffer_st * dest, int pos, const void *str,
 
317
                            size_t str_size)
 
318
{
 
319
  size_t orig_length = dest->length;
 
320
  int ret;
 
321
 
 
322
  ret = _gnutls_buffer_resize (dest, dest->length + str_size);  /* resize to make space */
 
323
  if (ret < 0)
 
324
    return ret;
 
325
 
 
326
  memmove (&dest->data[pos + str_size], &dest->data[pos], orig_length - pos);
 
327
 
 
328
  memcpy (&dest->data[pos], str, str_size);
 
329
  dest->length += str_size;
 
330
 
 
331
  return 0;
 
332
}
 
333
 
 
334
static void
 
335
_gnutls_buffer_delete_data (gnutls_buffer_st * dest, int pos, size_t str_size)
 
336
{
 
337
  memmove (&dest->data[pos], &dest->data[pos + str_size],
 
338
           dest->length - pos - str_size);
 
339
 
 
340
  dest->length -= str_size;
 
341
 
 
342
  return;
 
343
}
 
344
 
 
345
 
 
346
int
 
347
_gnutls_buffer_escape (gnutls_buffer_st * dest, int all,
 
348
                       const char *const invalid_chars)
 
349
{
 
350
  int rv = -1;
 
351
  char t[5];
 
352
  int pos = 0;
 
353
 
 
354
  while (pos < dest->length)
 
355
    {
 
356
 
 
357
      if (all != 0 || (dest->data[pos] == '\\' || strchr (invalid_chars, dest->data[pos])
 
358
          || !c_isgraph (dest->data[pos])))
 
359
        {
 
360
 
 
361
          snprintf (t, sizeof (t), "%%%.2X", (unsigned int) dest->data[pos]);
 
362
 
 
363
          _gnutls_buffer_delete_data (dest, pos, 1);
 
364
 
 
365
          if (_gnutls_buffer_insert_data (dest, pos, t, 3) < 0)
 
366
            {
 
367
              rv = -1;
 
368
              goto cleanup;
 
369
            }
 
370
          pos+=3;
 
371
        }
 
372
      else
 
373
        pos++;
 
374
    }
 
375
 
 
376
  rv = 0;
 
377
 
 
378
cleanup:
 
379
 
 
380
  return rv;
 
381
}
 
382
 
 
383
int
 
384
_gnutls_buffer_unescape (gnutls_buffer_st * dest)
 
385
{
 
386
  int rv = -1;
 
387
  int pos = 0;
 
388
 
 
389
  while (pos < dest->length)
 
390
    {
 
391
      if (dest->data[pos] == '%')
 
392
        {
 
393
          char b[3];
 
394
          unsigned int u;
 
395
          unsigned char x;
 
396
 
 
397
          b[0] = dest->data[pos + 1];
 
398
          b[1] = dest->data[pos + 2];
 
399
          b[2] = 0;
 
400
 
 
401
          sscanf (b, "%02x", &u);
 
402
 
 
403
          x = u;
 
404
 
 
405
          _gnutls_buffer_delete_data (dest, pos, 3);
 
406
          _gnutls_buffer_insert_data (dest, pos, &x, 1);
 
407
        }
 
408
      pos++;
 
409
    }
 
410
 
 
411
  rv = 0;
 
412
 
 
413
  return rv;
 
414
}
 
415
 
 
416
 
286
417
/* Converts the given string (old) to hex. A buffer must be provided
287
418
 * to hold the new hex string. The new string will be null terminated.
288
419
 * If the buffer does not have enough space to hold the string, a
290
421
 */
291
422
char *
292
423
_gnutls_bin2hex (const void *_old, size_t oldlen,
293
 
                 char *buffer, size_t buffer_size)
 
424
                 char *buffer, size_t buffer_size, const char *separator)
294
425
{
295
426
  unsigned int i, j;
296
427
  const opaque *old = _old;
297
 
 
298
 
  for (i = j = 0; i < oldlen && j + 2 < buffer_size; j += 2)
299
 
    {
300
 
      sprintf (&buffer[j], "%.2x", old[i]);
 
428
  int step = 2;
 
429
  const char empty[] = "";
 
430
 
 
431
  if (separator != NULL && separator[0] != 0)
 
432
    step = 3;
 
433
  else
 
434
    separator = empty;
 
435
 
 
436
  if (buffer_size < 3)
 
437
    {
 
438
      gnutls_assert();
 
439
      return NULL;
 
440
    }
 
441
 
 
442
  i = j = 0;
 
443
  sprintf (&buffer[j], "%.2x", old[i]);
 
444
  j += 2;
 
445
  i++;
 
446
 
 
447
  for (; i < oldlen && j + step < buffer_size; j += step)
 
448
    {
 
449
      sprintf (&buffer[j], "%s%.2x", separator, old[i]);
301
450
      i++;
302
451
    }
303
452
  buffer[j] = '\0';
321
470
 **/
322
471
int
323
472
gnutls_hex2bin (const char *hex_data,
324
 
                size_t hex_size, char *bin_data, size_t * bin_size)
 
473
                size_t hex_size, char *bin_data, size_t * bin_size)
325
474
{
326
475
  return _gnutls_hex2bin (hex_data, (int) hex_size, bin_data, bin_size);
327
476
}
328
477
 
329
478
int
330
479
_gnutls_hex2bin (const opaque * hex_data, int hex_size, opaque * bin_data,
331
 
                 size_t * bin_size)
 
480
                 size_t * bin_size)
332
481
{
333
482
  int i, j;
334
483
  opaque hex2_data[3];
335
484
  unsigned long val;
336
485
 
337
 
  /* FIXME: we don't handle whitespace.
338
 
   */
339
 
  hex_size /= 2;
340
 
 
341
 
  if (*bin_size < (size_t) hex_size)
342
 
    {
343
 
      gnutls_assert ();
344
 
      return GNUTLS_E_SHORT_MEMORY_BUFFER;
345
 
    }
346
 
 
347
 
  for (i = j = 0; j < hex_size; i += 2, j++)
348
 
    {
 
486
  hex2_data[2] = 0;
 
487
 
 
488
  for (i = j = 0; i < hex_size;)
 
489
    {
 
490
      if (!isxdigit (hex_data[i]))      /* skip non-hex such as the ':' in 00:FF */
 
491
        {
 
492
          i++;
 
493
          continue;
 
494
        }
 
495
 
 
496
      if (j > *bin_size)
 
497
        {
 
498
          gnutls_assert ();
 
499
          return GNUTLS_E_SHORT_MEMORY_BUFFER;
 
500
        }
 
501
 
349
502
      hex2_data[0] = hex_data[i];
350
503
      hex2_data[1] = hex_data[i + 1];
351
 
      hex2_data[2] = 0;
 
504
      i += 2;
 
505
 
352
506
      val = strtoul ((char *) hex2_data, NULL, 16);
353
507
      if (val == ULONG_MAX)
354
 
        {
355
 
          gnutls_assert ();
356
 
          return GNUTLS_E_SRP_PWD_PARSING_ERROR;
357
 
        }
 
508
        {
 
509
          gnutls_assert ();
 
510
          return GNUTLS_E_PARSING_ERROR;
 
511
        }
358
512
      bin_data[j] = val;
 
513
      j++;
359
514
    }
 
515
  *bin_size = j;
360
516
 
361
517
  return 0;
362
518
}
366
522
 * return 1 on success or 0 on error
367
523
 *
368
524
 * note: certnamesize is required as X509 certs can contain embedded NULs in
369
 
 * the strings such as CN or subjectAltName
 
525
 * the strings such as CN or subjectAltName.
 
526
 *
 
527
 * @level: is used for recursion. Use 0 when you call this function.
370
528
 */
371
529
int
372
530
_gnutls_hostname_compare (const char *certname,
373
 
                          size_t certnamesize, const char *hostname)
 
531
                          size_t certnamesize, const char *hostname, int level)
374
532
{
 
533
 
 
534
  if (level > 5)
 
535
    return 0;
 
536
 
375
537
  /* find the first different character */
376
 
  for (; *certname && *hostname && toupper (*certname) == toupper (*hostname);
 
538
  for (; *certname && *hostname && c_toupper (*certname) == c_toupper (*hostname);
377
539
       certname++, hostname++, certnamesize--)
378
540
    ;
379
541
 
389
551
      certnamesize--;
390
552
 
391
553
      while (1)
392
 
        {
393
 
          /* Use a recursive call to allow multiple wildcards */
394
 
          if (_gnutls_hostname_compare (certname, certnamesize, hostname))
395
 
            return 1;
 
554
        {
 
555
          /* Use a recursive call to allow multiple wildcards */
 
556
          if (_gnutls_hostname_compare (certname, certnamesize, hostname, level+1))
 
557
            return 1;
396
558
 
397
 
          /* wildcards are only allowed to match a single domain
398
 
             component or component fragment */
399
 
          if (*hostname == '\0' || *hostname == '.')
400
 
            break;
401
 
          hostname++;
402
 
        }
 
559
          /* wildcards are only allowed to match a single domain
 
560
             component or component fragment */
 
561
          if (*hostname == '\0' || *hostname == '.')
 
562
            break;
 
563
          hostname++;
 
564
        }
403
565
 
404
566
      return 0;
405
567
    }
406
568
 
407
569
  return 0;
408
570
}
 
571
 
 
572
int
 
573
_gnutls_buffer_append_prefix (gnutls_buffer_st * buf, size_t data_size)
 
574
{
 
575
  opaque ss[4];
 
576
  _gnutls_write_uint32 (data_size, ss);
 
577
  return _gnutls_buffer_append_data (buf, ss, 4);
 
578
}
 
579
 
 
580
/* Reads an uint32 number from the buffer. If check is non zero it will also check whether
 
581
 * the number read, is less than the data in the buffer
 
582
 */
 
583
int
 
584
_gnutls_buffer_pop_prefix (gnutls_buffer_st * buf, size_t * data_size,
 
585
                           int check)
 
586
{
 
587
  size_t size;
 
588
 
 
589
  if (buf->length < 4)
 
590
    {
 
591
      gnutls_assert ();
 
592
      return GNUTLS_E_PARSING_ERROR;
 
593
    }
 
594
 
 
595
  size = _gnutls_read_uint32 (buf->data);
 
596
  if (check && size > buf->length - 4)
 
597
    {
 
598
      gnutls_assert ();
 
599
      return GNUTLS_E_PARSING_ERROR;
 
600
    }
 
601
 
 
602
  buf->data += 4;
 
603
  buf->length -= 4;
 
604
 
 
605
  *data_size = size;
 
606
 
 
607
  return 0;
 
608
}
 
609
 
 
610
int
 
611
_gnutls_buffer_pop_datum_prefix (gnutls_buffer_st * buf,
 
612
                                 gnutls_datum_t * data)
 
613
{
 
614
  size_t size;
 
615
  int ret;
 
616
 
 
617
  ret = _gnutls_buffer_pop_prefix (buf, &size, 1);
 
618
  if (ret < 0)
 
619
    {
 
620
      gnutls_assert ();
 
621
      return ret;
 
622
    }
 
623
 
 
624
  if (size > 0)
 
625
    {
 
626
      size_t osize = size;
 
627
      _gnutls_buffer_pop_datum (buf, data, size);
 
628
      if (osize != data->size)
 
629
        {
 
630
          gnutls_assert ();
 
631
          return GNUTLS_E_PARSING_ERROR;
 
632
        }
 
633
    }
 
634
  else
 
635
    {
 
636
      data->size = 0;
 
637
      data->data = NULL;
 
638
    }
 
639
 
 
640
  return 0;
 
641
}
 
642
 
 
643
int
 
644
_gnutls_buffer_append_data_prefix (gnutls_buffer_st * buf, const void *data,
 
645
                                   size_t data_size)
 
646
{
 
647
  _gnutls_buffer_append_prefix (buf, data_size);
 
648
  if (data_size > 0)
 
649
    return _gnutls_buffer_append_data (buf, data, data_size);
 
650
 
 
651
  return 0;
 
652
}
 
653
 
 
654
int
 
655
_gnutls_buffer_pop_data_prefix (gnutls_buffer_st * buf, void *data,
 
656
                                size_t * data_size)
 
657
{
 
658
  size_t size;
 
659
  int ret;
 
660
 
 
661
  ret = _gnutls_buffer_pop_prefix (buf, &size, 1);
 
662
  if (ret < 0)
 
663
    {
 
664
      gnutls_assert ();
 
665
      return ret;
 
666
    }
 
667
 
 
668
  if (size > 0)
 
669
    _gnutls_buffer_pop_data (buf, data, data_size);
 
670
 
 
671
  return 0;
 
672
}