?? eap.c
字號:
} break; } break; case EAPT_MD5CHAP: if (esp->es_server.ea_state != eapMD5Chall) { error("EAP: unexpected MD5-Response"); eap_figure_next_state(esp, 1); break; } if (len < 1) { error("EAP: received MD5-Response with no data"); eap_figure_next_state(esp, 1); break; } GETCHAR(vallen, inp); len--; if (vallen != 16 || vallen > len) { error("EAP: MD5-Response with bad length %d", vallen); eap_figure_next_state(esp, 1); break; } /* Not so likely to happen. */ if (vallen >= len + sizeof (rhostname)) { dbglog("EAP: trimming really long peer name down"); BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1); rhostname[sizeof (rhostname) - 1] = '\0'; } else { BCOPY(inp + vallen, rhostname, len - vallen); rhostname[len - vallen] = '\0'; } /* In case the remote doesn't give us his name. */ if (explicit_remote || (remote_name[0] != '\0' && vallen == len)) strlcpy(rhostname, remote_name, sizeof (rhostname)); /* * Get the secret for authenticating the specified * host. */ if (!get_secret(esp->es_unit, rhostname, esp->es_server.ea_name, secret, &secret_len, 1)) { dbglog("EAP: no MD5 secret for auth of %q", rhostname); eap_send_failure(esp); break; } MD5_Init(&mdContext); MD5_Update(&mdContext, &esp->es_server.ea_id, 1); MD5_Update(&mdContext, secret, secret_len); BZERO(secret, sizeof (secret)); MD5_Update(&mdContext, esp->es_challenge, esp->es_challen); MD5_Final(hash, &mdContext); if (BCMP(hash, inp, MD5_SIGNATURE_SIZE) != 0) { eap_send_failure(esp); break; } esp->es_server.ea_type = EAPT_MD5CHAP; eap_send_success(esp); eap_figure_next_state(esp, 0); if (esp->es_rechallenge != 0) TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge); break;#ifdef USE_SRP case EAPT_SRP: if (len < 1) { error("EAP: empty SRP Response"); eap_figure_next_state(esp, 1); break; } GETCHAR(typenum, inp); len--; switch (typenum) { case EAPSRP_CKEY: if (esp->es_server.ea_state != eapSRP1) { error("EAP: unexpected SRP Subtype 1 Response"); eap_figure_next_state(esp, 1); break; } A.data = inp; A.len = len; ts = (struct t_server *)esp->es_server.ea_session; assert(ts != NULL); esp->es_server.ea_skey = t_servergetkey(ts, &A); if (esp->es_server.ea_skey == NULL) { /* Client's A value is bogus; terminate now */ error("EAP: bogus A value from client"); eap_send_failure(esp); } else { eap_figure_next_state(esp, 0); } break; case EAPSRP_CVALIDATOR: if (esp->es_server.ea_state != eapSRP2) { error("EAP: unexpected SRP Subtype 2 Response"); eap_figure_next_state(esp, 1); break; } if (len < sizeof (u_int32_t) + SHA_DIGESTSIZE) { error("EAP: M1 length %d < %d", len, sizeof (u_int32_t) + SHA_DIGESTSIZE); eap_figure_next_state(esp, 1); break; } GETLONG(esp->es_server.ea_keyflags, inp); ts = (struct t_server *)esp->es_server.ea_session; assert(ts != NULL); if (t_serververify(ts, inp)) { info("EAP: unable to validate client identity"); eap_send_failure(esp); break; } eap_figure_next_state(esp, 0); break; case EAPSRP_ACK: if (esp->es_server.ea_state != eapSRP3) { error("EAP: unexpected SRP Subtype 3 Response"); eap_send_failure(esp); break; } esp->es_server.ea_type = EAPT_SRP; eap_send_success(esp); eap_figure_next_state(esp, 0); if (esp->es_rechallenge != 0) TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge); if (esp->es_lwrechallenge != 0) TIMEOUT(srp_lwrechallenge, esp, esp->es_lwrechallenge); break; case EAPSRP_LWRECHALLENGE: if (esp->es_server.ea_state != eapSRP4) { info("EAP: unexpected SRP Subtype 4 Response"); return; } if (len != SHA_DIGESTSIZE) { error("EAP: bad Lightweight rechallenge " "response"); return; } SHA1Init(&ctxt); vallen = id; SHA1Update(&ctxt, &vallen, 1); SHA1Update(&ctxt, esp->es_server.ea_skey, SESSION_KEY_LEN); SHA1Update(&ctxt, esp->es_challenge, esp->es_challen); SHA1Update(&ctxt, esp->es_server.ea_peer, esp->es_server.ea_peerlen); SHA1Final(dig, &ctxt); if (BCMP(dig, inp, SHA_DIGESTSIZE) != 0) { error("EAP: failed Lightweight rechallenge"); eap_send_failure(esp); break; } esp->es_server.ea_state = eapOpen; if (esp->es_lwrechallenge != 0) TIMEOUT(srp_lwrechallenge, esp, esp->es_lwrechallenge); break; } break;#endif /* USE_SRP */ default: /* This can't happen. */ error("EAP: unknown Response type %d; ignored", typenum); return; } if (esp->es_server.ea_timeout > 0) { UNTIMEOUT(eap_server_timeout, (void *)esp); } if (esp->es_server.ea_state != eapBadAuth && esp->es_server.ea_state != eapOpen) { esp->es_server.ea_id++; eap_send_request(esp); }}/* * eap_success - Receive EAP Success message (client mode). */static voideap_success(esp, inp, id, len)eap_state *esp;u_char *inp;int id;int len;{ if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)) { dbglog("EAP unexpected success message in state %s (%d)", eap_state_name(esp->es_client.ea_state), esp->es_client.ea_state); return; } if (esp->es_client.ea_timeout > 0) { UNTIMEOUT(eap_client_timeout, (void *)esp); } if (len > 0) { /* This is odd. The spec doesn't allow for this. */ PRINTMSG(inp, len); } esp->es_client.ea_state = eapOpen; auth_withpeer_success(esp->es_unit, PPP_EAP, 0);}/* * eap_failure - Receive EAP Failure message (client mode). */static voideap_failure(esp, inp, id, len)eap_state *esp;u_char *inp;int id;int len;{ if (!eap_client_active(esp)) { dbglog("EAP unexpected failure message in state %s (%d)", eap_state_name(esp->es_client.ea_state), esp->es_client.ea_state); } if (esp->es_client.ea_timeout > 0) { UNTIMEOUT(eap_client_timeout, (void *)esp); } if (len > 0) { /* This is odd. The spec doesn't allow for this. */ PRINTMSG(inp, len); } esp->es_client.ea_state = eapBadAuth; error("EAP: peer reports authentication failure"); auth_withpeer_fail(esp->es_unit, PPP_EAP);}/* * eap_input - Handle received EAP message. */static voideap_input(unit, inp, inlen)int unit;u_char *inp;int inlen;{ eap_state *esp = &eap_states[unit]; u_char code, id; int len; /* * Parse header (code, id and length). If packet too short, * drop it. */ if (inlen < EAP_HEADERLEN) { error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN); return; } GETCHAR(code, inp); GETCHAR(id, inp); GETSHORT(len, inp); if (len < EAP_HEADERLEN || len > inlen) { error("EAP: packet has illegal length field %d (%d..%d)", len, EAP_HEADERLEN, inlen); return; } len -= EAP_HEADERLEN; /* Dispatch based on message code */ switch (code) { case EAP_REQUEST: eap_request(esp, inp, id, len); break; case EAP_RESPONSE: eap_response(esp, inp, id, len); break; case EAP_SUCCESS: eap_success(esp, inp, id, len); break; case EAP_FAILURE: eap_failure(esp, inp, id, len); break; default: /* XXX Need code reject */ /* Note: it's not legal to send EAP Nak here. */ warn("EAP: unknown code %d received", code); break; }}/* * eap_printpkt - print the contents of an EAP packet. */static char *eap_codenames[] = { "Request", "Response", "Success", "Failure"};static char *eap_typenames[] = { "Identity", "Notification", "Nak", "MD5-Challenge", "OTP", "Generic-Token", NULL, NULL, "RSA", "DSS", "KEA", "KEA-Validate", "TLS", "Defender", "Windows 2000", "Arcot", "Cisco", "Nokia", "SRP"};static inteap_printpkt(inp, inlen, printer, arg)u_char *inp;int inlen;void (*printer) __P((void *, char *, ...));void *arg;{ int code, id, len, rtype, vallen; u_char *pstart; u_int32_t uval; if (inlen < EAP_HEADERLEN) return (0); pstart = inp; GETCHAR(code, inp); GETCHAR(id, inp); GETSHORT(len, inp); if (len < EAP_HEADERLEN || len > inlen) return (0); if (code >= 1 && code <= sizeof(eap_codenames) / sizeof(char *)) printer(arg, " %s", eap_codenames[code-1]); else printer(arg, " code=0x%x", code); printer(arg, " id=0x%x", id); len -= EAP_HEADERLEN; switch (code) { case EAP_REQUEST: if (len < 1) { printer(arg, " <missing type>"); break; } GETCHAR(rtype, inp); len--; if (rtype >= 1 && rtype <= sizeof (eap_typenames) / sizeof (char *)) printer(arg, " %s", eap_typenames[rtype-1]); else printer(arg, " type=0x%x", rtype); switch (rtype) { case EAPT_IDENTITY: case EAPT_NOTIFICATION: if (len > 0) { printer(arg, " <Message "); print_string((char *)inp, len, printer, arg); printer(arg, ">"); INCPTR(len, inp); len = 0; } else { printer(arg, " <No message>"); } break; case EAPT_MD5CHAP: if (len <= 0) break; GETCHAR(vallen, inp); len--; if (vallen > len) goto truncated; printer(arg, " <Value%.*B>", vallen, inp); INCPTR(vallen, inp); len -= vallen; if (len > 0) { printer(arg, " <Name "); print_string((char *)inp, len, printer, arg); printer(arg, ">"); INCPTR(len, inp); len = 0; } else { printer(arg, " <No name>"); } break; case EAPT_SRP: if (len < 3) goto truncated; GETCHAR(vallen, inp); len--; printer(arg, "-%d", vallen); switch (vallen) { case EAPSRP_CHALLENGE: GETCHAR(vallen, inp); len--; if (vallen >= len) goto truncated; if (vallen > 0) { printer(arg, " <Name "); print_string((char *)inp, vallen, printer, arg); printer(arg, ">"); } else { printer(arg, " <No name>"); } INCPTR(vallen, inp); len -= vallen; GETCHAR(vallen, inp); len--; if (vallen >= len) goto truncated; printer(arg, " <s%.*B>", vallen, inp); INCPTR(vallen, inp); len -= vallen; GETCHAR(vallen, inp); len--; if (vallen > len) goto truncated; if (vallen == 0) { printer(arg, " <Default g=2>"); } else { printer(arg, " <g%.*B>", vallen, inp); } INCPTR(vallen, inp); len -= vallen; if (len == 0) { printer(arg, " <Default N>"); } else { printer(arg, " <N%.*B>", len, inp); INCPTR(len, inp); len = 0; } break; case EAPSRP_SKEY: printer(arg, " <B%.*B>", len, inp); INCPTR(len, inp); len = 0; break; case EAPSRP_SVALIDATOR: if (len < sizeof (u_int32_t)) break; GETLONG(uval, inp); len -= sizeof (u_int32_t); if (uval & SRPVAL_EBIT) { printer(arg, " E"); uval &= ~SRPVAL_EBIT; } if (uval != 0) { printer(arg, " f<%X>", uval); } if ((vallen = len) > SHA_DIGESTSIZE) vallen = SHA_DIGESTSIZE; printer(arg, " <M2%.*B%s>", len, inp, len < SHA_DIGESTSIZE ? "?" : ""); INCPTR(vallen, inp); len -= vallen; if (len > 0) { printer(arg, " <PN%.*B>", len, inp); INCPTR(len, inp); len = 0; } break; case EAPSRP_LWRECHALLENGE: printer(arg, " <Challenge%.*B>", len, inp); INCPTR(len, inp); len = 0; break; } break; } break; case EAP_RESPONSE: if (len < 1) break; GETCHAR(rtype, inp); len--; if (rtype >= 1 && rtype <= sizeof (eap_typenames) / sizeof (char *)) printer(arg, " %s", eap_typenames[rtype-1]); else printer(arg, " type=0x%x", rtype); switch (rtype) { case EAPT_IDENTITY: if (len > 0) { printer(arg, " <Name "); print_string((char *)inp, len, printer, arg); printer(arg, ">"); INCPTR(len, inp); len = 0; } break; case EAPT_NAK: if (len <= 0) { printer(arg, " <missing hint>"); break; } GETCHAR(rtype, inp); len--; printer(arg, " <Suggested-type %02X", rtype); if (rtype >= 1 && rtype < sizeof (eap_typenames) / sizeof (char *)) printer(arg, " (%s)", eap_typenames[rtype-1]); printer(arg, ">"); break; case EAPT_MD5CHAP: if (len <= 0) { printer(arg, " <missing length>"); break; } GETCHAR(vallen, inp); len--; if (vallen > len) goto truncated; printer(arg, " <Value%.*B>", vallen, inp); INCPTR(vallen, inp); len -= vallen; if (len > 0) { printer(arg, " <Name "); print_string((char *)inp, len, printer, arg); printer(arg, ">"); INCPTR(len, inp); len = 0; } else { printer(arg, " <No name>"); } break; case EAPT_SRP: if (len < 1) goto truncated; GETCHAR(vallen, inp); len--; printer(arg, "-%d", vallen); switch (vallen) { case EAPSRP_CKEY: printer(arg, " <A%.*B>", len, inp); INCPTR(len, inp); len = 0; break; case EAPSRP_CVALIDATOR: if (len < sizeof (u_int32_t)) break; GETLONG(uval, inp); len -= sizeof (u_int32_t); if (uval & SRPVAL_EBIT) { printer(arg, " E"); uval &= ~SRPVAL_EBIT; } if (uval != 0) { printer(arg, " f<%X>", uval); } printer(arg, " <M1%.*B%s>", len, inp, len == SHA_DIGESTSIZE ? "" : "?"); INCPTR(len, inp); len = 0; break; case EAPSRP_ACK: break; case EAPSRP_LWRECHALLENGE: printer(arg, " <Response%.*B%s>", len, inp, len == SHA_DIGESTSIZE ? "" : "?"); if ((vallen = len) > SHA_DIGESTSIZE) vallen = SHA_DIGESTSIZE; INCPTR(vallen, inp); len -= vallen; break; } break; } break; case EAP_SUCCESS: /* No payload expected for these! */ case EAP_FAILURE: break; truncated: printer(arg, " <truncated>"); break; } if (len > 8) printer(arg, "%8B...", inp); else if (len > 0) printer(arg, "%.*B", len, inp); INCPTR(len, inp); return (inp - pstart);}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -