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.
46
void gnutls_credentials_clear(gnutls_session_t session)
48
if (session->key && session->key->cred) { /* beginning of the list */
49
auth_cred_st *ccred, *ncred;
50
ccred = session->key->cred;
51
while (ccred != NULL) {
56
session->key->cred = NULL;
61
* This creates a linked list of the form:
62
* { algorithm, credentials, pointer to next }
65
* gnutls_credentials_set - Sets the needed credentials for the specified authentication algorithm.
66
* @session: is a #gnutls_session_t structure.
67
* @type: is the type of the credentials
68
* @cred: is a pointer to a structure.
70
* Sets the needed credentials for the specified type.
71
* Eg username, password - or public and private keys etc.
72
* The (void* cred) parameter is a structure that depends on the
73
* specified type and on the current session (client or server).
74
* [ In order to minimize memory usage, and share credentials between
75
* several threads gnutls keeps a pointer to cred, and not the whole cred
76
* structure. Thus you will have to keep the structure allocated until
77
* you call gnutls_deinit(). ]
79
* For GNUTLS_CRD_ANON cred should be gnutls_anon_client_credentials_t in case of a client.
80
* In case of a server it should be gnutls_anon_server_credentials_t.
82
* For GNUTLS_CRD_SRP cred should be gnutls_srp_client_credentials_t
83
* in case of a client, and gnutls_srp_server_credentials_t, in case
86
* For GNUTLS_CRD_CERTIFICATE cred should be gnutls_certificate_credentials_t.
89
int gnutls_credentials_set(gnutls_session_t session,
90
gnutls_credentials_type_t type, void *cred)
92
auth_cred_st *ccred = NULL, *pcred = NULL;
95
if (session->key->cred == NULL) { /* beginning of the list */
97
session->key->cred = gnutls_malloc(sizeof(auth_cred_st));
98
if (session->key->cred == NULL)
99
return GNUTLS_E_MEMORY_ERROR;
101
/* copy credentials locally */
102
session->key->cred->credentials = cred;
104
session->key->cred->next = NULL;
105
session->key->cred->algorithm = type;
107
ccred = session->key->cred;
108
while (ccred != NULL) {
109
if (ccred->algorithm == type) {
116
/* After this, pcred is not null.
119
if (exists == 0) { /* new entry */
120
pcred->next = gnutls_malloc(sizeof(auth_cred_st));
121
if (pcred->next == NULL)
122
return GNUTLS_E_MEMORY_ERROR;
126
/* copy credentials locally */
127
ccred->credentials = cred;
130
ccred->algorithm = type;
131
} else { /* modify existing entry */
132
gnutls_free(ccred->credentials);
133
ccred->credentials = cred;
141
* gnutls_auth_get_type - Returns the type of credentials for the current authentication schema.
142
* @session: is a #gnutls_session_t structure.
144
* Returns type of credentials for the current authentication schema.
145
* The returned information is to be used to distinguish the function used
146
* to access authentication data.
148
* Eg. for CERTIFICATE ciphersuites (key exchange algorithms: KX_RSA, KX_DHE_RSA),
149
* the same function are to be used to access the authentication data.
151
gnutls_credentials_type_t gnutls_auth_get_type(gnutls_session_t session)
153
/* This is not the credentials we must set, but the authentication data
154
* we get by the peer, so it should be reversed.
157
session->security_parameters.entity == GNUTLS_SERVER ? 0 : 1;
160
_gnutls_map_kx_get_cred(_gnutls_cipher_suite_get_kx_algo
161
(&session->security_parameters.
162
current_cipher_suite), server);
166
* gnutls_auth_server_get_type - Returns the type of credentials for the server authentication schema.
167
* @session: is a #gnutls_session_t structure.
169
* Returns the type of credentials that were used for server authentication.
170
* The returned information is to be used to distinguish the function used
171
* to access authentication data.
174
gnutls_credentials_type_t
175
gnutls_auth_server_get_type(gnutls_session_t session)
178
_gnutls_map_kx_get_cred(_gnutls_cipher_suite_get_kx_algo
179
(&session->security_parameters.
180
current_cipher_suite), 1);
184
* gnutls_auth_client_get_type - Returns the type of credentials for the client authentication schema.
185
* @session: is a #gnutls_session_t structure.
187
* Returns the type of credentials that were used for client authentication.
188
* The returned information is to be used to distinguish the function used
189
* to access authentication data.
192
gnutls_credentials_type_t
193
gnutls_auth_client_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), 0);
203
* This returns a pointer to the linked list. Don't
206
const void *_gnutls_get_kx_cred(gnutls_session_t session,
207
gnutls_kx_algorithm_t algo, int *err)
210
session->security_parameters.entity == GNUTLS_SERVER ? 1 : 0;
212
return _gnutls_get_cred(session->key,
213
_gnutls_map_kx_get_cred(algo, server), err);
216
const void *_gnutls_get_cred(gnutls_key_st key,
217
gnutls_credentials_type_t type, int *err)
219
const void *retval = NULL;
227
while (ccred != NULL) {
228
if (ccred->algorithm == type) {
237
retval = ccred->credentials;
246
* _gnutls_get_auth_info - Returns a pointer to authentication information.
247
* @session: is a #gnutls_session_t structure.
249
* This function must be called after a succesful gnutls_handshake().
250
* Returns a pointer to authentication information. That information
251
* is data obtained by the handshake protocol, the key exchange algorithm,
252
* and the TLS extensions messages.
254
* In case of GNUTLS_CRD_ANON returns a type of &anon_(server/client)_auth_info_t;
255
* In case of GNUTLS_CRD_CERTIFICATE returns a type of &cert_auth_info_t;
256
* In case of GNUTLS_CRD_SRP returns a type of &srp_(server/client)_auth_info_t;
258
void *_gnutls_get_auth_info(gnutls_session_t session)
260
return session->key->auth_info;
264
* _gnutls_free_auth_info - Frees the auth info structure
265
* @session: is a #gnutls_session_t structure.
267
* This function frees the auth info structure and sets it to
268
* null. It must be called since some structures contain malloced
271
void _gnutls_free_auth_info(gnutls_session_t session)
274
rsa_info_st * rsa_info;
276
if (session == NULL || session->key == NULL) {
281
switch (session->key->auth_info_type) {
284
case GNUTLS_CRD_ANON: {
285
anon_auth_info_t info = _gnutls_get_auth_info(session);
291
_gnutls_free_dh_info( dh_info);
294
case GNUTLS_CRD_CERTIFICATE:{
296
cert_auth_info_t info = _gnutls_get_auth_info(session);
302
rsa_info = &info->rsa_export;
303
for (i = 0; i < info->ncerts; i++) {
304
_gnutls_free_datum(&info->raw_certificate_list[i]);
307
gnutls_free(info->raw_certificate_list);
308
info->raw_certificate_list = NULL;
311
_gnutls_free_dh_info( dh_info);
312
_gnutls_free_rsa_info( rsa_info);
322
gnutls_free(session->key->auth_info);
323
session->key->auth_info = NULL;
324
session->key->auth_info_size = 0;
325
session->key->auth_info_type = 0;
329
/* This function will set the auth info structure in the key
331
* If allow change is !=0 then this will allow changing the auth
332
* info structure to a different type.
334
int _gnutls_auth_info_set(gnutls_session_t session,
335
gnutls_credentials_type_t type, int size,
338
if (session->key->auth_info == NULL) {
339
session->key->auth_info = gnutls_calloc(1, size);
340
if (session->key->auth_info == NULL) {
342
return GNUTLS_E_MEMORY_ERROR;
344
session->key->auth_info_type = type;
345
session->key->auth_info_size = size;
347
if (allow_change == 0) {
348
/* If the credentials for the current authentication scheme,
349
* are not the one we want to set, then it's an error.
350
* This may happen if a rehandshake is performed an the
351
* ciphersuite which is negotiated has different authentication
354
if (gnutls_auth_get_type(session) !=
355
session->key->auth_info_type) {
357
return GNUTLS_E_INVALID_REQUEST;
360
/* The new behaviour: Here we reallocate the auth info structure
361
* in order to be able to negotiate different authentication
362
* types. Ie. perform an auth_anon and then authenticate again using a
363
* certificate (in order to prevent revealing the certificate's contents,
364
* to passive eavesdropers.
366
if (gnutls_auth_get_type(session) !=
367
session->key->auth_info_type) {
368
session->key->auth_info =
369
gnutls_realloc_fast(session->key->auth_info, size);
370
if (session->key->auth_info == NULL) {
372
return GNUTLS_E_MEMORY_ERROR;
374
memset(session->key->auth_info, 0, size);
375
session->key->auth_info_type = type;
376
session->key->auth_info_size = size;
383
/* this function will copy an mpi_t key to
386
int _gnutls_generate_session_key(gnutls_key_st key)
390
_gnutls_mpi_print(NULL, &tmp, key->KEY);
391
key->key.data = gnutls_secure_malloc(tmp);
392
if (key->key.data == NULL) {
393
return GNUTLS_E_MEMORY_ERROR;
395
_gnutls_mpi_print(key->key.data, &tmp, key->KEY);