~ubuntu-branches/ubuntu/dapper/gnutls12/dapper

« back to all changes in this revision

Viewing changes to lib/gnutls_auth.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Urlichs
  • Date: 2005-11-15 19:26:02 UTC
  • Revision ID: james.westby@ubuntu.com-20051115192602-f1ux56uyducz3f96
Tags: upstream-1.2.9
ImportĀ upstreamĀ versionĀ 1.2.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation
 
3
 *
 
4
 * Author: Nikos Mavroyanopoulos
 
5
 *
 
6
 * This file is part of GNUTLS.
 
7
 *
 
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.
 
12
 *
 
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.
 
17
 *
 
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
 
22
 *
 
23
 */
 
24
 
 
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>
 
32
 
 
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.
 
37
 */
 
38
 
 
39
/**
 
40
  * gnutls_credentials_clear - Clears all the credentials previously set
 
41
  * @session: is a #gnutls_session_t structure.
 
42
  *
 
43
  * Clears all the credentials previously set in this session.
 
44
  *
 
45
  **/
 
46
void gnutls_credentials_clear(gnutls_session_t session)
 
47
{
 
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) {
 
52
            ncred = ccred->next;
 
53
            gnutls_free(ccred);
 
54
            ccred = ncred;
 
55
        }
 
56
        session->key->cred = NULL;
 
57
    }
 
58
}
 
59
 
 
60
/* 
 
61
 * This creates a linked list of the form:
 
62
 * { algorithm, credentials, pointer to next }
 
63
 */
 
64
/**
 
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.
 
69
  *
 
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(). ]
 
78
  *
 
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.
 
81
  * 
 
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
 
84
  * of a server.
 
85
  *
 
86
  * For GNUTLS_CRD_CERTIFICATE cred should be gnutls_certificate_credentials_t.
 
87
  *
 
88
  **/
 
89
int gnutls_credentials_set(gnutls_session_t session,
 
90
                           gnutls_credentials_type_t type, void *cred)
 
91
{
 
92
    auth_cred_st *ccred = NULL, *pcred = NULL;
 
93
    int exists = 0;
 
94
 
 
95
    if (session->key->cred == NULL) {   /* beginning of the list */
 
96
 
 
97
        session->key->cred = gnutls_malloc(sizeof(auth_cred_st));
 
98
        if (session->key->cred == NULL)
 
99
            return GNUTLS_E_MEMORY_ERROR;
 
100
 
 
101
        /* copy credentials locally */
 
102
        session->key->cred->credentials = cred;
 
103
 
 
104
        session->key->cred->next = NULL;
 
105
        session->key->cred->algorithm = type;
 
106
    } else {
 
107
        ccred = session->key->cred;
 
108
        while (ccred != NULL) {
 
109
            if (ccred->algorithm == type) {
 
110
                exists = 1;
 
111
                break;
 
112
            }
 
113
            pcred = ccred;
 
114
            ccred = ccred->next;
 
115
        }
 
116
        /* After this, pcred is not null.
 
117
         */
 
118
 
 
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;
 
123
 
 
124
            ccred = pcred->next;
 
125
 
 
126
            /* copy credentials locally */
 
127
            ccred->credentials = cred;
 
128
 
 
129
            ccred->next = NULL;
 
130
            ccred->algorithm = type;
 
131
        } else {                /* modify existing entry */
 
132
            gnutls_free(ccred->credentials);
 
133
            ccred->credentials = cred;
 
134
        }
 
135
    }
 
136
 
 
137
    return 0;
 
138
}
 
139
 
 
140
/**
 
141
  * gnutls_auth_get_type - Returns the type of credentials for the current authentication schema.
 
142
  * @session: is a #gnutls_session_t structure.
 
143
  *
 
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.
 
147
  * 
 
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.
 
150
  **/
 
151
gnutls_credentials_type_t gnutls_auth_get_type(gnutls_session_t session)
 
