eap_gtc.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. * hostapd / EAP-GTC (RFC 3748)
  3. * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. * See README and COPYING for more details.
  13. */
  14. #include "includes.h"
  15. #include "common.h"
  16. #include "eap_i.h"
  17. struct eap_gtc_data {
  18. enum { CONTINUE, SUCCESS, FAILURE } state;
  19. int prefix;
  20. };
  21. static void * eap_gtc_init(struct eap_sm *sm)
  22. {
  23. struct eap_gtc_data *data;
  24. data = os_zalloc(sizeof(*data));
  25. if (data == NULL)
  26. return NULL;
  27. data->state = CONTINUE;
  28. #ifdef EAP_FAST
  29. if (sm->m && sm->m->vendor == EAP_VENDOR_IETF &&
  30. sm->m->method == EAP_TYPE_FAST) {
  31. wpa_printf(MSG_DEBUG, "EAP-GTC: EAP-FAST tunnel - use prefix "
  32. "with challenge/response");
  33. data->prefix = 1;
  34. }
  35. #endif /* EAP_FAST */
  36. return data;
  37. }
  38. static void eap_gtc_reset(struct eap_sm *sm, void *priv)
  39. {
  40. struct eap_gtc_data *data = priv;
  41. os_free(data);
  42. }
  43. static struct wpabuf * eap_gtc_buildReq(struct eap_sm *sm, void *priv, u8 id)
  44. {
  45. struct eap_gtc_data *data = priv;
  46. struct wpabuf *req;
  47. char *msg;
  48. size_t msg_len;
  49. msg = data->prefix ? "CHALLENGE=Password" : "Password";
  50. msg_len = os_strlen(msg);
  51. req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, msg_len,
  52. EAP_CODE_REQUEST, id);
  53. if (req == NULL) {
  54. wpa_printf(MSG_ERROR, "EAP-GTC: Failed to allocate memory for "
  55. "request");
  56. data->state = FAILURE;
  57. return NULL;
  58. }
  59. wpabuf_put_data(req, msg, msg_len);
  60. data->state = CONTINUE;
  61. return req;
  62. }
  63. static Boolean eap_gtc_check(struct eap_sm *sm, void *priv,
  64. struct wpabuf *respData)
  65. {
  66. const u8 *pos;
  67. size_t len;
  68. pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, respData, &len);
  69. if (pos == NULL || len < 1) {
  70. wpa_printf(MSG_INFO, "EAP-GTC: Invalid frame");
  71. return TRUE;
  72. }
  73. return FALSE;
  74. }
  75. static void eap_gtc_process(struct eap_sm *sm, void *priv,
  76. struct wpabuf *respData)
  77. {
  78. struct eap_gtc_data *data = priv;
  79. const u8 *pos;
  80. size_t rlen;
  81. pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, respData, &rlen);
  82. if (pos == NULL || rlen < 1)
  83. return; /* Should not happen - frame already validated */
  84. wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response", pos, rlen);
  85. #ifdef EAP_FAST
  86. if (data->prefix) {
  87. const u8 *pos2, *end;
  88. /* "RESPONSE=<user>\0<password>" */
  89. if (rlen < 10) {
  90. wpa_printf(MSG_DEBUG, "EAP-GTC: Too short response "
  91. "for EAP-FAST prefix");
  92. data->state = FAILURE;
  93. return;
  94. }
  95. end = pos + rlen;
  96. pos += 9;
  97. pos2 = pos;
  98. while (pos2 < end && *pos2)
  99. pos2++;
  100. if (pos2 == end) {
  101. wpa_printf(MSG_DEBUG, "EAP-GTC: No password in "
  102. "response to EAP-FAST prefix");
  103. data->state = FAILURE;
  104. return;
  105. }
  106. wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Response user",
  107. pos, pos2 - pos);
  108. if (sm->identity && sm->require_identity_match &&
  109. (pos2 - pos != (int) sm->identity_len ||
  110. os_memcmp(pos, sm->identity, sm->identity_len))) {
  111. wpa_printf(MSG_DEBUG, "EAP-GTC: Phase 2 Identity did "
  112. "not match with required Identity");
  113. wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Expected "
  114. "identity",
  115. sm->identity, sm->identity_len);
  116. data->state = FAILURE;
  117. return;
  118. } else {
  119. os_free(sm->identity);
  120. sm->identity_len = pos2 - pos;
  121. sm->identity = os_malloc(sm->identity_len);
  122. if (sm->identity == NULL) {
  123. data->state = FAILURE;
  124. return;
  125. }
  126. os_memcpy(sm->identity, pos, sm->identity_len);
  127. }
  128. if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
  129. wpa_hexdump_ascii(MSG_DEBUG, "EAP-GTC: Phase2 "
  130. "Identity not found in the user "
  131. "database",
  132. sm->identity, sm->identity_len);
  133. data->state = FAILURE;
  134. return;
  135. }
  136. pos = pos2 + 1;
  137. rlen = end - pos;
  138. wpa_hexdump_ascii_key(MSG_MSGDUMP,
  139. "EAP-GTC: Response password",
  140. pos, rlen);
  141. }
  142. #endif /* EAP_FAST */
  143. if (sm->user == NULL || sm->user->password == NULL ||
  144. sm->user->password_hash) {
  145. wpa_printf(MSG_INFO, "EAP-GTC: Plaintext password not "
  146. "configured");
  147. data->state = FAILURE;
  148. return;
  149. }
  150. if (rlen != sm->user->password_len ||
  151. os_memcmp(pos, sm->user->password, rlen) != 0) {
  152. wpa_printf(MSG_DEBUG, "EAP-GTC: Done - Failure");
  153. data->state = FAILURE;
  154. } else {
  155. wpa_printf(MSG_DEBUG, "EAP-GTC: Done - Success");
  156. data->state = SUCCESS;
  157. }
  158. }
  159. static Boolean eap_gtc_isDone(struct eap_sm *sm, void *priv)
  160. {
  161. struct eap_gtc_data *data = priv;
  162. return data->state != CONTINUE;
  163. }
  164. static Boolean eap_gtc_isSuccess(struct eap_sm *sm, void *priv)
  165. {
  166. struct eap_gtc_data *data = priv;
  167. return data->state == SUCCESS;
  168. }
  169. int eap_server_gtc_register(void)
  170. {
  171. struct eap_method *eap;
  172. int ret;
  173. eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
  174. EAP_VENDOR_IETF, EAP_TYPE_GTC, "GTC");
  175. if (eap == NULL)
  176. return -1;
  177. eap->init = eap_gtc_init;
  178. eap->reset = eap_gtc_reset;
  179. eap->buildReq = eap_gtc_buildReq;
  180. eap->check = eap_gtc_check;
  181. eap->process = eap_gtc_process;
  182. eap->isDone = eap_gtc_isDone;
  183. eap->isSuccess = eap_gtc_isSuccess;
  184. ret = eap_server_method_register(eap);
  185. if (ret)
  186. eap_server_method_free(eap);
  187. return ret;
  188. }