~ubuntu-branches/ubuntu/quantal/gnutls26/quantal-security

« back to all changes in this revision

Viewing changes to lib/ext_server_name.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:
29
29
#include "gnutls_num.h"
30
30
#include <ext_server_name.h>
31
31
 
 
32
static int _gnutls_server_name_recv_params (gnutls_session_t session,
 
33
                                            const opaque * data,
 
34
                                            size_t data_size);
 
35
static int _gnutls_server_name_send_params (gnutls_session_t session,
 
36
                                            opaque * data, size_t);
 
37
 
 
38
static int _gnutls_server_name_unpack (gnutls_buffer_st * ps,
 
39
                                       extension_priv_data_t * _priv);
 
40
static int _gnutls_server_name_pack (extension_priv_data_t _priv,
 
41
                                     gnutls_buffer_st * ps);
 
42
static void _gnutls_server_name_deinit_data (extension_priv_data_t priv);
 
43
 
 
44
 
 
45
extension_entry_st ext_mod_server_name = {
 
46
  .name = "SERVER NAME",
 
47
  .type = GNUTLS_EXTENSION_SERVER_NAME,
 
48
  .parse_type = GNUTLS_EXT_APPLICATION,
 
49
 
 
50
  .recv_func = _gnutls_server_name_recv_params,
 
51
  .send_func = _gnutls_server_name_send_params,
 
52
  .pack_func = _gnutls_server_name_pack,
 
53
  .unpack_func = _gnutls_server_name_unpack,
 
54
  .deinit_func = _gnutls_server_name_deinit_data,
 
55
};
 
56
 
32
57
/*
33
58
 * In case of a server: if a NAME_DNS extension type is received then
34
59
 * it stores into the session the value of NAME_DNS. The server may
38
63
 * in the session then it sends the extension to the peer.
39
64
 *
40
65
 */
41
 
 
42
 
int
 
66
static int
43
67
_gnutls_server_name_recv_params (gnutls_session_t session,
44
 
                                 const opaque * data, size_t _data_size)
 
68
                                 const opaque * data, size_t _data_size)
45
69
{
46
70
  int i;
47
71
  const unsigned char *p;
48
72
  uint16_t len, type;
49
73
  ssize_t data_size = _data_size;
50
74
  int server_names = 0;
 
75
  server_name_ext_st *priv;
 
76
  extension_priv_data_t epriv;
51
77
 
52
78
  if (session->security_parameters.entity == GNUTLS_SERVER)
53
79
    {
55
81
      len = _gnutls_read_uint16 (data);
56
82
 
57
83
      if (len != data_size)
58
 
        {
59
 
          /* This is unexpected packet length, but
60
 
           * just ignore it, for now.
61
 
           */
62
 
          gnutls_assert ();
63
 
          return 0;
64
 
        }
 
84
        {
 
85
          /* This is unexpected packet length, but
 
86
           * just ignore it, for now.
 
87
           */
 
88
          gnutls_assert ();
 
89
          return 0;
 
90
        }
65
91
 
66
92
      p = data + 2;
67
93
 
68
94
      /* Count all server_names in the packet. */
69
95
      while (data_size > 0)
70
 
        {
71
 
          DECR_LENGTH_RET (data_size, 1, 0);
72
 
          p++;
73
 
 
74
 
          DECR_LEN (data_size, 2);
75
 
          len = _gnutls_read_uint16 (p);
76
 
          p += 2;
77
 
 
78
 
          if (len > 0)
79
 
            {
80
 
              DECR_LENGTH_RET (data_size, len, 0);
81
 
              server_names++;
82
 
              p += len;
83
 
            }
84
 
          else
85
 
            _gnutls_handshake_log
86
 
              ("HSK[%p]: Received zero size server name (under attack?)\n",
87
 
               session);
88
 
 
89
 
        }
 
96
        {
 
97
          DECR_LENGTH_RET (data_size, 1, 0);
 
98
          p++;
 
99
 
 
100
          DECR_LEN (data_size, 2);
 
101
          len = _gnutls_read_uint16 (p);
 
102
          p += 2;
 
103
 
 
104
          if (len > 0)
 
105
            {
 
106
              DECR_LENGTH_RET (data_size, len, 0);
 
107
              server_names++;
 
108
              p += len;
 
109
            }
 
110
          else
 
111
            _gnutls_handshake_log
 
112
              ("HSK[%p]: Received zero size server name (under attack?)\n",
 
113
               session);
 
114
 
 
115
        }
90
116
 
91
117
      /* we cannot accept more server names.
92
118
       */
93
119
      if (server_names > MAX_SERVER_NAME_EXTENSIONS)
94
 
        {
95
 
          _gnutls_handshake_log
96
 
            ("HSK[%p]: Too many server names received (under attack?)\n",
97
 
             session);
98
 
          server_names = MAX_SERVER_NAME_EXTENSIONS;
99
 
        }
 
120
        {
 
121
          _gnutls_handshake_log
 
122
            ("HSK[%p]: Too many server names received (under attack?)\n",
 
123
             session);
 
124
          server_names = MAX_SERVER_NAME_EXTENSIONS;
 
125
        }
100
126
 
101
 
      session->security_parameters.extensions.server_names_size =
102
 
        server_names;
103
127
      if (server_names == 0)
104
 
        return 0;               /* no names found */
105
 
 
 
128
        return 0;               /* no names found */
 
129
 
 
130
      priv = gnutls_calloc (1, sizeof (*priv));
 
131
      if (priv == NULL)
 
132
        {
 
133
          gnutls_assert ();
 
134
          return GNUTLS_E_MEMORY_ERROR;
 
135
        }
 
136
 
 
137
      priv->server_names_size = server_names;
106
138
 
107
139
      p = data + 2;
108
140
      for (i = 0; i < server_names; i++)
109
 
        {
110
 
          type = *p;
111
 
          p++;
112
 
 
113
 
          len = _gnutls_read_uint16 (p);
114
 
          p += 2;
115
 
 
116
 
          switch (type)
117
 
            {
118
 
            case 0:             /* NAME_DNS */
119
 
              if (len <= MAX_SERVER_NAME_SIZE)
120
 
                {
121
 
                  memcpy (session->security_parameters.
122
 
                          extensions.server_names[i].name, p, len);
123
 
                  session->security_parameters.extensions.server_names[i].
124
 
                    name_length = len;
125
 
                  session->security_parameters.extensions.server_names[i].
126
 
                    type = GNUTLS_NAME_DNS;
127
 
                  break;
128
 
                }
129
 
            }
130
 
 
131
 
          /* move to next record */
132
 
          p += len;
133
 
        }
 
141
        {
 
142
          type = *p;
 
143
          p++;
 
144
 
 
145
          len = _gnutls_read_uint16 (p);
 
146
          p += 2;
 
147
 
 
148
          switch (type)
 
149
            {
 
150
            case 0:            /* NAME_DNS */
 
151
              if (len <= MAX_SERVER_NAME_SIZE)
 
152
                {
 
153
                  memcpy (priv->server_names[i].name, p, len);
 
154
                  priv->server_names[i].name_length = len;
 
155
                  priv->server_names[i].type = GNUTLS_NAME_DNS;
 
156
                  break;
 
157
                }
 
158
            }
 
159
 
 
160
          /* move to next record */
 
161
          p += len;
 
162
        }
 
163
 
 
164
      epriv.ptr = priv;
 
165
      _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SERVER_NAME,
 
166
                                    epriv);
 
167
 
134
168
    }
 
169
 
135
170
  return 0;
136
171
}
137
172
 
138
173
/* returns data_size or a negative number on failure
139
174
 */
140
 
int
 
175
static int
141
176
_gnutls_server_name_send_params (gnutls_session_t session,
142
 
                                 opaque * data, size_t _data_size)
 
177
                                 opaque * data, size_t _data_size)
143
178
{
144
179
  uint16_t len;
145
180
  opaque *p;
146
181
  unsigned i;
147
182
  ssize_t data_size = _data_size;
148
 
  int total_size = 0;
 
183
  int total_size = 0, ret;
 
184
  server_name_ext_st *priv;
 
185
  extension_priv_data_t epriv;
 
186
 
 
187
  ret =
 
188
    _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SERVER_NAME,
 
189
                                  &epriv);
 
