📄 rlm_eap_sim.c
字号:
/* * rlm_eap_sim.c Handles that are called from eap for SIM * * The development of the EAP/SIM support was funded by Internet Foundation * Austria (http://www.nic.at/ipa). * * Version: $Id: rlm_eap_sim.c,v 1.12 2004/03/19 02:20:35 mcr Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Copyright 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca> * Copyright 2003 The FreeRADIUS server project * */#include "autoconf.h"#include <stdio.h>#include <stdlib.h>#include "../../eap.h"#include "eap_types.h"#include "eap_sim.h"#include <rad_assert.h>struct eap_sim_server_state { enum eapsim_serverstates state; struct eapsim_keys keys; int sim_id;};/* * Add value pair to reply */static void add_reply(VALUE_PAIR** vp, const char* name, const char* value, int len){ VALUE_PAIR *reply_attr; reply_attr = pairmake(name, "", T_OP_EQ); if (!reply_attr) { DEBUG("rlm_eap_sim: " "add_reply failed to create attribute %s: %s\n", name, librad_errstr); return; } memcpy(reply_attr->strvalue, value, len); reply_attr->length = len; pairadd(vp, reply_attr);}static void eap_sim_state_free(void *opaque){ struct eap_sim_server_state *ess = (struct eap_sim_server_state *)opaque; if (!ess) return; free(ess);}/* * build a reply to be sent. */static int eap_sim_compose(EAP_HANDLER *handler){ /* we will set the ID on requests, since we have to HMAC it */ handler->eap_ds->set_request_id = 1; return map_eapsim_basictypes(handler->request->reply, handler->eap_ds->request);}static int eap_sim_sendstart(EAP_HANDLER *handler){ VALUE_PAIR **vps, *newvp; uint16_t *words; struct eap_sim_server_state *ess; rad_assert(handler->request != NULL); rad_assert(handler->request->reply); ess = (struct eap_sim_server_state *)handler->opaque; /* these are the outgoing attributes */ vps = &handler->request->reply->vps; rad_assert(vps != NULL); /* * add appropriate TLVs for the EAP things we wish to send. */ /* the version list. We support only version 1. */ newvp = paircreate(ATTRIBUTE_EAP_SIM_BASE+PW_EAP_SIM_VERSION_LIST, PW_TYPE_OCTETS); words = (uint16_t *)newvp->strvalue; newvp->length = 3*sizeof(uint16_t); words[0] = htons(1*sizeof(uint16_t)); words[1] = htons(EAP_SIM_VERSION); words[2] = 0; pairadd(vps, newvp); /* set the EAP_ID - new value */ newvp = paircreate(ATTRIBUTE_EAP_ID, PW_TYPE_INTEGER); newvp->lvalue = ess->sim_id++; pairreplace(vps, newvp); /* record it in the ess */ ess->keys.versionlistlen = 2; memcpy(ess->keys.versionlist, words+1, ess->keys.versionlistlen); /* the ANY_ID attribute. We do not support re-auth or pseudonym */ newvp = paircreate(ATTRIBUTE_EAP_SIM_BASE+PW_EAP_SIM_FULLAUTH_ID_REQ, PW_TYPE_OCTETS); newvp->length = 2; newvp->strvalue[0]=0; newvp->strvalue[0]=1; pairadd(vps, newvp); /* the SUBTYPE, set to start. */ newvp = paircreate(ATTRIBUTE_EAP_SIM_SUBTYPE, PW_TYPE_INTEGER); newvp->lvalue = eapsim_start; pairreplace(vps, newvp); return 1;}static int eap_sim_getchalans(VALUE_PAIR *vps, int chalno, struct eap_sim_server_state *ess){ VALUE_PAIR *vp; rad_assert(chalno >= 0 && chalno < 3); vp = pairfind(vps, ATTRIBUTE_EAP_SIM_RAND1+chalno); if(vp == NULL) { /* bad, we can't find stuff! */ DEBUG2(" eap-sim can not find sim-challenge%d",chalno+1); return 0; } if(vp->length != EAPSIM_RAND_SIZE) { DEBUG2(" eap-sim chal%d is not 8-bytes: %d", chalno+1, vp->length); return 0; } memcpy(ess->keys.rand[chalno], vp->strvalue, EAPSIM_RAND_SIZE); vp = pairfind(vps, ATTRIBUTE_EAP_SIM_SRES1+chalno); if(vp == NULL) { /* bad, we can't find stuff! */ DEBUG2(" eap-sim can not find sim-sres%d",chalno+1); return 0; } if(vp->length != EAPSIM_SRES_SIZE) { DEBUG2(" eap-sim sres%d is not 16-bytes: %d", chalno+1, vp->length); return 0; } memcpy(ess->keys.sres[chalno], vp->strvalue, EAPSIM_SRES_SIZE); vp = pairfind(vps, ATTRIBUTE_EAP_SIM_KC1+chalno); if(vp == NULL) { /* bad, we can't find stuff! */ DEBUG2(" eap-sim can not find sim-kc%d",chalno+1); return 0; } if(vp->length != EAPSIM_Kc_SIZE) { DEBUG2(" eap-sim kc%d is not 8-bytes: %d", chalno+1, vp->length); return 0; } memcpy(ess->keys.Kc[chalno], vp->strvalue, EAPSIM_Kc_SIZE); return 1;}/* * this code sends the challenge itself. * * Challenges will come from one of three places eventually: * * 1 from attributes like ATTRIBUTE_EAP_SIM_RANDx * (these might be retrived from a database) * * 2 from internally implemented SIM authenticators * (a simple one based upon XOR will be provided) * * 3 from some kind of SS7 interface. * * For now, they only come from attributes. * It might be that the best way to do 2/3 will be with a different * module to generate/calculate things. * */static int eap_sim_sendchallenge(EAP_HANDLER *handler){ struct eap_sim_server_state *ess; VALUE_PAIR **invps, **outvps, *newvp; ess = (struct eap_sim_server_state *)handler->opaque; rad_assert(handler->request != NULL); rad_assert(handler->request->reply); /* invps is the data from the client. * but, this is for non-protocol data here. We should * already have consumed any client originated data. */ invps = &handler->request->packet->vps; /* outvps is the data to the client. */ outvps= &handler->request->reply->vps; printf("+++> EAP-sim decoded packet:\n"); vp_printlist(stdout, *invps); /* okay, we got the challenges! Put them into an attribute */ newvp = paircreate(ATTRIBUTE_EAP_SIM_BASE+PW_EAP_SIM_RAND, PW_TYPE_OCTETS); memset(newvp->strvalue, 0, 2); /* clear reserved bytes */ memcpy(newvp->strvalue+2+EAPSIM_RAND_SIZE*0, ess->keys.rand[0], EAPSIM_RAND_SIZE); memcpy(newvp->strvalue+2+EAPSIM_RAND_SIZE*1, ess->keys.rand[1], EAPSIM_RAND_SIZE); memcpy(newvp->strvalue+2+EAPSIM_RAND_SIZE*2, ess->keys.rand[2], EAPSIM_RAND_SIZE); newvp->length = 2+EAPSIM_RAND_SIZE*3; pairadd(outvps, newvp); /* set the EAP_ID - new value */ newvp = paircreate(ATTRIBUTE_EAP_ID, PW_TYPE_INTEGER); newvp->lvalue = ess->sim_id++; pairreplace(outvps, newvp); /* make a copy of the identity */ ess->keys.identitylen = strlen(handler->identity); memcpy(ess->keys.identity, handler->identity, ess->keys.identitylen); /* all set, calculate keys! */ eapsim_calculate_keys(&ess->keys);#ifdef EAP_SIM_DEBUG_PRF eapsim_dump_mk(&ess->keys);#endif /* * need to include an AT_MAC attribute so that it will get * calculated. The NONCE_MT and the MAC are both 16 bytes, so * we store the NONCE_MT in the MAC for the encoder, which * will pull it out before it does the operation. */ newvp = paircreate(ATTRIBUTE_EAP_SIM_BASE+PW_EAP_SIM_MAC, PW_TYPE_OCTETS); memcpy(newvp->strvalue, ess->keys.nonce_mt, 16); newvp->length = 16; pairreplace(outvps, newvp); newvp = paircreate(ATTRIBUTE_EAP_SIM_KEY, PW_TYPE_OCTETS); memcpy(newvp->strvalue, ess->keys.K_aut, 16); newvp->length = 16; pairreplace(outvps, newvp); /* the SUBTYPE, set to challenge. */ newvp = paircreate(ATTRIBUTE_EAP_SIM_SUBTYPE, PW_TYPE_INTEGER); newvp->lvalue = eapsim_challenge; pairreplace(outvps, newvp); return 1;}#ifndef EAPTLS_MPPE_KEY_LEN#define EAPTLS_MPPE_KEY_LEN 32#endif/* * this code sends the success message. * * the only work to be done is the add the appropriate SEND/RECV * radius attributes derived from the MSK. * */static int eap_sim_sendsuccess(EAP_HANDLER *handler){ unsigned char *p; struct eap_sim_server_state *ess; VALUE_PAIR **outvps; VALUE_PAIR *newvp; /* outvps is the data to the client. */ outvps= &handler->request->reply->vps; ess = (struct eap_sim_server_state *)handler->opaque; /* set the EAP_ID - new value */ newvp = paircreate(ATTRIBUTE_EAP_ID, PW_TYPE_INTEGER); newvp->lvalue = ess->sim_id++; pairreplace(outvps, newvp); p = ess->keys.msk; add_reply(outvps, "MS-MPPE-Recv-Key", p, EAPTLS_MPPE_KEY_LEN); p += EAPTLS_MPPE_KEY_LEN; add_reply(outvps, "MS-MPPE-Send-Key", p, EAPTLS_MPPE_KEY_LEN); return 1;}/* * 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: /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -