eap_user_db.c 7.2 KB

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