Guile: Fix `x509-certificate-dn-oid' and related functions.
[gnutls.git] / lib / gnutls_auth.c
blobd72944321d23f1045f8815c2d45911dda50a9107
1 /*
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation
4 * Author: Nikos Mavroyanopoulos
6 * This file is part of GNUTLS.
8 * The GNUTLS library 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 2.1 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
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21 * USA
25 #include "gnutls_int.h"
26 #include "gnutls_errors.h"
27 #include "gnutls_auth.h"
28 #include "gnutls_auth_int.h"
29 #include "gnutls_algorithms.h"
30 #include "auth_cert.h"
31 #include <gnutls_datum.h>
33 #include "auth_anon.h"
34 /* The functions here are used in order for authentication algorithms
35 * to be able to retrieve the needed credentials eg public and private
36 * key etc.
39 /**
40 * gnutls_credentials_clear - Clears all the credentials previously set
41 * @session: is a #gnutls_session_t structure.
43 * Clears all the credentials previously set in this session.
45 **/
46 void
47 gnutls_credentials_clear (gnutls_session_t session)
49 if (session->key && session->key->cred)
50 { /* beginning of the list */
51 auth_cred_st *ccred, *ncred;
52 ccred = session->key->cred;
53 while (ccred != NULL)
55 ncred = ccred->next;
56 gnutls_free (ccred);
57 ccred = ncred;
59 session->key->cred = NULL;
63 /*
64 * This creates a linked list of the form:
65 * { algorithm, credentials, pointer to next }
67 /**
68 * gnutls_credentials_set - Sets the needed credentials for the specified authentication algorithm.
69 * @session: is a #gnutls_session_t structure.
70 * @type: is the type of the credentials
71 * @cred: is a pointer to a structure.
73 * Sets the needed credentials for the specified type.
74 * Eg username, password - or public and private keys etc.
75 * The (void* cred) parameter is a structure that depends on the
76 * specified type and on the current session (client or server).
77 * [ In order to minimize memory usage, and share credentials between
78 * several threads gnutls keeps a pointer to cred, and not the whole cred
79 * structure. Thus you will have to keep the structure allocated until
80 * you call gnutls_deinit(). ]
82 * For GNUTLS_CRD_ANON cred should be gnutls_anon_client_credentials_t in case of a client.
83 * In case of 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 gnutls_certificate_credentials_t.
91 **/
92 int
93 gnutls_credentials_set (gnutls_session_t session,
94 gnutls_credentials_type_t type, void *cred)
96 auth_cred_st *ccred = NULL, *pcred = NULL;
97 int exists = 0;
99 if (session->key->cred == NULL)
100 { /* beginning of the list */
102 session->key->cred = gnutls_malloc (sizeof (auth_cred_st));
103 if (session->key->cred == NULL)
104 return GNUTLS_E_MEMORY_ERROR;
106 /* copy credentials locally */
107 session->key->cred->credentials = cred;
109 session->key->cred->next = NULL;
110 session->key->cred->algorithm = type;
112 else
114 ccred = session->key->cred;
115 while (ccred != NULL)
117 if (ccred->algorithm == type)
119 exists = 1;
120 break;
122 pcred = ccred;
123 ccred = ccred->next;
125 /* After this, pcred is not null.
128 if (exists == 0)
129 { /* new entry */
130 pcred->next = gnutls_malloc (sizeof (auth_cred_st));
131 if (pcred->next == NULL)
132 return GNUTLS_E_MEMORY_ERROR;
134 ccred = pcred->next;
136 /* copy credentials locally */
137 ccred->credentials = cred;
139 ccred->next = NULL;
140 ccred->algorithm = type;
142 else
143 { /* modify existing entry */
144 gnutls_free (ccred->credentials);
145 ccred->credentials = cred;
149 return 0;
153 * gnutls_auth_get_type - Returns the type of credentials for the current authentication schema.
154 * @session: is a #gnutls_session_t structure.
156 * Returns type of credentials for the current authentication schema.
157 * The returned information is to be used to distinguish the function used
158 * to access authentication data.
160 * Eg. for CERTIFICATE ciphersuites (key exchange algorithms: KX_RSA, KX_DHE_RSA),
161 * the same function are to be used to access the authentication data.
163 gnutls_credentials_type_t
164 gnutls_auth_get_type (gnutls_session_t session)
166 /* This is not the credentials we must set, but the authentication data
167 * we get by the peer, so it should be reversed.
169 int server = session->security_parameters.entity == GNUTLS_SERVER ? 0 : 1;
171 return
172 _gnutls_map_kx_get_cred (_gnutls_cipher_suite_get_kx_algo
173 (&session->security_parameters.
174 current_cipher_suite), server);
178 * gnutls_auth_server_get_type - Returns the type of credentials for the server authentication schema.
179 * @session: is a #gnutls_session_t structure.
181 * Returns the type of credentials that were used for server authentication.
182 * The returned information is to be used to distinguish the function used
183 * to access authentication data.
186 gnutls_credentials_type_t
187 gnutls_auth_server_get_type (gnutls_session_t session)
189 return
190 _gnutls_map_kx_get_cred (_gnutls_cipher_suite_get_kx_algo
191 (&session->security_parameters.
192 current_cipher_suite), 1);
196 * gnutls_auth_client_get_type - Returns the type of credentials for the client authentication schema.
197 * @session: is a #gnutls_session_t structure.
199 * Returns the type of credentials that were used for client authentication.
200 * The returned information is to be used to distinguish the function used
201 * to access authentication data.
204 gnutls_credentials_type_t
205 gnutls_auth_client_get_type (gnutls_session_t session)
207 return
208 _gnutls_map_kx_get_cred (_gnutls_cipher_suite_get_kx_algo
209 (&session->security_parameters.
210 current_cipher_suite), 0);
215 * This returns a pointer to the linked list. Don't
216 * free that!!!
218 const void *
219 _gnutls_get_kx_cred (gnutls_session_t session,
220 gnutls_kx_algorithm_t algo, int *err)
222 int server = session->security_parameters.entity == GNUTLS_SERVER ? 1 : 0;
224 return _gnutls_get_cred (session->key,
225 _gnutls_map_kx_get_cred (algo, server), err);
228 const void *
229 _gnutls_get_cred (gnutls_key_st key, gnutls_credentials_type_t type, int *err)
231 const void *retval = NULL;
232 int _err = -1;
233 auth_cred_st *ccred;
235 if (key == NULL)
236 goto out;
238 ccred = key->cred;
239 while (ccred != NULL)
241 if (ccred->algorithm == type)
243 break;
245 ccred = ccred->next;
247 if (ccred == NULL)
248 goto out;
250 _err = 0;
251 retval = ccred->credentials;
253 out:
254 if (err != NULL)
255 *err = _err;
256 return retval;
260 * _gnutls_get_auth_info - Returns a pointer to authentication information.
261 * @session: is a #gnutls_session_t structure.
263 * This function must be called after a succesful gnutls_handshake().
264 * Returns a pointer to authentication information. That information
265 * is data obtained by the handshake protocol, the key exchange algorithm,
266 * and the TLS extensions messages.
268 * In case of GNUTLS_CRD_ANON returns a type of &anon_(server/client)_auth_info_t;
269 * In case of GNUTLS_CRD_CERTIFICATE returns a type of &cert_auth_info_t;
270 * In case of GNUTLS_CRD_SRP returns a type of &srp_(server/client)_auth_info_t;
272 void *
273 _gnutls_get_auth_info (gnutls_session_t session)
275 return session->key->auth_info;
279 * _gnutls_free_auth_info - Frees the auth info structure
280 * @session: is a #gnutls_session_t structure.
282 * This function frees the auth info structure and sets it to
283 * null. It must be called since some structures contain malloced
284 * elements.
286 void
287 _gnutls_free_auth_info (gnutls_session_t session)
289 dh_info_st *dh_info;
290 rsa_info_st *rsa_info;
292 if (session == NULL || session->key == NULL)
294 gnutls_assert ();
295 return;
298 switch (session->key->auth_info_type)
300 case GNUTLS_CRD_SRP:
301 break;
302 case GNUTLS_CRD_ANON:
304 anon_auth_info_t info = _gnutls_get_auth_info (session);
306 if (info == NULL)
307 break;
309 dh_info = &info->dh;
310 _gnutls_free_dh_info (dh_info);
312 break;
313 case GNUTLS_CRD_CERTIFICATE:
315 unsigned int i;
316 cert_auth_info_t info = _gnutls_get_auth_info (session);
318 if (info == NULL)
319 break;
321 dh_info = &info->dh;
322 rsa_info = &info->rsa_export;
323 for (i = 0; i < info->ncerts; i++)
325 _gnutls_free_datum (&info->raw_certificate_list[i]);
328 gnutls_free (info->raw_certificate_list);
329 info->raw_certificate_list = NULL;
330 info->ncerts = 0;
332 _gnutls_free_dh_info (dh_info);
333 _gnutls_free_rsa_info (rsa_info);
337 break;
338 default:
339 return;
343 gnutls_free (session->key->auth_info);
344 session->key->auth_info = NULL;
345 session->key->auth_info_size = 0;
346 session->key->auth_info_type = 0;
350 /* This function will set the auth info structure in the key
351 * structure.
352 * If allow change is !=0 then this will allow changing the auth
353 * info structure to a different type.
356 _gnutls_auth_info_set (gnutls_session_t session,
357 gnutls_credentials_type_t type, int size,
358 int allow_change)
360 if (session->key->auth_info == NULL)
362 session->key->auth_info = gnutls_calloc (1, size);
363 if (session->key->auth_info == NULL)
365 gnutls_assert ();
366 return GNUTLS_E_MEMORY_ERROR;
368 session->key->auth_info_type = type;
369 session->key->auth_info_size = size;
371 else
373 if (allow_change == 0)
375 /* If the credentials for the current authentication scheme,
376 * are not the one we want to set, then it's an error.
377 * This may happen if a rehandshake is performed an the
378 * ciphersuite which is negotiated has different authentication
379 * schema.
381 if (gnutls_auth_get_type (session) != session->key->auth_info_type)
383 gnutls_assert ();
384 return GNUTLS_E_INVALID_REQUEST;
387 else
389 /* The new behaviour: Here we reallocate the auth info structure
390 * in order to be able to negotiate different authentication
391 * types. Ie. perform an auth_anon and then authenticate again using a
392 * certificate (in order to prevent revealing the certificate's contents,
393 * to passive eavesdropers.
395 if (gnutls_auth_get_type (session) != session->key->auth_info_type)
397 session->key->auth_info =
398 gnutls_realloc_fast (session->key->auth_info, size);
399 if (session->key->auth_info == NULL)
401 gnutls_assert ();
402 return GNUTLS_E_MEMORY_ERROR;
404 memset (session->key->auth_info, 0, size);
405 session->key->auth_info_type = type;
406 session->key->auth_info_size = size;
410 return 0;