Filter invalid EAP authentication types when enumerating them
[strongswan.git] / src / libcharon / sa / eap / eap_manager.c
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
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>.
10 *
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
14 * for more details.
15 */
16
17 #include "eap_manager.h"
18
19 #include <utils/linked_list.h>
20 #include <threading/rwlock.h>
21
22 typedef struct private_eap_manager_t private_eap_manager_t;
23 typedef struct eap_entry_t eap_entry_t;
24
25 /**
26 * EAP constructor entry
27 */
28 struct eap_entry_t {
29
30 /**
31 * EAP method type, vendor specific if vendor is set
32 */
33 eap_type_t type;
34
35 /**
36 * vendor ID, 0 for default EAP methods
37 */
38 u_int32_t vendor;
39
40 /**
41 * Role of the method returned by the constructor, EAP_SERVER or EAP_PEER
42 */
43 eap_role_t role;
44
45 /**
46 * constructor function to create instance
47 */
48 eap_constructor_t constructor;
49 };
50
51 /**
52 * private data of eap_manager
53 */
54 struct private_eap_manager_t {
55
56 /**
57 * public functions
58 */
59 eap_manager_t public;
60
61 /**
62 * list of eap_entry_t's
63 */
64 linked_list_t *methods;
65
66 /**
67 * rwlock to lock methods
68 */
69 rwlock_t *lock;
70 };
71
72 METHOD(eap_manager_t, add_method, void,
73 private_eap_manager_t *this, eap_type_t type, u_int32_t vendor,
74 eap_role_t role, eap_constructor_t constructor)
75 {
76 eap_entry_t *entry = malloc_thing(eap_entry_t);
77
78 entry->type = type;
79 entry->vendor = vendor;
80 entry->role = role;
81 entry->constructor = constructor;
82
83 this->lock->write_lock(this->lock);
84 this->methods->insert_last(this->methods, entry);
85 this->lock->unlock(this->lock);
86 }
87
88 METHOD(eap_manager_t, remove_method, void,
89 private_eap_manager_t *this, eap_constructor_t constructor)
90 {
91 enumerator_t *enumerator;
92 eap_entry_t *entry;
93
94 this->lock->write_lock(this->lock);
95 enumerator = this->methods->create_enumerator(this->methods);
96 while (enumerator->enumerate(enumerator, &entry))
97 {
98 if (constructor == entry->constructor)
99 {
100 this->methods->remove_at(this->methods, enumerator);
101 free(entry);
102 }
103 }
104 enumerator->destroy(enumerator);
105 this->lock->unlock(this->lock);
106 }
107
108 /**
109 * filter the registered methods
110 */
111 static bool filter_methods(uintptr_t role, eap_entry_t **entry,
112 eap_type_t *type, void *in, u_int32_t *vendor)
113 {
114 if ((*entry)->role != (eap_role_t)role)
115 {
116 return FALSE;
117 }
118 if ((*entry)->vendor == 0 &&
119 ((*entry)->type < 4 || (*entry)->type == EAP_EXPANDED ||
120 (*entry)->type > EAP_EXPERIMENTAL))
121 { /* filter invalid types */
122 return FALSE;
123 }
124 if (type)
125 {
126 *type = (*entry)->type;
127 }
128 if (vendor)
129 {
130 *vendor = (*entry)->vendor;
131 }
132 return TRUE;
133 }
134
135 METHOD(eap_manager_t, create_enumerator, enumerator_t*,
136 private_eap_manager_t *this, eap_role_t role)
137 {
138 this->lock->read_lock(this->lock);
139 return enumerator_create_cleaner(
140 enumerator_create_filter(
141 this->methods->create_enumerator(this->methods),
142 (void*)filter_methods, (void*)(uintptr_t)role, NULL),
143 (void*)this->lock->unlock, this->lock);
144 }
145
146 METHOD(eap_manager_t, create_instance, eap_method_t*,
147 private_eap_manager_t *this, eap_type_t type, u_int32_t vendor,
148 eap_role_t role, identification_t *server, identification_t *peer)
149 {
150 enumerator_t *enumerator;
151 eap_entry_t *entry;
152 eap_method_t *method = NULL;
153
154 this->lock->read_lock(this->lock);
155 enumerator = this->methods->create_enumerator(this->methods);
156 while (enumerator->enumerate(enumerator, &entry))
157 {
158 if (type == entry->type && vendor == entry->vendor &&
159 role == entry->role)
160 {
161 method = entry->constructor(server, peer);
162 if (method)
163 {
164 break;
165 }
166 }
167 }
168 enumerator->destroy(enumerator);
169 this->lock->unlock(this->lock);
170 return method;
171 }
172
173 METHOD(eap_manager_t, destroy, void,
174 private_eap_manager_t *this)
175 {
176 this->methods->destroy_function(this->methods, free);
177 this->lock->destroy(this->lock);
178 free(this);
179 }
180
181 /*
182 * See header
183 */
184 eap_manager_t *eap_manager_create()
185 {
186 private_eap_manager_t *this;
187
188 INIT(this,
189 .public = {
190 .add_method = _add_method,
191 .remove_method = _remove_method,
192 .create_enumerator = _create_enumerator,
193 .create_instance = _create_instance,
194 .destroy = _destroy,
195 },
196 .methods = linked_list_create(),
197 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
198 );
199
200 return &this->public;
201 }