190
  if (ret < 0)
 
191
    return 0;
 
192
 
149
193
 
150
194
  /* this function sends the client extension data (dnsname)
151
195
   */
152
196
  if (session->security_parameters.entity == GNUTLS_CLIENT)
153
197
    {
 
198
      priv = epriv.ptr;
154
199
 
155
 
      if (session->security_parameters.extensions.server_names_size == 0)
156
 
        return 0;
 
200
      if (priv->server_names_size == 0)
 
201
        return 0;
157
202
 
158
203
      /* uint16_t
159
204
       */
160
205
      total_size = 2;
161
 
      for (i = 0;
162
 
           i < session->security_parameters.extensions.server_names_size; i++)
163
 
        {
164
 
          /* count the total size
165
 
           */
166
 
          len =
167
 
            session->security_parameters.extensions.
168
 
            server_names[i].name_length;
 
206
      for (i = 0; i < priv->server_names_size; i++)
 
207
        {
 
208
          /* count the total size
 
209
           */
 
210
          len = priv->server_names[i].name_length;
169
211
 
170
 
          /* uint8_t + uint16_t + size
171
 
           */
172
 
          total_size += 1 + 2 + len;
173
 
        }
 
212
          /* uint8_t + uint16_t + size
 
213
           */
 
214
          total_size += 1 + 2 + len;
 
215
        }
174
216
 
175
217
      p = data;
176
218
 
179
221
      DECR_LENGTH_RET (data_size, 2, GNUTLS_E_SHORT_MEMORY_BUFFER);
180
222
      _gnutls_write_uint16 (total_size - 2, p);
181
223
      p += 2;
182
 
 
183
 
      for (i = 0;
184
 
           i < session->security_parameters.extensions.server_names_size; i++)
185
 
        {
186
 
 
187
 
          switch (session->security_parameters.extensions.server_names[i].
188
 
                  type)
189
 
            {
190
 
            case GNUTLS_NAME_DNS:
191
 
 
192
 
              len =
193
 
                session->security_parameters.extensions.server_names[i].
194
 
                name_length;
195
 
              if (len == 0)
196
 
                break;
197
 
 
198
 
              /* UINT8: type of this extension
199
 
               * UINT16: size of the first name
200
 
               * LEN: the actual server name.
201
 
               */
202
 
              DECR_LENGTH_RET (data_size, len + 3,
203
 
                               GNUTLS_E_SHORT_MEMORY_BUFFER);
204
 
 
205
 
              *p = 0;           /* NAME_DNS type */
206
 
              p++;
207
 
 
208
 
              _gnutls_write_uint16 (len, p);
209
 
              p += 2;
210
 
 
211
 
              memcpy (p,
212
 
                      session->security_parameters.extensions.server_names[i].
213
 
                      name, len);
214
 
              p += len;
215
 
              break;
216
 
            default:
217
 
              gnutls_assert ();
218
 
              return GNUTLS_E_INTERNAL_ERROR;
219
 
            }
220
 
        }
 
224
      for (i = 0; i < priv->server_names_size; i++)
 
225
        {
 
226
 
 
227
          switch (priv->server_names[i].type)
 
228
            {
 
229
            case GNUTLS_NAME_DNS:
 
230
              len = priv->server_names[i].name_length;
 
231
              if (len == 0)
 
232
                break;
 
233
 
 
234
              /* UINT8: type of this extension
 
235
               * UINT16: size of the first name
 
236
               * LEN: the actual server name.
 
237
               */
 
238
              DECR_LENGTH_RET (data_size, len + 3,
 
239
                               GNUTLS_E_SHORT_MEMORY_BUFFER);
 
240
 
 
241
              *p = 0;           /* NAME_DNS type */
 
242
              p++;
 
243
 
 
244
              _gnutls_write_uint16 (len, p);
 
245
              p += 2;
 
246
 
 
247
              memcpy (p, priv->server_names[i].name, len);
 
248
              p += len;
 
249
              break;
 
250
            default:
 
251
              gnutls_assert ();
 
252
              return GNUTLS_E_INTERNAL_ERROR;
 
253
            }
 
254
        }
221
255
    }
