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,
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
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.
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
;
59 session
->key
->cred
= NULL
;
64 * This creates a linked list of the form:
65 * { algorithm, credentials, pointer to next }
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
89 * For GNUTLS_CRD_CERTIFICATE cred should be gnutls_certificate_credentials_t.
93 gnutls_credentials_set (gnutls_session_t session
,
94 gnutls_credentials_type_t type
, void *cred
)
96 auth_cred_st
*ccred
= NULL
, *pcred
= NULL
;
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
;
114 ccred
= session
->key
->cred
;
115 while (ccred
!= NULL
)
117 if (ccred
->algorithm
== type
)
125 /* After this, pcred is not null.
130 pcred
->next
= gnutls_malloc (sizeof (auth_cred_st
));
131 if (pcred
->next
== NULL
)
132 return GNUTLS_E_MEMORY_ERROR
;
136 /* copy credentials locally */
137 ccred
->credentials
= cred
;
140 ccred
->algorithm
= type
;
143 { /* modify existing entry */
144 gnutls_free (ccred
->credentials
);
145 ccred
->credentials
= cred
;
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;
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
)
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
)
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
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
);
229 _gnutls_get_cred (gnutls_key_st key
, gnutls_credentials_type_t type
, int *err
)
231 const void *retval
= NULL
;
239 while (ccred
!= NULL
)
241 if (ccred
->algorithm
== type
)
251 retval
= ccred
->credentials
;
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;
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
287 _gnutls_free_auth_info (gnutls_session_t session
)
290 rsa_info_st
*rsa_info
;
292 if (session
== NULL
|| session
->key
== NULL
)
298 switch (session
->key
->auth_info_type
)
302 case GNUTLS_CRD_ANON
:
304 anon_auth_info_t info
= _gnutls_get_auth_info (session
);
310 _gnutls_free_dh_info (dh_info
);
313 case GNUTLS_CRD_CERTIFICATE
:
316 cert_auth_info_t info
= _gnutls_get_auth_info (session
);
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
;
332 _gnutls_free_dh_info (dh_info
);
333 _gnutls_free_rsa_info (rsa_info
);
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
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
,
360 if (session
->key
->auth_info
== NULL
)
362 session
->key
->auth_info
= gnutls_calloc (1, size
);
363 if (session
->key
->auth_info
== NULL
)
366 return GNUTLS_E_MEMORY_ERROR
;
368 session
->key
->auth_info_type
= type
;
369 session
->key
->auth_info_size
= size
;
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
381 if (gnutls_auth_get_type (session
) != session
->key
->auth_info_type
)
384 return GNUTLS_E_INVALID_REQUEST
;
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
)
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
;