no need to check for DTLS
[gnutls.git] / lib / gnutls_auth.c
blob13eb63e546a27e1de0e55cb7af73698816bf14ee
1 /*
2 * Copyright (C) 2001-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 #include "gnutls_int.h"
24 #include "gnutls_errors.h"
25 #include "gnutls_auth.h"
26 #include "gnutls_auth.h"
27 #include "algorithms.h"
28 #include <auth/cert.h>
29 #include <auth/psk.h>
30 #include <auth/anon.h>
31 #include <gnutls_datum.h>
33 /* The functions here are used in order for authentication algorithms
34 * to be able to retrieve the needed credentials eg public and private
35 * key etc.
38 /**
39 * gnutls_credentials_clear:
40 * @session: is a #gnutls_session_t structure.
42 * Clears all the credentials previously set in this session.
43 **/
44 void
45 gnutls_credentials_clear (gnutls_session_t session)
47 if (session->key && session->key->cred)
48 { /* beginning of the list */
49 auth_cred_st *ccred, *ncred;
50 ccred = session->key->cred;
51 while (ccred != NULL)
53 ncred = ccred->next;
54 gnutls_free (ccred);
55 ccred = ncred;
57 session->key->cred = NULL;
61 /*
62 * This creates a linked list of the form:
63 * { algorithm, credentials, pointer to next }
65 /**
66 * gnutls_credentials_set:
67 * @session: is a #gnutls_session_t structure.
68 * @type: is the type of the credentials
69 * @cred: is a pointer to a structure.
71 * Sets the needed credentials for the specified type. Eg username,
72 * password - or public and private keys etc. The @cred parameter is
73 * a structure that depends on the specified type and on the current
74 * session (client or server).
76 * In order to minimize memory usage, and share credentials between
77 * several threads gnutls keeps a pointer to cred, and not the whole
78 * cred structure. Thus you will have to keep the structure allocated
79 * until you call gnutls_deinit().
81 * For %GNUTLS_CRD_ANON, @cred should be
82 * #gnutls_anon_client_credentials_t in case of a client. In case of
83 * a server it should be #gnutls_anon_server_credentials_t.
85 * For %GNUTLS_CRD_SRP, @cred should be #gnutls_srp_client_credentials_t
86 * in case of a client, and #gnutls_srp_server_credentials_t, in case
87 * of a server.
89 * For %GNUTLS_CRD_CERTIFICATE, @cred should be
90 * #gnutls_certificate_credentials_t.
92 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
93 * otherwise a negative error code is returned.
94 **/
95 int
96 gnutls_credentials_set (gnutls_session_t session,
97 gnutls_credentials_type_t type, void *cred)
99 auth_cred_st *ccred = NULL, *pcred = NULL;
100 int exists = 0;
102 if (session->key->cred == NULL)
103 { /* beginning of the list */
105 session->key->cred = gnutls_malloc (sizeof (auth_cred_st));
106 if (session->key->cred == NULL)
107 return GNUTLS_E_MEMORY_ERROR;
109 /* copy credentials locally */
110 session->key->cred->credentials = cred;
112 session->key->cred->next = NULL;
113 session->key->cred->algorithm = type;
115 else
117 ccred = session->key->cred;
118 while (ccred != NULL)
120 if (ccred->algorithm == type)
122 exists = 1;
123 break;
125 pcred = ccred;
126 ccred = ccred->next;
128 /* After this, pcred is not null.
131 if (exists == 0)
132 { /* new entry */
133 pcred->next = gnutls_malloc (sizeof (auth_cred_st));
134 if (pcred->next == NULL)
135 return GNUTLS_E_MEMORY_ERROR;
137 ccred = pcred->next;
139 /* copy credentials locally */
140 ccred->credentials = cred;
142 ccred->next = NULL;
143 ccred->algorithm = type;
145 else
146 { /* modify existing entry */
147 ccred->credentials = cred;
151 return 0;
155 * gnutls_auth_get_type:
156 * @session: is a #gnutls_session_t structure.
158 * Returns type of credentials for the current authentication schema.
159 * The returned information is to be used to distinguish the function used
160 * to access authentication data.
162 * Eg. for CERTIFICATE ciphersuites (key exchange algorithms:
163 * %GNUTLS_KX_RSA, %GNUTLS_KX_DHE_RSA), the same function are to be
164 * used to access the authentication data.
166 * Returns: The type of credentials for the current authentication
167 * schema, a #gnutls_credentials_type_t type.
169 gnutls_credentials_type_t
170 gnutls_auth_get_type (gnutls_session_t session)
172 /* This is not the credentials we must set, but the authentication data
173 * we get by the peer, so it should be reversed.
175 int server = session->security_parameters.entity == GNUTLS_SERVER ? 0 : 1;
177 return
178 _gnutls_map_kx_get_cred (_gnutls_cipher_suite_get_kx_algo
179 (session->
180 security_parameters.cipher_suite),
181 server);
185 * gnutls_auth_server_get_type:
186 * @session: is a #gnutls_session_t structure.
188 * Returns the type of credentials that were used for server authentication.
189 * The returned information is to be used to distinguish the function used
190 * to access authentication data.
192 * Returns: The type of credentials for the server authentication
193 * schema, a #gnutls_credentials_type_t type.
195 gnutls_credentials_type_t
196 gnutls_auth_server_get_type (gnutls_session_t session)
198 return
199 _gnutls_map_kx_get_cred (_gnutls_cipher_suite_get_kx_algo
200 (session->
201 security_parameters.cipher_suite), 1);
205 * gnutls_auth_client_get_type:
206 * @session: is a #gnutls_session_t structure.
208 * Returns the type of credentials that were used for client authentication.
209 * The returned information is to be used to distinguish the function used
210 * to access authentication data.
212 * Returns: The type of credentials for the client authentication
213 * schema, a #gnutls_credentials_type_t type.
215 gnutls_credentials_type_t
216 gnutls_auth_client_get_type (gnutls_session_t session)
218 return
219 _gnutls_map_kx_get_cred (_gnutls_cipher_suite_get_kx_algo
220 (session->
221 security_parameters.cipher_suite), 0);
226 * This returns a pointer to the linked list. Don't
227 * free that!!!
229 const void *
230 _gnutls_get_kx_cred (gnutls_session_t session,
231 gnutls_kx_algorithm_t algo, int *err)
233 int server = session->security_parameters.entity == GNUTLS_SERVER ? 1 : 0;
235 return _gnutls_get_cred (session->key,
236 _gnutls_map_kx_get_cred (algo, server), err);
239 const void *
240 _gnutls_get_cred (gnutls_key_st key, gnutls_credentials_type_t type, int *err)
242 const void *retval = NULL;
243 int _err = -1;
244 auth_cred_st *ccred;
246 if (key == NULL)
247 goto out;
249 ccred = key->cred;
250 while (ccred != NULL)
252 if (ccred->algorithm == type)
254 break;
256 ccred = ccred->next;
258 if (ccred == NULL)
259 goto out;
261 _err = 0;
262 retval = ccred->credentials;
264 out:
265 if (err != NULL)
266 *err = _err;
267 return retval;
271 * _gnutls_get_auth_info - Returns a pointer to authentication information.
272 * @session: is a #gnutls_session_t structure.
274 * This function must be called after a successful gnutls_handshake().
275 * Returns a pointer to authentication information. That information
276 * is data obtained by the handshake protocol, the key exchange algorithm,
277 * and the TLS extensions messages.
279 * In case of GNUTLS_CRD_ANON returns a type of &anon_(server/client)_auth_info_t;
280 * In case of GNUTLS_CRD_CERTIFICATE returns a type of &cert_auth_info_t;
281 * In case of GNUTLS_CRD_SRP returns a type of &srp_(server/client)_auth_info_t;
283 void *
284 _gnutls_get_auth_info (gnutls_session_t session)
286 return session->key->auth_info;
290 * _gnutls_free_auth_info - Frees the auth info structure
291 * @session: is a #gnutls_session_t structure.
293 * This function frees the auth info structure and sets it to
294 * null. It must be called since some structures contain malloced
295 * elements.
297 void
298 _gnutls_free_auth_info (gnutls_session_t session)
300 dh_info_st *dh_info;
301 rsa_info_st *rsa_info;
303 if (session == NULL || session->key == NULL)
305 gnutls_assert ();
306 return;
309 switch (session->key->auth_info_type)
311 case GNUTLS_CRD_SRP:
312 break;
313 case GNUTLS_CRD_ANON:
315 anon_auth_info_t info = _gnutls_get_auth_info (session);
317 if (info == NULL)
318 break;
320 dh_info = &info->dh;
321 _gnutls_free_dh_info (dh_info);
323 break;
324 case GNUTLS_CRD_PSK:
326 psk_auth_info_t info = _gnutls_get_auth_info (session);
328 if (info == NULL)
329 break;
331 dh_info = &info->dh;
332 _gnutls_free_dh_info (dh_info);
334 break;
335 case GNUTLS_CRD_CERTIFICATE:
337 unsigned int i;
338 cert_auth_info_t info = _gnutls_get_auth_info (session);
340 if (info == NULL)
341 break;
343 dh_info = &info->dh;
344 rsa_info = &info->rsa_export;
345 for (i = 0; i < info->ncerts; i++)
347 _gnutls_free_datum (&info->raw_certificate_list[i]);
350 gnutls_free (info->raw_certificate_list);
351 info->raw_certificate_list = NULL;
352 info->ncerts = 0;
354 _gnutls_free_dh_info (dh_info);
355 _gnutls_free_rsa_info (rsa_info);
359 break;
360 default:
361 return;
365 gnutls_free (session->key->auth_info);
366 session->key->auth_info = NULL;
367 session->key->auth_info_size = 0;
368 session->key->auth_info_type = 0;
372 /* This function will set the auth info structure in the key
373 * structure.
374 * If allow change is !=0 then this will allow changing the auth
375 * info structure to a different type.
378 _gnutls_auth_info_set (gnutls_session_t session,
379 gnutls_credentials_type_t type, int size,
380 int allow_change)
382 if (session->key->auth_info == NULL)
384 session->key->auth_info = gnutls_calloc (1, size);
385 if (session->key->auth_info == NULL)
387 gnutls_assert ();
388 return GNUTLS_E_MEMORY_ERROR;
390 session->key->auth_info_type = type;
391 session->key->auth_info_size = size;
393 else
395 if (allow_change == 0)
397 /* If the credentials for the current authentication scheme,
398 * are not the one we want to set, then it's an error.
399 * This may happen if a rehandshake is performed an the
400 * ciphersuite which is negotiated has different authentication
401 * schema.
403 if (gnutls_auth_get_type (session) != session->key->auth_info_type)
405 gnutls_assert ();
406 return GNUTLS_E_INVALID_REQUEST;
409 else
411 /* The new behaviour: Here we reallocate the auth info structure
412 * in order to be able to negotiate different authentication
413 * types. Ie. perform an auth_anon and then authenticate again using a
414 * certificate (in order to prevent revealing the certificate's contents,
415 * to passive eavesdropers.
417 if (gnutls_auth_get_type (session) != session->key->auth_info_type)
420 _gnutls_free_auth_info (session);
422 session->key->auth_info = calloc (1, size);
423 if (session->key->auth_info == NULL)
425 gnutls_assert ();
426 return GNUTLS_E_MEMORY_ERROR;
429 session->key->auth_info_type = type;
430 session->key->auth_info_size = size;
434 return 0;