222
256
 
223
257
  return total_size;
253
287
 **/
254
288
int
255
289
gnutls_server_name_get (gnutls_session_t session, void *data,
256
 
                        size_t * data_length,
257
 
                        unsigned int *type, unsigned int indx)
 
290
                        size_t * data_length,
 
291
                        unsigned int *type, unsigned int indx)
258
292
{
259
293
  char *_data = data;
 
294
  server_name_ext_st *priv;
 
295
  int ret;
 
296
  extension_priv_data_t epriv;
260
297
 
261
298
  if (session->security_parameters.entity == GNUTLS_CLIENT)
262
299
    {
264
301
      return GNUTLS_E_INVALID_REQUEST;
265
302
    }
266
303
 
267
 
  if (indx + 1 > session->security_parameters.extensions.server_names_size)
268
 
    {
269
 
      return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
270
 
    }
271
 
 
272
 
  *type = session->security_parameters.extensions.server_names[indx].type;
273
 
 
274
 
  if (*data_length >            /* greater since we need one extra byte for the null */
275
 
      session->security_parameters.extensions.server_names[indx].name_length)
276
 
    {
277
 
      *data_length =
278
 
        session->security_parameters.extensions.
279
 
        server_names[indx].name_length;
280
 
      memcpy (data,
281
 
              session->security_parameters.extensions.server_names[indx].name,
282
 
              *data_length);
283
 
 
284
 
      if (*type == GNUTLS_NAME_DNS)     /* null terminate */
285
 
        _data[(*data_length)] = 0;
 
304
  ret =
 
305
    _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SERVER_NAME,
 
306
                                  &epriv);
 
307
  if (ret < 0)
 
308
    {
 
309
      gnutls_assert ();
 
310
      return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
 
311
    }
 
312
 
 
313
  priv = epriv.ptr;
 
314
 
 
315
  if (indx + 1 > priv->server_names_size)
 
316
    {
 
317
      return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
 
318
    }
 
319
 
 
320
  *type = priv->server_names[indx].type;
 
321
 
 
322
  if (*data_length >            /* greater since we need one extra byte for the null */
 
323
      priv->server_names[indx].name_length)
 
324
    {
 
325
      *data_length = priv->server_names[indx].name_length;
 
326
      memcpy (data, priv->server_names[indx].name, *data_length);
 
327
 
 
328
      if (*type == GNUTLS_NAME_DNS)     /* null terminate */
 
329
        _data[(*data_length)] = 0;
286
330
 
287
331
    }
288
332
  else
289
333
    {
290
 
      *data_length =
291
 
        session->security_parameters.extensions.
292
 
        server_names[indx].name_length;
 
334
      *data_length = priv->server_names[indx].name_length;
293
335
      return GNUTLS_E_SHORT_MEMORY_BUFFER;
294
336
    }
295
337
 
318
360
 **/
319
361
int
320
362
gnutls_server_name_set (gnutls_session_t session,
321
 
                        gnutls_server_name_type_t type,
322
 
                        const void *name, size_t name_length)
 
363
                        gnutls_server_name_type_t type,
 
364
                        const void *name, size_t name_length)
