eap2mschap_local.h revision 1.1
1/* $OpenBSD: eap2mschap_local.h,v 1.1 2024/07/14 16:09:23 yasuoka Exp $ */ 2 3/* 4 * Copyright (c) 2024 Internet Initiative Japan Inc. 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19#define EAP_CODE_REQUEST 1 20#define EAP_CODE_RESPONSE 2 21#define EAP_CODE_SUCCESS 3 22#define EAP_CODE_FAILURE 4 23 24#define EAP_TYPE_IDENTITY 1 25#define EAP_TYPE_NOTIFICATION 2 26#define EAP_TYPE_NAK 3 27#define EAP_TYPE_MSCHAPV2 0x1a /* [MS-CHAP] MS-EAP-Authentication */ 28 29#define CHAP_CHALLENGE 1 30#define CHAP_RESPONSE 2 31#define CHAP_SUCCESS 3 32#define CHAP_FAILURE 4 33 34/* From [MS-CHAP] */ 35enum eap_chap_status { 36 EAP_CHAP_NONE, 37 EAP_CHAP_CHALLENGE_SENT, 38 EAP_CHAP_SUCCESS_REQUEST_SENT, 39 EAP_CHAP_FAILURE_REQUEST_SENT, 40 EAP_CHAP_CHANGE_PASSWORD_SENT, 41 EAP_CHAP_FAILED, 42 EAP_CHAP_SUCCESS 43}; 44 45struct eap { 46 uint8_t code; 47 uint8_t id; 48 uint16_t length; 49 uint8_t value[0]; 50} __packed; 51 52struct chap { 53 uint8_t code; 54 uint8_t id; 55 uint16_t length; 56 int8_t value[0]; 57} __packed; 58 59struct eap_chap { 60 struct eap eap; 61 uint8_t eap_type; 62 struct chap chap; 63}; 64 65struct eap_mschap_challenge { 66 struct eap eap; 67 uint8_t eap_type; 68 struct chap chap; 69 uint8_t challsiz; 70 uint8_t chall[16]; 71 char chap_name[0]; 72} __packed; 73static_assert(sizeof(struct eap_mschap_challenge) == 26, ""); 74static_assert(offsetof(struct eap_mschap_challenge, chap) == 5, ""); 75static_assert(offsetof(struct eap_mschap_challenge, chall) == 10, ""); 76 77struct eap_mschap_response { 78 struct eap eap; 79 uint8_t eap_type; 80 struct chap chap; 81 uint8_t challsiz; 82 uint8_t peerchall[16]; 83 uint8_t reserved[8]; 84 uint8_t ntresponse[24]; 85 uint8_t flags; 86 uint8_t chap_name[0]; 87} __packed; 88static_assert(sizeof(struct eap_mschap_response) == 59, ""); 89static_assert(offsetof(struct eap_mschap_response, chap) == 5, ""); 90static_assert(offsetof(struct eap_mschap_response, peerchall) == 10, ""); 91 92struct radius_ms_chap2_response { 93 uint8_t ident; 94 uint8_t flags; 95 uint8_t peerchall[16]; 96 uint8_t reserved[8]; 97 uint8_t ntresponse[24]; 98} __packed; 99 100 101struct eap2mschap; 102 103struct access_req { 104 struct eap2mschap *eap2mschap; 105 char *username; 106 u_int q_id; 107 TAILQ_ENTRY(access_req) next; 108 RB_ENTRY(access_req) tree; 109 /* for EAP */ 110 enum eap_chap_status eap_chap_status; 111 char state[16]; 112 unsigned char chap_id; 113 unsigned char eap_id; 114 time_t eap_time; 115 char chall[16]; 116 RADIUS_PACKET *pkt; 117 118}; 119TAILQ_HEAD(access_reqq, access_req); 120RB_HEAD(access_reqt, access_req); 121 122#define CHAP_NAME_MAX 40 123 124struct eap2mschap { 125 struct module_base *base; 126 char *secret; 127 char chap_name[CHAP_NAME_MAX + 1]; 128 struct access_reqq reqq; 129 struct access_reqt eapt; 130 struct event ev_eapt; 131}; 132 133/* Attributes copied from CHAP Access-Accept to EAP Access-Access-Accept */ 134struct preserve_attrs { 135 uint8_t type; 136 uint32_t vendor; 137} preserve_attrs[] = { 138 { RADIUS_TYPE_FRAMED_PROTOCOL, 0}, 139 { RADIUS_TYPE_FRAMED_IP_ADDRESS, 0}, 140 { RADIUS_TYPE_FRAMED_IP_NETMASK, 0}, 141 { RADIUS_TYPE_FRAMED_IPV6_ADDRESS, 0}, 142 { RADIUS_TYPE_DNS_SERVER_IPV6_ADDRESS, 0}, 143 { RADIUS_TYPE_FRAMED_ROUTING, 0}, 144 { RADIUS_VTYPE_MS_PRIMARY_DNS_SERVER, RADIUS_VENDOR_MICROSOFT }, 145 { RADIUS_VTYPE_MS_SECONDARY_DNS_SERVER, RADIUS_VENDOR_MICROSOFT }, 146 { RADIUS_VTYPE_MS_PRIMARY_NBNS_SERVER, RADIUS_VENDOR_MICROSOFT }, 147 { RADIUS_VTYPE_MS_SECONDARY_NBNS_SERVER,RADIUS_VENDOR_MICROSOFT }, 148 { RADIUS_VTYPE_MPPE_SEND_KEY, RADIUS_VENDOR_MICROSOFT }, 149 { RADIUS_VTYPE_MPPE_RECV_KEY, RADIUS_VENDOR_MICROSOFT } 150}; 151 152#ifndef EAP2MSCHAP_DEBUG 153#define EAP2MSCHAP_DBG(...) 154#define EAP2MSCHAP_ASSERT(_cond) 155#else 156#define EAP2MSCHAP_DBG(...) logit(LOG_DEBUG, __VA_ARGS__) 157#define EAP2MSCHAP_ASSERT(_cond) \ 158 do { \ 159 if (!(_cond)) { \ 160 log_warnx( \ 161 "ASSERT(%s) failed in %s() at %s:%d",\ 162 #_cond, __func__, __FILE__, __LINE__);\ 163 abort(); \ 164 } \ 165 } while (0/* CONSTCOND */); 166#endif 167#ifndef nitems 168#define nitems(_x) (sizeof((_x)) / sizeof((_x)[0])) 169#endif 170 171static void eap2mschap_init(struct eap2mschap *); 172static void eap2mschap_start(void *); 173static void eap2mschap_config_set(void *, const char *, int, 174 char * const *); 175static void eap2mschap_stop(void *); 176static void eap2mschap_access_request(void *, u_int, const u_char *, 177 size_t); 178static void eap2mschap_next_response(void *, u_int, const u_char *, 179 size_t); 180 181static void eap2mschap_on_eapt (int, short, void *); 182static void eap2mschap_reset_eaptimer (struct eap2mschap *); 183 184static struct access_req 185 *access_request_new(struct eap2mschap *, u_int); 186static void access_request_free(struct access_req *); 187static int access_request_compar(struct access_req *, 188 struct access_req *); 189 190 191static struct access_req 192 *eap_recv(struct eap2mschap *, u_int, RADIUS_PACKET *); 193static struct access_req 194 *eap_recv_mschap(struct eap2mschap *, struct access_req *, 195 RADIUS_PACKET *, struct eap_chap *); 196static void eap_resp_mschap(struct eap2mschap *, struct access_req *, 197 RADIUS_PACKET *); 198static void eap_send_reject(struct access_req *, RADIUS_PACKET *, u_int); 199static const char 200 *eap_chap_status_string(enum eap_chap_status); 201static const char 202 *hex_string(const char *, size_t, char *, size_t); 203static time_t monotime(void); 204 205RB_PROTOTYPE_STATIC(access_reqt, access_req, tree, access_request_compar); 206