Branch data Line data Source code
1 : : /*
2 : : * hostapd / EAP user database
3 : : * Copyright (c) 2012, Jouni Malinen <j@w1.fi>
4 : : *
5 : : * This software may be distributed under the terms of the BSD license.
6 : : * See README for more details.
7 : : */
8 : :
9 : : #include "includes.h"
10 : : #ifdef CONFIG_SQLITE
11 : : #include <sqlite3.h>
12 : : #endif /* CONFIG_SQLITE */
13 : :
14 : : #include "common.h"
15 : : #include "eap_common/eap_wsc_common.h"
16 : : #include "eap_server/eap_methods.h"
17 : : #include "eap_server/eap.h"
18 : : #include "ap_config.h"
19 : : #include "hostapd.h"
20 : :
21 : : #ifdef CONFIG_SQLITE
22 : :
23 : : static void set_user_methods(struct hostapd_eap_user *user, const char *methods)
24 : : {
25 : : char *buf, *start;
26 : : int num_methods;
27 : :
28 : : buf = os_strdup(methods);
29 : : if (buf == NULL)
30 : : return;
31 : :
32 : : os_memset(&user->methods, 0, sizeof(user->methods));
33 : : num_methods = 0;
34 : : start = buf;
35 : : while (*start) {
36 : : char *pos3 = os_strchr(start, ',');
37 : : if (pos3)
38 : : *pos3++ = '\0';
39 : : user->methods[num_methods].method =
40 : : eap_server_get_type(start,
41 : : &user->methods[num_methods].vendor);
42 : : if (user->methods[num_methods].vendor == EAP_VENDOR_IETF &&
43 : : user->methods[num_methods].method == EAP_TYPE_NONE) {
44 : : if (os_strcmp(start, "TTLS-PAP") == 0) {
45 : : user->ttls_auth |= EAP_TTLS_AUTH_PAP;
46 : : goto skip_eap;
47 : : }
48 : : if (os_strcmp(start, "TTLS-CHAP") == 0) {
49 : : user->ttls_auth |= EAP_TTLS_AUTH_CHAP;
50 : : goto skip_eap;
51 : : }
52 : : if (os_strcmp(start, "TTLS-MSCHAP") == 0) {
53 : : user->ttls_auth |= EAP_TTLS_AUTH_MSCHAP;
54 : : goto skip_eap;
55 : : }
56 : : if (os_strcmp(start, "TTLS-MSCHAPV2") == 0) {
57 : : user->ttls_auth |= EAP_TTLS_AUTH_MSCHAPV2;
58 : : goto skip_eap;
59 : : }
60 : : wpa_printf(MSG_INFO, "DB: Unsupported EAP type '%s'",
61 : : start);
62 : : os_free(buf);
63 : : return;
64 : : }
65 : :
66 : : num_methods++;
67 : : if (num_methods >= EAP_MAX_METHODS)
68 : : break;
69 : : skip_eap:
70 : : if (pos3 == NULL)
71 : : break;
72 : : start = pos3;
73 : : }
74 : :
75 : : os_free(buf);
76 : : }
77 : :
78 : :
79 : : static int get_user_cb(void *ctx, int argc, char *argv[], char *col[])
80 : : {
81 : : struct hostapd_eap_user *user = ctx;
82 : : int i;
83 : :
84 : : for (i = 0; i < argc; i++) {
85 : : if (os_strcmp(col[i], "password") == 0 && argv[i]) {
86 : : os_free(user->password);
87 : : user->password_len = os_strlen(argv[i]);
88 : : user->password = (u8 *) os_strdup(argv[i]);
89 : : user->next = (void *) 1;
90 : : } else if (os_strcmp(col[i], "methods") == 0 && argv[i]) {
91 : : set_user_methods(user, argv[i]);
92 : : } else if (os_strcmp(col[i], "remediation") == 0 && argv[i]) {
93 : : user->remediation = strlen(argv[i]) > 0;
94 : : }
95 : : }
96 : :
97 : : return 0;
98 : : }
99 : :
100 : :
101 : : static int get_wildcard_cb(void *ctx, int argc, char *argv[], char *col[])
102 : : {
103 : : struct hostapd_eap_user *user = ctx;
104 : : int i, id = -1, methods = -1;
105 : : size_t len;
106 : :
107 : : for (i = 0; i < argc; i++) {
108 : : if (os_strcmp(col[i], "identity") == 0 && argv[i])
109 : : id = i;
110 : : else if (os_strcmp(col[i], "methods") == 0 && argv[i])
111 : : methods = i;
112 : : }
113 : :
114 : : if (id < 0 || methods < 0)
115 : : return 0;
116 : :
117 : : len = os_strlen(argv[id]);
118 : : if (len <= user->identity_len &&
119 : : os_memcmp(argv[id], user->identity, len) == 0 &&
120 : : (user->password == NULL || len > user->password_len)) {
121 : : os_free(user->password);
122 : : user->password_len = os_strlen(argv[id]);
123 : : user->password = (u8 *) os_strdup(argv[id]);
124 : : user->next = (void *) 1;
125 : : set_user_methods(user, argv[methods]);
126 : : }
127 : :
128 : : return 0;
129 : : }
130 : :
131 : :
132 : : static const struct hostapd_eap_user *
133 : : eap_user_sqlite_get(struct hostapd_data *hapd, const u8 *identity,
134 : : size_t identity_len, int phase2)
135 : : {
136 : : sqlite3 *db;
137 : : struct hostapd_eap_user *user = NULL;
138 : : char id_str[256], cmd[300];
139 : : size_t i;
140 : :
141 : : if (identity_len >= sizeof(id_str))
142 : : return NULL;
143 : : os_memcpy(id_str, identity, identity_len);
144 : : id_str[identity_len] = '\0';
145 : : for (i = 0; i < identity_len; i++) {
146 : : if (id_str[i] >= 'a' && id_str[i] <= 'z')
147 : : continue;
148 : : if (id_str[i] >= 'A' && id_str[i] <= 'Z')
149 : : continue;
150 : : if (id_str[i] >= '0' && id_str[i] <= '9')
151 : : continue;
152 : : if (id_str[i] == '-' || id_str[i] == '_' || id_str[i] == '.' ||
153 : : id_str[i] == ',' || id_str[i] == '@' || id_str[i] == '\\' ||
154 : : id_str[i] == '!' || id_str[i] == '#' || id_str[i] == '%' ||
155 : : id_str[i] == '=' || id_str[i] == ' ')
156 : : continue;
157 : : wpa_printf(MSG_INFO, "DB: Unsupported character in identity");
158 : : return NULL;
159 : : }
160 : :
161 : : os_free(hapd->tmp_eap_user.identity);
162 : : os_free(hapd->tmp_eap_user.password);
163 : : os_memset(&hapd->tmp_eap_user, 0, sizeof(hapd->tmp_eap_user));
164 : : hapd->tmp_eap_user.phase2 = phase2;
165 : : hapd->tmp_eap_user.identity = os_zalloc(identity_len + 1);
166 : : if (hapd->tmp_eap_user.identity == NULL)
167 : : return NULL;
168 : : os_memcpy(hapd->tmp_eap_user.identity, identity, identity_len);
169 : :
170 : : if (sqlite3_open(hapd->conf->eap_user_sqlite, &db)) {
171 : : wpa_printf(MSG_INFO, "DB: Failed to open database %s: %s",
172 : : hapd->conf->eap_user_sqlite, sqlite3_errmsg(db));
173 : : sqlite3_close(db);
174 : : return NULL;
175 : : }
176 : :
177 : : os_snprintf(cmd, sizeof(cmd),
178 : : "SELECT * FROM users WHERE identity='%s' AND phase2=%d;",
179 : : id_str, phase2);
180 : : wpa_printf(MSG_DEBUG, "DB: %s", cmd);
181 : : if (sqlite3_exec(db, cmd, get_user_cb, &hapd->tmp_eap_user, NULL) !=
182 : : SQLITE_OK) {
183 : : wpa_printf(MSG_DEBUG, "DB: Failed to complete SQL operation");
184 : : } else if (hapd->tmp_eap_user.next)
185 : : user = &hapd->tmp_eap_user;
186 : :
187 : : if (user == NULL && !phase2) {
188 : : os_snprintf(cmd, sizeof(cmd),
189 : : "SELECT identity,methods FROM wildcards;");
190 : : wpa_printf(MSG_DEBUG, "DB: %s", cmd);
191 : : if (sqlite3_exec(db, cmd, get_wildcard_cb, &hapd->tmp_eap_user,
192 : : NULL) != SQLITE_OK) {
193 : : wpa_printf(MSG_DEBUG, "DB: Failed to complete SQL "
194 : : "operation");
195 : : } else if (hapd->tmp_eap_user.next) {
196 : : user = &hapd->tmp_eap_user;
197 : : os_free(user->identity);
198 : : user->identity = user->password;
199 : : user->identity_len = user->password_len;
200 : : user->password = NULL;
201 : : user->password_len = 0;
202 : : }
203 : : }
204 : :
205 : : sqlite3_close(db);
206 : :
207 : : return user;
208 : : }
209 : :
210 : : #endif /* CONFIG_SQLITE */
211 : :
212 : :
213 : : const struct hostapd_eap_user *
214 : 686 : hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
215 : : size_t identity_len, int phase2)
216 : : {
217 : 686 : const struct hostapd_bss_config *conf = hapd->conf;
218 : 686 : struct hostapd_eap_user *user = conf->eap_user;
219 : :
220 : : #ifdef CONFIG_WPS
221 [ + + ][ + + ]: 686 : if (conf->wps_state && identity_len == WSC_ID_ENROLLEE_LEN &&
[ + - ]
222 : 116 : os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) {
223 : : static struct hostapd_eap_user wsc_enrollee;
224 : 116 : os_memset(&wsc_enrollee, 0, sizeof(wsc_enrollee));
225 : 116 : wsc_enrollee.methods[0].method = eap_server_get_type(
226 : : "WSC", &wsc_enrollee.methods[0].vendor);
227 : 116 : return &wsc_enrollee;
228 : : }
229 : :
230 [ + + ][ + - ]: 570 : if (conf->wps_state && identity_len == WSC_ID_REGISTRAR_LEN &&
[ + - ]
231 : 28 : os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) {
232 : : static struct hostapd_eap_user wsc_registrar;
233 : 28 : os_memset(&wsc_registrar, 0, sizeof(wsc_registrar));
234 : 28 : wsc_registrar.methods[0].method = eap_server_get_type(
235 : : "WSC", &wsc_registrar.methods[0].vendor);
236 : 28 : wsc_registrar.password = (u8 *) conf->ap_pin;
237 : 56 : wsc_registrar.password_len = conf->ap_pin ?
238 [ + + ]: 28 : os_strlen(conf->ap_pin) : 0;
239 : 28 : return &wsc_registrar;
240 : : }
241 : : #endif /* CONFIG_WPS */
242 : :
243 [ + - ]: 9633 : while (user) {
244 [ + + ][ + + ]: 9633 : if (!phase2 && user->identity == NULL) {
245 : : /* Wildcard match */
246 : 248 : break;
247 : : }
248 : :
249 [ + + ][ + + ]: 9385 : if (user->phase2 == !!phase2 && user->wildcard_prefix &&
[ + - ]
250 [ + + ]: 3364 : identity_len >= user->identity_len &&
251 : 3364 : os_memcmp(user->identity, identity, user->identity_len) ==
252 : : 0) {
253 : : /* Wildcard prefix match */
254 : 36 : break;
255 : : }
256 : :
257 [ + + ][ + + ]: 9349 : if (user->phase2 == !!phase2 &&
258 [ + + ]: 450 : user->identity_len == identity_len &&
259 : 450 : os_memcmp(user->identity, identity, identity_len) == 0)
260 : 258 : break;
261 : 9091 : user = user->next;
262 : : }
263 : :
264 : : #ifdef CONFIG_SQLITE
265 : : if (user == NULL && conf->eap_user_sqlite) {
266 : : return eap_user_sqlite_get(hapd, identity, identity_len,
267 : : phase2);
268 : : }
269 : : #endif /* CONFIG_SQLITE */
270 : :
271 : 686 : return user;
272 : : }
|