323
365
{
324
 
  int server_names;
 
366
  int server_names, ret;
 
367
  server_name_ext_st *priv;
 
368
  extension_priv_data_t epriv;
 
369
  int set = 0;
325
370
 
326
371
  if (session->security_parameters.entity == GNUTLS_SERVER)
327
372
    {
332
377
  if (name_length > MAX_SERVER_NAME_SIZE)
333
378
    return GNUTLS_E_SHORT_MEMORY_BUFFER;
334
379
 
335
 
  server_names =
336
 
    session->security_parameters.extensions.server_names_size + 1;
 
380
  ret =
 
381
    _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SERVER_NAME,
 
382
                                  &epriv);
 
383
  if (ret < 0)
 
384
    {
 
385
      set = 1;
 
386
    }
 
387
 
 
388
  if (set != 0)
 
389
    {
 
390
      priv = gnutls_calloc (1, sizeof (*priv));
 
391
      if (priv == NULL)
 
392
        {
 
393
          gnutls_assert ();
 
394
          return GNUTLS_E_MEMORY_ERROR;
 
395
        }
 
396
      epriv.ptr = priv;
 
397
    }
 
398
  else
 
399
    priv = epriv.ptr;
 
400
 
 
401
  server_names = priv->server_names_size + 1;
337
402
 
338
403
  if (server_names > MAX_SERVER_NAME_EXTENSIONS)
339
404
    server_names = MAX_SERVER_NAME_EXTENSIONS;
340
405
 
341
 
  session->security_parameters.extensions.server_names
342
 
    [server_names - 1].type = type;
343
 
  memcpy (session->security_parameters.
344
 
          extensions.server_names[server_names - 1].name, name, name_length);
345
 
  session->security_parameters.extensions.server_names[server_names -
346
 
                                                       1].name_length =
347
 
    name_length;
348
 
 
349
 
  session->security_parameters.extensions.server_names_size++;
350
 
 
351
 
  return 0;
 
406
  priv->server_names[server_names - 1].type = type;
 
407
  memcpy (priv->server_names[server_names - 1].name, name, name_length);
 
408
  priv->server_names[server_names - 1].name_length = name_length;
 
409
 
 
410
  priv->server_names_size++;
 
411
 
 
412
  if (set != 0)
 
413
    _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SERVER_NAME,
 
414
                                  epriv);
 
415
 
 
416
  return 0;
 
417
}
 
418
 
 
419
static void
 
420
_gnutls_server_name_deinit_data (extension_priv_data_t priv)
 
421
{
 
422
  gnutls_free (priv.ptr);
 
423
}
 
424
 
 
425
static int
 
426
_gnutls_server_name_pack (extension_priv_data_t epriv, gnutls_buffer_st * ps)
 
427
{
 
428
  server_name_ext_st *priv = epriv.ptr;
 
429
  int i, ret;
 
430
 
 
431
  BUFFER_APPEND_NUM (ps, priv->server_names_size);
 
432
  for (i = 0; i < priv->server_names_size; i++)
 
433
    {
 
434
      BUFFER_APPEND_NUM (ps, priv->server_names[i].type);
 
435
      BUFFER_APPEND_PFX (ps, priv->server_names[i].name,
 
436
                         priv->server_names[i].name_length);
 
437
    }
 
438
  return 0;
 
439
}
 
440
 
 
441
static int
 
442
_gnutls_server_name_unpack (gnutls_buffer_st * ps,
 
443
                            extension_priv_data_t * _priv)
 
444
{
 
445
  server_name_ext_st *priv;
 
446
  int i, ret;
 
447
  extension_priv_data_t epriv;
 
448
 
 
449
  priv = gnutls_calloc (1, sizeof (*priv));
 
450
  if (priv == NULL)
 
451
    {
 
452
      gnutls_assert ();
 
453
      return GNUTLS_E_MEMORY_ERROR;
 
454
    }
 
455
 
 
456
  BUFFER_POP_NUM (ps, priv->server_names_size);
 
457
  for (i = 0; i < priv->server_names_size; i++)
 
458
    {
 
459
      BUFFER_POP_NUM (ps, priv->server_names[i].type);
 
460
      BUFFER_POP_NUM (ps, priv->server_names[i].name_length);
 
461
      if (priv->server_names[i].name_length >
 
462
          sizeof (priv->server_names[i].name))
 
463
        {
 
464
          gnutls_assert ();
 
465
          return GNUTLS_E_PARSING_ERROR;
 
466
        }
 
467
      BUFFER_POP (ps, priv->server_names[i].name,
 
468
                  priv->server_names[i].name_length);
 
469
    }
 
470
 
 
471
  epriv.ptr = priv;
 
472
  *_priv = epriv;
 
473
 
 
474
  return 0;
 
475
 
 
476
error:
 
477
  gnutls_free (priv);
 
478
  return ret;
352
479
}