2 * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2008 Free Software Foundation
4 * Author: Nikos Mavrogiannopoulos
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,
161 * KX_DHE_RSA), the same function are to be used to access the
162 * authentication data.
164 * Returns: The type of credentials for the current authentication
165 * schema, an #gnutls_credentials_type_t type.
167 gnutls_credentials_type_t
168 gnutls_auth_get_type (gnutls_session_t session
)
170 /* This is not the credentials we must set, but the authentication data
171 * we get by the peer, so it should be reversed.
173 int server
= session
->security_parameters
.entity
== GNUTLS_SERVER
? 0 : 1;
176 _gnutls_map_kx_get_cred (_gnutls_cipher_suite_get_kx_algo
177 (&session
->security_parameters
.
178 current_cipher_suite
), server
);
182 * gnutls_auth_server_get_type - Returns the type of credentials for the server authentication schema.
183 * @session: is a #gnutls_session_t structure.
185 * Returns the type of credentials that were used for server authentication.
186 * The returned information is to be used to distinguish the function used
187 * to access authentication data.
189 * Returns: The type of credentials for the server authentication
190 * schema, an #gnutls_credentials_type_t type.
192 gnutls_credentials_type_t
193 gnutls_auth_server_get_type (gnutls_session_t session
)
196 _gnutls_map_kx_get_cred (_gnutls_cipher_suite_get_kx_algo
197 (&session
->security_parameters
.
198 current_cipher_suite
), 1);
202 * gnutls_auth_client_get_type - Returns the type of credentials for the client authentication schema.
203 * @session: is a #gnutls_session_t structure.
205 * Returns the type of credentials that were used for client authentication.
206 * The returned information is to be used to distinguish the function used
207 * to access authentication data.
209 * Returns: The type of credentials for the client authentication
210 * schema, an #gnutls_credentials_type_t type.
212 gnutls_credentials_type_t
213 gnutls_auth_client_get_type (gnutls_session_t session
)
216 _gnutls_map_kx_get_cred (_gnutls_cipher_suite_get_kx_algo
217 (&session
->security_parameters
.
218 current_cipher_suite
), 0);
223 * This returns a pointer to the linked list. Don't
227 _gnutls_get_kx_cred (gnutls_session_t session
,
228 gnutls_kx_algorithm_t algo
, int *err
)
230 int server
= session
->security_parameters
.entity
== GNUTLS_SERVER
? 1 : 0;
232 return _gnutls_get_cred (session
->key
,
233 _gnutls_map_kx_get_cred (algo
, server
), err
);
237 _gnutls_get_cred (gnutls_key_st key
, gnutls_credentials_type_t type
, int *err
)
239 const void *retval
= NULL
;
247 while (ccred
!= NULL
)
249 if (ccred
->algorithm
== type
)
259 retval
= ccred
->credentials
;
268 * _gnutls_get_auth_info - Returns a pointer to authentication information.
269 * @session: is a #gnutls_session_t structure.
271 * This function must be called after a succesful gnutls_handshake().
272 * Returns a pointer to authentication information. That information
273 * is data obtained by the handshake protocol, the key exchange algorithm,
274 * and the TLS extensions messages.
276 * In case of GNUTLS_CRD_ANON returns a type of &anon_(server/client)_auth_info_t;
277 * In case of GNUTLS_CRD_CERTIFICATE returns a type of &cert_auth_info_t;
278 * In case of GNUTLS_CRD_SRP returns a type of &srp_(server/client)_auth_info_t;
281 _gnutls_get_auth_info (gnutls_session_t session
)
283 return session
->key
->auth_info
;
287 * _gnutls_free_auth_info - Frees the auth info structure
288 * @session: is a #gnutls_session_t structure.
290 * This function frees the auth info structure and sets it to
291 * null. It must be called since some structures contain malloced
295 _gnutls_free_auth_info (gnutls_session_t session
)
298 rsa_info_st
*rsa_info
;
300 if (session
== NULL
|| session
->key
== NULL
)
306 switch (session
->key
->auth_info_type
)
310 case GNUTLS_CRD_ANON
:
312 anon_auth_info_t info
= _gnutls_get_auth_info (session
);
318 _gnutls_free_dh_info (dh_info
);
321 case GNUTLS_CRD_CERTIFICATE
:
324 cert_auth_info_t info
= _gnutls_get_auth_info (session
);
330 rsa_info
= &info
->rsa_export
;
331 for (i
= 0; i
< info
->ncerts
; i
++)
333 _gnutls_free_datum (&info
->raw_certificate_list
[i
]);
336 gnutls_free (info
->raw_certificate_list
);
337 info
->raw_certificate_list
= NULL
;
340 _gnutls_free_dh_info (dh_info
);
341 _gnutls_free_rsa_info (rsa_info
);
351 gnutls_free (session
->key
->auth_info
);
352 session
->key
->auth_info
= NULL
;
353 session
->key
->auth_info_size
= 0;
354 session
->key
->auth_info_type
= 0;
358 /* This function will set the auth info structure in the key
360 * If allow change is !=0 then this will allow changing the auth
361 * info structure to a different type.
364 _gnutls_auth_info_set (gnutls_session_t session
,
365 gnutls_credentials_type_t type
, int size
,
368 if (session
->key
->auth_info
== NULL
)
370 session
->key
->auth_info
= gnutls_calloc (1, size
);
371 if (session
->key
->auth_info
== NULL
)
374 return GNUTLS_E_MEMORY_ERROR
;
376 session
->key
->auth_info_type
= type
;
377 session
->key
->auth_info_size
= size
;
381 if (allow_change
== 0)
383 /* If the credentials for the current authentication scheme,
384 * are not the one we want to set, then it's an error.
385 * This may happen if a rehandshake is performed an the
386 * ciphersuite which is negotiated has different authentication
389 if (gnutls_auth_get_type (session
) != session
->key
->auth_info_type
)
392 return GNUTLS_E_INVALID_REQUEST
;
397 /* The new behaviour: Here we reallocate the auth info structure
398 * in order to be able to negotiate different authentication
399 * types. Ie. perform an auth_anon and then authenticate again using a
400 * certificate (in order to prevent revealing the certificate's contents,
401 * to passive eavesdropers.
403 if (gnutls_auth_get_type (session
) != session
->key
->auth_info_type
)
406 _gnutls_free_auth_info (session
);
408 session
->key
->auth_info
=
410 if (session
->key
->auth_info
== NULL
)
413 return GNUTLS_E_MEMORY_ERROR
;
416 session
->key
->auth_info_type
= type
;
417 session
->key
->auth_info_size
= size
;