?? eap.c
字號:
esp->es_server.ea_skey = NULL; }#endif /* USE_SRP */ if (status != 0 || esp->es_server.ea_session == NULL) { esp->es_server.ea_state = eapBadAuth; } else { esp->es_server.ea_state = eapOpen; } break; case eapMD5Chall: if (status != 0) { esp->es_server.ea_state = eapBadAuth; } else { esp->es_server.ea_state = eapOpen; } break; default: esp->es_server.ea_state = eapBadAuth; break; } if (esp->es_server.ea_state == eapBadAuth) eap_send_failure(esp);}/* * Format an EAP Request message and send it to the peer. Message * type depends on current state. (Server operation) */static voideap_send_request(esp)eap_state *esp;{ u_char *outp; u_char *lenloc; u_char *ptr; int outlen; int challen; char *str;#ifdef USE_SRP struct t_server *ts; u_char clear[8], cipher[8], dig[SHA_DIGESTSIZE], *optr, *cp; int i, j; struct b64state b64; SHA1_CTX ctxt;#endif /* USE_SRP */ /* Handle both initial auth and restart */ if (esp->es_server.ea_state < eapIdentify && esp->es_server.ea_state != eapInitial) { esp->es_server.ea_state = eapIdentify; if (explicit_remote) { /* * If we already know the peer's * unauthenticated name, then there's no * reason to ask. Go to next state instead. */ esp->es_server.ea_peer = remote_name; esp->es_server.ea_peerlen = strlen(remote_name); eap_figure_next_state(esp, 0); } } if (esp->es_server.ea_maxrequests > 0 && esp->es_server.ea_requests >= esp->es_server.ea_maxrequests) { if (esp->es_server.ea_responses > 0) error("EAP: too many Requests sent"); else error("EAP: no response to Requests"); eap_send_failure(esp); return; } outp = outpacket_buf; MAKEHEADER(outp, PPP_EAP); PUTCHAR(EAP_REQUEST, outp); PUTCHAR(esp->es_server.ea_id, outp); lenloc = outp; INCPTR(2, outp); switch (esp->es_server.ea_state) { case eapIdentify: PUTCHAR(EAPT_IDENTITY, outp); str = "Name"; challen = strlen(str); BCOPY(str, outp, challen); INCPTR(challen, outp); break; case eapMD5Chall: PUTCHAR(EAPT_MD5CHAP, outp); /* * pick a random challenge length between * MIN_CHALLENGE_LENGTH and MAX_CHALLENGE_LENGTH */ challen = (drand48() * (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) + MIN_CHALLENGE_LENGTH; PUTCHAR(challen, outp); esp->es_challen = challen; ptr = esp->es_challenge; while (--challen >= 0) *ptr++ = (u_char) (drand48() * 0x100); BCOPY(esp->es_challenge, outp, esp->es_challen); INCPTR(esp->es_challen, outp); BCOPY(esp->es_server.ea_name, outp, esp->es_server.ea_namelen); INCPTR(esp->es_server.ea_namelen, outp); break;#ifdef USE_SRP case eapSRP1: PUTCHAR(EAPT_SRP, outp); PUTCHAR(EAPSRP_CHALLENGE, outp); PUTCHAR(esp->es_server.ea_namelen, outp); BCOPY(esp->es_server.ea_name, outp, esp->es_server.ea_namelen); INCPTR(esp->es_server.ea_namelen, outp); ts = (struct t_server *)esp->es_server.ea_session; assert(ts != NULL); PUTCHAR(ts->s.len, outp); BCOPY(ts->s.data, outp, ts->s.len); INCPTR(ts->s.len, outp); if (ts->g.len == 1 && ts->g.data[0] == 2) { PUTCHAR(0, outp); } else { PUTCHAR(ts->g.len, outp); BCOPY(ts->g.data, outp, ts->g.len); INCPTR(ts->g.len, outp); } if (ts->n.len != sizeof (wkmodulus) || BCMP(ts->n.data, wkmodulus, sizeof (wkmodulus)) != 0) { BCOPY(ts->n.data, outp, ts->n.len); INCPTR(ts->n.len, outp); } break; case eapSRP2: PUTCHAR(EAPT_SRP, outp); PUTCHAR(EAPSRP_SKEY, outp); ts = (struct t_server *)esp->es_server.ea_session; assert(ts != NULL); BCOPY(ts->B.data, outp, ts->B.len); INCPTR(ts->B.len, outp); break; case eapSRP3: PUTCHAR(EAPT_SRP, outp); PUTCHAR(EAPSRP_SVALIDATOR, outp); PUTLONG(SRPVAL_EBIT, outp); ts = (struct t_server *)esp->es_server.ea_session; assert(ts != NULL); BCOPY(t_serverresponse(ts), outp, SHA_DIGESTSIZE); INCPTR(SHA_DIGESTSIZE, outp); if (pncrypt_setkey(0)) { /* Generate pseudonym */ optr = outp; cp = (unsigned char *)esp->es_server.ea_peer; if ((j = i = esp->es_server.ea_peerlen) > 7) j = 7; clear[0] = i; BCOPY(cp, clear + 1, j); i -= j; cp += j; if (!DesEncrypt(clear, cipher)) { dbglog("no DES here; not generating pseudonym"); break; } BZERO(&b64, sizeof (b64)); outp++; /* space for pseudonym length */ outp += b64enc(&b64, cipher, 8, outp); while (i >= 8) { (void) DesEncrypt(cp, cipher); outp += b64enc(&b64, cipher, 8, outp); cp += 8; i -= 8; } if (i > 0) { BCOPY(cp, clear, i); cp += i; while (i < 8) { *cp++ = drand48() * 0x100; i++; } (void) DesEncrypt(clear, cipher); outp += b64enc(&b64, cipher, 8, outp); } outp += b64flush(&b64, outp); /* Set length and pad out to next 20 octet boundary */ i = outp - optr - 1; *optr = i; i %= SHA_DIGESTSIZE; if (i != 0) { while (i < SHA_DIGESTSIZE) { *outp++ = drand48() * 0x100; i++; } } /* Obscure the pseudonym with SHA1 hash */ SHA1Init(&ctxt); SHA1Update(&ctxt, &esp->es_server.ea_id, 1); SHA1Update(&ctxt, esp->es_server.ea_skey, SESSION_KEY_LEN); SHA1Update(&ctxt, esp->es_server.ea_peer, esp->es_server.ea_peerlen); while (optr < outp) { SHA1Final(dig, &ctxt); cp = dig; while (cp < dig + SHA_DIGESTSIZE) *optr++ ^= *cp++; SHA1Init(&ctxt); SHA1Update(&ctxt, &esp->es_server.ea_id, 1); SHA1Update(&ctxt, esp->es_server.ea_skey, SESSION_KEY_LEN); SHA1Update(&ctxt, optr - SHA_DIGESTSIZE, SHA_DIGESTSIZE); } } break; case eapSRP4: PUTCHAR(EAPT_SRP, outp); PUTCHAR(EAPSRP_LWRECHALLENGE, outp); challen = MIN_CHALLENGE_LENGTH + ((MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH) * drand48()); esp->es_challen = challen; ptr = esp->es_challenge; while (--challen >= 0) *ptr++ = drand48() * 0x100; BCOPY(esp->es_challenge, outp, esp->es_challen); INCPTR(esp->es_challen, outp); break;#endif /* USE_SRP */ default: return; } outlen = (outp - outpacket_buf) - PPP_HDRLEN; PUTSHORT(outlen, lenloc); output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN); esp->es_server.ea_requests++; if (esp->es_server.ea_timeout > 0) TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);}/* * eap_authpeer - Authenticate our peer (behave as server). * * Start server state and send first request. This is called only * after eap_lowerup. */voideap_authpeer(unit, localname)int unit;char *localname;{ eap_state *esp = &eap_states[unit]; /* Save the name we're given. */ esp->es_server.ea_name = localname; esp->es_server.ea_namelen = strlen(localname); esp->es_savedtime = esp->es_server.ea_timeout; /* Lower layer up yet? */ if (esp->es_server.ea_state == eapInitial || esp->es_server.ea_state == eapPending) { esp->es_server.ea_state = eapPending; return; } esp->es_server.ea_state = eapPending; /* ID number not updated here intentionally; hashed into M1 */ eap_send_request(esp);}/* * eap_server_timeout - Retransmission timer for sending Requests * expired. */static voideap_server_timeout(arg)void *arg;{ eap_state *esp = (eap_state *) arg; if (!eap_server_active(esp)) return; /* EAP ID number must not change on timeout. */ eap_send_request(esp);}/* * When it's time to send rechallenge the peer, this timeout is * called. Once the rechallenge is successful, the response handler * will restart the timer. If it fails, then the link is dropped. */static voideap_rechallenge(arg)void *arg;{ eap_state *esp = (eap_state *)arg; if (esp->es_server.ea_state != eapOpen && esp->es_server.ea_state != eapSRP4) return; esp->es_server.ea_requests = 0; esp->es_server.ea_state = eapIdentify; eap_figure_next_state(esp, 0); esp->es_server.ea_id++; eap_send_request(esp);}static voidsrp_lwrechallenge(arg)void *arg;{ eap_state *esp = (eap_state *)arg; if (esp->es_server.ea_state != eapOpen || esp->es_server.ea_type != EAPT_SRP) return; esp->es_server.ea_requests = 0; esp->es_server.ea_state = eapSRP4; esp->es_server.ea_id++; eap_send_request(esp);}/* * eap_lowerup - The lower layer is now up. * * This is called before either eap_authpeer or eap_authwithpeer. See * link_established() in auth.c. All that's necessary here is to * return to closed state so that those two routines will do the right * thing. */static voideap_lowerup(unit)int unit;{ eap_state *esp = &eap_states[unit]; /* Discard any (possibly authenticated) peer name. */ if (esp->es_server.ea_peer != NULL && esp->es_server.ea_peer != remote_name) free(esp->es_server.ea_peer); esp->es_server.ea_peer = NULL; if (esp->es_client.ea_peer != NULL) free(esp->es_client.ea_peer); esp->es_client.ea_peer = NULL; esp->es_client.ea_state = eapClosed; esp->es_server.ea_state = eapClosed;}/* * eap_lowerdown - The lower layer is now down. * * Cancel all timeouts and return to initial state. */static voideap_lowerdown(unit)int unit;{ eap_state *esp = &eap_states[unit]; if (eap_client_active(esp) && esp->es_client.ea_timeout > 0) { UNTIMEOUT(eap_client_timeout, (void *)esp); } if (eap_server_active(esp)) { if (esp->es_server.ea_timeout > 0) { UNTIMEOUT(eap_server_timeout, (void *)esp); } } else { if ((esp->es_server.ea_state == eapOpen || esp->es_server.ea_state == eapSRP4) && esp->es_rechallenge > 0) { UNTIMEOUT(eap_rechallenge, (void *)esp); } if (esp->es_server.ea_state == eapOpen && esp->es_lwrechallenge > 0) { UNTIMEOUT(srp_lwrechallenge, (void *)esp); } } esp->es_client.ea_state = esp->es_server.ea_state = eapInitial; esp->es_client.ea_requests = esp->es_server.ea_requests = 0;}/* * eap_protrej - Peer doesn't speak this protocol. * * This shouldn't happen. If it does, it represents authentication * failure. */static voideap_protrej(unit)int unit;{ eap_state *esp = &eap_states[unit]; if (eap_client_active(esp)) { error("EAP authentication failed due to Protocol-Reject"); auth_withpeer_fail(unit, PPP_EAP); } if (eap_server_active(esp)) { error("EAP authentication of peer failed on Protocol-Reject"); auth_peer_fail(unit, PPP_EAP); } eap_lowerdown(unit);}/* * Format and send a regular EAP Response message. */static voideap_send_response(esp, id, typenum, str, lenstr)eap_state *esp;u_char id;u_char typenum;u_char *str;int lenstr;{ u_char *outp; int msglen; outp = outpacket_buf; MAKEHEADER(outp, PPP_EAP); PUTCHAR(EAP_RESPONSE, outp); PUTCHAR(id, outp); esp->es_client.ea_id = id; msglen = EAP_HEADERLEN + sizeof (u_char) + lenstr; PUTSHORT(msglen, outp); PUTCHAR(typenum, outp); if (lenstr > 0) { BCOPY(str, outp, lenstr); } output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);}/* * Format and send an MD5-Challenge EAP Response message. */static voideap_chap_response(esp, id, hash, name, namelen)eap_state *esp;u_char id;u_char *hash;char *name;int namelen;{ u_char *outp; int msglen; outp = outpacket_buf; MAKEHEADER(outp, PPP_EAP); PUTCHAR(EAP_RESPONSE, outp); PUTCHAR(id, outp); esp->es_client.ea_id = id; msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + MD5_SIGNATURE_SIZE + namelen; PUTSHORT(msglen, outp); PUTCHAR(EAPT_MD5CHAP, outp); PUTCHAR(MD5_SIGNATURE_SIZE, outp); BCOPY(hash, outp, MD5_SIGNATURE_SIZE); INCPTR(MD5_SIGNATURE_SIZE, outp); if (namelen > 0) { BCOPY(name, outp, namelen); } output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);}#ifdef USE_SRP/* * Format and send a SRP EAP Response message. */static voideap_srp_response(esp, id, subtypenum, str, lenstr)eap_state *esp;u_char id;u_char subtypenum;u_char *str;int lenstr;{ u_char *outp; int msglen; outp = outpacket_buf; MAKEHEADER(outp, PPP_EAP); PUTCHAR(EAP_RESPONSE, outp); PUTCHAR(id, outp); esp->es_client.ea_id = id; msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + lenstr; PUTSHORT(msglen, outp); PUTCHAR(EAPT_SRP, outp); PUTCHAR(subtypenum, outp); if (lenstr > 0) { BCOPY(str, outp, lenstr); } output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);}/* * Format and send a SRP EAP Client Validator Response message. */static voideap_srpval_response(esp, id, flags, str)eap_state *esp;u_char id;u_int32_t flags;u_char *str;{ u_char *outp; int msglen; outp = outpacket_buf; MAKEHEADER(outp, PPP_EAP); PUTCHAR(EAP_RESPONSE, outp); PUTCHAR(id, outp); esp->es_client.ea_id = id; msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + sizeof (u_int32_t) + SHA_DIGESTSIZE; PUTSHORT(msglen, outp); PUTCHAR(EAPT_SRP, outp); PUTCHAR(EAPSRP_CVALIDATOR, outp); PUTLONG(flags, outp); BCOPY(str, outp, SHA_DIGESTSIZE); output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);}#endif /* USE_SRP */static voideap_send_nak(esp, id, type)eap_state *esp;u_char id;u_char type;{ u_char *outp; int msglen; outp = outpacket_buf; MAKEHEADER(outp, PPP_EAP); PUTCHAR(EAP_RESPONSE, outp); PUTCHAR(id, outp); esp->es_client.ea_id = id; msglen = EAP_HEADERLEN + 2 * sizeof (u_char); PUTSHORT(msglen, outp); PUTCHAR(EAPT_NAK, outp); PUTCHAR(type, outp); output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);}#ifdef USE_SRPstatic char *name_of_pn_file(){ char *user, *path, *file; struct passwd *pw; size_t pl; static bool pnlogged = 0; pw = getpwuid(getuid()); if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) { errno = EINVAL; return (NULL); } file = _PATH_PSEUDONYM; pl = strlen(user) + strlen(file) + 2; path = malloc(pl); if (path == NULL) return (NULL); (void) slprintf(path, pl, "%s/%s", user, file); if (!pnlogged) { dbglog("pseudonym file: %s", path); pnlogged = 1; }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -