BA
/
BaBoRo1
Embed:
(wiki syntax)
Show/hide line numbers
lwip_eap.c
00001 /* 00002 * eap.c - Extensible Authentication Protocol for PPP (RFC 2284) 00003 * 00004 * Copyright (c) 2001 by Sun Microsystems, Inc. 00005 * All rights reserved. 00006 * 00007 * Non-exclusive rights to redistribute, modify, translate, and use 00008 * this software in source and binary forms, in whole or in part, is 00009 * hereby granted, provided that the above copyright notice is 00010 * duplicated in any source form, and that neither the name of the 00011 * copyright holder nor the author is used to endorse or promote 00012 * products derived from this software. 00013 * 00014 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 00015 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 00016 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00017 * 00018 * Original version by James Carlson 00019 * 00020 * This implementation of EAP supports MD5-Challenge and SRP-SHA1 00021 * authentication styles. Note that support of MD5-Challenge is a 00022 * requirement of RFC 2284, and that it's essentially just a 00023 * reimplementation of regular RFC 1994 CHAP using EAP messages. 00024 * 00025 * As an authenticator ("server"), there are multiple phases for each 00026 * style. In the first phase of each style, the unauthenticated peer 00027 * name is queried using the EAP Identity request type. If the 00028 * "remotename" option is used, then this phase is skipped, because 00029 * the peer's name is presumed to be known. 00030 * 00031 * For MD5-Challenge, there are two phases, and the second phase 00032 * consists of sending the challenge itself and handling the 00033 * associated response. 00034 * 00035 * For SRP-SHA1, there are four phases. The second sends 's', 'N', 00036 * and 'g'. The reply contains 'A'. The third sends 'B', and the 00037 * reply contains 'M1'. The forth sends the 'M2' value. 00038 * 00039 * As an authenticatee ("client"), there's just a single phase -- 00040 * responding to the queries generated by the peer. EAP is an 00041 * authenticator-driven protocol. 00042 * 00043 * Based on draft-ietf-pppext-eap-srp-03.txt. 00044 */ 00045 00046 #include "netif/ppp/ppp_opts.h" 00047 #if PPP_SUPPORT && EAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ 00048 00049 #include "netif/ppp/ppp_impl.h" 00050 #include "netif/ppp/eap.h" 00051 #include "netif/ppp/magic.h" 00052 #include "netif/ppp/pppcrypt.h" 00053 00054 #ifdef USE_SRP 00055 #include <t_pwd.h> 00056 #include <t_server.h> 00057 #include <t_client.h> 00058 #endif /* USE_SRP */ 00059 00060 #ifndef SHA_DIGESTSIZE 00061 #define SHA_DIGESTSIZE 20 00062 #endif 00063 00064 #ifdef USE_SRP 00065 static char *pn_secret = NULL; /* Pseudonym generating secret */ 00066 #endif 00067 00068 #if PPP_OPTIONS 00069 /* 00070 * Command-line options. 00071 */ 00072 static option_t eap_option_list[] = { 00073 { "eap-restart", o_int, &eap_states[0].es_server.ea_timeout, 00074 "Set retransmit timeout for EAP Requests (server)" }, 00075 { "eap-max-sreq", o_int, &eap_states[0].es_server.ea_maxrequests, 00076 "Set max number of EAP Requests sent (server)" }, 00077 { "eap-timeout", o_int, &eap_states[0].es_client.ea_timeout, 00078 "Set time limit for peer EAP authentication" }, 00079 { "eap-max-rreq", o_int, &eap_states[0].es_client.ea_maxrequests, 00080 "Set max number of EAP Requests allows (client)" }, 00081 { "eap-interval", o_int, &eap_states[0].es_rechallenge, 00082 "Set interval for EAP rechallenge" }, 00083 #ifdef USE_SRP 00084 { "srp-interval", o_int, &eap_states[0].es_lwrechallenge, 00085 "Set interval for SRP lightweight rechallenge" }, 00086 { "srp-pn-secret", o_string, &pn_secret, 00087 "Long term pseudonym generation secret" }, 00088 { "srp-use-pseudonym", o_bool, &eap_states[0].es_usepseudo, 00089 "Use pseudonym if offered one by server", 1 }, 00090 #endif 00091 { NULL } 00092 }; 00093 #endif /* PPP_OPTIONS */ 00094 00095 /* 00096 * Protocol entry points. 00097 */ 00098 static void eap_init(ppp_pcb *pcb); 00099 static void eap_input(ppp_pcb *pcb, u_char *inp, int inlen); 00100 static void eap_protrej(ppp_pcb *pcb); 00101 static void eap_lowerup(ppp_pcb *pcb); 00102 static void eap_lowerdown(ppp_pcb *pcb); 00103 #if PRINTPKT_SUPPORT 00104 static int eap_printpkt(const u_char *inp, int inlen, 00105 void (*)(void *arg, const char *fmt, ...), void *arg); 00106 #endif /* PRINTPKT_SUPPORT */ 00107 00108 const struct protent eap_protent = { 00109 PPP_EAP, /* protocol number */ 00110 eap_init, /* initialization procedure */ 00111 eap_input, /* process a received packet */ 00112 eap_protrej, /* process a received protocol-reject */ 00113 eap_lowerup, /* lower layer has gone up */ 00114 eap_lowerdown, /* lower layer has gone down */ 00115 NULL, /* open the protocol */ 00116 NULL, /* close the protocol */ 00117 #if PRINTPKT_SUPPORT 00118 eap_printpkt, /* print a packet in readable form */ 00119 #endif /* PRINTPKT_SUPPORT */ 00120 #if PPP_DATAINPUT 00121 NULL, /* process a received data packet */ 00122 #endif /* PPP_DATAINPUT */ 00123 #if PRINTPKT_SUPPORT 00124 "EAP", /* text name of protocol */ 00125 NULL, /* text name of corresponding data protocol */ 00126 #endif /* PRINTPKT_SUPPORT */ 00127 #if PPP_OPTIONS 00128 eap_option_list, /* list of command-line options */ 00129 NULL, /* check requested options; assign defaults */ 00130 #endif /* PPP_OPTIONS */ 00131 #if DEMAND_SUPPORT 00132 NULL, /* configure interface for demand-dial */ 00133 NULL /* say whether to bring up link for this pkt */ 00134 #endif /* DEMAND_SUPPORT */ 00135 }; 00136 00137 #ifdef USE_SRP 00138 /* 00139 * A well-known 2048 bit modulus. 00140 */ 00141 static const u_char wkmodulus[] = { 00142 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B, 00143 0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F, 00144 0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07, 00145 0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50, 00146 0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED, 00147 0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D, 00148 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D, 00149 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50, 00150 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0, 00151 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3, 00152 0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8, 00153 0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8, 00154 0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA, 00155 0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74, 00156 0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7, 00157 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B, 00158 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16, 00159 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81, 00160 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A, 00161 0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48, 00162 0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D, 00163 0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA, 00164 0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78, 00165 0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6, 00166 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29, 00167 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8, 00168 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82, 00169 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6, 00170 0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4, 00171 0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75, 00172 0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2, 00173 0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73 00174 }; 00175 #endif 00176 00177 #if PPP_SERVER 00178 /* Local forward declarations. */ 00179 static void eap_server_timeout(void *arg); 00180 #endif /* PPP_SERVER */ 00181 00182 /* 00183 * Convert EAP state code to printable string for debug. 00184 */ 00185 static const char * eap_state_name(enum eap_state_code esc) 00186 { 00187 static const char *state_names[] = { EAP_STATES }; 00188 00189 return (state_names[(int)esc]); 00190 } 00191 00192 /* 00193 * eap_init - Initialize state for an EAP user. This is currently 00194 * called once by main() during start-up. 00195 */ 00196 static void eap_init(ppp_pcb *pcb) { 00197 00198 BZERO(&pcb->eap, sizeof(eap_state)); 00199 #if PPP_SERVER 00200 pcb->eap.es_server.ea_id = magic(); 00201 #endif /* PPP_SERVER */ 00202 } 00203 00204 /* 00205 * eap_client_timeout - Give up waiting for the peer to send any 00206 * Request messages. 00207 */ 00208 static void eap_client_timeout(void *arg) { 00209 ppp_pcb *pcb = (ppp_pcb*)arg; 00210 00211 if (!eap_client_active(pcb)) 00212 return; 00213 00214 ppp_error("EAP: timeout waiting for Request from peer"); 00215 auth_withpeer_fail(pcb, PPP_EAP); 00216 pcb->eap.es_client.ea_state = eapBadAuth; 00217 } 00218 00219 /* 00220 * eap_authwithpeer - Authenticate to our peer (behave as client). 00221 * 00222 * Start client state and wait for requests. This is called only 00223 * after eap_lowerup. 00224 */ 00225 void eap_authwithpeer(ppp_pcb *pcb, const char *localname) { 00226 00227 if(NULL == localname) 00228 return; 00229 00230 /* Save the peer name we're given */ 00231 pcb->eap.es_client.ea_name = localname; 00232 pcb->eap.es_client.ea_namelen = strlen(localname); 00233 00234 pcb->eap.es_client.ea_state = eapListen; 00235 00236 /* 00237 * Start a timer so that if the other end just goes 00238 * silent, we don't sit here waiting forever. 00239 */ 00240 if (pcb->settings.eap_req_time > 0) 00241 TIMEOUT(eap_client_timeout, pcb, 00242 pcb->settings.eap_req_time); 00243 } 00244 00245 #if PPP_SERVER 00246 /* 00247 * Format a standard EAP Failure message and send it to the peer. 00248 * (Server operation) 00249 */ 00250 static void eap_send_failure(ppp_pcb *pcb) { 00251 struct pbuf *p; 00252 u_char *outp; 00253 00254 p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + EAP_HEADERLEN), PPP_CTRL_PBUF_TYPE); 00255 if(NULL == p) 00256 return; 00257 if(p->tot_len != p->len) { 00258 pbuf_free(p); 00259 return; 00260 } 00261 00262 outp = (u_char*)p->payload; 00263 00264 MAKEHEADER(outp, PPP_EAP); 00265 00266 PUTCHAR(EAP_FAILURE, outp); 00267 pcb->eap.es_server.ea_id++; 00268 PUTCHAR(pcb->eap.es_server.ea_id, outp); 00269 PUTSHORT(EAP_HEADERLEN, outp); 00270 00271 ppp_write(pcb, p); 00272 00273 pcb->eap.es_server.ea_state = eapBadAuth; 00274 auth_peer_fail(pcb, PPP_EAP); 00275 } 00276 00277 /* 00278 * Format a standard EAP Success message and send it to the peer. 00279 * (Server operation) 00280 */ 00281 static void eap_send_success(ppp_pcb *pcb) { 00282 struct pbuf *p; 00283 u_char *outp; 00284 00285 p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + EAP_HEADERLEN), PPP_CTRL_PBUF_TYPE); 00286 if(NULL == p) 00287 return; 00288 if(p->tot_len != p->len) { 00289 pbuf_free(p); 00290 return; 00291 } 00292 00293 outp = (u_char*)p->payload; 00294 00295 MAKEHEADER(outp, PPP_EAP); 00296 00297 PUTCHAR(EAP_SUCCESS, outp); 00298 pcb->eap.es_server.ea_id++; 00299 PUTCHAR(pcb->eap.es_server.ea_id, outp); 00300 PUTSHORT(EAP_HEADERLEN, outp); 00301 00302 ppp_write(pcb, p); 00303 00304 auth_peer_success(pcb, PPP_EAP, 0, 00305 pcb->eap.es_server.ea_peer, pcb->eap.es_server.ea_peerlen); 00306 } 00307 #endif /* PPP_SERVER */ 00308 00309 #ifdef USE_SRP 00310 /* 00311 * Set DES key according to pseudonym-generating secret and current 00312 * date. 00313 */ 00314 static bool 00315 pncrypt_setkey(int timeoffs) 00316 { 00317 struct tm *tp; 00318 char tbuf[9]; 00319 SHA1_CTX ctxt; 00320 u_char dig[SHA_DIGESTSIZE]; 00321 time_t reftime; 00322 00323 if (pn_secret == NULL) 00324 return (0); 00325 reftime = time(NULL) + timeoffs; 00326 tp = localtime(&reftime); 00327 SHA1Init(&ctxt); 00328 SHA1Update(&ctxt, pn_secret, strlen(pn_secret)); 00329 strftime(tbuf, sizeof (tbuf), "%Y%m%d", tp); 00330 SHA1Update(&ctxt, tbuf, strlen(tbuf)); 00331 SHA1Final(dig, &ctxt); 00332 /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ 00333 return (DesSetkey(dig)); 00334 } 00335 00336 static char base64[] = 00337 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 00338 00339 struct b64state { 00340 u32_t bs_bits; 00341 int bs_offs; 00342 }; 00343 00344 static int 00345 b64enc(bs, inp, inlen, outp) 00346 struct b64state *bs; 00347 u_char *inp; 00348 int inlen; 00349 u_char *outp; 00350 { 00351 int outlen = 0; 00352 00353 while (inlen > 0) { 00354 bs->bs_bits = (bs->bs_bits << 8) | *inp++; 00355 inlen--; 00356 bs->bs_offs += 8; 00357 if (bs->bs_offs >= 24) { 00358 *outp++ = base64[(bs->bs_bits >> 18) & 0x3F]; 00359 *outp++ = base64[(bs->bs_bits >> 12) & 0x3F]; 00360 *outp++ = base64[(bs->bs_bits >> 6) & 0x3F]; 00361 *outp++ = base64[bs->bs_bits & 0x3F]; 00362 outlen += 4; 00363 bs->bs_offs = 0; 00364 bs->bs_bits = 0; 00365 } 00366 } 00367 return (outlen); 00368 } 00369 00370 static int 00371 b64flush(bs, outp) 00372 struct b64state *bs; 00373 u_char *outp; 00374 { 00375 int outlen = 0; 00376 00377 if (bs->bs_offs == 8) { 00378 *outp++ = base64[(bs->bs_bits >> 2) & 0x3F]; 00379 *outp++ = base64[(bs->bs_bits << 4) & 0x3F]; 00380 outlen = 2; 00381 } else if (bs->bs_offs == 16) { 00382 *outp++ = base64[(bs->bs_bits >> 10) & 0x3F]; 00383 *outp++ = base64[(bs->bs_bits >> 4) & 0x3F]; 00384 *outp++ = base64[(bs->bs_bits << 2) & 0x3F]; 00385 outlen = 3; 00386 } 00387 bs->bs_offs = 0; 00388 bs->bs_bits = 0; 00389 return (outlen); 00390 } 00391 00392 static int 00393 b64dec(bs, inp, inlen, outp) 00394 struct b64state *bs; 00395 u_char *inp; 00396 int inlen; 00397 u_char *outp; 00398 { 00399 int outlen = 0; 00400 char *cp; 00401 00402 while (inlen > 0) { 00403 if ((cp = strchr(base64, *inp++)) == NULL) 00404 break; 00405 bs->bs_bits = (bs->bs_bits << 6) | (cp - base64); 00406 inlen--; 00407 bs->bs_offs += 6; 00408 if (bs->bs_offs >= 8) { 00409 *outp++ = bs->bs_bits >> (bs->bs_offs - 8); 00410 outlen++; 00411 bs->bs_offs -= 8; 00412 } 00413 } 00414 return (outlen); 00415 } 00416 #endif /* USE_SRP */ 00417 00418 #if PPP_SERVER 00419 /* 00420 * Assume that current waiting server state is complete and figure 00421 * next state to use based on available authentication data. 'status' 00422 * indicates if there was an error in handling the last query. It is 00423 * 0 for success and non-zero for failure. 00424 */ 00425 static void eap_figure_next_state(ppp_pcb *pcb, int status) { 00426 #ifdef USE_SRP 00427 unsigned char secbuf[MAXSECRETLEN], clear[8], *sp, *dp; 00428 struct t_pw tpw; 00429 struct t_confent *tce, mytce; 00430 char *cp, *cp2; 00431 struct t_server *ts; 00432 int id, i, plen, toffs; 00433 u_char vals[2]; 00434 struct b64state bs; 00435 #endif /* USE_SRP */ 00436 00437 pcb->settings.eap_timeout_time = pcb->eap.es_savedtime; 00438 switch (pcb->eap.es_server.ea_state) { 00439 case eapBadAuth: 00440 return; 00441 00442 case eapIdentify: 00443 #ifdef USE_SRP 00444 /* Discard any previous session. */ 00445 ts = (struct t_server *)pcb->eap.es_server.ea_session; 00446 if (ts != NULL) { 00447 t_serverclose(ts); 00448 pcb->eap.es_server.ea_session = NULL; 00449 pcb->eap.es_server.ea_skey = NULL; 00450 } 00451 #endif /* USE_SRP */ 00452 if (status != 0) { 00453 pcb->eap.es_server.ea_state = eapBadAuth; 00454 break; 00455 } 00456 #ifdef USE_SRP 00457 /* If we've got a pseudonym, try to decode to real name. */ 00458 if (pcb->eap.es_server.ea_peerlen > SRP_PSEUDO_LEN && 00459 strncmp(pcb->eap.es_server.ea_peer, SRP_PSEUDO_ID, 00460 SRP_PSEUDO_LEN) == 0 && 00461 (pcb->eap.es_server.ea_peerlen - SRP_PSEUDO_LEN) * 3 / 4 < 00462 sizeof (secbuf)) { 00463 BZERO(&bs, sizeof (bs)); 00464 plen = b64dec(&bs, 00465 pcb->eap.es_server.ea_peer + SRP_PSEUDO_LEN, 00466 pcb->eap.es_server.ea_peerlen - SRP_PSEUDO_LEN, 00467 secbuf); 00468 toffs = 0; 00469 for (i = 0; i < 5; i++) { 00470 pncrypt_setkey(toffs); 00471 toffs -= 86400; 00472 /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ 00473 if (!DesDecrypt(secbuf, clear)) { 00474 ppp_dbglog("no DES here; cannot decode " 00475 "pseudonym"); 00476 return; 00477 } 00478 id = *(unsigned char *)clear; 00479 if (id + 1 <= plen && id + 9 > plen) 00480 break; 00481 } 00482 if (plen % 8 == 0 && i < 5) { 00483 /* 00484 * Note that this is always shorter than the 00485 * original stored string, so there's no need 00486 * to realloc. 00487 */ 00488 if ((i = plen = *(unsigned char *)clear) > 7) 00489 i = 7; 00490 pcb->eap.es_server.ea_peerlen = plen; 00491 dp = (unsigned char *)pcb->eap.es_server.ea_peer; 00492 MEMCPY(dp, clear + 1, i); 00493 plen -= i; 00494 dp += i; 00495 sp = secbuf + 8; 00496 while (plen > 0) { 00497 /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ 00498 (void) DesDecrypt(sp, dp); 00499 sp += 8; 00500 dp += 8; 00501 plen -= 8; 00502 } 00503 pcb->eap.es_server.ea_peer[ 00504 pcb->eap.es_server.ea_peerlen] = '\0'; 00505 ppp_dbglog("decoded pseudonym to \"%.*q\"", 00506 pcb->eap.es_server.ea_peerlen, 00507 pcb->eap.es_server.ea_peer); 00508 } else { 00509 ppp_dbglog("failed to decode real name"); 00510 /* Stay in eapIdentfy state; requery */ 00511 break; 00512 } 00513 } 00514 /* Look up user in secrets database. */ 00515 if (get_srp_secret(pcb->eap.es_unit, pcb->eap.es_server.ea_peer, 00516 pcb->eap.es_server.ea_name, (char *)secbuf, 1) != 0) { 00517 /* Set up default in case SRP entry is bad */ 00518 pcb->eap.es_server.ea_state = eapMD5Chall; 00519 /* Get t_confent based on index in srp-secrets */ 00520 id = strtol((char *)secbuf, &cp, 10); 00521 if (*cp++ != ':' || id < 0) 00522 break; 00523 if (id == 0) { 00524 mytce.index = 0; 00525 mytce.modulus.data = (u_char *)wkmodulus; 00526 mytce.modulus.len = sizeof (wkmodulus); 00527 mytce.generator.data = (u_char *)"\002"; 00528 mytce.generator.len = 1; 00529 tce = &mytce; 00530 } else if ((tce = gettcid(id)) != NULL) { 00531 /* 00532 * Client will have to verify this modulus/ 00533 * generator combination, and that will take 00534 * a while. Lengthen the timeout here. 00535 */ 00536 if (pcb->settings.eap_timeout_time > 0 && 00537 pcb->settings.eap_timeout_time < 30) 00538 pcb->settings.eap_timeout_time = 30; 00539 } else { 00540 break; 00541 } 00542 if ((cp2 = strchr(cp, ':')) == NULL) 00543 break; 00544 *cp2++ = '\0'; 00545 tpw.pebuf.name = pcb->eap.es_server.ea_peer; 00546 tpw.pebuf.password.len = t_fromb64((char *)tpw.pwbuf, 00547 cp); 00548 tpw.pebuf.password.data = tpw.pwbuf; 00549 tpw.pebuf.salt.len = t_fromb64((char *)tpw.saltbuf, 00550 cp2); 00551 tpw.pebuf.salt.data = tpw.saltbuf; 00552 if ((ts = t_serveropenraw(&tpw.pebuf, tce)) == NULL) 00553 break; 00554 pcb->eap.es_server.ea_session = (void *)ts; 00555 pcb->eap.es_server.ea_state = eapSRP1; 00556 vals[0] = pcb->eap.es_server.ea_id + 1; 00557 vals[1] = EAPT_SRP; 00558 t_serveraddexdata(ts, vals, 2); 00559 /* Generate B; must call before t_servergetkey() */ 00560 t_servergenexp(ts); 00561 break; 00562 } 00563 #endif /* USE_SRP */ 00564 pcb->eap.es_server.ea_state = eapMD5Chall; 00565 break; 00566 00567 case eapSRP1: 00568 #ifdef USE_SRP 00569 ts = (struct t_server *)pcb->eap.es_server.ea_session; 00570 if (ts != NULL && status != 0) { 00571 t_serverclose(ts); 00572 pcb->eap.es_server.ea_session = NULL; 00573 pcb->eap.es_server.ea_skey = NULL; 00574 } 00575 #endif /* USE_SRP */ 00576 if (status == 1) { 00577 pcb->eap.es_server.ea_state = eapMD5Chall; 00578 } else if (status != 0 || pcb->eap.es_server.ea_session == NULL) { 00579 pcb->eap.es_server.ea_state = eapBadAuth; 00580 } else { 00581 pcb->eap.es_server.ea_state = eapSRP2; 00582 } 00583 break; 00584 00585 case eapSRP2: 00586 #ifdef USE_SRP 00587 ts = (struct t_server *)pcb->eap.es_server.ea_session; 00588 if (ts != NULL && status != 0) { 00589 t_serverclose(ts); 00590 pcb->eap.es_server.ea_session = NULL; 00591 pcb->eap.es_server.ea_skey = NULL; 00592 } 00593 #endif /* USE_SRP */ 00594 if (status != 0 || pcb->eap.es_server.ea_session == NULL) { 00595 pcb->eap.es_server.ea_state = eapBadAuth; 00596 } else { 00597 pcb->eap.es_server.ea_state = eapSRP3; 00598 } 00599 break; 00600 00601 case eapSRP3: 00602 case eapSRP4: 00603 #ifdef USE_SRP 00604 ts = (struct t_server *)pcb->eap.es_server.ea_session; 00605 if (ts != NULL && status != 0) { 00606 t_serverclose(ts); 00607 pcb->eap.es_server.ea_session = NULL; 00608 pcb->eap.es_server.ea_skey = NULL; 00609 } 00610 #endif /* USE_SRP */ 00611 if (status != 0 || pcb->eap.es_server.ea_session == NULL) { 00612 pcb->eap.es_server.ea_state = eapBadAuth; 00613 } else { 00614 pcb->eap.es_server.ea_state = eapOpen; 00615 } 00616 break; 00617 00618 case eapMD5Chall: 00619 if (status != 0) { 00620 pcb->eap.es_server.ea_state = eapBadAuth; 00621 } else { 00622 pcb->eap.es_server.ea_state = eapOpen; 00623 } 00624 break; 00625 00626 default: 00627 pcb->eap.es_server.ea_state = eapBadAuth; 00628 break; 00629 } 00630 if (pcb->eap.es_server.ea_state == eapBadAuth) 00631 eap_send_failure(pcb); 00632 } 00633 00634 /* 00635 * Format an EAP Request message and send it to the peer. Message 00636 * type depends on current state. (Server operation) 00637 */ 00638 static void eap_send_request(ppp_pcb *pcb) { 00639 struct pbuf *p; 00640 u_char *outp; 00641 u_char *lenloc; 00642 int outlen; 00643 int len; 00644 const char *str; 00645 #ifdef USE_SRP 00646 struct t_server *ts; 00647 u_char clear[8], cipher[8], dig[SHA_DIGESTSIZE], *optr, *cp; 00648 int i, j; 00649 struct b64state b64; 00650 SHA1_CTX ctxt; 00651 #endif /* USE_SRP */ 00652 00653 /* Handle both initial auth and restart */ 00654 if (pcb->eap.es_server.ea_state < eapIdentify && 00655 pcb->eap.es_server.ea_state != eapInitial) { 00656 pcb->eap.es_server.ea_state = eapIdentify; 00657 #if PPP_REMOTENAME 00658 if (pcb->settings.explicit_remote && pcb->remote_name) { 00659 /* 00660 * If we already know the peer's 00661 * unauthenticated name, then there's no 00662 * reason to ask. Go to next state instead. 00663 */ 00664 int len = (int)strlen(pcb->remote_name); 00665 if (len > MAXNAMELEN) { 00666 len = MAXNAMELEN; 00667 } 00668 MEMCPY(pcb->eap.es_server.ea_peer, pcb->remote_name, len); 00669 pcb->eap.es_server.ea_peer[len] = '\0'; 00670 pcb->eap.es_server.ea_peerlen = len; 00671 eap_figure_next_state(pcb, 0); 00672 } 00673 #endif /* PPP_REMOTENAME */ 00674 } 00675 00676 if (pcb->settings.eap_max_transmits > 0 && 00677 pcb->eap.es_server.ea_requests >= pcb->settings.eap_max_transmits) { 00678 if (pcb->eap.es_server.ea_responses > 0) 00679 ppp_error("EAP: too many Requests sent"); 00680 else 00681 ppp_error("EAP: no response to Requests"); 00682 eap_send_failure(pcb); 00683 return; 00684 } 00685 00686 p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_CTRL_PBUF_MAX_SIZE), PPP_CTRL_PBUF_TYPE); 00687 if(NULL == p) 00688 return; 00689 if(p->tot_len != p->len) { 00690 pbuf_free(p); 00691 return; 00692 } 00693 00694 outp = (u_char*)p->payload; 00695 00696 MAKEHEADER(outp, PPP_EAP); 00697 00698 PUTCHAR(EAP_REQUEST, outp); 00699 PUTCHAR(pcb->eap.es_server.ea_id, outp); 00700 lenloc = outp; 00701 INCPTR(2, outp); 00702 00703 switch (pcb->eap.es_server.ea_state) { 00704 case eapIdentify: 00705 PUTCHAR(EAPT_IDENTITY, outp); 00706 str = "Name"; 00707 len = strlen(str); 00708 MEMCPY(outp, str, len); 00709 INCPTR(len, outp); 00710 break; 00711 00712 case eapMD5Chall: 00713 PUTCHAR(EAPT_MD5CHAP, outp); 00714 /* 00715 * pick a random challenge length between 00716 * EAP_MIN_CHALLENGE_LENGTH and EAP_MAX_CHALLENGE_LENGTH 00717 */ 00718 pcb->eap.es_challen = EAP_MIN_CHALLENGE_LENGTH + 00719 magic_pow(EAP_MIN_MAX_POWER_OF_TWO_CHALLENGE_LENGTH); 00720 PUTCHAR(pcb->eap.es_challen, outp); 00721 magic_random_bytes(pcb->eap.es_challenge, pcb->eap.es_challen); 00722 MEMCPY(outp, pcb->eap.es_challenge, pcb->eap.es_challen); 00723 INCPTR(pcb->eap.es_challen, outp); 00724 MEMCPY(outp, pcb->eap.es_server.ea_name, pcb->eap.es_server.ea_namelen); 00725 INCPTR(pcb->eap.es_server.ea_namelen, outp); 00726 break; 00727 00728 #ifdef USE_SRP 00729 case eapSRP1: 00730 PUTCHAR(EAPT_SRP, outp); 00731 PUTCHAR(EAPSRP_CHALLENGE, outp); 00732 00733 PUTCHAR(pcb->eap.es_server.ea_namelen, outp); 00734 MEMCPY(outp, pcb->eap.es_server.ea_name, pcb->eap.es_server.ea_namelen); 00735 INCPTR(pcb->eap.es_server.ea_namelen, outp); 00736 00737 ts = (struct t_server *)pcb->eap.es_server.ea_session; 00738 assert(ts != NULL); 00739 PUTCHAR(ts->s.len, outp); 00740 MEMCPY(outp, ts->s.data, ts->s.len); 00741 INCPTR(ts->s.len, outp); 00742 00743 if (ts->g.len == 1 && ts->g.data[0] == 2) { 00744 PUTCHAR(0, outp); 00745 } else { 00746 PUTCHAR(ts->g.len, outp); 00747 MEMCPY(outp, ts->g.data, ts->g.len); 00748 INCPTR(ts->g.len, outp); 00749 } 00750 00751 if (ts->n.len != sizeof (wkmodulus) || 00752 BCMP(ts->n.data, wkmodulus, sizeof (wkmodulus)) != 0) { 00753 MEMCPY(outp, ts->n.data, ts->n.len); 00754 INCPTR(ts->n.len, outp); 00755 } 00756 break; 00757 00758 case eapSRP2: 00759 PUTCHAR(EAPT_SRP, outp); 00760 PUTCHAR(EAPSRP_SKEY, outp); 00761 00762 ts = (struct t_server *)pcb->eap.es_server.ea_session; 00763 assert(ts != NULL); 00764 MEMCPY(outp, ts->B.data, ts->B.len); 00765 INCPTR(ts->B.len, outp); 00766 break; 00767 00768 case eapSRP3: 00769 PUTCHAR(EAPT_SRP, outp); 00770 PUTCHAR(EAPSRP_SVALIDATOR, outp); 00771 PUTLONG(SRPVAL_EBIT, outp); 00772 ts = (struct t_server *)pcb->eap.es_server.ea_session; 00773 assert(ts != NULL); 00774 MEMCPY(outp, t_serverresponse(ts), SHA_DIGESTSIZE); 00775 INCPTR(SHA_DIGESTSIZE, outp); 00776 00777 if (pncrypt_setkey(0)) { 00778 /* Generate pseudonym */ 00779 optr = outp; 00780 cp = (unsigned char *)pcb->eap.es_server.ea_peer; 00781 if ((j = i = pcb->eap.es_server.ea_peerlen) > 7) 00782 j = 7; 00783 clear[0] = i; 00784 MEMCPY(clear + 1, cp, j); 00785 i -= j; 00786 cp += j; 00787 /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ 00788 if (!DesEncrypt(clear, cipher)) { 00789 ppp_dbglog("no DES here; not generating pseudonym"); 00790 break; 00791 } 00792 BZERO(&b64, sizeof (b64)); 00793 outp++; /* space for pseudonym length */ 00794 outp += b64enc(&b64, cipher, 8, outp); 00795 while (i >= 8) { 00796 /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ 00797 (void) DesEncrypt(cp, cipher); 00798 outp += b64enc(&b64, cipher, 8, outp); 00799 cp += 8; 00800 i -= 8; 00801 } 00802 if (i > 0) { 00803 MEMCPY(clear, cp, i); 00804 cp += i; 00805 magic_random_bytes(cp, 8-i); 00806 /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ 00807 (void) DesEncrypt(clear, cipher); 00808 outp += b64enc(&b64, cipher, 8, outp); 00809 } 00810 outp += b64flush(&b64, outp); 00811 00812 /* Set length and pad out to next 20 octet boundary */ 00813 i = outp - optr - 1; 00814 *optr = i; 00815 i %= SHA_DIGESTSIZE; 00816 if (i != 0) { 00817 magic_random_bytes(outp, SHA_DIGESTSIZE-i); 00818 INCPTR(SHA_DIGESTSIZE-i, outp); 00819 } 00820 00821 /* Obscure the pseudonym with SHA1 hash */ 00822 SHA1Init(&ctxt); 00823 SHA1Update(&ctxt, &pcb->eap.es_server.ea_id, 1); 00824 SHA1Update(&ctxt, pcb->eap.es_server.ea_skey, 00825 SESSION_KEY_LEN); 00826 SHA1Update(&ctxt, pcb->eap.es_server.ea_peer, 00827 pcb->eap.es_server.ea_peerlen); 00828 while (optr < outp) { 00829 SHA1Final(dig, &ctxt); 00830 cp = dig; 00831 while (cp < dig + SHA_DIGESTSIZE) 00832 *optr++ ^= *cp++; 00833 SHA1Init(&ctxt); 00834 SHA1Update(&ctxt, &pcb->eap.es_server.ea_id, 1); 00835 SHA1Update(&ctxt, pcb->eap.es_server.ea_skey, 00836 SESSION_KEY_LEN); 00837 SHA1Update(&ctxt, optr - SHA_DIGESTSIZE, 00838 SHA_DIGESTSIZE); 00839 } 00840 } 00841 break; 00842 00843 case eapSRP4: 00844 PUTCHAR(EAPT_SRP, outp); 00845 PUTCHAR(EAPSRP_LWRECHALLENGE, outp); 00846 pcb->eap.es_challen = EAP_MIN_CHALLENGE_LENGTH + 00847 magic_pow(EAP_MIN_MAX_POWER_OF_TWO_CHALLENGE_LENGTH); 00848 magic_random_bytes(pcb->eap.es_challenge, pcb->eap.es_challen); 00849 MEMCPY(outp, pcb->eap.es_challenge, pcb->eap.es_challen); 00850 INCPTR(pcb->eap.es_challen, outp); 00851 break; 00852 #endif /* USE_SRP */ 00853 00854 default: 00855 return; 00856 } 00857 00858 outlen = (outp - (unsigned char*)p->payload) - PPP_HDRLEN; 00859 PUTSHORT(outlen, lenloc); 00860 00861 pbuf_realloc(p, outlen + PPP_HDRLEN); 00862 ppp_write(pcb, p); 00863 00864 pcb->eap.es_server.ea_requests++; 00865 00866 if (pcb->settings.eap_timeout_time > 0) 00867 TIMEOUT(eap_server_timeout, pcb, pcb->settings.eap_timeout_time); 00868 } 00869 00870 /* 00871 * eap_authpeer - Authenticate our peer (behave as server). 00872 * 00873 * Start server state and send first request. This is called only 00874 * after eap_lowerup. 00875 */ 00876 void eap_authpeer(ppp_pcb *pcb, const char *localname) { 00877 00878 /* Save the name we're given. */ 00879 pcb->eap.es_server.ea_name = localname; 00880 pcb->eap.es_server.ea_namelen = strlen(localname); 00881 00882 pcb->eap.es_savedtime = pcb->settings.eap_timeout_time; 00883 00884 /* Lower layer up yet? */ 00885 if (pcb->eap.es_server.ea_state == eapInitial || 00886 pcb->eap.es_server.ea_state == eapPending) { 00887 pcb->eap.es_server.ea_state = eapPending; 00888 return; 00889 } 00890 00891 pcb->eap.es_server.ea_state = eapPending; 00892 00893 /* ID number not updated here intentionally; hashed into M1 */ 00894 eap_send_request(pcb); 00895 } 00896 00897 /* 00898 * eap_server_timeout - Retransmission timer for sending Requests 00899 * expired. 00900 */ 00901 static void eap_server_timeout(void *arg) { 00902 ppp_pcb *pcb = (ppp_pcb*)arg; 00903 00904 if (!eap_server_active(pcb)) 00905 return; 00906 00907 /* EAP ID number must not change on timeout. */ 00908 eap_send_request(pcb); 00909 } 00910 00911 /* 00912 * When it's time to send rechallenge the peer, this timeout is 00913 * called. Once the rechallenge is successful, the response handler 00914 * will restart the timer. If it fails, then the link is dropped. 00915 */ 00916 static void eap_rechallenge(void *arg) { 00917 ppp_pcb *pcb = (ppp_pcb*)arg; 00918 00919 if (pcb->eap.es_server.ea_state != eapOpen && 00920 pcb->eap.es_server.ea_state != eapSRP4) 00921 return; 00922 00923 pcb->eap.es_server.ea_requests = 0; 00924 pcb->eap.es_server.ea_state = eapIdentify; 00925 eap_figure_next_state(pcb, 0); 00926 pcb->eap.es_server.ea_id++; 00927 eap_send_request(pcb); 00928 } 00929 00930 static void srp_lwrechallenge(void *arg) { 00931 ppp_pcb *pcb = (ppp_pcb*)arg; 00932 00933 if (pcb->eap.es_server.ea_state != eapOpen || 00934 pcb->eap.es_server.ea_type != EAPT_SRP) 00935 return; 00936 00937 pcb->eap.es_server.ea_requests = 0; 00938 pcb->eap.es_server.ea_state = eapSRP4; 00939 pcb->eap.es_server.ea_id++; 00940 eap_send_request(pcb); 00941 } 00942 #endif /* PPP_SERVER */ 00943 00944 /* 00945 * eap_lowerup - The lower layer is now up. 00946 * 00947 * This is called before either eap_authpeer or eap_authwithpeer. See 00948 * link_established() in auth.c. All that's necessary here is to 00949 * return to closed state so that those two routines will do the right 00950 * thing. 00951 */ 00952 static void eap_lowerup(ppp_pcb *pcb) { 00953 pcb->eap.es_client.ea_state = eapClosed; 00954 #if PPP_SERVER 00955 pcb->eap.es_server.ea_state = eapClosed; 00956 #endif /* PPP_SERVER */ 00957 } 00958 00959 /* 00960 * eap_lowerdown - The lower layer is now down. 00961 * 00962 * Cancel all timeouts and return to initial state. 00963 */ 00964 static void eap_lowerdown(ppp_pcb *pcb) { 00965 00966 if (eap_client_active(pcb) && pcb->settings.eap_req_time > 0) { 00967 UNTIMEOUT(eap_client_timeout, pcb); 00968 } 00969 #if PPP_SERVER 00970 if (eap_server_active(pcb)) { 00971 if (pcb->settings.eap_timeout_time > 0) { 00972 UNTIMEOUT(eap_server_timeout, pcb); 00973 } 00974 } else { 00975 if ((pcb->eap.es_server.ea_state == eapOpen || 00976 pcb->eap.es_server.ea_state == eapSRP4) && 00977 pcb->eap.es_rechallenge > 0) { 00978 UNTIMEOUT(eap_rechallenge, (void *)pcb); 00979 } 00980 if (pcb->eap.es_server.ea_state == eapOpen && 00981 pcb->eap.es_lwrechallenge > 0) { 00982 UNTIMEOUT(srp_lwrechallenge, (void *)pcb); 00983 } 00984 } 00985 00986 pcb->eap.es_client.ea_state = pcb->eap.es_server.ea_state = eapInitial; 00987 pcb->eap.es_client.ea_requests = pcb->eap.es_server.ea_requests = 0; 00988 #endif /* PPP_SERVER */ 00989 } 00990 00991 /* 00992 * eap_protrej - Peer doesn't speak this protocol. 00993 * 00994 * This shouldn't happen. If it does, it represents authentication 00995 * failure. 00996 */ 00997 static void eap_protrej(ppp_pcb *pcb) { 00998 00999 if (eap_client_active(pcb)) { 01000 ppp_error("EAP authentication failed due to Protocol-Reject"); 01001 auth_withpeer_fail(pcb, PPP_EAP); 01002 } 01003 #if PPP_SERVER 01004 if (eap_server_active(pcb)) { 01005 ppp_error("EAP authentication of peer failed on Protocol-Reject"); 01006 auth_peer_fail(pcb, PPP_EAP); 01007 } 01008 #endif /* PPP_SERVER */ 01009 eap_lowerdown(pcb); 01010 } 01011 01012 /* 01013 * Format and send a regular EAP Response message. 01014 */ 01015 static void eap_send_response(ppp_pcb *pcb, u_char id, u_char typenum, const u_char *str, int lenstr) { 01016 struct pbuf *p; 01017 u_char *outp; 01018 int msglen; 01019 01020 msglen = EAP_HEADERLEN + sizeof (u_char) + lenstr; 01021 p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); 01022 if(NULL == p) 01023 return; 01024 if(p->tot_len != p->len) { 01025 pbuf_free(p); 01026 return; 01027 } 01028 01029 outp = (u_char*)p->payload; 01030 01031 MAKEHEADER(outp, PPP_EAP); 01032 01033 PUTCHAR(EAP_RESPONSE, outp); 01034 PUTCHAR(id, outp); 01035 pcb->eap.es_client.ea_id = id; 01036 PUTSHORT(msglen, outp); 01037 PUTCHAR(typenum, outp); 01038 if (lenstr > 0) { 01039 MEMCPY(outp, str, lenstr); 01040 } 01041 01042 ppp_write(pcb, p); 01043 } 01044 01045 /* 01046 * Format and send an MD5-Challenge EAP Response message. 01047 */ 01048 static void eap_chap_response(ppp_pcb *pcb, u_char id, u_char *hash, const char *name, int namelen) { 01049 struct pbuf *p; 01050 u_char *outp; 01051 int msglen; 01052 01053 msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + MD5_SIGNATURE_SIZE + 01054 namelen; 01055 p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); 01056 if(NULL == p) 01057 return; 01058 if(p->tot_len != p->len) { 01059 pbuf_free(p); 01060 return; 01061 } 01062 01063 outp = (u_char*)p->payload; 01064 01065 MAKEHEADER(outp, PPP_EAP); 01066 01067 PUTCHAR(EAP_RESPONSE, outp); 01068 PUTCHAR(id, outp); 01069 pcb->eap.es_client.ea_id = id; 01070 PUTSHORT(msglen, outp); 01071 PUTCHAR(EAPT_MD5CHAP, outp); 01072 PUTCHAR(MD5_SIGNATURE_SIZE, outp); 01073 MEMCPY(outp, hash, MD5_SIGNATURE_SIZE); 01074 INCPTR(MD5_SIGNATURE_SIZE, outp); 01075 if (namelen > 0) { 01076 MEMCPY(outp, name, namelen); 01077 } 01078 01079 ppp_write(pcb, p); 01080 } 01081 01082 #ifdef USE_SRP 01083 /* 01084 * Format and send a SRP EAP Response message. 01085 */ 01086 static void 01087 eap_srp_response(esp, id, subtypenum, str, lenstr) 01088 eap_state *esp; 01089 u_char id; 01090 u_char subtypenum; 01091 u_char *str; 01092 int lenstr; 01093 { 01094 ppp_pcb *pcb = &ppp_pcb_list[pcb->eap.es_unit]; 01095 struct pbuf *p; 01096 u_char *outp; 01097 int msglen; 01098 01099 msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + lenstr; 01100 p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); 01101 if(NULL == p) 01102 return; 01103 if(p->tot_len != p->len) { 01104 pbuf_free(p); 01105 return; 01106 } 01107 01108 outp = p->payload; 01109 01110 MAKEHEADER(outp, PPP_EAP); 01111 01112 PUTCHAR(EAP_RESPONSE, outp); 01113 PUTCHAR(id, outp); 01114 pcb->eap.es_client.ea_id = id; 01115 PUTSHORT(msglen, outp); 01116 PUTCHAR(EAPT_SRP, outp); 01117 PUTCHAR(subtypenum, outp); 01118 if (lenstr > 0) { 01119 MEMCPY(outp, str, lenstr); 01120 } 01121 01122 ppp_write(pcb, p); 01123 } 01124 01125 /* 01126 * Format and send a SRP EAP Client Validator Response message. 01127 */ 01128 static void 01129 eap_srpval_response(esp, id, flags, str) 01130 eap_state *esp; 01131 u_char id; 01132 u32_t flags; 01133 u_char *str; 01134 { 01135 ppp_pcb *pcb = &ppp_pcb_list[pcb->eap.es_unit]; 01136 struct pbuf *p; 01137 u_char *outp; 01138 int msglen; 01139 01140 msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + sizeof (u32_t) + 01141 SHA_DIGESTSIZE; 01142 p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); 01143 if(NULL == p) 01144 return; 01145 if(p->tot_len != p->len) { 01146 pbuf_free(p); 01147 return; 01148 } 01149 01150 outp = p->payload; 01151 01152 MAKEHEADER(outp, PPP_EAP); 01153 01154 PUTCHAR(EAP_RESPONSE, outp); 01155 PUTCHAR(id, outp); 01156 pcb->eap.es_client.ea_id = id; 01157 PUTSHORT(msglen, outp); 01158 PUTCHAR(EAPT_SRP, outp); 01159 PUTCHAR(EAPSRP_CVALIDATOR, outp); 01160 PUTLONG(flags, outp); 01161 MEMCPY(outp, str, SHA_DIGESTSIZE); 01162 01163 ppp_write(pcb, p); 01164 } 01165 #endif /* USE_SRP */ 01166 01167 static void eap_send_nak(ppp_pcb *pcb, u_char id, u_char type) { 01168 struct pbuf *p; 01169 u_char *outp; 01170 int msglen; 01171 01172 msglen = EAP_HEADERLEN + 2 * sizeof (u_char); 01173 p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); 01174 if(NULL == p) 01175 return; 01176 if(p->tot_len != p->len) { 01177 pbuf_free(p); 01178 return; 01179 } 01180 01181 outp = (u_char*)p->payload; 01182 01183 MAKEHEADER(outp, PPP_EAP); 01184 01185 PUTCHAR(EAP_RESPONSE, outp); 01186 PUTCHAR(id, outp); 01187 pcb->eap.es_client.ea_id = id; 01188 PUTSHORT(msglen, outp); 01189 PUTCHAR(EAPT_NAK, outp); 01190 PUTCHAR(type, outp); 01191 01192 ppp_write(pcb, p); 01193 } 01194 01195 #ifdef USE_SRP 01196 static char * 01197 name_of_pn_file() 01198 { 01199 char *user, *path, *file; 01200 struct passwd *pw; 01201 size_t pl; 01202 static bool pnlogged = 0; 01203 01204 pw = getpwuid(getuid()); 01205 if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) { 01206 errno = EINVAL; 01207 return (NULL); 01208 } 01209 file = _PATH_PSEUDONYM; 01210 pl = strlen(user) + strlen(file) + 2; 01211 path = malloc(pl); 01212 if (path == NULL) 01213 return (NULL); 01214 (void) slprintf(path, pl, "%s/%s", user, file); 01215 if (!pnlogged) { 01216 ppp_dbglog("pseudonym file: %s", path); 01217 pnlogged = 1; 01218 } 01219 return (path); 01220 } 01221 01222 static int 01223 open_pn_file(modebits) 01224 mode_t modebits; 01225 { 01226 char *path; 01227 int fd, err; 01228 01229 if ((path = name_of_pn_file()) == NULL) 01230 return (-1); 01231 fd = open(path, modebits, S_IRUSR | S_IWUSR); 01232 err = errno; 01233 free(path); 01234 errno = err; 01235 return (fd); 01236 } 01237 01238 static void 01239 remove_pn_file() 01240 { 01241 char *path; 01242 01243 if ((path = name_of_pn_file()) != NULL) { 01244 (void) unlink(path); 01245 (void) free(path); 01246 } 01247 } 01248 01249 static void 01250 write_pseudonym(esp, inp, len, id) 01251 eap_state *esp; 01252 u_char *inp; 01253 int len, id; 01254 { 01255 u_char val; 01256 u_char *datp, *digp; 01257 SHA1_CTX ctxt; 01258 u_char dig[SHA_DIGESTSIZE]; 01259 int dsize, fd, olen = len; 01260 01261 /* 01262 * Do the decoding by working backwards. This eliminates the need 01263 * to save the decoded output in a separate buffer. 01264 */ 01265 val = id; 01266 while (len > 0) { 01267 if ((dsize = len % SHA_DIGESTSIZE) == 0) 01268 dsize = SHA_DIGESTSIZE; 01269 len -= dsize; 01270 datp = inp + len; 01271 SHA1Init(&ctxt); 01272 SHA1Update(&ctxt, &val, 1); 01273 SHA1Update(&ctxt, pcb->eap.es_client.ea_skey, SESSION_KEY_LEN); 01274 if (len > 0) { 01275 SHA1Update(&ctxt, datp, SHA_DIGESTSIZE); 01276 } else { 01277 SHA1Update(&ctxt, pcb->eap.es_client.ea_name, 01278 pcb->eap.es_client.ea_namelen); 01279 } 01280 SHA1Final(dig, &ctxt); 01281 for (digp = dig; digp < dig + SHA_DIGESTSIZE; digp++) 01282 *datp++ ^= *digp; 01283 } 01284 01285 /* Now check that the result is sane */ 01286 if (olen <= 0 || *inp + 1 > olen) { 01287 ppp_dbglog("EAP: decoded pseudonym is unusable <%.*B>", olen, inp); 01288 return; 01289 } 01290 01291 /* Save it away */ 01292 fd = open_pn_file(O_WRONLY | O_CREAT | O_TRUNC); 01293 if (fd < 0) { 01294 ppp_dbglog("EAP: error saving pseudonym: %m"); 01295 return; 01296 } 01297 len = write(fd, inp + 1, *inp); 01298 if (close(fd) != -1 && len == *inp) { 01299 ppp_dbglog("EAP: saved pseudonym"); 01300 pcb->eap.es_usedpseudo = 0; 01301 } else { 01302 ppp_dbglog("EAP: failed to save pseudonym"); 01303 remove_pn_file(); 01304 } 01305 } 01306 #endif /* USE_SRP */ 01307 01308 /* 01309 * eap_request - Receive EAP Request message (client mode). 01310 */ 01311 static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { 01312 u_char typenum; 01313 u_char vallen; 01314 int secret_len; 01315 char secret[MAXSECRETLEN]; 01316 char rhostname[MAXNAMELEN]; 01317 lwip_md5_context mdContext; 01318 u_char hash[MD5_SIGNATURE_SIZE]; 01319 #ifdef USE_SRP 01320 struct t_client *tc; 01321 struct t_num sval, gval, Nval, *Ap, Bval; 01322 u_char vals[2]; 01323 SHA1_CTX ctxt; 01324 u_char dig[SHA_DIGESTSIZE]; 01325 int fd; 01326 #endif /* USE_SRP */ 01327 01328 /* 01329 * Note: we update es_client.ea_id *only if* a Response 01330 * message is being generated. Otherwise, we leave it the 01331 * same for duplicate detection purposes. 01332 */ 01333 01334 pcb->eap.es_client.ea_requests++; 01335 if (pcb->settings.eap_allow_req != 0 && 01336 pcb->eap.es_client.ea_requests > pcb->settings.eap_allow_req) { 01337 ppp_info("EAP: received too many Request messages"); 01338 if (pcb->settings.eap_req_time > 0) { 01339 UNTIMEOUT(eap_client_timeout, pcb); 01340 } 01341 auth_withpeer_fail(pcb, PPP_EAP); 01342 return; 01343 } 01344 01345 if (len <= 0) { 01346 ppp_error("EAP: empty Request message discarded"); 01347 return; 01348 } 01349 01350 GETCHAR(typenum, inp); 01351 len--; 01352 01353 switch (typenum) { 01354 case EAPT_IDENTITY: 01355 if (len > 0) 01356 ppp_info("EAP: Identity prompt \"%.*q\"", len, inp); 01357 #ifdef USE_SRP 01358 if (pcb->eap.es_usepseudo && 01359 (pcb->eap.es_usedpseudo == 0 || 01360 (pcb->eap.es_usedpseudo == 1 && 01361 id == pcb->eap.es_client.ea_id))) { 01362 pcb->eap.es_usedpseudo = 1; 01363 /* Try to get a pseudonym */ 01364 if ((fd = open_pn_file(O_RDONLY)) >= 0) { 01365 strcpy(rhostname, SRP_PSEUDO_ID); 01366 len = read(fd, rhostname + SRP_PSEUDO_LEN, 01367 sizeof (rhostname) - SRP_PSEUDO_LEN); 01368 /* XXX NAI unsupported */ 01369 if (len > 0) { 01370 eap_send_response(pcb, id, typenum, 01371 rhostname, len + SRP_PSEUDO_LEN); 01372 } 01373 (void) close(fd); 01374 if (len > 0) 01375 break; 01376 } 01377 } 01378 /* Stop using pseudonym now. */ 01379 if (pcb->eap.es_usepseudo && pcb->eap.es_usedpseudo != 2) { 01380 remove_pn_file(); 01381 pcb->eap.es_usedpseudo = 2; 01382 } 01383 #endif /* USE_SRP */ 01384 eap_send_response(pcb, id, typenum, (const u_char*)pcb->eap.es_client.ea_name, 01385 pcb->eap.es_client.ea_namelen); 01386 break; 01387 01388 case EAPT_NOTIFICATION: 01389 if (len > 0) 01390 ppp_info("EAP: Notification \"%.*q\"", len, inp); 01391 eap_send_response(pcb, id, typenum, NULL, 0); 01392 break; 01393 01394 case EAPT_NAK: 01395 /* 01396 * Avoid the temptation to send Response Nak in reply 01397 * to Request Nak here. It can only lead to trouble. 01398 */ 01399 ppp_warn("EAP: unexpected Nak in Request; ignored"); 01400 /* Return because we're waiting for something real. */ 01401 return; 01402 01403 case EAPT_MD5CHAP: 01404 if (len < 1) { 01405 ppp_error("EAP: received MD5-Challenge with no data"); 01406 /* Bogus request; wait for something real. */ 01407 return; 01408 } 01409 GETCHAR(vallen, inp); 01410 len--; 01411 if (vallen < 8 || vallen > len) { 01412 ppp_error("EAP: MD5-Challenge with bad length %d (8..%d)", 01413 vallen, len); 01414 /* Try something better. */ 01415 eap_send_nak(pcb, id, EAPT_SRP); 01416 break; 01417 } 01418 01419 /* Not so likely to happen. */ 01420 if (vallen >= len + sizeof (rhostname)) { 01421 ppp_dbglog("EAP: trimming really long peer name down"); 01422 MEMCPY(rhostname, inp + vallen, sizeof (rhostname) - 1); 01423 rhostname[sizeof (rhostname) - 1] = '\0'; 01424 } else { 01425 MEMCPY(rhostname, inp + vallen, len - vallen); 01426 rhostname[len - vallen] = '\0'; 01427 } 01428 01429 #if PPP_REMOTENAME 01430 /* In case the remote doesn't give us his name. */ 01431 if (pcb->settings.explicit_remote || 01432 (pcb->settings.remote_name[0] != '\0' && vallen == len)) 01433 strlcpy(rhostname, pcb->settings.remote_name, sizeof (rhostname)); 01434 #endif /* PPP_REMOTENAME */ 01435 01436 /* 01437 * Get the secret for authenticating ourselves with 01438 * the specified host. 01439 */ 01440 if (!get_secret(pcb, pcb->eap.es_client.ea_name, 01441 rhostname, secret, &secret_len, 0)) { 01442 ppp_dbglog("EAP: no MD5 secret for auth to %q", rhostname); 01443 eap_send_nak(pcb, id, EAPT_SRP); 01444 break; 01445 } 01446 lwip_md5_init(&mdContext); 01447 lwip_md5_starts(&mdContext); 01448 typenum = id; 01449 lwip_md5_update(&mdContext, &typenum, 1); 01450 lwip_md5_update(&mdContext, (u_char *)secret, secret_len); 01451 BZERO(secret, sizeof (secret)); 01452 lwip_md5_update(&mdContext, inp, vallen); 01453 lwip_md5_finish(&mdContext, hash); 01454 lwip_md5_free(&mdContext); 01455 eap_chap_response(pcb, id, hash, pcb->eap.es_client.ea_name, 01456 pcb->eap.es_client.ea_namelen); 01457 break; 01458 01459 #ifdef USE_SRP 01460 case EAPT_SRP: 01461 if (len < 1) { 01462 ppp_error("EAP: received empty SRP Request"); 01463 /* Bogus request; wait for something real. */ 01464 return; 01465 } 01466 01467 /* Get subtype */ 01468 GETCHAR(vallen, inp); 01469 len--; 01470 switch (vallen) { 01471 case EAPSRP_CHALLENGE: 01472 tc = NULL; 01473 if (pcb->eap.es_client.ea_session != NULL) { 01474 tc = (struct t_client *)pcb->eap.es_client. 01475 ea_session; 01476 /* 01477 * If this is a new challenge, then start 01478 * over with a new client session context. 01479 * Otherwise, just resend last response. 01480 */ 01481 if (id != pcb->eap.es_client.ea_id) { 01482 t_clientclose(tc); 01483 pcb->eap.es_client.ea_session = NULL; 01484 tc = NULL; 01485 } 01486 } 01487 /* No session key just yet */ 01488 pcb->eap.es_client.ea_skey = NULL; 01489 if (tc == NULL) { 01490 int rhostnamelen; 01491 01492 GETCHAR(vallen, inp); 01493 len--; 01494 if (vallen >= len) { 01495 ppp_error("EAP: badly-formed SRP Challenge" 01496 " (name)"); 01497 /* Ignore badly-formed messages */ 01498 return; 01499 } 01500 MEMCPY(rhostname, inp, vallen); 01501 rhostname[vallen] = '\0'; 01502 INCPTR(vallen, inp); 01503 len -= vallen; 01504 01505 /* 01506 * In case the remote doesn't give us his name, 01507 * use configured name. 01508 */ 01509 if (explicit_remote || 01510 (remote_name[0] != '\0' && vallen == 0)) { 01511 strlcpy(rhostname, remote_name, 01512 sizeof (rhostname)); 01513 } 01514 01515 rhostnamelen = (int)strlen(rhostname); 01516 if (rhostnamelen > MAXNAMELEN) { 01517 rhostnamelen = MAXNAMELEN; 01518 } 01519 MEMCPY(pcb->eap.es_client.ea_peer, rhostname, rhostnamelen); 01520 pcb->eap.es_client.ea_peer[rhostnamelen] = '\0'; 01521 pcb->eap.es_client.ea_peerlen = rhostnamelen; 01522 01523 GETCHAR(vallen, inp); 01524 len--; 01525 if (vallen >= len) { 01526 ppp_error("EAP: badly-formed SRP Challenge" 01527 " (s)"); 01528 /* Ignore badly-formed messages */ 01529 return; 01530 } 01531 sval.data = inp; 01532 sval.len = vallen; 01533 INCPTR(vallen, inp); 01534 len -= vallen; 01535 01536 GETCHAR(vallen, inp); 01537 len--; 01538 if (vallen > len) { 01539 ppp_error("EAP: badly-formed SRP Challenge" 01540 " (g)"); 01541 /* Ignore badly-formed messages */ 01542 return; 01543 } 01544 /* If no generator present, then use value 2 */ 01545 if (vallen == 0) { 01546 gval.data = (u_char *)"\002"; 01547 gval.len = 1; 01548 } else { 01549 gval.data = inp; 01550 gval.len = vallen; 01551 } 01552 INCPTR(vallen, inp); 01553 len -= vallen; 01554 01555 /* 01556 * If no modulus present, then use well-known 01557 * value. 01558 */ 01559 if (len == 0) { 01560 Nval.data = (u_char *)wkmodulus; 01561 Nval.len = sizeof (wkmodulus); 01562 } else { 01563 Nval.data = inp; 01564 Nval.len = len; 01565 } 01566 tc = t_clientopen(pcb->eap.es_client.ea_name, 01567 &Nval, &gval, &sval); 01568 if (tc == NULL) { 01569 eap_send_nak(pcb, id, EAPT_MD5CHAP); 01570 break; 01571 } 01572 pcb->eap.es_client.ea_session = (void *)tc; 01573 01574 /* Add Challenge ID & type to verifier */ 01575 vals[0] = id; 01576 vals[1] = EAPT_SRP; 01577 t_clientaddexdata(tc, vals, 2); 01578 } 01579 Ap = t_clientgenexp(tc); 01580 eap_srp_response(esp, id, EAPSRP_CKEY, Ap->data, 01581 Ap->len); 01582 break; 01583 01584 case EAPSRP_SKEY: 01585 tc = (struct t_client *)pcb->eap.es_client.ea_session; 01586 if (tc == NULL) { 01587 ppp_warn("EAP: peer sent Subtype 2 without 1"); 01588 eap_send_nak(pcb, id, EAPT_MD5CHAP); 01589 break; 01590 } 01591 if (pcb->eap.es_client.ea_skey != NULL) { 01592 /* 01593 * ID number should not change here. Warn 01594 * if it does (but otherwise ignore). 01595 */ 01596 if (id != pcb->eap.es_client.ea_id) { 01597 ppp_warn("EAP: ID changed from %d to %d " 01598 "in SRP Subtype 2 rexmit", 01599 pcb->eap.es_client.ea_id, id); 01600 } 01601 } else { 01602 if (get_srp_secret(pcb->eap.es_unit, 01603 pcb->eap.es_client.ea_name, 01604 pcb->eap.es_client.ea_peer, secret, 0) == 0) { 01605 /* 01606 * Can't work with this peer because 01607 * the secret is missing. Just give 01608 * up. 01609 */ 01610 eap_send_nak(pcb, id, EAPT_MD5CHAP); 01611 break; 01612 } 01613 Bval.data = inp; 01614 Bval.len = len; 01615 t_clientpasswd(tc, secret); 01616 BZERO(secret, sizeof (secret)); 01617 pcb->eap.es_client.ea_skey = 01618 t_clientgetkey(tc, &Bval); 01619 if (pcb->eap.es_client.ea_skey == NULL) { 01620 /* Server is rogue; stop now */ 01621 ppp_error("EAP: SRP server is rogue"); 01622 goto client_failure; 01623 } 01624 } 01625 eap_srpval_response(esp, id, SRPVAL_EBIT, 01626 t_clientresponse(tc)); 01627 break; 01628 01629 case EAPSRP_SVALIDATOR: 01630 tc = (struct t_client *)pcb->eap.es_client.ea_session; 01631 if (tc == NULL || pcb->eap.es_client.ea_skey == NULL) { 01632 ppp_warn("EAP: peer sent Subtype 3 without 1/2"); 01633 eap_send_nak(pcb, id, EAPT_MD5CHAP); 01634 break; 01635 } 01636 /* 01637 * If we're already open, then this ought to be a 01638 * duplicate. Otherwise, check that the server is 01639 * who we think it is. 01640 */ 01641 if (pcb->eap.es_client.ea_state == eapOpen) { 01642 if (id != pcb->eap.es_client.ea_id) { 01643 ppp_warn("EAP: ID changed from %d to %d " 01644 "in SRP Subtype 3 rexmit", 01645 pcb->eap.es_client.ea_id, id); 01646 } 01647 } else { 01648 len -= sizeof (u32_t) + SHA_DIGESTSIZE; 01649 if (len < 0 || t_clientverify(tc, inp + 01650 sizeof (u32_t)) != 0) { 01651 ppp_error("EAP: SRP server verification " 01652 "failed"); 01653 goto client_failure; 01654 } 01655 GETLONG(pcb->eap.es_client.ea_keyflags, inp); 01656 /* Save pseudonym if user wants it. */ 01657 if (len > 0 && pcb->eap.es_usepseudo) { 01658 INCPTR(SHA_DIGESTSIZE, inp); 01659 write_pseudonym(esp, inp, len, id); 01660 } 01661 } 01662 /* 01663 * We've verified our peer. We're now mostly done, 01664 * except for waiting on the regular EAP Success 01665 * message. 01666 */ 01667 eap_srp_response(esp, id, EAPSRP_ACK, NULL, 0); 01668 break; 01669 01670 case EAPSRP_LWRECHALLENGE: 01671 if (len < 4) { 01672 ppp_warn("EAP: malformed Lightweight rechallenge"); 01673 return; 01674 } 01675 SHA1Init(&ctxt); 01676 vals[0] = id; 01677 SHA1Update(&ctxt, vals, 1); 01678 SHA1Update(&ctxt, pcb->eap.es_client.ea_skey, 01679 SESSION_KEY_LEN); 01680 SHA1Update(&ctxt, inp, len); 01681 SHA1Update(&ctxt, pcb->eap.es_client.ea_name, 01682 pcb->eap.es_client.ea_namelen); 01683 SHA1Final(dig, &ctxt); 01684 eap_srp_response(esp, id, EAPSRP_LWRECHALLENGE, dig, 01685 SHA_DIGESTSIZE); 01686 break; 01687 01688 default: 01689 ppp_error("EAP: unknown SRP Subtype %d", vallen); 01690 eap_send_nak(pcb, id, EAPT_MD5CHAP); 01691 break; 01692 } 01693 break; 01694 #endif /* USE_SRP */ 01695 01696 default: 01697 ppp_info("EAP: unknown authentication type %d; Naking", typenum); 01698 eap_send_nak(pcb, id, EAPT_SRP); 01699 break; 01700 } 01701 01702 if (pcb->settings.eap_req_time > 0) { 01703 UNTIMEOUT(eap_client_timeout, pcb); 01704 TIMEOUT(eap_client_timeout, pcb, 01705 pcb->settings.eap_req_time); 01706 } 01707 return; 01708 01709 #ifdef USE_SRP 01710 client_failure: 01711 pcb->eap.es_client.ea_state = eapBadAuth; 01712 if (pcb->settings.eap_req_time > 0) { 01713 UNTIMEOUT(eap_client_timeout, (void *)esp); 01714 } 01715 pcb->eap.es_client.ea_session = NULL; 01716 t_clientclose(tc); 01717 auth_withpeer_fail(pcb, PPP_EAP); 01718 #endif /* USE_SRP */ 01719 } 01720 01721 #if PPP_SERVER 01722 /* 01723 * eap_response - Receive EAP Response message (server mode). 01724 */ 01725 static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) { 01726 u_char typenum; 01727 u_char vallen; 01728 int secret_len; 01729 char secret[MAXSECRETLEN]; 01730 char rhostname[MAXNAMELEN]; 01731 lwip_md5_context mdContext; 01732 u_char hash[MD5_SIGNATURE_SIZE]; 01733 #ifdef USE_SRP 01734 struct t_server *ts; 01735 struct t_num A; 01736 SHA1_CTX ctxt; 01737 u_char dig[SHA_DIGESTSIZE]; 01738 #endif /* USE_SRP */ 01739 01740 if (pcb->eap.es_server.ea_id != id) { 01741 ppp_dbglog("EAP: discarding Response %d; expected ID %d", id, 01742 pcb->eap.es_server.ea_id); 01743 return; 01744 } 01745 01746 pcb->eap.es_server.ea_responses++; 01747 01748 if (len <= 0) { 01749 ppp_error("EAP: empty Response message discarded"); 01750 return; 01751 } 01752 01753 GETCHAR(typenum, inp); 01754 len--; 01755 01756 switch (typenum) { 01757 case EAPT_IDENTITY: 01758 if (pcb->eap.es_server.ea_state != eapIdentify) { 01759 ppp_dbglog("EAP discarding unwanted Identify \"%.q\"", len, 01760 inp); 01761 break; 01762 } 01763 ppp_info("EAP: unauthenticated peer name \"%.*q\"", len, inp); 01764 if (len > MAXNAMELEN) { 01765 len = MAXNAMELEN; 01766 } 01767 MEMCPY(pcb->eap.es_server.ea_peer, inp, len); 01768 pcb->eap.es_server.ea_peer[len] = '\0'; 01769 pcb->eap.es_server.ea_peerlen = len; 01770 eap_figure_next_state(pcb, 0); 01771 break; 01772 01773 case EAPT_NOTIFICATION: 01774 ppp_dbglog("EAP unexpected Notification; response discarded"); 01775 break; 01776 01777 case EAPT_NAK: 01778 if (len < 1) { 01779 ppp_info("EAP: Nak Response with no suggested protocol"); 01780 eap_figure_next_state(pcb, 1); 01781 break; 01782 } 01783 01784 GETCHAR(vallen, inp); 01785 len--; 01786 01787 if ( 01788 #if PPP_REMOTENAME 01789 !pcb->explicit_remote && 01790 #endif /* PPP_REMOTENAME */ 01791 pcb->eap.es_server.ea_state == eapIdentify){ 01792 /* Peer cannot Nak Identify Request */ 01793 eap_figure_next_state(pcb, 1); 01794 break; 01795 } 01796 01797 switch (vallen) { 01798 case EAPT_SRP: 01799 /* Run through SRP validator selection again. */ 01800 pcb->eap.es_server.ea_state = eapIdentify; 01801 eap_figure_next_state(pcb, 0); 01802 break; 01803 01804 case EAPT_MD5CHAP: 01805 pcb->eap.es_server.ea_state = eapMD5Chall; 01806 break; 01807 01808 default: 01809 ppp_dbglog("EAP: peer requesting unknown Type %d", vallen); 01810 switch (pcb->eap.es_server.ea_state) { 01811 case eapSRP1: 01812 case eapSRP2: 01813 case eapSRP3: 01814 pcb->eap.es_server.ea_state = eapMD5Chall; 01815 break; 01816 case eapMD5Chall: 01817 case eapSRP4: 01818 pcb->eap.es_server.ea_state = eapIdentify; 01819 eap_figure_next_state(pcb, 0); 01820 break; 01821 default: 01822 break; 01823 } 01824 break; 01825 } 01826 break; 01827 01828 case EAPT_MD5CHAP: 01829 if (pcb->eap.es_server.ea_state != eapMD5Chall) { 01830 ppp_error("EAP: unexpected MD5-Response"); 01831 eap_figure_next_state(pcb, 1); 01832 break; 01833 } 01834 if (len < 1) { 01835 ppp_error("EAP: received MD5-Response with no data"); 01836 eap_figure_next_state(pcb, 1); 01837 break; 01838 } 01839 GETCHAR(vallen, inp); 01840 len--; 01841 if (vallen != 16 || vallen > len) { 01842 ppp_error("EAP: MD5-Response with bad length %d", vallen); 01843 eap_figure_next_state(pcb, 1); 01844 break; 01845 } 01846 01847 /* Not so likely to happen. */ 01848 if (vallen >= len + sizeof (rhostname)) { 01849 ppp_dbglog("EAP: trimming really long peer name down"); 01850 MEMCPY(rhostname, inp + vallen, sizeof (rhostname) - 1); 01851 rhostname[sizeof (rhostname) - 1] = '\0'; 01852 } else { 01853 MEMCPY(rhostname, inp + vallen, len - vallen); 01854 rhostname[len - vallen] = '\0'; 01855 } 01856 01857 #if PPP_REMOTENAME 01858 /* In case the remote doesn't give us his name. */ 01859 if (explicit_remote || 01860 (remote_name[0] != '\0' && vallen == len)) 01861 strlcpy(rhostname, remote_name, sizeof (rhostname)); 01862 #endif /* PPP_REMOTENAME */ 01863 01864 /* 01865 * Get the secret for authenticating the specified 01866 * host. 01867 */ 01868 if (!get_secret(pcb, rhostname, 01869 pcb->eap.es_server.ea_name, secret, &secret_len, 1)) { 01870 ppp_dbglog("EAP: no MD5 secret for auth of %q", rhostname); 01871 eap_send_failure(pcb); 01872 break; 01873 } 01874 lwip_md5_init(&mdContext); 01875 lwip_md5_starts(&mdContext); 01876 lwip_md5_update(&mdContext, &pcb->eap.es_server.ea_id, 1); 01877 lwip_md5_update(&mdContext, (u_char *)secret, secret_len); 01878 BZERO(secret, sizeof (secret)); 01879 lwip_md5_update(&mdContext, pcb->eap.es_challenge, pcb->eap.es_challen); 01880 lwip_md5_finish(&mdContext, hash); 01881 lwip_md5_free(&mdContext); 01882 if (BCMP(hash, inp, MD5_SIGNATURE_SIZE) != 0) { 01883 eap_send_failure(pcb); 01884 break; 01885 } 01886 pcb->eap.es_server.ea_type = EAPT_MD5CHAP; 01887 eap_send_success(pcb); 01888 eap_figure_next_state(pcb, 0); 01889 if (pcb->eap.es_rechallenge != 0) 01890 TIMEOUT(eap_rechallenge, pcb, pcb->eap.es_rechallenge); 01891 break; 01892 01893 #ifdef USE_SRP 01894 case EAPT_SRP: 01895 if (len < 1) { 01896 ppp_error("EAP: empty SRP Response"); 01897 eap_figure_next_state(pcb, 1); 01898 break; 01899 } 01900 GETCHAR(typenum, inp); 01901 len--; 01902 switch (typenum) { 01903 case EAPSRP_CKEY: 01904 if (pcb->eap.es_server.ea_state != eapSRP1) { 01905 ppp_error("EAP: unexpected SRP Subtype 1 Response"); 01906 eap_figure_next_state(pcb, 1); 01907 break; 01908 } 01909 A.data = inp; 01910 A.len = len; 01911 ts = (struct t_server *)pcb->eap.es_server.ea_session; 01912 assert(ts != NULL); 01913 pcb->eap.es_server.ea_skey = t_servergetkey(ts, &A); 01914 if (pcb->eap.es_server.ea_skey == NULL) { 01915 /* Client's A value is bogus; terminate now */ 01916 ppp_error("EAP: bogus A value from client"); 01917 eap_send_failure(pcb); 01918 } else { 01919 eap_figure_next_state(pcb, 0); 01920 } 01921 break; 01922 01923 case EAPSRP_CVALIDATOR: 01924 if (pcb->eap.es_server.ea_state != eapSRP2) { 01925 ppp_error("EAP: unexpected SRP Subtype 2 Response"); 01926 eap_figure_next_state(pcb, 1); 01927 break; 01928 } 01929 if (len < sizeof (u32_t) + SHA_DIGESTSIZE) { 01930 ppp_error("EAP: M1 length %d < %d", len, 01931 sizeof (u32_t) + SHA_DIGESTSIZE); 01932 eap_figure_next_state(pcb, 1); 01933 break; 01934 } 01935 GETLONG(pcb->eap.es_server.ea_keyflags, inp); 01936 ts = (struct t_server *)pcb->eap.es_server.ea_session; 01937 assert(ts != NULL); 01938 if (t_serververify(ts, inp)) { 01939 ppp_info("EAP: unable to validate client identity"); 01940 eap_send_failure(pcb); 01941 break; 01942 } 01943 eap_figure_next_state(pcb, 0); 01944 break; 01945 01946 case EAPSRP_ACK: 01947 if (pcb->eap.es_server.ea_state != eapSRP3) { 01948 ppp_error("EAP: unexpected SRP Subtype 3 Response"); 01949 eap_send_failure(esp); 01950 break; 01951 } 01952 pcb->eap.es_server.ea_type = EAPT_SRP; 01953 eap_send_success(pcb, esp); 01954 eap_figure_next_state(pcb, 0); 01955 if (pcb->eap.es_rechallenge != 0) 01956 TIMEOUT(eap_rechallenge, pcb, 01957 pcb->eap.es_rechallenge); 01958 if (pcb->eap.es_lwrechallenge != 0) 01959 TIMEOUT(srp_lwrechallenge, pcb, 01960 pcb->eap.es_lwrechallenge); 01961 break; 01962 01963 case EAPSRP_LWRECHALLENGE: 01964 if (pcb->eap.es_server.ea_state != eapSRP4) { 01965 ppp_info("EAP: unexpected SRP Subtype 4 Response"); 01966 return; 01967 } 01968 if (len != SHA_DIGESTSIZE) { 01969 ppp_error("EAP: bad Lightweight rechallenge " 01970 "response"); 01971 return; 01972 } 01973 SHA1Init(&ctxt); 01974 vallen = id; 01975 SHA1Update(&ctxt, &vallen, 1); 01976 SHA1Update(&ctxt, pcb->eap.es_server.ea_skey, 01977 SESSION_KEY_LEN); 01978 SHA1Update(&ctxt, pcb->eap.es_challenge, pcb->eap.es_challen); 01979 SHA1Update(&ctxt, pcb->eap.es_server.ea_peer, 01980 pcb->eap.es_server.ea_peerlen); 01981 SHA1Final(dig, &ctxt); 01982 if (BCMP(dig, inp, SHA_DIGESTSIZE) != 0) { 01983 ppp_error("EAP: failed Lightweight rechallenge"); 01984 eap_send_failure(pcb); 01985 break; 01986 } 01987 pcb->eap.es_server.ea_state = eapOpen; 01988 if (pcb->eap.es_lwrechallenge != 0) 01989 TIMEOUT(srp_lwrechallenge, esp, 01990 pcb->eap.es_lwrechallenge); 01991 break; 01992 } 01993 break; 01994 #endif /* USE_SRP */ 01995 01996 default: 01997 /* This can't happen. */ 01998 ppp_error("EAP: unknown Response type %d; ignored", typenum); 01999 return; 02000 } 02001 02002 if (pcb->settings.eap_timeout_time > 0) { 02003 UNTIMEOUT(eap_server_timeout, pcb); 02004 } 02005 02006 if (pcb->eap.es_server.ea_state != eapBadAuth && 02007 pcb->eap.es_server.ea_state != eapOpen) { 02008 pcb->eap.es_server.ea_id++; 02009 eap_send_request(pcb); 02010 } 02011 } 02012 #endif /* PPP_SERVER */ 02013 02014 /* 02015 * eap_success - Receive EAP Success message (client mode). 02016 */ 02017 static void eap_success(ppp_pcb *pcb, u_char *inp, int id, int len) { 02018 LWIP_UNUSED_ARG(id); 02019 02020 if (pcb->eap.es_client.ea_state != eapOpen && !eap_client_active(pcb)) { 02021 ppp_dbglog("EAP unexpected success message in state %s (%d)", 02022 eap_state_name(pcb->eap.es_client.ea_state), 02023 pcb->eap.es_client.ea_state); 02024 return; 02025 } 02026 02027 if (pcb->settings.eap_req_time > 0) { 02028 UNTIMEOUT(eap_client_timeout, pcb); 02029 } 02030 02031 if (len > 0) { 02032 /* This is odd. The spec doesn't allow for this. */ 02033 PRINTMSG(inp, len); 02034 } 02035 02036 pcb->eap.es_client.ea_state = eapOpen; 02037 auth_withpeer_success(pcb, PPP_EAP, 0); 02038 } 02039 02040 /* 02041 * eap_failure - Receive EAP Failure message (client mode). 02042 */ 02043 static void eap_failure(ppp_pcb *pcb, u_char *inp, int id, int len) { 02044 LWIP_UNUSED_ARG(id); 02045 02046 if (!eap_client_active(pcb)) { 02047 ppp_dbglog("EAP unexpected failure message in state %s (%d)", 02048 eap_state_name(pcb->eap.es_client.ea_state), 02049 pcb->eap.es_client.ea_state); 02050 } 02051 02052 if (pcb->settings.eap_req_time > 0) { 02053 UNTIMEOUT(eap_client_timeout, pcb); 02054 } 02055 02056 if (len > 0) { 02057 /* This is odd. The spec doesn't allow for this. */ 02058 PRINTMSG(inp, len); 02059 } 02060 02061 pcb->eap.es_client.ea_state = eapBadAuth; 02062 02063 ppp_error("EAP: peer reports authentication failure"); 02064 auth_withpeer_fail(pcb, PPP_EAP); 02065 } 02066 02067 /* 02068 * eap_input - Handle received EAP message. 02069 */ 02070 static void eap_input(ppp_pcb *pcb, u_char *inp, int inlen) { 02071 u_char code, id; 02072 int len; 02073 02074 /* 02075 * Parse header (code, id and length). If packet too short, 02076 * drop it. 02077 */ 02078 if (inlen < EAP_HEADERLEN) { 02079 ppp_error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN); 02080 return; 02081 } 02082 GETCHAR(code, inp); 02083 GETCHAR(id, inp); 02084 GETSHORT(len, inp); 02085 if (len < EAP_HEADERLEN || len > inlen) { 02086 ppp_error("EAP: packet has illegal length field %d (%d..%d)", len, 02087 EAP_HEADERLEN, inlen); 02088 return; 02089 } 02090 len -= EAP_HEADERLEN; 02091 02092 /* Dispatch based on message code */ 02093 switch (code) { 02094 case EAP_REQUEST: 02095 eap_request(pcb, inp, id, len); 02096 break; 02097 02098 #if PPP_SERVER 02099 case EAP_RESPONSE: 02100 eap_response(pcb, inp, id, len); 02101 break; 02102 #endif /* PPP_SERVER */ 02103 02104 case EAP_SUCCESS: 02105 eap_success(pcb, inp, id, len); 02106 break; 02107 02108 case EAP_FAILURE: 02109 eap_failure(pcb, inp, id, len); 02110 break; 02111 02112 default: /* XXX Need code reject */ 02113 /* Note: it's not legal to send EAP Nak here. */ 02114 ppp_warn("EAP: unknown code %d received", code); 02115 break; 02116 } 02117 } 02118 02119 #if PRINTPKT_SUPPORT 02120 /* 02121 * eap_printpkt - print the contents of an EAP packet. 02122 */ 02123 static const char* const eap_codenames[] = { 02124 "Request", "Response", "Success", "Failure" 02125 }; 02126 02127 static const char* const eap_typenames[] = { 02128 "Identity", "Notification", "Nak", "MD5-Challenge", 02129 "OTP", "Generic-Token", NULL, NULL, 02130 "RSA", "DSS", "KEA", "KEA-Validate", 02131 "TLS", "Defender", "Windows 2000", "Arcot", 02132 "Cisco", "Nokia", "SRP" 02133 }; 02134 02135 static int eap_printpkt(const u_char *inp, int inlen, void (*printer) (void *, const char *, ...), void *arg) { 02136 int code, id, len, rtype, vallen; 02137 const u_char *pstart; 02138 u32_t uval; 02139 02140 if (inlen < EAP_HEADERLEN) 02141 return (0); 02142 pstart = inp; 02143 GETCHAR(code, inp); 02144 GETCHAR(id, inp); 02145 GETSHORT(len, inp); 02146 if (len < EAP_HEADERLEN || len > inlen) 02147 return (0); 02148 02149 if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(eap_codenames)) 02150 printer(arg, " %s", eap_codenames[code-1]); 02151 else 02152 printer(arg, " code=0x%x", code); 02153 printer(arg, " id=0x%x", id); 02154 len -= EAP_HEADERLEN; 02155 switch (code) { 02156 case EAP_REQUEST: 02157 if (len < 1) { 02158 printer(arg, " <missing type>"); 02159 break; 02160 } 02161 GETCHAR(rtype, inp); 02162 len--; 02163 if (rtype >= 1 && rtype <= (int)LWIP_ARRAYSIZE(eap_typenames)) 02164 printer(arg, " %s", eap_typenames[rtype-1]); 02165 else 02166 printer(arg, " type=0x%x", rtype); 02167 switch (rtype) { 02168 case EAPT_IDENTITY: 02169 case EAPT_NOTIFICATION: 02170 if (len > 0) { 02171 printer(arg, " <Message "); 02172 ppp_print_string(inp, len, printer, arg); 02173 printer(arg, ">"); 02174 INCPTR(len, inp); 02175 len = 0; 02176 } else { 02177 printer(arg, " <No message>"); 02178 } 02179 break; 02180 02181 case EAPT_MD5CHAP: 02182 if (len <= 0) 02183 break; 02184 GETCHAR(vallen, inp); 02185 len--; 02186 if (vallen > len) 02187 goto truncated; 02188 printer(arg, " <Value%.*B>", vallen, inp); 02189 INCPTR(vallen, inp); 02190 len -= vallen; 02191 if (len > 0) { 02192 printer(arg, " <Name "); 02193 ppp_print_string(inp, len, printer, arg); 02194 printer(arg, ">"); 02195 INCPTR(len, inp); 02196 len = 0; 02197 } else { 02198 printer(arg, " <No name>"); 02199 } 02200 break; 02201 02202 case EAPT_SRP: 02203 if (len < 3) 02204 goto truncated; 02205 GETCHAR(vallen, inp); 02206 len--; 02207 printer(arg, "-%d", vallen); 02208 switch (vallen) { 02209 case EAPSRP_CHALLENGE: 02210 GETCHAR(vallen, inp); 02211 len--; 02212 if (vallen >= len) 02213 goto truncated; 02214 if (vallen > 0) { 02215 printer(arg, " <Name "); 02216 ppp_print_string(inp, vallen, printer, 02217 arg); 02218 printer(arg, ">"); 02219 } else { 02220 printer(arg, " <No name>"); 02221 } 02222 INCPTR(vallen, inp); 02223 len -= vallen; 02224 GETCHAR(vallen, inp); 02225 len--; 02226 if (vallen >= len) 02227 goto truncated; 02228 printer(arg, " <s%.*B>", vallen, inp); 02229 INCPTR(vallen, inp); 02230 len -= vallen; 02231 GETCHAR(vallen, inp); 02232 len--; 02233 if (vallen > len) 02234 goto truncated; 02235 if (vallen == 0) { 02236 printer(arg, " <Default g=2>"); 02237 } else { 02238 printer(arg, " <g%.*B>", vallen, inp); 02239 } 02240 INCPTR(vallen, inp); 02241 len -= vallen; 02242 if (len == 0) { 02243 printer(arg, " <Default N>"); 02244 } else { 02245 printer(arg, " <N%.*B>", len, inp); 02246 INCPTR(len, inp); 02247 len = 0; 02248 } 02249 break; 02250 02251 case EAPSRP_SKEY: 02252 printer(arg, " <B%.*B>", len, inp); 02253 INCPTR(len, inp); 02254 len = 0; 02255 break; 02256 02257 case EAPSRP_SVALIDATOR: 02258 if (len < (int)sizeof (u32_t)) 02259 break; 02260 GETLONG(uval, inp); 02261 len -= sizeof (u32_t); 02262 if (uval & SRPVAL_EBIT) { 02263 printer(arg, " E"); 02264 uval &= ~SRPVAL_EBIT; 02265 } 02266 if (uval != 0) { 02267 printer(arg, " f<%X>", uval); 02268 } 02269 if ((vallen = len) > SHA_DIGESTSIZE) 02270 vallen = SHA_DIGESTSIZE; 02271 printer(arg, " <M2%.*B%s>", len, inp, 02272 len < SHA_DIGESTSIZE ? "?" : ""); 02273 INCPTR(vallen, inp); 02274 len -= vallen; 02275 if (len > 0) { 02276 printer(arg, " <PN%.*B>", len, inp); 02277 INCPTR(len, inp); 02278 len = 0; 02279 } 02280 break; 02281 02282 case EAPSRP_LWRECHALLENGE: 02283 printer(arg, " <Challenge%.*B>", len, inp); 02284 INCPTR(len, inp); 02285 len = 0; 02286 break; 02287 default: 02288 break; 02289 } 02290 break; 02291 default: 02292 break; 02293 } 02294 break; 02295 02296 case EAP_RESPONSE: 02297 if (len < 1) 02298 break; 02299 GETCHAR(rtype, inp); 02300 len--; 02301 if (rtype >= 1 && rtype <= (int)LWIP_ARRAYSIZE(eap_typenames)) 02302 printer(arg, " %s", eap_typenames[rtype-1]); 02303 else 02304 printer(arg, " type=0x%x", rtype); 02305 switch (rtype) { 02306 case EAPT_IDENTITY: 02307 if (len > 0) { 02308 printer(arg, " <Name "); 02309 ppp_print_string(inp, len, printer, arg); 02310 printer(arg, ">"); 02311 INCPTR(len, inp); 02312 len = 0; 02313 } 02314 break; 02315 02316 case EAPT_NAK: 02317 if (len <= 0) { 02318 printer(arg, " <missing hint>"); 02319 break; 02320 } 02321 GETCHAR(rtype, inp); 02322 len--; 02323 printer(arg, " <Suggested-type %02X", rtype); 02324 if (rtype >= 1 && rtype < (int)LWIP_ARRAYSIZE(eap_typenames)) 02325 printer(arg, " (%s)", eap_typenames[rtype-1]); 02326 printer(arg, ">"); 02327 break; 02328 02329 case EAPT_MD5CHAP: 02330 if (len <= 0) { 02331 printer(arg, " <missing length>"); 02332 break; 02333 } 02334 GETCHAR(vallen, inp); 02335 len--; 02336 if (vallen > len) 02337 goto truncated; 02338 printer(arg, " <Value%.*B>", vallen, inp); 02339 INCPTR(vallen, inp); 02340 len -= vallen; 02341 if (len > 0) { 02342 printer(arg, " <Name "); 02343 ppp_print_string(inp, len, printer, arg); 02344 printer(arg, ">"); 02345 INCPTR(len, inp); 02346 len = 0; 02347 } else { 02348 printer(arg, " <No name>"); 02349 } 02350 break; 02351 02352 case EAPT_SRP: 02353 if (len < 1) 02354 goto truncated; 02355 GETCHAR(vallen, inp); 02356 len--; 02357 printer(arg, "-%d", vallen); 02358 switch (vallen) { 02359 case EAPSRP_CKEY: 02360 printer(arg, " <A%.*B>", len, inp); 02361 INCPTR(len, inp); 02362 len = 0; 02363 break; 02364 02365 case EAPSRP_CVALIDATOR: 02366 if (len < (int)sizeof (u32_t)) 02367 break; 02368 GETLONG(uval, inp); 02369 len -= sizeof (u32_t); 02370 if (uval & SRPVAL_EBIT) { 02371 printer(arg, " E"); 02372 uval &= ~SRPVAL_EBIT; 02373 } 02374 if (uval != 0) { 02375 printer(arg, " f<%X>", uval); 02376 } 02377 printer(arg, " <M1%.*B%s>", len, inp, 02378 len == SHA_DIGESTSIZE ? "" : "?"); 02379 INCPTR(len, inp); 02380 len = 0; 02381 break; 02382 02383 case EAPSRP_ACK: 02384 break; 02385 02386 case EAPSRP_LWRECHALLENGE: 02387 printer(arg, " <Response%.*B%s>", len, inp, 02388 len == SHA_DIGESTSIZE ? "" : "?"); 02389 if ((vallen = len) > SHA_DIGESTSIZE) 02390 vallen = SHA_DIGESTSIZE; 02391 INCPTR(vallen, inp); 02392 len -= vallen; 02393 break; 02394 default: 02395 break; 02396 } 02397 break; 02398 default: 02399 break; 02400 } 02401 break; 02402 02403 case EAP_SUCCESS: /* No payload expected for these! */ 02404 case EAP_FAILURE: 02405 default: 02406 break; 02407 02408 truncated: 02409 printer(arg, " <truncated>"); 02410 break; 02411 } 02412 02413 if (len > 8) 02414 printer(arg, "%8B...", inp); 02415 else if (len > 0) 02416 printer(arg, "%.*B", len, inp); 02417 INCPTR(len, inp); 02418 02419 return (inp - pstart); 02420 } 02421 #endif /* PRINTPKT_SUPPORT */ 02422 02423 #endif /* PPP_SUPPORT && EAP_SUPPORT */
Generated on Tue Jul 12 2022 12:22:00 by
