📄 rlm_eap_sim.c
字号:
}/* * run the server state machine. */static void eap_sim_stateenter(EAP_HANDLER *handler, struct eap_sim_server_state *ess, enum eapsim_serverstates newstate){ switch(newstate) { case eapsim_server_start: /* * send the EAP-SIM Start message, listing the * versions that we support. */ eap_sim_sendstart(handler); break; case eapsim_server_challenge: /* * send the EAP-SIM Challenge message. */ eap_sim_sendchallenge(handler); break; case eapsim_server_success: /* * 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->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->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->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; uint8_t srescat[EAPSIM_SRES_SIZE*3]; uint8_t 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; 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->vp_integer; /* * Client error supersedes anything else. */ if (subtype == eapsim_client_error) { return 0; } 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"); rad_assert(0 == 1); } 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 */};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -