2
* Copyright (C) 2007-2009 Martin Willi
3
* Copyright (C) 2008 Tobias Brunner
4
* Hochschule fuer Technik Rapperswil
6
* This program is free software; you can redistribute it and/or modify it
7
* under the terms of the GNU General Public License as published by the
8
* Free Software Foundation; either version 2 of the License, or (at your
9
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11
* This program is distributed in the hope that it will be useful, but
12
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20
#include <utils/linked_list.h>
21
#include <utils/identification.h>
22
#include <credentials/certificates/certificate.h>
24
ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_SUBJECT_HASH_URL,
33
"RULE_CRL_VALIDATION",
34
"RULE_OCSP_VALIDATION",
37
"HELPER_SUBJECT_CERT",
39
"HELPER_SUBJECT_HASH_URL",
42
typedef struct private_auth_cfg_t private_auth_cfg_t;
45
* private data of item_set
47
struct private_auth_cfg_t {
57
linked_list_t *entries;
60
typedef struct entry_t entry_t;
65
/** associated value */
70
* enumerator for auth_cfg_t.create_enumerator()
73
/** implements enumerator_t */
75
/** inner enumerator from linked_list_t */
82
* enumerate function for item_enumerator_t
84
static bool enumerate(entry_enumerator_t *this, auth_rule_t *type, void **value)
88
if (this->inner->enumerate(this->inner, &entry))
90
this->current = entry;
92
*value = entry->value;
99
* destroy function for item_enumerator_t
101
static void entry_enumerator_destroy(entry_enumerator_t *this)
103
this->inner->destroy(this->inner);
108
* Implementation of auth_cfg_t.create_enumerator.
110
static enumerator_t* create_enumerator(private_auth_cfg_t *this)
112
entry_enumerator_t *enumerator;
114
enumerator = malloc_thing(entry_enumerator_t);
115
enumerator->inner = this->entries->create_enumerator(this->entries);
116
enumerator->public.enumerate = (void*)enumerate;
117
enumerator->public.destroy = (void*)entry_enumerator_destroy;
118
enumerator->current = NULL;
119
return &enumerator->public;
123
* Destroy the value associated with an entry
125
static void destroy_entry_value(entry_t *entry)
129
case AUTH_RULE_IDENTITY:
130
case AUTH_RULE_EAP_IDENTITY:
131
case AUTH_RULE_AC_GROUP:
133
identification_t *id = (identification_t*)entry->value;
137
case AUTH_RULE_CA_CERT:
138
case AUTH_RULE_IM_CERT:
139
case AUTH_RULE_SUBJECT_CERT:
140
case AUTH_HELPER_IM_CERT:
141
case AUTH_HELPER_SUBJECT_CERT:
143
certificate_t *cert = (certificate_t*)entry->value;
147
case AUTH_HELPER_IM_HASH_URL:
148
case AUTH_HELPER_SUBJECT_HASH_URL:
153
case AUTH_RULE_AUTH_CLASS:
154
case AUTH_RULE_EAP_TYPE:
155
case AUTH_RULE_EAP_VENDOR:
156
case AUTH_RULE_CRL_VALIDATION:
157
case AUTH_RULE_OCSP_VALIDATION:
163
* Implementation of auth_cfg_t.replace.
165
static void replace(auth_cfg_t *this, entry_enumerator_t *enumerator,
166
auth_rule_t type, ...)
168
if (enumerator->current)
172
va_start(args, type);
174
destroy_entry_value(enumerator->current);
175
enumerator->current->type = type;
178
case AUTH_RULE_AUTH_CLASS:
179
case AUTH_RULE_EAP_TYPE:
180
case AUTH_RULE_EAP_VENDOR:
181
case AUTH_RULE_CRL_VALIDATION:
182
case AUTH_RULE_OCSP_VALIDATION:
184
enumerator->current->value = (void*)(uintptr_t)va_arg(args, u_int);
186
case AUTH_RULE_IDENTITY:
187
case AUTH_RULE_EAP_IDENTITY:
188
case AUTH_RULE_AC_GROUP:
189
case AUTH_RULE_CA_CERT:
190
case AUTH_RULE_IM_CERT:
191
case AUTH_RULE_SUBJECT_CERT:
192
case AUTH_HELPER_IM_CERT:
193
case AUTH_HELPER_SUBJECT_CERT:
194
case AUTH_HELPER_IM_HASH_URL:
195
case AUTH_HELPER_SUBJECT_HASH_URL:
197
enumerator->current->value = va_arg(args, void*);
205
* Implementation of auth_cfg_t.get.
207
static void* get(private_auth_cfg_t *this, auth_rule_t type)
209
enumerator_t *enumerator;
210
void *current_value, *best_value = NULL;
211
auth_rule_t current_type;
214
enumerator = create_enumerator(this);
215
while (enumerator->enumerate(enumerator, ¤t_type, ¤t_value))
217
if (type == current_type)
219
if (type == AUTH_RULE_CRL_VALIDATION ||
220
type == AUTH_RULE_OCSP_VALIDATION)
221
{ /* for CRL/OCSP validation, always get() the highest value */
222
if (!found || current_value > best_value)
224
best_value = current_value;
229
best_value = current_value;
234
enumerator->destroy(enumerator);
241
/* use some sane defaults if we don't find an entry */
242
case AUTH_RULE_AUTH_CLASS:
243
return (void*)AUTH_CLASS_ANY;
244
case AUTH_RULE_EAP_TYPE:
245
return (void*)EAP_NAK;
246
case AUTH_RULE_EAP_VENDOR:
248
case AUTH_RULE_CRL_VALIDATION:
249
case AUTH_RULE_OCSP_VALIDATION:
250
return (void*)VALIDATION_FAILED;
251
case AUTH_RULE_IDENTITY:
252
case AUTH_RULE_EAP_IDENTITY:
253
case AUTH_RULE_AC_GROUP:
254
case AUTH_RULE_CA_CERT:
255
case AUTH_RULE_IM_CERT:
256
case AUTH_RULE_SUBJECT_CERT:
257
case AUTH_HELPER_IM_CERT:
258
case AUTH_HELPER_SUBJECT_CERT:
259
case AUTH_HELPER_IM_HASH_URL:
260
case AUTH_HELPER_SUBJECT_HASH_URL:
267
* Implementation of auth_cfg_t.add.
269
static void add(private_auth_cfg_t *this, auth_rule_t type, ...)
271
entry_t *entry = malloc_thing(entry_t);
274
va_start(args, type);
278
case AUTH_RULE_AUTH_CLASS:
279
case AUTH_RULE_EAP_TYPE:
280
case AUTH_RULE_EAP_VENDOR:
281
case AUTH_RULE_CRL_VALIDATION:
282
case AUTH_RULE_OCSP_VALIDATION:
284
entry->value = (void*)(uintptr_t)va_arg(args, u_int);
286
case AUTH_RULE_IDENTITY:
287
case AUTH_RULE_EAP_IDENTITY:
288
case AUTH_RULE_AC_GROUP:
289
case AUTH_RULE_CA_CERT:
290
case AUTH_RULE_IM_CERT:
291
case AUTH_RULE_SUBJECT_CERT:
292
case AUTH_HELPER_IM_CERT:
293
case AUTH_HELPER_SUBJECT_CERT:
294
case AUTH_HELPER_IM_HASH_URL:
295
case AUTH_HELPER_SUBJECT_HASH_URL:
297
entry->value = va_arg(args, void*);
301
this->entries->insert_last(this->entries, entry);
305
* Implementation of auth_cfg_t.complies.
307
static bool complies(private_auth_cfg_t *this, auth_cfg_t *constraints,
310
enumerator_t *e1, *e2;
315
e1 = constraints->create_enumerator(constraints);
316
while (e1->enumerate(e1, &t1, &value))
320
case AUTH_RULE_CA_CERT:
321
case AUTH_RULE_IM_CERT:
323
certificate_t *c1, *c2;
325
c1 = (certificate_t*)value;
328
e2 = create_enumerator(this);
329
while (e2->enumerate(e2, &t2, &c2))
331
if ((t2 == AUTH_RULE_CA_CERT || t2 == AUTH_RULE_IM_CERT) &&
338
if (!success && log_error)
340
DBG1(DBG_CFG, "constraint check failed: peer not "
341
"authenticated by CA '%Y'.", c1->get_subject(c1));
345
case AUTH_RULE_SUBJECT_CERT:
347
certificate_t *c1, *c2;
349
c1 = (certificate_t*)value;
350
c2 = get(this, AUTH_RULE_SUBJECT_CERT);
351
if (!c2 || !c1->equals(c1, c2))
356
DBG1(DBG_CFG, "constraint check failed: peer not "
357
"authenticated with peer cert '%Y'.",
358
c1->get_subject(c1));
363
case AUTH_RULE_CRL_VALIDATION:
364
case AUTH_RULE_OCSP_VALIDATION:
366
cert_validation_t validated, required;
368
required = (uintptr_t)value;
369
validated = (uintptr_t)get(this, t1);
372
case VALIDATION_FAILED:
375
case VALIDATION_SKIPPED:
376
if (validated == VALIDATION_SKIPPED)
381
case VALIDATION_GOOD:
382
if (validated == VALIDATION_GOOD)
391
DBG1(DBG_CFG, "constraint check failed: %N is %N, "
392
"but requires at least %N", auth_rule_names,
393
t1, cert_validation_names, validated,
394
cert_validation_names, required);
400
case AUTH_RULE_IDENTITY:
401
case AUTH_RULE_EAP_IDENTITY:
403
identification_t *id1, *id2;
405
id1 = (identification_t*)value;
407
if (!id2 || !id2->matches(id2, id1))
412
DBG1(DBG_CFG, "constraint check failed: %sidentity '%Y'"
413
" required ", t1 == AUTH_RULE_IDENTITY ? "" :
419
case AUTH_RULE_AUTH_CLASS:
421
if ((uintptr_t)value != AUTH_CLASS_ANY &&
422
(uintptr_t)value != (uintptr_t)get(this, t1))
427
DBG1(DBG_CFG, "constraint requires %N authentication, "
428
"but %N was used", auth_class_names, (uintptr_t)value,
429
auth_class_names, (uintptr_t)get(this, t1));
434
case AUTH_RULE_EAP_TYPE:
436
if ((uintptr_t)value != (uintptr_t)get(this, t1))
441
DBG1(DBG_CFG, "constraint requires %N, "
442
"but %N was used", eap_type_names, (uintptr_t)value,
443
eap_type_names, (uintptr_t)get(this, t1));
448
case AUTH_RULE_EAP_VENDOR:
450
if ((uintptr_t)value != (uintptr_t)get(this, t1))
455
DBG1(DBG_CFG, "constraint requires EAP vendor %d, "
456
"but %d was used", (uintptr_t)value,
457
(uintptr_t)get(this, t1));
462
case AUTH_RULE_AC_GROUP:
467
DBG1(DBG_CFG, "constraint check %N not implemented!",
468
auth_rule_names, t1);
472
case AUTH_HELPER_IM_CERT:
473
case AUTH_HELPER_SUBJECT_CERT:
474
case AUTH_HELPER_IM_HASH_URL:
475
case AUTH_HELPER_SUBJECT_HASH_URL:
489
* Implementation of auth_cfg_t.merge.
491
static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy)
494
{ /* nothing to merge */
499
enumerator_t *enumerator;
503
enumerator = create_enumerator(other);
504
while (enumerator->enumerate(enumerator, &type, &value))
508
case AUTH_RULE_CA_CERT:
509
case AUTH_RULE_IM_CERT:
510
case AUTH_RULE_SUBJECT_CERT:
511
case AUTH_HELPER_IM_CERT:
512
case AUTH_HELPER_SUBJECT_CERT:
514
certificate_t *cert = (certificate_t*)value;
516
add(this, type, cert->get_ref(cert));
519
case AUTH_RULE_CRL_VALIDATION:
520
case AUTH_RULE_OCSP_VALIDATION:
521
case AUTH_RULE_AUTH_CLASS:
522
case AUTH_RULE_EAP_TYPE:
523
case AUTH_RULE_EAP_VENDOR:
525
add(this, type, (uintptr_t)value);
528
case AUTH_RULE_IDENTITY:
529
case AUTH_RULE_EAP_IDENTITY:
530
case AUTH_RULE_AC_GROUP:
532
identification_t *id = (identification_t*)value;
534
add(this, type, id->clone(id));
537
case AUTH_HELPER_IM_HASH_URL:
538
case AUTH_HELPER_SUBJECT_HASH_URL:
540
add(this, type, strdup((char*)value));
545
enumerator->destroy(enumerator);
551
while (other->entries->remove_first(other->entries,
552
(void**)&entry) == SUCCESS)
554
this->entries->insert_last(this->entries, entry);
560
* Implementation of auth_cfg_t.equals.
562
static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other)
564
enumerator_t *e1, *e2;
566
bool equal = TRUE, found;
568
if (this->entries->get_count(this->entries) !=
569
other->entries->get_count(other->entries))
573
e1 = this->entries->create_enumerator(this->entries);
574
while (e1->enumerate(e1, &i1))
577
e2 = other->entries->create_enumerator(other->entries);
578
while (e2->enumerate(e2, &i2))
580
if (i1->type == i2->type)
584
case AUTH_RULE_AUTH_CLASS:
585
case AUTH_RULE_EAP_TYPE:
586
case AUTH_RULE_EAP_VENDOR:
587
case AUTH_RULE_CRL_VALIDATION:
588
case AUTH_RULE_OCSP_VALIDATION:
590
if (i1->value == i2->value)
597
case AUTH_RULE_CA_CERT:
598
case AUTH_RULE_IM_CERT:
599
case AUTH_RULE_SUBJECT_CERT:
600
case AUTH_HELPER_IM_CERT:
601
case AUTH_HELPER_SUBJECT_CERT:
603
certificate_t *c1, *c2;
605
c1 = (certificate_t*)i1->value;
606
c2 = (certificate_t*)i2->value;
608
if (c1->equals(c1, c2))
615
case AUTH_RULE_IDENTITY:
616
case AUTH_RULE_EAP_IDENTITY:
617
case AUTH_RULE_AC_GROUP:
619
identification_t *id1, *id2;
621
id1 = (identification_t*)i1->value;
622
id2 = (identification_t*)i2->value;
624
if (id1->equals(id1, id2))
631
case AUTH_HELPER_IM_HASH_URL:
632
case AUTH_HELPER_SUBJECT_HASH_URL:
634
if (streq(i1->value, i2->value))
657
* Implementation of auth_cfg_t.purge
659
static void purge(private_auth_cfg_t *this, bool keep_ca)
664
cas = linked_list_create();
665
while (this->entries->remove_last(this->entries, (void**)&entry) == SUCCESS)
667
if (keep_ca && entry->type == AUTH_RULE_CA_CERT)
669
cas->insert_first(cas, entry);
673
destroy_entry_value(entry);
677
while (cas->remove_last(cas, (void**)&entry) == SUCCESS)
679
this->entries->insert_first(this->entries, entry);
685
* Implementation of auth_cfg_t.clone
687
static auth_cfg_t* clone_(private_auth_cfg_t *this)
689
enumerator_t *enumerator;
693
clone = auth_cfg_create();
694
enumerator = this->entries->create_enumerator(this->entries);
695
while (enumerator->enumerate(enumerator, &entry))
699
case AUTH_RULE_IDENTITY:
700
case AUTH_RULE_EAP_IDENTITY:
701
case AUTH_RULE_AC_GROUP:
703
identification_t *id = (identification_t*)entry->value;
704
clone->add(clone, entry->type, id->clone(id));
707
case AUTH_RULE_CA_CERT:
708
case AUTH_RULE_IM_CERT:
709
case AUTH_RULE_SUBJECT_CERT:
710
case AUTH_HELPER_IM_CERT:
711
case AUTH_HELPER_SUBJECT_CERT:
713
certificate_t *cert = (certificate_t*)entry->value;
714
clone->add(clone, entry->type, cert->get_ref(cert));
717
case AUTH_HELPER_IM_HASH_URL:
718
case AUTH_HELPER_SUBJECT_HASH_URL:
720
clone->add(clone, entry->type, strdup(entry->value));
723
case AUTH_RULE_AUTH_CLASS:
724
case AUTH_RULE_EAP_TYPE:
725
case AUTH_RULE_EAP_VENDOR:
726
case AUTH_RULE_CRL_VALIDATION:
727
case AUTH_RULE_OCSP_VALIDATION:
728
clone->add(clone, entry->type, (uintptr_t)entry->value);
732
enumerator->destroy(enumerator);
737
* Implementation of auth_cfg_t.destroy
739
static void destroy(private_auth_cfg_t *this)
742
this->entries->destroy(this->entries);
749
auth_cfg_t *auth_cfg_create()
751
private_auth_cfg_t *this = malloc_thing(private_auth_cfg_t);
753
this->public.add = (void(*)(auth_cfg_t*, auth_rule_t type, ...))add;
754
this->public.get = (void*(*)(auth_cfg_t*, auth_rule_t type))get;
755
this->public.create_enumerator = (enumerator_t*(*)(auth_cfg_t*))create_enumerator;
756
this->public.replace = (void(*)(auth_cfg_t*,enumerator_t*,auth_rule_t,...))replace;
757
this->public.complies = (bool(*)(auth_cfg_t*, auth_cfg_t *,bool))complies;
758
this->public.merge = (void(*)(auth_cfg_t*, auth_cfg_t *other,bool))merge;
759
this->public.purge = (void(*)(auth_cfg_t*,bool))purge;
760
this->public.equals = (bool(*)(auth_cfg_t*, auth_cfg_t *other))equals;
761
this->public.clone = (auth_cfg_t*(*)(auth_cfg_t*))clone_;
762
this->public.destroy = (void(*)(auth_cfg_t*))destroy;
764
this->entries = linked_list_create();
766
return &this->public;