152
{
 
153
/* This is not the credentials we must set, but the authentication data
 
154
 * we get by the peer, so it should be reversed.
 
155
 */
 
156
    int server =
 
157
        session->security_parameters.entity == GNUTLS_SERVER ? 0 : 1;
 
158
 
 
159
    return
 
160
        _gnutls_map_kx_get_cred(_gnutls_cipher_suite_get_kx_algo
 
161
                                (&session->security_parameters.
 
162
                                 current_cipher_suite), server);
 
163
}
 
164
 
 
165
/**
 
166
  * gnutls_auth_server_get_type - Returns the type of credentials for the server authentication schema.
 
167
  * @session: is a #gnutls_session_t structure.
 
168
  *
 
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.
 
172
  * 
 
173
  **/
 
174
gnutls_credentials_type_t
 
175
gnutls_auth_server_get_type(gnutls_session_t session)
 
176
{
 
177
    return
 
178
        _gnutls_map_kx_get_cred(_gnutls_cipher_suite_get_kx_algo
 
179
                                (&session->security_parameters.
 
180
                                 current_cipher_suite), 1);
 
181
}
 
182
 
 
183
/**
 
184
  * gnutls_auth_client_get_type - Returns the type of credentials for the client authentication schema.
 
185
  * @session: is a #gnutls_session_t structure.
 
186
  *
 
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.
 
190
  * 
 
191
  **/
 
192
gnutls_credentials_type_t
 
193
gnutls_auth_client_get_type(gnutls_session_t session)
 
194
{
 
195
    return
 
196
        _gnutls_map_kx_get_cred(_gnutls_cipher_suite_get_kx_algo
 
197
                                (&session->security_parameters.
 
198
                                 current_cipher_suite), 0);
 
199
}
 
200
 
 
201
 
 
202
/* 
 
203
 * This returns a pointer to the linked list. Don't
 
204
 * free that!!!
 
205
 */
 
206
const void *_gnutls_get_kx_cred(gnutls_session_t session,
 
207
                                gnutls_kx_algorithm_t algo, int *err)
 
208
{
 
209
    int server =
 
210
        session->security_parameters.entity == GNUTLS_SERVER ? 1 : 0;
 
211
 
 
212
    return _gnutls_get_cred(session->key,
 
213
                            _gnutls_map_kx_get_cred(algo, server), err);
 
214
}
 
215
 
 
216
const void *_gnutls_get_cred(gnutls_key_st key,
 
217
                             gnutls_credentials_type_t type, int *err)
 
218
{
 
219
    const void *retval = NULL;
 
220
    int _err = -1;
 
221
    auth_cred_st *ccred;
 
222
 
 
223
    if (key == NULL)
 
224
        goto out;
 
225
 
 
226
    ccred = key->cred;
 
227
    while (ccred != NULL) {
 
228
        if (ccred->algorithm == type) {
 
229
            break;
 
230
        }
 
231
        ccred = ccred->next;
 
232
    }
 
233
    if (ccred == NULL)
 
234
        goto out;
 
235
 
 
236
    _err = 0;
 
237
    retval = ccred->credentials;
 
238
 
 
239
  out:
 
240
    if (err != NULL)
 
241
        *err = _err;
 
242
    return retval;
 
243
}
 
244
 
 
245
/*-
 
246
  * _gnutls_get_auth_info - Returns a pointer to authentication information.
 
247
  * @session: is a #gnutls_session_t structure.
 
248
  *
 
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.
 
253
  *
 
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;
 
257
  -*/
 
258
void *_gnutls_get_auth_info(gnutls_session_t session)
 
259
{
 
260
    return session->key->auth_info;
 
261
}
 
262
 
 
263
/*-
 
264
  * _gnutls_free_auth_info - Frees the auth info structure
 
265
  * @session: is a #gnutls_session_t structure.
 
266
  *
 
267
  * This function frees the auth info structure and sets it to
 
268
  * null. It must be called since some structures contain malloced
 
269
  * elements.
 
270
  -*/
 
271
void _gnutls_free_auth_info(gnutls_session_t session)
 
272
{
 
273
dh_info_st *dh_info;
 
274
rsa_info_st * rsa_info;
 
275
 
 
276
    if (session == NULL || session->key == NULL) {
 
277
        gnutls_assert();
 
278
        return;
 
279
    }
 
280
 
 
281
    switch (session->key->auth_info_type) {
 
282
    case GNUTLS_CRD_SRP:
 
283
        break;
 
284
    case GNUTLS_CRD_ANON: {
 
285
            anon_auth_info_t info = _gnutls_get_auth_info(session);
 
286
            
 
287
            if (info == NULL)
 
288
                break;
 
289
 
 
290
            dh_info = &info->dh;
 
291
            _gnutls_free_dh_info( dh_info);
 
292
        }
 
293
        break;
 
294
    case GNUTLS_CRD_CERTIFICATE:{
 
295
            unsigned int i;
 
296
            cert_auth_info_t info = _gnutls_get_auth_info(session);
 
297
 
 
298
            if (info == NULL)
 
299
                break;
 
300
 
 
301
            dh_info = &info->dh;
 
302
            rsa_info = &info->rsa_export;
 
303
            for (i = 0; i < info->ncerts; i++) {
 
304
                _gnutls_free_datum(&info->raw_certificate_list[i]);
 
305
            }
 
306
 
 
307
            gnutls_free(info->raw_certificate_list);
 
308
            info->raw_certificate_list = NULL;
 
309
            info->ncerts = 0;
 
310
 
 
311
            _gnutls_free_dh_info( dh_info);
 
312
            _gnutls_free_rsa_info( rsa_info);
 
313
        }
 
314
 
 
315
 
 
316
        break;
 
317
    default:
 
318
        return;
 
319
 
 
320
    }
 
321
 
 
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;
 
326
 
 
327
}
 
328
 
 
329
/* This function will set the auth info structure in the key
 
330
 * structure.
 
331
 * If allow change is !=0 then this will allow changing the auth
 
332
 * info structure to a different type.
 
333
 */
 
334
int _gnutls_auth_info_set(gnutls_session_t session,
 
335
                          gnutls_credentials_type_t type, int size,
 
336
                          int allow_change)
 
337
{
 
338
    if (session->key->auth_info == NULL) {
 
339
        session->key->auth_info = gnutls_calloc(1, size);
 
340
        if (session->key->auth_info == NULL) {
 
341
            gnutls_assert();
 
342
            return GNUTLS_E_MEMORY_ERROR;
 
343
        }
 
344
        session->key->auth_info_type = type;
 
345
        session->key->auth_info_size = size;
 
346
    } else {
 
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
 
352
             * schema.
 
353
             */
 
354
            if (gnutls_auth_get_type(session) !=
 
355
                session->key->auth_info_type) {
 
356
                gnutls_assert();
 
357
                return GNUTLS_E_INVALID_REQUEST;
 
358
            }
 
359
        } else {
 
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.
 
365
             */
 
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) {
 
371
                    gnutls_assert();
 
372
                    return GNUTLS_E_MEMORY_ERROR;
 
373
                }
 
374
                memset(session->key->auth_info, 0, size);
 
375
                session->key->auth_info_type = type;
 
376
                session->key->auth_info_size = size;
 
377
            }
 
378
        }
 
379
    }
 
380
    return 0;
 
381
}
 
382
 
 
383
/* this function will copy an mpi_t key to 
 
384
 * opaque data.
 
385
 */
 
386
int _gnutls_generate_session_key(gnutls_key_st key)
 
387
{
 
388
    size_t tmp;
 
389
 
 
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;
 
394
    }
 
395
    _gnutls_mpi_print(key->key.data, &tmp, key->KEY);
 
396
 
 
397
    key->key.size = tmp;
 
398
    return 0;
 
399
}