~ubuntu-branches/ubuntu/trusty/gnutls26/trusty

« back to all changes in this revision

Viewing changes to lib/ext_max_record.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
* 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_int.h"
29
29
#include "gnutls_errors.h"
30
30
#include "gnutls_num.h"
 
31
#include <gnutls_extensions.h>
31
32
#include <ext_max_record.h>
32
33
 
 
34
static int _gnutls_max_record_recv_params (gnutls_session_t session,
 
35
                                           const opaque * data,
 
36
                                           size_t data_size);
 
37
static int _gnutls_max_record_send_params (gnutls_session_t session,
 
38
                                           opaque * data, size_t);
 
39
 
 
40
static int _gnutls_max_record_unpack (gnutls_buffer_st * ps,
 
41
                                      extension_priv_data_t * _priv);
 
42
static int _gnutls_max_record_pack (extension_priv_data_t _priv,
 
43
                                    gnutls_buffer_st * ps);
 
44
 
 
45
/* Maps record size to numbers according to the
 
46
 * extensions draft.
 
47
 */
 
48
static int _gnutls_mre_num2record (int num);
 
49
static int _gnutls_mre_record2num (uint16_t record_size);
 
50
 
 
51
 
 
52
extension_entry_st ext_mod_max_record_size = {
 
53
  .name = "MAX RECORD SIZE",
 
54
  .type = GNUTLS_EXTENSION_MAX_RECORD_SIZE,
 
55
  .parse_type = GNUTLS_EXT_TLS,
 
56
 
 
57
  .recv_func = _gnutls_max_record_recv_params,
 
58
  .send_func = _gnutls_max_record_send_params,
 
59
  .pack_func = _gnutls_max_record_pack,
 
60
  .unpack_func = _gnutls_max_record_unpack,
 
61
  .deinit_func = NULL
 
62
};
 
63
 
33
64
/* 
34
65
 * In case of a server: if a MAX_RECORD_SIZE extension type is received then it stores
35
66
 * into the session the new value. The server may use gnutls_get_max_record_size(),
40
71
 *
41
72
 */
42
73
 
43
 
int
 
74
static int
44
75
_gnutls_max_record_recv_params (gnutls_session_t session,
45
 
                                const opaque * data, size_t _data_size)
 
76
                                const opaque * data, size_t _data_size)
