~ubuntu-branches/ubuntu/oneiric/strongswan/oneiric

« back to all changes in this revision

Viewing changes to src/charon/sa/tasks/ike_cert_pre.c

  • Committer: Bazaar Package Importer
  • Author(s): Rene Mayrhofer
  • Date: 2009-04-18 20:28:51 UTC
  • mfrom: (1.1.9 upstream) (2.1.15 karmic)
  • Revision ID: james.westby@ubuntu.com-20090418202851-ep722qhmzvpxh6yj
Tags: 4.3.2-1
Urgency high because of security issue and FTBFS.
* New upstream release, fixes security bug.
* Fix padlock handling for i386 in debian/rules.
  Closes: #525652 (FTBFS on i386)
* Acknowledge NMUs by security team.
  Closes: #533837, #531612
* Add "Conflicts: strongswan (< 4.2.12-1)" to libstrongswan, 
  strongswan-starter, strongswan-ikev1, and strongswan-ikev2 to force
  update of the strongswan package on installation and avoid conflicts
  caused by package restructuring.
  Closes: #526037: strongswan-ikev2 and strongswan: error when trying to 
                   install together
  Closes: #526486: strongswan and libstrongswan: error when trying to 
                   install together
  Closes: #526487: strongswan-ikev1 and strongswan: error when trying to 
                   install together
  Closes: #526488: strongswan-starter and strongswan: error when trying to 
                   install together
* Debconf templates and debian/control reviewed by the debian-l10n-
  english team as part of the Smith review project. Closes: #528073
* Debconf translation updates:
  Closes: #525234: [INTL:ja] Update po-debconf template translation (ja.po) 
  Closes: #528323: [INTL:sv] po-debconf file for strongswan 
  Closes: #528370: [INTL:vi] Vietnamese debconf templates translation update 
  Closes: #529027: [INTL:pt] Updated Portuguese translation for debconf messages
  Closes: #529071: [INTL:fr] French debconf templates translation update 
  Closes: #529592: nb translation of debconf PO for strongSWAN 
  Closes: #529638: [INTL:ru] Russian debconf templates translation 
  Closes: #529661: Updated Czech translation of strongswan debconf messages 
  Closes: #529742: [INTL:eu] strongswan debconf basque translation 
  Closes: #530273: [INTL:fi] Finnish translation of the debconf templates
  Closes: #529063: [INTL:gl] strongswan 4.2.14-2 debconf translation update

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * Copyright (C) 2008 Tobias Brunner
3
 
 * Copyright (C) 2006-2007 Martin Willi
 
3
 * Copyright (C) 2006-2009 Martin Willi
4
4
 * Hochschule fuer Technik Rapperswil
5
5
 *
6
6
 * This program is free software; you can redistribute it and/or modify it
12
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
13
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14
14
 * for more details.
15
 
 *
16
 
 * $Id: ike_cert_pre.c 4285 2008-08-26 05:15:34Z andreas $
17
15
 */
18
16
 
19
17
#include "ike_cert_pre.h"
48
46
        bool initiator;
49
47
        
50
48
        /**
51
 
         * Did we send a HTTP_CERT_LOOKUP_SUPPORTED Notify?
52
 
         */
53
 
        bool http_cert_lookup_supported_sent;
 
49
         * Do we accept HTTP certificate lookup requests
 
50
         */
 
51
        bool do_http_lookup;
 
52
        
 
53
        /**
 
54
         * wheter this is the final authentication round
 
55
         */
 
56
        bool final;
54
57
};
55
58
 
56
59
/**
58
61
 */
59
62
static void process_certreqs(private_ike_cert_pre_t *this, message_t *message)
60
63
{
61
 
        iterator_t *iterator;
 
64
        enumerator_t *enumerator;
62
65
        payload_t *payload;
63
 
        auth_info_t *auth;
64
 
        bool ca_found = FALSE;
65
 
        
66
 
        auth = this->ike_sa->get_my_auth(this->ike_sa);
67
 
        
68
 
        iterator = message->get_payload_iterator(message);
69
 
        while (iterator->iterate(iterator, (void**)&payload))
 
66
        auth_cfg_t *auth;
 
67
        
 
68
        auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
 
69
        
 
70
        enumerator = message->create_payload_enumerator(message);
 
71
        while (enumerator->enumerate(enumerator, &payload))
70
72
        {
71
73
                switch(payload->get_type(payload))
72
74
                {
73
75
                        case CERTIFICATE_REQUEST:
74
76
                        {
75
77
                                certreq_payload_t *certreq = (certreq_payload_t*)payload;
 
78
                                enumerator_t *enumerator;
76
79
                                chunk_t keyid;
77
 
                                enumerator_t *enumerator;
78
80
                                
79
81
                                this->ike_sa->set_condition(this->ike_sa, COND_CERTREQ_SEEN, TRUE);
80
82
                                
96
98
                                                                                        CERT_X509, KEY_ANY, id, TRUE);
97
99
                                        if (cert)
98
100
                                        {
99
 
                                                DBG1(DBG_IKE, "received cert request for \"%D\"",
 
101
                                                DBG1(DBG_IKE, "received cert request for \"%Y\"",
100
102
                                                         cert->get_subject(cert));
101
 
                                                auth->add_item(auth, AUTHN_CA_CERT, cert);
102
 
                                                cert->destroy(cert);
103
 
                                                ca_found = TRUE;
 
103
                                                auth->add(auth, AUTH_RULE_CA_CERT, cert);
104
104
                                        }
105
105
                                        else
106
106
                                        {
107
107
                                                DBG1(DBG_IKE, "received cert request for unknown ca "
108
 
                                                                          "with keyid %D", id);
109
 
                                                auth->add_item(auth, AUTHN_CA_CERT_KEYID, id);
 
108
                                                                          "with keyid %Y", id);
110
109
                                        }
111
110
                                        id->destroy(id);
112
111
                                }
129
128
                                break;
130
129
                }
131
130
        }
132
 
        iterator->destroy(iterator);
 
131
        enumerator->destroy(enumerator);
133
132
}
134
133
 
135
134
/**
140
139
static certificate_t *try_get_cert(cert_payload_t *cert_payload)
141
140
{
142
141
        certificate_t *cert = NULL;
 
142
        
143
143
        switch (cert_payload->get_cert_encoding(cert_payload))
144
144
        {
145
145
                case ENC_X509_SIGNATURE:
158
158
                        }
159
159
                        id = identification_create_from_encoding(ID_CERT_DER_SHA1, hash);
160
160
                        cert = charon->credentials->get_cert(charon->credentials, 
161
 
                                                                        CERT_X509, KEY_ANY, id, FALSE);
 
161
                                                                                                 CERT_X509, KEY_ANY, id, FALSE);
162
162
                        id->destroy(id);
163
163
                        break;
164
164
                }
175
175
 */
176
176
static void process_certs(private_ike_cert_pre_t *this, message_t *message)
177
177
{
178
 
        iterator_t *iterator;
 
178
        enumerator_t *enumerator;
179
179
        payload_t *payload;
180
 
        auth_info_t *auth;
 
180
        auth_cfg_t *auth;
181
181
        bool first = TRUE;
182
182
        
183
 
        auth = this->ike_sa->get_other_auth(this->ike_sa);
 
183
        auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
184
184
        
185
 
        iterator = message->get_payload_iterator(message);
186
 
        while (iterator->iterate(iterator, (void**)&payload))
 
185
        enumerator = message->create_payload_enumerator(message);
 
186
        while (enumerator->enumerate(enumerator, &payload))
187
187
        {
188
188
                if (payload->get_type(payload) == CERTIFICATE)
189
189
                {
190
 
                        cert_payload_t *cert_payload = (cert_payload_t*)payload;
191
 
                        cert_encoding_t type = cert_payload->get_cert_encoding(cert_payload);
192
 
                        switch (type)
 
190
                        cert_payload_t *cert_payload;
 
191
                        cert_encoding_t encoding;
 
192
                        certificate_t *cert;
 
193
                        char *url;
 
194
                        
 
195
                        cert_payload = (cert_payload_t*)payload;
 
196
                        encoding = cert_payload->get_cert_encoding(cert_payload);
 
197
                        
 
198
                        switch (encoding)
193
199
                        {
194
 
                                case ENC_X509_SIGNATURE:
195
200
                                case ENC_X509_HASH_AND_URL:
196
201
                                {
197
 
                                        if (type == ENC_X509_HASH_AND_URL &&
198
 
                                                !this->http_cert_lookup_supported_sent)
 
202
                                        if (!this->do_http_lookup)
199
203
                                        {
200
204
                                                DBG1(DBG_IKE, "received hash-and-url encoded cert, but"
201
205
                                                                " we don't accept them, ignore");
202
206
                                                break;
203
207
                                        }
204
 
                                        
205
 
                                        certificate_t *cert = try_get_cert(cert_payload);
206
 
                                        
 
208
                                        /* FALL */
 
209
                                }
 
210
                                case ENC_X509_SIGNATURE:
 
211
                                {
 
212
                                        cert = try_get_cert(cert_payload);
207
213
                                        if (cert)
208
214
                                        {
209
 
                                                /* we've got a certificate from the payload or the cache */ 
210
215
                                                if (first)
211
 
                                                {       /* the first certificate MUST be an end entity one */
212
 
                                                        DBG1(DBG_IKE, "received end entity cert \"%D\"",
 
216
                                                {       /* the first is an end entity certificate */
 
217
                                                        DBG1(DBG_IKE, "received end entity cert \"%Y\"",
213
218
                                                                 cert->get_subject(cert));
214
 
                                                        auth->add_item(auth, AUTHN_SUBJECT_CERT, cert);
 
219
                                                        auth->add(auth, AUTH_HELPER_SUBJECT_CERT, cert);
215
220
                                                        first = FALSE;
216
221
                                                }
217
222
                                                else
218
223
                                                {
219
 
                                                        DBG1(DBG_IKE, "received issuer cert \"%D\"",
 
224
                                                        DBG1(DBG_IKE, "received issuer cert \"%Y\"",
220
225
                                                                 cert->get_subject(cert));
221
 
                                                        auth->add_item(auth, AUTHN_IM_CERT, cert);
 
226
                                                        auth->add(auth, AUTH_HELPER_IM_CERT, cert);
222
227
                                                }
223
 
                                                cert->destroy(cert);
224
228
                                        }
225
 
                                        else if (type == ENC_X509_HASH_AND_URL)
 
229
                                        else if (encoding == ENC_X509_HASH_AND_URL)
226
230
                                        {
227
 
                                                /* we received a "Hash and URL" encoded certificate that
228
 
                                                 * we haven't fetched yet, we store the URL and fetch
229
 
                                                 * it later */
230
 
                                                char *url = cert_payload->get_url(cert_payload);
 
231
                                                /* we fetch the certificate not yet, but only if
 
232
                                                 * it is really needed during authentication */
 
233
                                                url = cert_payload->get_url(cert_payload);
231
234
                                                if (!url)
232
235
                                                {
233
 
                                                        DBG1(DBG_IKE, "received invalid hash-and-url encoded"
234
 
                                                                        " cert, ignore");
 
236
                                                        DBG1(DBG_IKE, "received invalid hash-and-url "
 
237
                                                                 "encoded cert, ignore");
235
238
                                                        break;
236
239
                                                }
237
 
                                                
 
240
                                                url = strdup(url);
238
241
                                                if (first)
239
 
                                                {       /* the first certificate MUST be an end entity one */
 
242
                                                {       /* first URL is for an end entity certificate */
240
243
                                                        DBG1(DBG_IKE, "received hash-and-url for end"
241
 
                                                                        " entity cert \"%s\"", url);
242
 
                                                        auth->add_item(auth, AUTHN_SUBJECT_HASH_URL, url);
 
244
                                                                 " entity cert \"%s\"", url);
 
245
                                                        auth->add(auth, AUTH_HELPER_SUBJECT_HASH_URL, url);
243
246
                                                        first = FALSE;
244
247
                                                }
245
248
                                                else
246
249
                                                {
247
250
                                                        DBG1(DBG_IKE, "received hash-and-url for issuer"
248
251
                                                                        " cert \"%s\"", url);
249
 
                                                        auth->add_item(auth, AUTHN_IM_HASH_URL, url);
 
252
                                                        auth->add(auth, AUTH_HELPER_IM_HASH_URL, url);
250
253
                                                }
251
254
                                        }
252
255
                                        break;
264
267
                                case ENC_OCSP_CONTENT:
265
268
                                default:
266
269
                                        DBG1(DBG_ENC, "certificate encoding %N not supported",
267
 
                                                 cert_encoding_names, cert_payload->get_cert_encoding(cert_payload));
 
270
                                                 cert_encoding_names, encoding);
268
271
                        }
269
272
                }
270
273
        }
271
 
        iterator->destroy(iterator);
 
274
        enumerator->destroy(enumerator);
272
275
}
273
276
 
274
277
/**
275
 
 * add a certificate request to the message, building request payload if required.
 
278
 * add the keyid of a certificate to the certificate request payload
276
279
 */
277
 
static void add_certreq_payload(message_t *message, certreq_payload_t **reqp, 
278
 
                                                                certificate_t *cert)
 
280
static void add_certreq(certreq_payload_t **req, certificate_t *cert)
279
281
{
280
 
        public_key_t *public;
281
 
        certreq_payload_t *req;
282
 
 
283
 
        public = cert->get_public_key(cert);
284
 
        if (!public)
285
 
        {
286
 
                return;
287
 
        }
288
282
        switch (cert->get_type(cert))
289
283
        {
290
284
                case CERT_X509:
291
285
                {
 
286
                        public_key_t *public;
292
287
                        identification_t *keyid;
293
288
                        x509_t *x509 = (x509_t*)cert;
294
289
                        
296
291
                        {       /* no CA cert, skip */
297
292
                                break;
298
293
                        }
299
 
                        if (*reqp == NULL)
300
 
                        {
301
 
                                *reqp = certreq_payload_create_type(CERT_X509);
302
 
                                message->add_payload(message, (payload_t*)*reqp);
303
 
                        }
304
 
                        req = *reqp;
 
294
                        public = cert->get_public_key(cert);
 
295
                        if (!public)
 
296
                        {
 
297
                                break;
 
298
                        }
 
299
                        if (*req == NULL)
 
300
                        {
 
301
                                *req = certreq_payload_create_type(CERT_X509);
 
302
                        }
305
303
                        keyid = public->get_id(public, ID_PUBKEY_INFO_SHA1);
306
 
                        req->add_keyid(req, keyid->get_encoding(keyid));
307
 
                        DBG1(DBG_IKE, "sending cert request for \"%D\"",
 
304
                        (*req)->add_keyid(*req, keyid->get_encoding(keyid));
 
305
                        public->destroy(public);
 
306
                        DBG1(DBG_IKE, "sending cert request for \"%Y\"",
308
307
                                 cert->get_subject(cert));
309
308
                        break;
310
309
                }
311
310
                default:
312
311
                        break;
313
312
        }
314
 
        public->destroy(public);
 
313
}
 
314
 
 
315
/**
 
316
 * add a auth_cfg's CA certificates to the certificate request
 
317
 */
 
318
static void add_certreqs(certreq_payload_t **req, auth_cfg_t *auth)
 
319
{
 
320
        enumerator_t *enumerator;
 
321
        auth_rule_t type;
 
322
        void *value;
 
323
        
 
324
        enumerator = auth->create_enumerator(auth);
 
325
        while (enumerator->enumerate(enumerator, &type, &value))
 
326
        {
 
327
                switch (type)
 
328
                {
 
329
                        case AUTH_RULE_CA_CERT:
 
330
                                add_certreq(req, (certificate_t*)value);
 
331
                                break;
 
332
                        default:
 
333
                                break;
 
334
                }
 
335
        }
 
336
        enumerator->destroy(enumerator);
315
337
}
316
338
 
317
339
/**
319
341
 */
320
342
static void build_certreqs(private_ike_cert_pre_t *this, message_t *message)
321
343
{
 
344
        enumerator_t *enumerator;
322
345
        ike_cfg_t *ike_cfg;
323
346
        peer_cfg_t *peer_cfg;
324
 
        enumerator_t *enumerator;
325
347
        certificate_t *cert;
326
 
        bool restricted = FALSE;
327
 
        certreq_payload_t *x509_req = NULL;
 
348
        auth_cfg_t *auth;
 
349
        certreq_payload_t *req = NULL;
328
350
        
329
351
        ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
330
352
        if (!ike_cfg->send_certreq(ike_cfg))
331
353
        {
332
354
                return;
333
355
        }
334
 
 
 
356
        
335
357
        /* check if we require a specific CA for that peer */
336
358
        peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
337
359
        if (peer_cfg)
338
360
        {
339
 
                void *ptr;
340
 
                identification_t *id;
341
 
                auth_item_t item;
342
 
                auth_info_t *auth = peer_cfg->get_auth(peer_cfg);
343
 
                enumerator_t *auth_enumerator = auth->create_item_enumerator(auth);
344
 
 
345
 
                while (auth_enumerator->enumerate(auth_enumerator, &item, &ptr))
 
361
                enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, FALSE);
 
362
                while (enumerator->enumerate(enumerator, &auth))
346
363
                {
347
 
                        switch (item)
348
 
                        {
349
 
                                case AUTHZ_CA_CERT:
350
 
                                        cert = (certificate_t *)ptr;
351
 
                                        add_certreq_payload(message, &x509_req, cert);
352
 
                                        restricted = TRUE;
353
 
                                        break;
354
 
                                case AUTHZ_CA_CERT_NAME:
355
 
                                        id = (identification_t *)ptr;
356
 
                                        enumerator = charon->credentials->create_cert_enumerator(
357
 
                                                        charon->credentials, CERT_ANY, KEY_ANY, id, TRUE);
358
 
                                        while (enumerator->enumerate(enumerator, &cert, TRUE))
359
 
                                        {
360
 
                                                add_certreq_payload(message, &x509_req, cert);
361
 
                                                restricted = TRUE;
362
 
                                        }
363
 
                                        enumerator->destroy(enumerator);
364
 
                                        break;
365
 
                                default:
366
 
                                        break;
367
 
                        }
 
364
                        add_certreqs(&req, auth);
368
365
                }
369
 
                auth_enumerator->destroy(auth_enumerator);
 
366
                enumerator->destroy(enumerator);
370
367
        }
371
 
                
372
 
        if (!restricted)
 
368
        
 
369
        if (!req)
373
370
        {
374
 
                /* otherwise include all trusted CA certificates */
 
371
                /* otherwise add all trusted CA certificates */
375
372
                enumerator = charon->credentials->create_cert_enumerator(
376
373
                                                        charon->credentials, CERT_ANY, KEY_ANY, NULL, TRUE);
377
 
                while (enumerator->enumerate(enumerator, &cert, TRUE))
 
374
                while (enumerator->enumerate(enumerator, &cert))
378
375
                {
379
 
                        add_certreq_payload(message, &x509_req, cert);
 
376
                        add_certreq(&req, cert);
380
377
                }
381
378
                enumerator->destroy(enumerator);
382
379
        }
383
380
        
384
 
        /* if we've added at least one certreq, we notify our peer that we support
385
 
         * "Hash and URL" for the requested certificates */
386
 
        if (lib->settings->get_bool(lib->settings, "charon.hash_and_url", FALSE) &&
387
 
                message->get_payload(message, CERTIFICATE_REQUEST))
388
 
        {
389
 
                message->add_notify(message, FALSE, HTTP_CERT_LOOKUP_SUPPORTED, chunk_empty);
390
 
                this->http_cert_lookup_supported_sent = TRUE;
391
 
        }
 
381
        if (req)
 
382
        {
 
383
                message->add_payload(message, (payload_t*)req);
 
384
                
 
385
                if (lib->settings->get_bool(lib->settings, "charon.hash_and_url", FALSE))
 
386
                {
 
387
                        message->add_notify(message, FALSE, HTTP_CERT_LOOKUP_SUPPORTED,
 
388
                                                                chunk_empty);
 
389
                        this->do_http_lookup = TRUE;
 
390
                }
 
391
        }
 
392
}
 
393
 
 
394
/**
 
395
 * Check if this is the final authentication round
 
396
 */
 
397
static bool final_auth(message_t *message)
 
398
{
 
399
        enumerator_t *enumerator;
 
400
        payload_t *payload;
 
401
        notify_payload_t *notify;
 
402
        
 
403
        /* we check for an AUTH payload without a ANOTHER_AUTH_FOLLOWS notify */
 
404
        if (message->get_payload(message, AUTHENTICATION) == NULL)
 
405
        {
 
406
                return FALSE;
 
407
        }
 
408
        enumerator = message->create_payload_enumerator(message);
 
409
        while (enumerator->enumerate(enumerator, &payload))
 
410
        {
 
411
                if (payload->get_type(payload) == NOTIFY)
 
412
                {
 
413
                        notify = (notify_payload_t*)payload;
 
414
                        if (notify->get_notify_type(notify) == ANOTHER_AUTH_FOLLOWS)
 
415
                        {
 
416
                                enumerator->destroy(enumerator);
 
417
                                return FALSE;
 
418
                        }
 
419
                }
 
420
        }
 
421
        enumerator->destroy(enumerator);
 
422
        return TRUE;
392
423
}
393
424
 
394
425
/**
396
427
 */
397
428
static status_t build_i(private_ike_cert_pre_t *this, message_t *message)
398
429
{       
399
 
        if (message->get_exchange_type(message) == IKE_SA_INIT)
400
 
        {
401
 
                return NEED_MORE;
 
430
        if (message->get_message_id(message) == 1)
 
431
        {       /* initiator sends CERTREQs in first IKE_AUTH */
 
432
                build_certreqs(this, message);
402
433
        }
403
 
        build_certreqs(this, message);
404
434
        return NEED_MORE;
405
435
}
406
436
 
408
438
 * Implementation of task_t.process for responder
409
439
 */
410
440
static status_t process_r(private_ike_cert_pre_t *this, message_t *message)
411
 
{       
412
 
        if (message->get_exchange_type(message) == IKE_SA_INIT)
413
 
        {
414
 
                return NEED_MORE;
 
441
{
 
442
        if (message->get_exchange_type(message) != IKE_SA_INIT)
 
443
        {       /* handle certreqs/certs in any IKE_AUTH, just in case */
 
444
                process_certreqs(this, message);
 
445
                process_certs(this, message);
415
446
        }
416
 
        process_certreqs(this, message);
417
 
        process_certs(this, message);
 
447
        this->final = final_auth(message);
418
448
        return NEED_MORE;
419
449
}
420
450
 
426
456
        if (message->get_exchange_type(message) == IKE_SA_INIT)
427
457
        {
428
458
                build_certreqs(this, message);
429
 
                return NEED_MORE;
430
 
        }
431
 
        return SUCCESS;
 
459
        }
 
460
        if (this->final)
 
461
        {
 
462
                return SUCCESS;
 
463
        }
 
464
        return NEED_MORE;
432
465
}
433
466
 
434
467
/**
439
472
        if (message->get_exchange_type(message) == IKE_SA_INIT)
440
473
        {
441
474
                process_certreqs(this, message);
442
 
                return NEED_MORE;
443
475
        }
444
476
        process_certs(this, message);
445
 
        return SUCCESS;
 
477
        
 
478
        if (final_auth(message))
 
479
        {
 
480
                return SUCCESS;
 
481
        }
 
482
        return NEED_MORE;
446
483
}
447
484
 
448
485
/**
493
530
        
494
531
        this->ike_sa = ike_sa;
495
532
        this->initiator = initiator;
496
 
        this->http_cert_lookup_supported_sent = FALSE;
 
533
        this->do_http_lookup = FALSE;
 
534
        this->final = FALSE;
497
535
        
498
536
        return &this->public;
499
537
}