📄 rlm_eap_sim.c
字号:
* send the EAP Success message */ eap_sim_sendsuccess(handler); handler->eap_ds->request->code = PW_EAP_SUCCESS; break; default: /* * nothing to do for this transition. */ break; } ess->state = newstate; /* build the target packet */ eap_sim_compose(handler);}/* * Initiate the EAP-SIM session by starting the state machine * and initiating the state. */static int eap_sim_initiate(void *type_data, EAP_HANDLER *handler){ struct eap_sim_server_state *ess; VALUE_PAIR *vp; VALUE_PAIR *outvps; time_t n; outvps = handler->request->reply->vps; type_data = type_data; /* shut up compiler */ vp = pairfind(outvps, ATTRIBUTE_EAP_SIM_RAND1); if(vp == NULL) { DEBUG2(" can not initiate sim, no RAND1 attribute"); return 0; } ess = malloc(sizeof(struct eap_sim_server_state)); if(ess == NULL) { DEBUG2(" no space for eap sim state"); return 0; } handler->opaque = ((void *)ess); handler->free_opaque = eap_sim_state_free; handler->stage = AUTHENTICATE; /* * save the keying material, because it could change on a subsequent * retrival. * */ if((eap_sim_getchalans(outvps, 0, ess) + eap_sim_getchalans(outvps, 1, ess) + eap_sim_getchalans(outvps, 2, ess)) != 3) { DEBUG2(" can not initiate sim, missing attributes"); return 0; } /* * this value doesn't have be strong, but it is good if it * is different now and then */ time(&n); ess->sim_id = (n & 0xff); eap_sim_stateenter(handler, ess, eapsim_server_start); return 1;}/* * process an EAP-Sim/Response/Start. * * verify that client chose a version, and provided a NONCE_MT, * and if so, then change states to challenge, and send the new * challenge, else, resend the Request/Start. * */static int process_eap_sim_start(EAP_HANDLER *handler, VALUE_PAIR *vps){ VALUE_PAIR *nonce_vp, *selectedversion_vp; struct eap_sim_server_state *ess; uint16_t simversion; ess = (struct eap_sim_server_state *)handler->opaque; nonce_vp = pairfind(vps, ATTRIBUTE_EAP_SIM_BASE+PW_EAP_SIM_NONCE_MT); selectedversion_vp = pairfind(vps, ATTRIBUTE_EAP_SIM_BASE+PW_EAP_SIM_SELECTED_VERSION); if(nonce_vp == NULL || selectedversion_vp == NULL) { DEBUG2(" client did not select a version and send a NONCE"); eap_sim_stateenter(handler, ess, eapsim_server_start); return 1; } /* * okay, good got stuff that we need. Check the version we found. */ if(selectedversion_vp->length < 2) { DEBUG2(" EAP-Sim version field is too short."); return 0; } memcpy(&simversion, selectedversion_vp->strvalue, sizeof(simversion)); simversion = ntohs(simversion); if(simversion != EAP_SIM_VERSION) { DEBUG2(" EAP-Sim version %d is unknown.", simversion); return 0; } /* record it for later keying */ memcpy(ess->keys.versionselect, selectedversion_vp->strvalue, sizeof(ess->keys.versionselect)); /* * double check the nonce size. */ if(nonce_vp->length != 18) { DEBUG2(" EAP-Sim nonce_mt must be 16 bytes (+2 bytes padding), not %d", nonce_vp->length); return 0; } memcpy(ess->keys.nonce_mt, nonce_vp->strvalue+2, 16); /* everything looks good, change states */ eap_sim_stateenter(handler, ess, eapsim_server_challenge); return 1;}/* * process an EAP-Sim/Response/Challenge * * verify that MAC that we received matches what we would have * calculated from the packet with the SRESx appended. * */static int process_eap_sim_challenge(EAP_HANDLER *handler, VALUE_PAIR *vps){ struct eap_sim_server_state *ess; unsigned char srescat[EAPSIM_SRES_SIZE*3]; unsigned char calcmac[EAPSIM_CALCMAC_SIZE]; ess = (struct eap_sim_server_state *)handler->opaque; memcpy(srescat +(0*EAPSIM_SRES_SIZE), ess->keys.sres[0], EAPSIM_SRES_SIZE); memcpy(srescat +(1*EAPSIM_SRES_SIZE), ess->keys.sres[1], EAPSIM_SRES_SIZE); memcpy(srescat +(2*EAPSIM_SRES_SIZE), ess->keys.sres[2], EAPSIM_SRES_SIZE); /* verify the MAC, now that we have all the keys. */ if(eapsim_checkmac(vps, ess->keys.K_aut, srescat, sizeof(srescat), calcmac)) { DEBUG2("MAC check succeed\n"); } else { int i, j; unsigned char macline[20*3]; char *m = macline; j=0; for (i = 0; i < EAPSIM_CALCMAC_SIZE; i++) { if(j==4) { *m++ = '_'; j=0; } j++; sprintf(m, "%02x", calcmac[i]); m = m + strlen(m); } DEBUG2("calculated MAC (%s) did not match", macline); return 0; } /* everything looks good, change states */ eap_sim_stateenter(handler, ess, eapsim_server_success); return 1;}/* * Authenticate a previously sent challenge. */static int eap_sim_authenticate(void *arg, EAP_HANDLER *handler){ struct eap_sim_server_state *ess; VALUE_PAIR *vp, *vps; enum eapsim_subtype subtype; int success; arg = arg; /* shut up compiler */ ess = (struct eap_sim_server_state *)handler->opaque; /* vps is the data from the client */ vps = handler->request->packet->vps; success= unmap_eapsim_basictypes(handler->request->packet, handler->eap_ds->response->type.data, handler->eap_ds->response->type.length); if(!success) { return 0; } /* see what kind of message we have gotten */ if((vp = pairfind(vps, ATTRIBUTE_EAP_SIM_SUBTYPE)) == NULL) { DEBUG2(" no subtype attribute was created, message dropped"); return 0; } subtype = vp->lvalue; switch(ess->state) { case eapsim_server_start: switch(subtype) { default: /* * pretty much anything else here is illegal, * so we will retransmit the request. */ eap_sim_stateenter(handler, ess, eapsim_server_start); return 1; case eapsim_start: /* * a response to our EAP-Sim/Request/Start! * */ return process_eap_sim_start(handler, vps); } break; case eapsim_server_challenge: switch(subtype) { default: /* * pretty much anything else here is illegal, * so we will retransmit the request. */ eap_sim_stateenter(handler, ess, eapsim_server_challenge); return 1; case eapsim_challenge: /* * a response to our EAP-Sim/Request/Challenge! * */ return process_eap_sim_challenge(handler, vps); } break; default: /* if we get into some other state, die, as this * is a coding error! */ DEBUG2(" illegal-unknown state reached in eap_sim_authenticate\n"); abort(); } return 0;}/* * The module name should be the only globally exported symbol. * That is, everything else should be 'static'. */EAP_TYPE rlm_eap_sim = { "eap_sim", NULL, /* XXX attach */ eap_sim_initiate, /* Start the initial request */ NULL, /* XXX authorization */ eap_sim_authenticate, /* authentication */ NULL /* XXX detach */};/* * $Log: rlm_eap_sim.c,v $ * Revision 1.12 2004/03/19 02:20:35 mcr * increment the EAP-id on each stage of the transaction. * * Revision 1.11 2004/02/26 19:04:31 aland * perl -i -npe "s/[ \t]+$//g" `find src -name "*.[ch]" -print` * * Whitespace changes only, from a fresh checkout. * * For bug # 13 * * Revision 1.10 2004/01/30 20:35:33 mcr * capture the RAND/SRES/Kc when we initialize the SIM * rather than later, when they may have changed. * * Revision 1.9 2004/01/30 19:38:29 mcr * added some debugging of why EAP-sim might not want to * handle the request - lacking RAND1 attribute. * * Revision 1.8 2003/12/29 01:13:43 mcr * if the un-marshalling fails, then fail the packet. * * Revision 1.7 2003/11/22 00:21:17 mcr * send the encryption keys to the AccessPoint. * * Revision 1.6 2003/11/22 00:10:18 mcr * the version list attribute's length of versions is in bytes, * not entries. * * Revision 1.5 2003/11/21 19:15:51 mcr * rename "SIM-Chal" to "SIM-Rand" to sync with names in official * documentation. * * Revision 1.4 2003/11/21 19:02:19 mcr * pack the RAND attribute properly - should have 2 bytes * reserved. * * Revision 1.3 2003/11/06 15:45:12 aland * u_int -> uint * * Revision 1.2 2003/10/31 22:33:45 mcr * fixes for version list length types. * do not include length in hash. * use defines rather than constant sizes. * * Revision 1.1 2003/10/29 02:49:19 mcr * initial commit of eap-sim * * Revision 1.3 2003/09/14 00:44:42 mcr * finished trivial challenge state. * * * Local Variables: * c-file-style: "linux" * End Variables: * */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -