c218bd48b68209778de8cecd4e9a1ce6cb4c8f49
[strongswan.git] / src / libcharon / plugins / eap_radius / eap_radius_plugin.c
1 /*
2 * Copyright (C) 2009 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "eap_radius_plugin.h"
17
18 #include "eap_radius.h"
19 #include "radius_client.h"
20 #include "radius_server.h"
21
22 #include <daemon.h>
23 #include <threading/rwlock.h>
24
25 /**
26 * Default RADIUS server port, when not configured
27 */
28 #define RADIUS_PORT 1812
29
30 typedef struct private_eap_radius_plugin_t private_eap_radius_plugin_t;
31
32 /**
33 * Private data of an eap_radius_plugin_t object.
34 */
35 struct private_eap_radius_plugin_t {
36
37 /**
38 * Public radius_plugin_t interface.
39 */
40 eap_radius_plugin_t public;
41
42 /**
43 * List of RADIUS servers
44 */
45 linked_list_t *servers;
46
47 /**
48 * Lock for server list
49 */
50 rwlock_t *lock;
51 };
52
53 /**
54 * Instance of the EAP plugin
55 */
56 static private_eap_radius_plugin_t *instance = NULL;
57
58 /**
59 * Load RADIUS servers from configuration
60 */
61 static void load_servers(private_eap_radius_plugin_t *this)
62 {
63 enumerator_t *enumerator;
64 radius_server_t *server;
65 char *nas_identifier, *secret, *address, *section;
66 int port, sockets, preference;
67
68 address = lib->settings->get_str(lib->settings,
69 "charon.plugins.eap-radius.server", NULL);
70 if (address)
71 { /* legacy configuration */
72 secret = lib->settings->get_str(lib->settings,
73 "charon.plugins.eap-radius.secret", NULL);
74 if (!secret)
75 {
76 DBG1(DBG_CFG, "no RADUIS secret defined");
77 return;
78 }
79 nas_identifier = lib->settings->get_str(lib->settings,
80 "charon.plugins.eap-radius.nas_identifier", "strongSwan");
81 port = lib->settings->get_int(lib->settings,
82 "charon.plugins.eap-radius.port", RADIUS_PORT);
83 sockets = lib->settings->get_int(lib->settings,
84 "charon.plugins.eap-radius.sockets", 1);
85 server = radius_server_create(address, address, port, nas_identifier,
86 secret, sockets, 0);
87 if (!server)
88 {
89 DBG1(DBG_CFG, "no RADUIS server defined");
90 return;
91 }
92 this->servers->insert_last(this->servers, server);
93 return;
94 }
95
96 enumerator = lib->settings->create_section_enumerator(lib->settings,
97 "charon.plugins.eap-radius.servers");
98 while (enumerator->enumerate(enumerator, &section))
99 {
100 address = lib->settings->get_str(lib->settings,
101 "charon.plugins.eap-radius.servers.%s.address", NULL, section);
102 if (!address)
103 {
104 DBG1(DBG_CFG, "RADIUS server '%s' misses address, skipped", section);
105 continue;
106 }
107 secret = lib->settings->get_str(lib->settings,
108 "charon.plugins.eap-radius.servers.%s.secret", NULL, section);
109 if (!secret)
110 {
111 DBG1(DBG_CFG, "RADIUS server '%s' misses secret, skipped", section);
112 continue;
113 }
114 nas_identifier = lib->settings->get_str(lib->settings,
115 "charon.plugins.eap-radius.servers.%s.nas_identifier",
116 "strongSwan", section);
117 port = lib->settings->get_int(lib->settings,
118 "charon.plugins.eap-radius.servers.%s.port", RADIUS_PORT, section);
119 sockets = lib->settings->get_int(lib->settings,
120 "charon.plugins.eap-radius.servers.%s.sockets", 1, section);
121 preference = lib->settings->get_int(lib->settings,
122 "charon.plugins.eap-radius.servers.%s.preference", 0, section);
123 server = radius_server_create(section, address, port, nas_identifier,
124 secret, sockets, preference);
125 if (!server)
126 {
127 DBG1(DBG_CFG, "loading RADIUS server '%s' failed, skipped", section);
128 continue;
129 }
130 this->servers->insert_last(this->servers, server);
131 }
132 enumerator->destroy(enumerator);
133
134 DBG1(DBG_CFG, "loaded %d RADIUS server configuration%s",
135 this->servers->get_count(this->servers),
136 this->servers->get_count(this->servers) == 1 ? "" : "s");
137 }
138
139 METHOD(plugin_t, get_name, char*,
140 private_eap_radius_plugin_t *this)
141 {
142 return "eap-radius";
143 }
144
145 METHOD(plugin_t, reload, bool,
146 private_eap_radius_plugin_t *this)
147 {
148 this->lock->write_lock(this->lock);
149 this->servers->destroy_offset(this->servers,
150 offsetof(radius_server_t, destroy));
151 this->servers = linked_list_create();
152 load_servers(this);
153 this->lock->unlock(this->lock);
154 return TRUE;
155 }
156
157 METHOD(plugin_t, destroy, void,
158 private_eap_radius_plugin_t *this)
159 {
160 charon->eap->remove_method(charon->eap, (eap_constructor_t)eap_radius_create);
161 this->servers->destroy_offset(this->servers,
162 offsetof(radius_server_t, destroy));
163 this->lock->destroy(this->lock);
164 free(this);
165 instance = NULL;
166 }
167
168 /*
169 * see header file
170 */
171 plugin_t *eap_radius_plugin_create()
172 {
173 private_eap_radius_plugin_t *this;
174
175 INIT(this,
176 .public = {
177 .plugin = {
178 .get_name = _get_name,
179 .reload = _reload,
180 .destroy = _destroy,
181 },
182 },
183 .servers = linked_list_create(),
184 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
185 );
186
187 load_servers(this);
188
189 charon->eap->add_method(charon->eap, EAP_RADIUS, 0,
190 EAP_SERVER, (eap_constructor_t)eap_radius_create);
191
192 instance = this;
193
194 return &this->public.plugin;
195 }
196
197 /**
198 * See header
199 */
200 enumerator_t *eap_radius_create_server_enumerator()
201 {
202 if (instance)
203 {
204 instance->lock->read_lock(instance->lock);
205 return enumerator_create_cleaner(
206 instance->servers->create_enumerator(instance->servers),
207 (void*)instance->lock->unlock, instance->lock);
208 }
209 return enumerator_create_empty();
210 }
211