1/* $OpenBSD: eap2mschap_local.h,v 1.2 2024/07/16 06:18:20 miod 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; 73#if defined(__STDC_VERSION__) && __STDC_VERSION >= 201112L 74static_assert(sizeof(struct eap_mschap_challenge) == 26, ""); 75static_assert(offsetof(struct eap_mschap_challenge, chap) == 5, ""); 76static_assert(offsetof(struct eap_mschap_challenge, chall) == 10, ""); 77#endif 78 79struct eap_mschap_response { 80 struct eap eap; 81 uint8_t eap_type; 82 struct chap chap; 83 uint8_t challsiz; 84 uint8_t peerchall[16]; 85 uint8_t reserved[8]; 86 uint8_t ntresponse[24]; 87 uint8_t flags; 88 uint8_t chap_name[0]; 89} __packed; 90#if defined(__STDC_VERSION__) && __STDC_VERSION >= 201112L 91static_assert(sizeof(struct eap_mschap_response) == 59, ""); 92static_assert(offsetof(struct eap_mschap_response, chap) == 5, ""); 93static_assert(offsetof(struct eap_mschap_response, peerchall) == 10, ""); 94#endif 95 96struct radius_ms_chap2_response { 97 uint8_t ident; 98 uint8_t flags; 99 uint8_t peerchall[16]; 100 uint8_t reserved[8]; 101 uint8_t ntresponse[24]; 102} __packed; 103 104 105struct eap2mschap; 106 107struct access_req { 108 struct eap2mschap *eap2mschap; 109 char *username; 110 u_int q_id; 111 TAILQ_ENTRY(access_req) next; 112 RB_ENTRY(access_req) tree; 113 /* for EAP */ 114 enum eap_chap_status eap_chap_status; 115 char state[16]; 116 unsigned char chap_id; 117 unsigned char eap_id; 118 time_t eap_time; 119 char chall[16]; 120 RADIUS_PACKET *pkt; 121 122}; 123TAILQ_HEAD(access_reqq, access_req); 124RB_HEAD(access_reqt, access_req); 125 126#define CHAP_NAME_MAX 40 127 128struct eap2mschap { 129 struct module_base *base; 130 char *secret; 131 char chap_name[CHAP_NAME_MAX + 1]; 132 struct access_reqq reqq; 133 struct access_reqt eapt; 134 struct event ev_eapt; 135}; 136 137/* Attributes copied from CHAP Access-Accept to EAP Access-Access-Accept */ 138struct preserve_attrs { 139 uint8_t type; 140 uint32_t vendor; 141} preserve_attrs[] = { 142 { RADIUS_TYPE_FRAMED_PROTOCOL, 0}, 143 { RADIUS_TYPE_FRAMED_IP_ADDRESS, 0}, 144 { RADIUS_TYPE_FRAMED_IP_NETMASK, 0}, 145 { RADIUS_TYPE_FRAMED_IPV6_ADDRESS, 0}, 146 { RADIUS_TYPE_DNS_SERVER_IPV6_ADDRESS, 0}, 147 { RADIUS_TYPE_FRAMED_ROUTING, 0}, 148 { RADIUS_VTYPE_MS_PRIMARY_DNS_SERVER, RADIUS_VENDOR_MICROSOFT }, 149 { RADIUS_VTYPE_MS_SECONDARY_DNS_SERVER, RADIUS_VENDOR_MICROSOFT }, 150 { RADIUS_VTYPE_MS_PRIMARY_NBNS_SERVER, RADIUS_VENDOR_MICROSOFT }, 151 { RADIUS_VTYPE_MS_SECONDARY_NBNS_SERVER,RADIUS_VENDOR_MICROSOFT }, 152 { RADIUS_VTYPE_MPPE_SEND_KEY, RADIUS_VENDOR_MICROSOFT }, 153 { RADIUS_VTYPE_MPPE_RECV_KEY, RADIUS_VENDOR_MICROSOFT } 154}; 155 156#ifndef EAP2MSCHAP_DEBUG 157#define EAP2MSCHAP_DBG(...) 158#define EAP2MSCHAP_ASSERT(_cond) 159#else 160#define EAP2MSCHAP_DBG(...) logit(LOG_DEBUG, __VA_ARGS__) 161#define EAP2MSCHAP_ASSERT(_cond) \ 162 do { \ 163 if (!(_cond)) { \ 164 log_warnx( \ 165 "ASSERT(%s) failed in %s() at %s:%d",\ 166 #_cond, __func__, __FILE__, __LINE__);\ 167 abort(); \ 168 } \ 169 } while (0/* CONSTCOND */); 170#endif 171#ifndef nitems 172#define nitems(_x) (sizeof((_x)) / sizeof((_x)[0])) 173#endif 174 175static void eap2mschap_init(struct eap2mschap *); 176static void eap2mschap_start(void *); 177static void eap2mschap_config_set(void *, const char *, int, 178 char * const *); 179static void eap2mschap_stop(void *); 180static void eap2mschap_access_request(void *, u_int, const u_char *, 181 size_t); 182static void eap2mschap_next_response(void *, u_int, const u_char *, 183 size_t); 184 185static void eap2mschap_on_eapt (int, short, void *); 186static void eap2mschap_reset_eaptimer (struct eap2mschap *); 187 188static struct access_req 189 *access_request_new(struct eap2mschap *, u_int); 190static void access_request_free(struct access_req *); 191static int access_request_compar(struct access_req *, 192 struct access_req *); 193 194 195static struct access_req 196 *eap_recv(struct eap2mschap *, u_int, RADIUS_PACKET *); 197static struct access_req 198 *eap_recv_mschap(struct eap2mschap *, struct access_req *, 199 RADIUS_PACKET *, struct eap_chap *); 200static void eap_resp_mschap(struct eap2mschap *, struct access_req *, 201 RADIUS_PACKET *); 202static void eap_send_reject(struct access_req *, RADIUS_PACKET *, u_int); 203static const char 204 *eap_chap_status_string(enum eap_chap_status); 205static const char 206 *hex_string(const char *, size_t, char *, size_t); 207static time_t monotime(void); 208 209RB_PROTOTYPE_STATIC(access_reqt, access_req, tree, access_request_compar); 210