documented fix
[gnutls.git] / lib / ext_cert_type.c
blobca5f7a0e0cb6f5b6eda7ab8068f42450417f3464
1 /*
2 * Copyright (C) 2002, 2003, 2004, 2005, 2010 Free Software Foundation,
3 * Inc.
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GnuTLS.
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.
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.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22 * USA
26 /* This file contains the code the Certificate Type TLS extension.
27 * This extension is currently gnutls specific.
30 #include "gnutls_int.h"
31 #include "gnutls_errors.h"
32 #include "gnutls_num.h"
33 #include "ext_cert_type.h"
34 #include <gnutls_state.h>
35 #include <gnutls_num.h>
37 /* Maps record size to numbers according to the
38 * extensions draft.
40 inline static int _gnutls_num2cert_type (int num);
41 inline static int _gnutls_cert_type2num (int record_size);
42 static int _gnutls_cert_type_recv_params (gnutls_session_t session,
43 const opaque * data,
44 size_t data_size);
45 static int _gnutls_cert_type_send_params (gnutls_session_t session,
46 opaque * data, size_t);
48 extension_entry_st ext_mod_cert_type = {
49 .name = "CERT TYPE",
50 .type = GNUTLS_EXTENSION_CERT_TYPE,
51 .parse_type = GNUTLS_EXT_TLS,
53 .recv_func = _gnutls_cert_type_recv_params,
54 .send_func = _gnutls_cert_type_send_params,
55 .pack_func = NULL,
56 .unpack_func = NULL,
57 .deinit_func = NULL
60 /*
61 * In case of a server: if a CERT_TYPE extension type is received then it stores
62 * into the session security parameters the new value. The server may use gnutls_session_certificate_type_get(),
63 * to access it.
65 * In case of a client: If a cert_types have been specified then we send the extension.
69 static int
70 _gnutls_cert_type_recv_params (gnutls_session_t session,
71 const opaque * data, size_t _data_size)
73 int new_type = -1, ret, i;
74 ssize_t data_size = _data_size;
76 if (session->security_parameters.entity == GNUTLS_CLIENT)
78 if (data_size > 0)
80 if (data_size != 1)
82 gnutls_assert ();
83 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
86 new_type = _gnutls_num2cert_type (data[0]);
88 if (new_type < 0)
90 gnutls_assert ();
91 return new_type;
94 /* Check if we support this cert_type */
95 if ((ret =
96 _gnutls_session_cert_type_supported (session, new_type)) < 0)
98 gnutls_assert ();
99 return ret;
102 _gnutls_session_cert_type_set (session, new_type);
105 else
106 { /* SERVER SIDE - we must check if the sent cert type is the right one
108 if (data_size > 1)
110 uint8_t len;
112 DECR_LEN (data_size, 1);
113 len = data[0];
114 DECR_LEN (data_size, len);
116 for (i = 0; i < len; i++)
118 new_type = _gnutls_num2cert_type (data[i + 1]);
120 if (new_type < 0)
121 continue;
123 /* Check if we support this cert_type */
124 if ((ret =
125 _gnutls_session_cert_type_supported (session,
126 new_type)) < 0)
128 gnutls_assert ();
129 continue;
131 else
132 break;
133 /* new_type is ok */
136 if (new_type < 0)
138 gnutls_assert ();
139 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
142 if ((ret =
143 _gnutls_session_cert_type_supported (session, new_type)) < 0)
145 gnutls_assert ();
146 /* The peer has requested unsupported certificate
147 * types. Instead of failing, procceed normally.
148 * (the ciphersuite selection would fail, or a
149 * non certificate ciphersuite will be selected).
151 return 0;
154 _gnutls_session_cert_type_set (session, new_type);
160 return 0;
163 /* returns data_size or a negative number on failure
165 static int
166 _gnutls_cert_type_send_params (gnutls_session_t session, opaque * data,
167 size_t data_size)
169 unsigned len, i;
171 /* this function sends the client extension data (dnsname) */
172 if (session->security_parameters.entity == GNUTLS_CLIENT)
175 if (session->internals.priorities.cert_type.algorithms > 0)
178 len = session->internals.priorities.cert_type.algorithms;
180 if (len == 1 &&
181 session->internals.priorities.cert_type.priority[0] ==
182 GNUTLS_CRT_X509)
184 /* We don't use this extension if X.509 certificates
185 * are used.
187 return 0;
190 if (data_size < len + 1)
192 gnutls_assert ();
193 return GNUTLS_E_SHORT_MEMORY_BUFFER;
196 /* this is a vector!
198 data[0] = (uint8_t) len;
200 for (i = 0; i < len; i++)
202 data[i + 1] =
203 _gnutls_cert_type2num (session->internals.priorities.
204 cert_type.priority[i]);
206 return len + 1;
210 else
211 { /* server side */
212 if (session->security_parameters.cert_type != DEFAULT_CERT_TYPE)
214 len = 1;
215 if (data_size < len)
217 gnutls_assert ();
218 return GNUTLS_E_SHORT_MEMORY_BUFFER;
221 data[0] =
222 _gnutls_cert_type2num (session->security_parameters.cert_type);
223 return len;
229 return 0;
232 /* Maps numbers to record sizes according to the
233 * extensions draft.
235 inline static int
236 _gnutls_num2cert_type (int num)
238 switch (num)
240 case 0:
241 return GNUTLS_CRT_X509;
242 case 1:
243 return GNUTLS_CRT_OPENPGP;
244 default:
245 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
249 /* Maps record size to numbers according to the
250 * extensions draft.
252 inline static int
253 _gnutls_cert_type2num (int cert_type)
255 switch (cert_type)
257 case GNUTLS_CRT_X509:
258 return 0;
259 case GNUTLS_CRT_OPENPGP:
260 return 1;
261 default:
262 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;