*** empty log message ***
[gnutls.git] / lib / gnutls_auth.c
blob6aed393e896fdf0c3f42668f38ffe31d8f6895e7
1 /*
2 * Copyright (C) 2001,2002 Nikos Mavroyanopoulos
4 * This file is part of GNUTLS.
6 * The GNUTLS library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "gnutls_int.h"
23 #include "gnutls_errors.h"
24 #include "gnutls_auth.h"
25 #include "gnutls_auth_int.h"
26 #include "gnutls_algorithms.h"
27 #include "auth_cert.h"
28 #include <gnutls_datum.h>
30 #include "auth_anon.h"
31 /* The functions here are used in order for authentication algorithms
32 * to be able to retrieve the needed credentials eg public and private
33 * key etc.
36 /* This clears the whole linked list */
37 int gnutls_clear_creds( GNUTLS_STATE state) {
38 AUTH_CRED * ccred, *ncred;
40 if (state->gnutls_key->cred!=NULL) { /* begining of the list */
41 ccred = state->gnutls_key->cred;
42 while(ccred!=NULL) {
43 ncred = ccred->next;
44 if (ccred!=NULL) gnutls_free(ccred);
45 ccred = ncred;
47 state->gnutls_key->cred = NULL;
50 return 0;
53 /*
54 * This creates a linked list of the form:
55 * { algorithm, credentials, pointer to next }
57 /**
58 * gnutls_cred_set - Sets the needed credentials for the specified authentication algorithm.
59 * @state: is a &GNUTLS_STATE structure.
60 * @type: is the type of the credentials
61 * @cred: is a pointer to a structure.
63 * Sets the needed credentials for the specified type.
64 * Eg username, password - or public and private keys etc.
65 * The (void* cred) parameter is a structure that depends on the
66 * specified type and on the current state (client or server).
67 * [ In order to minimize memory usage, and share credentials between
68 * several threads gnutls keeps a pointer to cred, and not the whole cred
69 * structure. Thus you will have to keep the structure allocated until
70 * you call gnutls_deinit(). ]
72 * For GNUTLS_CRD_ANON cred should be ANON_CLIENT_CREDENTIALS in case of a client.
73 * In case of a server it should be ANON_SERVER_CREDENTIALS.
75 * For GNUTLS_CRD_SRP cred should be SRP_CLIENT_CREDENTIALS
76 * in case of a client, and SRP_SERVER_CREDENTIALS, in case
77 * of a server.
79 * For GNUTLS_CRD_CERTIFICATE cred should be CERTIFICATE_CLIENT_CREDENTIALS
80 * in case of a client, and CERTIFICATE_SERVER_CREDENTIALS, in case
81 * of a server.
82 **/
83 int gnutls_cred_set( GNUTLS_STATE state, GNUTLS_CredType type, void* cred) {
84 AUTH_CRED * ccred=NULL, *pcred=NULL;
85 int exists=0;
87 if (state->gnutls_key->cred==NULL) { /* begining of the list */
89 state->gnutls_key->cred = gnutls_malloc(sizeof(AUTH_CRED));
90 if (state->gnutls_key->cred == NULL) return GNUTLS_E_MEMORY_ERROR;
92 /* copy credentials localy */
93 state->gnutls_key->cred->credentials = cred;
95 state->gnutls_key->cred->next = NULL;
96 state->gnutls_key->cred->algorithm = type;
97 } else {
98 ccred = state->gnutls_key->cred;
99 while(ccred!=NULL) {
100 if (ccred->algorithm==type) {
101 exists=1;
102 break;
104 pcred = ccred;
105 ccred = ccred->next;
107 /* After this, pcred is not null.
110 if (exists==0) { /* new entry */
111 pcred->next = gnutls_malloc(sizeof(AUTH_CRED));
112 if (pcred->next == NULL) return GNUTLS_E_MEMORY_ERROR;
114 ccred = pcred->next;
116 /* copy credentials localy */
117 ccred->credentials = cred;
119 ccred->next = NULL;
120 ccred->algorithm = type;
121 } else { /* modify existing entry */
122 gnutls_free(ccred->credentials);
123 ccred->credentials = cred;
127 return 0;
131 * gnutls_auth_get_type - Returns the type of credentials for the current authentication schema.
132 * @state: is a &GNUTLS_STATE structure.
134 * Returns type of credentials for the current authentication schema.
135 * The returned information is to be used to distinguish the function used
136 * to access authentication data.
138 * Eg. for CERTIFICATE ciphersuites (key exchange algorithms: KX_RSA, KX_DHE_RSA),
139 * the same function are to be used to access the authentication data.
141 GNUTLS_CredType gnutls_auth_get_type( GNUTLS_STATE state) {
143 return _gnutls_map_kx_get_cred(
144 _gnutls_cipher_suite_get_kx_algo
145 (state->security_parameters.current_cipher_suite));
149 * This returns an pointer to the linked list. Don't
150 * free that!!!
152 const void *_gnutls_get_kx_cred( GNUTLS_KEY key, KXAlgorithm algo, int *err) {
153 return _gnutls_get_cred( key, _gnutls_map_kx_get_cred(algo), err);
155 const void *_gnutls_get_cred( GNUTLS_KEY key, CredType type, int *err) {
156 AUTH_CRED * ccred;
158 ccred = key->cred;
159 while(ccred!=NULL) {
160 if (ccred->algorithm==type) {
161 break;
163 ccred = ccred->next;
165 if (ccred==NULL) {
166 if (err!=NULL) *err=-1;
167 return NULL;
170 if (err!=NULL) *err=0;
171 return ccred->credentials;
175 * _gnutls_get_auth_info - Returns a pointer to authentication information.
176 * @state: is a &GNUTLS_STATE structure.
178 * This function must be called after a succesful gnutls_handshake().
179 * Returns a pointer to authentication information. That information
180 * is data obtained by the handshake protocol, the key exchange algorithm,
181 * and the TLS extensions messages.
183 * In case of GNUTLS_CRD_ANON returns a pointer to &ANON_(SERVER/CLIENT)_AUTH_INFO;
184 * In case of GNUTLS_CRD_CERTIFICATE returns a pointer to structure &CERTIFICATE_(SERVER/CLIENT)_AUTH_INFO;
185 * In case of GNUTLS_CRD_SRP returns a pointer to structure &SRP_(SERVER/CLIENT)_AUTH_INFO;
187 void* _gnutls_get_auth_info( GNUTLS_STATE state) {
188 return state->gnutls_key->auth_info;
192 * _gnutls_free_auth_info - Frees the auth info structure
193 * @state: is a &GNUTLS_STATE structure.
195 * this function frees the auth info structure and sets it to
196 * null. It must be called since some structures contain malloced
197 * elements.
199 void _gnutls_free_auth_info( GNUTLS_STATE state) {
200 if (state==NULL || state->gnutls_key==NULL) {
201 gnutls_assert();
202 return;
205 switch ( state->gnutls_key->auth_info_type) {
206 case GNUTLS_CRD_SRP:
207 case GNUTLS_CRD_ANON:
209 break;
210 case GNUTLS_CRD_CERTIFICATE: {
211 int i;
212 CERTIFICATE_AUTH_INFO info =
213 _gnutls_get_auth_info(state);
215 if (info==NULL) break;
216 for (i=0;i<info->ncerts;i++) {
217 gnutls_free_datum( &info->raw_certificate_list[i]);
220 gnutls_free( info->raw_certificate_list);
221 info->raw_certificate_list = NULL;
222 info->ncerts = 0;
226 break;
227 default:
228 return;
232 gnutls_free( state->gnutls_key->auth_info);
233 state->gnutls_key->auth_info = NULL;
234 state->gnutls_key->auth_info_size = 0;
235 state->gnutls_key->auth_info_type = 0;
239 /* This function will set the auth info structure in the gnutls_key
240 * structure.
241 * If allow change is !=0 then this will allow changing the auth
242 * info structure to a different type.
244 int _gnutls_auth_info_set( GNUTLS_STATE state, CredType type, int size, int allow_change) {
245 if ( state->gnutls_key->auth_info == NULL) {
246 state->gnutls_key->auth_info = gnutls_calloc( 1, size);
247 if (state->gnutls_key->auth_info == NULL) {
248 gnutls_assert();
249 return GNUTLS_E_MEMORY_ERROR;
251 state->gnutls_key->auth_info_type = type;
252 state->gnutls_key->auth_info_size = size;
253 } else {
254 if (allow_change==0) {
255 /* If the credentials for the current authentication scheme,
256 * are not the one we want to set, then it's an error.
257 * This may happen if a rehandshake is performed an the
258 * ciphersuite which is negotiated has different authentication
259 * schema.
261 if ( gnutls_auth_get_type( state) != state->gnutls_key->auth_info_type) {
262 gnutls_assert();
263 return GNUTLS_E_INVALID_REQUEST;
265 } else {
266 /* The new behaviour: Here we reallocate the auth info structure
267 * in order to be able to negotiate different authentication
268 * types. Ie. perform an auth_anon and then authenticate again using a
269 * certificate (in order to prevent revealing the certificate's contents,
270 * to passive eavesdropers.
272 if ( gnutls_auth_get_type( state) != state->gnutls_key->auth_info_type) {
273 state->gnutls_key->auth_info = gnutls_realloc_fast(
274 state->gnutls_key->auth_info, size);
275 if (state->gnutls_key->auth_info == NULL) {
276 gnutls_assert();
277 return GNUTLS_E_MEMORY_ERROR;
279 memset( state->gnutls_key->auth_info, 0, size);
280 state->gnutls_key->auth_info_type = type;
281 state->gnutls_key->auth_info_size = size;
285 return 0;
288 /* this function will copy an GNUTLS_MPI key to
289 * opaque data.
291 int _gnutls_generate_key(GNUTLS_KEY key) {
292 _gnutls_mpi_print( NULL, &key->key.size, key->KEY);
293 key->key.data = gnutls_secure_malloc( key->key.size);
294 if ( key->key.data==NULL) {
295 return GNUTLS_E_MEMORY_ERROR;
297 _gnutls_mpi_print( key->key.data, &key->key.size, key->KEY);
298 return 0;