eap_server_gtc.c 5.0 KB

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