46
77
{
47
78
  ssize_t new_size;
48
79
  ssize_t data_size = _data_size;
 
80
  extension_priv_data_t epriv;
 
81
  int ret;
49
82
 
50
83
  if (session->security_parameters.entity == GNUTLS_SERVER)
51
84
    {
52
85
      if (data_size > 0)
53
 
        {
54
 
          DECR_LEN (data_size, 1);
55
 
 
56
 
          new_size = _gnutls_mre_num2record (data[0]);
57
 
 
58
 
          if (new_size < 0)
59
 
            {
60
 
              gnutls_assert ();
61
 
              return new_size;
62
 
            }
63
 
 
64
 
          session->security_parameters.max_record_send_size = new_size;
65
 
          session->security_parameters.max_record_recv_size = new_size;
66
 
        }
 
86
        {
 
87
          DECR_LEN (data_size, 1);
 
88
 
 
89
          new_size = _gnutls_mre_num2record (data[0]);
 
90
 
 
91
          if (new_size < 0)
 
92
            {
 
93
              gnutls_assert ();
 
94
              return new_size;
 
95
            }
 
96
 
 
97
          session->security_parameters.max_record_send_size = new_size;
 
98
          session->security_parameters.max_record_recv_size = new_size;
 
99
        }
67
100
    }
68
101
  else
69
 
    {                           /* CLIENT SIDE - we must check if the sent record size is the right one 
70
 
                                 */
 
102
    {                           /* CLIENT SIDE - we must check if the sent record size is the right one 
 
103
                                 */
71
104
      if (data_size > 0)
72
 
        {
73
 
 
74
 
          if (data_size != 1)
75
 
            {
76
 
              gnutls_assert ();
77
 
              return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
78
 
            }
79
 
 
80
 
          new_size = _gnutls_mre_num2record (data[0]);
81
 
 
82
 
          if (new_size < 0
83
 
              || new_size != session->internals.proposed_record_size)
84
 
            {
85
 
              gnutls_assert ();
86
 
              return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
87
 
            }
88
 
          else
89
 
            {
90
 
              session->security_parameters.max_record_recv_size =
91
 
                session->internals.proposed_record_size;
92
 
            }
93
 
 
94
 
        }
 
105
        {
 
106
          ret = _gnutls_ext_get_session_data (session,
 
107
                                              GNUTLS_EXTENSION_MAX_RECORD_SIZE,
 
108
                                              &epriv);
 
109
          if (ret < 0)
 
110
            {
 
111
              gnutls_assert ();
 
112
              return GNUTLS_E_INTERNAL_ERROR;
 
113
            }
 
114
 
 
115
          if (data_size != 1)
 
116
            {
 
117
              gnutls_assert ();
 
118
              return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
 
119
            }
 
120
 
 
121
          new_size = _gnutls_mre_num2record (data[0]);
 
122
 
 
123
          if (new_size < 0 || new_size != epriv.num)
 
124
            {
 
125
              gnutls_assert ();
 
126
              return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
 
127
            }
 
128
          else
 
129
            {
 
130
              session->security_parameters.max_record_recv_size = epriv.num;
 
131
            }
 
132
 
 
133
        }
95
134
 
96
135
 
97
136
    }
101
140
 
102
141
/* returns data_size or a negative number on failure
103
142
 */
104
 
int
 
143
static int
105
144
_gnutls_max_record_send_params (gnutls_session_t session, opaque * data,
106
 
                                size_t data_size)
 
145
                                size_t data_size)
107
146
{
108
147
  uint16_t len;
 
148
  int ret;
 
149
 
109
150
  /* this function sends the client extension data (dnsname) */
110
151
  if (session->security_parameters.entity == GNUTLS_CLIENT)
111
152
    {
112
 
 
113
 
      if (session->internals.proposed_record_size != DEFAULT_MAX_RECORD_SIZE)
114
 
        {
115
 
          len = 1;
116
 
          if (data_size < len)
117
 
            {
118
 
              gnutls_assert ();
119
 
              return GNUTLS_E_SHORT_MEMORY_BUFFER;
120
 
            }
121
 
 
122
 
          data[0] =
123
 
            (uint8_t) _gnutls_mre_record2num (session->
124
 
                                              internals.proposed_record_size);
125
 
          return len;
126
 
        }
 
153
      extension_priv_data_t epriv;
 
154
 
 
155
      ret = _gnutls_ext_get_session_data (session,
 
156
                                          GNUTLS_EXTENSION_MAX_RECORD_SIZE,
 
157
                                          &epriv);
 
158
      if (ret < 0)              /* it is ok not to have it */
 
159
        {
 
160
          return 0;
 
161
        }
 
162
 
 
163
      if (epriv.num != DEFAULT_MAX_RECORD_SIZE)
 
164
        {
 
165
          len = 1;
 
166
          if (data_size < len)
 
167
            {
 
168
              gnutls_assert ();
 
169
              return GNUTLS_E_SHORT_MEMORY_BUFFER;
 
170
            }
 
171
 
 
172
          data[0] = (uint8_t) _gnutls_mre_record2num (epriv.num);
 
173
          return len;
 
174
        }
127
175
 
128
176
    }
129
177
  else
130
 
    {                           /* server side */
 
178
    {                           /* server side */
131
179
 
132
180
      if (session->security_parameters.max_record_recv_size !=
133
 
          DEFAULT_MAX_RECORD_SIZE)
134
 
        {
135
 
          len = 1;
136
 
          if (data_size < len)
137
 
            {
138
 
              gnutls_assert ();
139
 
              return GNUTLS_E_SHORT_MEMORY_BUFFER;
140
 
            }
 
181
          DEFAULT_MAX_RECORD_SIZE)
 
182
        {
 
183
          len = 1;
 
184
          if (data_size < len)
 
185
            {
 
186
              gnutls_assert ();
 
187
              return GNUTLS_E_SHORT_MEMORY_BUFFER;
 
188
            }
141
189
 
142
 
          data[0] =
143
 
            (uint8_t)
144
 
            _gnutls_mre_record2num
145
 
            (session->security_parameters.max_record_recv_size);
146
 
          return len;
147
 
        }
 
190
          data[0] =
 
191
            (uint8_t)
 
192
            _gnutls_mre_record2num
 
193
            (session->security_parameters.max_record_recv_size);
 
194
          return len;
 
195
        }
148
196
 
149
197
 
150
198
    }
152
200
  return 0;
153
201
}
154
202
 
 
203
 
 
204
static int
 
205
_gnutls_max_record_pack (extension_priv_data_t epriv, gnutls_buffer_st * ps)
 
206
{
 
207
  int ret;
 
208
 
 
209
  BUFFER_APPEND_NUM (ps, epriv.num);
 
210
 
 
211
  return 0;
 
212
 
 
213
}
 
214
 
 
215
static int
 
216
_gnutls_max_record_unpack (gnutls_buffer_st * ps,
 
217
                           extension_priv_data_t * _priv)
 
218
{
 
219
  extension_priv_data_t epriv;
 
220
  int ret;
 
221
 
 
222
  BUFFER_POP_NUM (ps, epriv.num);
 
223
 
 
224
  *_priv = epriv;
 
225
 
 
226
  ret = 0;
 
227
error:
 
228
  return ret;
 
229
}
 
230
 
 
231
 
155
232
/* Maps numbers to record sizes according to the
156
233
 * extensions draft.
157
234
 */
158
 
int
 
235
static int
159
236
_gnutls_mre_num2record (int num)
160
237
{
161
238
  switch (num)
176
253
/* Maps record size to numbers according to the
177
254
 * extensions draft.
178
255
 */
179
 
int
 
256
static int
180
257
_gnutls_mre_record2num (uint16_t record_size)
181
258
{
182
259
  switch (record_size)
194
271
    }
195
272
 
196
273
}
 
274
 
 
275
/**
 
276
 * gnutls_record_get_max_size:
 
277
 * @session: is a #gnutls_session_t structure.
 
278
 *
 
279
 * Get the record size.  The maximum record size is negotiated by the
 
280
 * client after the first handshake message.
 
281
 *
 
282
 * Returns: The maximum record packet size in this connection.
 
283
 **/
 
284
size_t
 
285
gnutls_record_get_max_size (gnutls_session_t session)
 
286
{
 
287
  /* Recv will hold the negotiated max record size
 
288
   * always.
 
289
   */
 
290
  return session->security_parameters.max_record_recv_size;
 
291
}
 
292
 
 
293
 
 
294
/**
 
295
 * gnutls_record_set_max_size:
 
296
 * @session: is a #gnutls_session_t structure.
 
297
 * @size: is the new size
 
298
 *
 
299
 * This function sets the maximum record packet size in this
 
300
 * connection.  This property can only be set to clients.  The server
 
301
 * may choose not to accept the requested size.
 
302
 *
 
303
 * Acceptable values are 512(=2^9), 1024(=2^10), 2048(=2^11) and
 
304
 * 4096(=2^12).  The requested record size does get in effect
 
305
 * immediately only while sending data. The receive part will take
 
306
 * effect after a successful handshake.
 
307
 *
 
308
 * This function uses a TLS extension called 'max record size'.  Not
 
309
 * all TLS implementations use or even understand this extension.
 
310
 *
 
311
 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
 
312
 *   otherwise an error code is returned.
 
313
 **/
 
314
ssize_t
 
315
gnutls_record_set_max_size (gnutls_session_t session, size_t size)
 
316
{
 
317
  ssize_t new_size;
 
318
  extension_priv_data_t epriv;
 
319
 
 
320
  if (session->security_parameters.entity == GNUTLS_SERVER)
 
321
    return GNUTLS_E_INVALID_REQUEST;
 
322
 
 
323
  new_size = _gnutls_mre_record2num (size);
 
324
 
 
325
  if (new_size < 0)
 
326
    {
 
327
      gnutls_assert ();
 
328
      return new_size;
 
329
    }
 
330
 
 
331
  session->security_parameters.max_record_send_size = size;
 
332
  epriv.num = size;
 
333
 
 
334
  _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_MAX_RECORD_SIZE,
 
335
                                epriv);
 
336
 
 
337
  return 0;
 
338
}