#include <freeradius-devel/ident.h>
RCSID("$Id$")
#include <freeradius-devel/radiusd.h>
#include <freeradius-devel/modules.h>
#include <freeradius-devel/rad_assert.h>
#include <sys/stat.h>
#include <ctype.h>
#include <fcntl.h>
#include <limits.h>
#include "../rlm_eap/libeap/eap_sim.h"
struct sim_file_instance {
char *file;
};
static const CONF_PARSER module_config[] = {
{ "simtriplets", PW_TYPE_STRING_PTR,
offsetof(struct sim_file_instance, file),
NULL, "${raddbdir}/simtriplets.dat" },
{ NULL, -1, 0, NULL, NULL }
};
static int sim_file_instantiate(CONF_SECTION *conf, void **instance)
{
struct sim_file_instance *inst;
inst = rad_malloc(sizeof *inst);
if (!inst) {
return -1;
}
memset(inst, 0, sizeof(*inst));
if (cf_section_parse(conf, inst, module_config) < 0) {
free(inst);
return -1;
}
*instance = inst;
return 0;
}
static int sim_file_authorize(void *instance, REQUEST *request)
{
VALUE_PAIR *namepair;
VALUE_PAIR *reply_tmp;
const char *name;
struct sim_file_instance *inst = instance;
VALUE_PAIR **reply_pairs;
VALUE_PAIR **config_pairs;
FILE *triplets;
char tripbuf[sizeof("232420100000015,30000000000000000000000000000000,30112233,445566778899AABB")*2];
char imsi[128], chal[256], kc[128], sres[128];
int imsicount;
int fieldcount;
int lineno;
reply_pairs = &request->reply->vps;
config_pairs = &request->config_items;
namepair = request->username;
name = namepair ? (char *) namepair->vp_strvalue : "NONE";
triplets = fopen(inst->file, "r");
if(triplets == NULL) {
radlog(L_ERR, "can not open %s: %s",
inst->file, strerror(errno));
return RLM_MODULE_NOTFOUND;
}
imsicount = 0;
lineno = 0;
while(fgets(tripbuf, sizeof(tripbuf), triplets) == tripbuf
&& imsicount < 3)
{
char *f;
char *l;
VALUE_PAIR *r, *k, *s;
lineno++;
if(tripbuf[0]=='#') continue;
l = tripbuf;
fieldcount = 0;
chal[0]='0'; chal[1]='x';
kc[0]='0'; kc[1]='x';
sres[0]='0'; sres[1]='x';
f = strsep(&l, ",");
if(f)
{
strlcpy(imsi, f, sizeof(imsi));
fieldcount++;
}
if(strcmp(imsi, name) != 0)
{
continue;
}
f = strsep(&l, ",");
if(f)
{
strlcpy(chal + 2, f, sizeof(chal) - 2);
fieldcount++;
}
f = strsep(&l, ",");
if(f)
{
strlcpy(sres + 2, f, sizeof(sres) - 2);
fieldcount++;
}
f = strsep(&l, ",\n");
if(f)
{
strlcpy(kc + 2, f, sizeof(kc) - 2);
fieldcount++;
}
if(fieldcount != 4)
{
radlog(L_ERR, "invalid number of fields %d at line %d",
fieldcount, lineno);
continue;
}
r = paircreate(ATTRIBUTE_EAP_SIM_RAND1 + imsicount, PW_TYPE_OCTETS);
r = pairparsevalue(r, chal);
pairadd(reply_pairs, r);
k = paircreate(ATTRIBUTE_EAP_SIM_KC1 + imsicount, PW_TYPE_OCTETS);
k = pairparsevalue(k, kc);
rad_assert(k != NULL);
pairadd(reply_pairs, k);
s = paircreate(ATTRIBUTE_EAP_SIM_SRES1 + imsicount, PW_TYPE_OCTETS);
s = pairparsevalue(s, sres);
pairadd(reply_pairs, s);
imsicount++;
}
fclose(triplets);
if (imsicount < 3)
{
DEBUG("rlm_sim_files: "
"insufficient number of challenges for imsi %s: %d\n",
name, imsicount);
return RLM_MODULE_NOTFOUND;
}
DEBUG("rlm_sim_files: "
"authorized user/imsi %s\n", name);
if((reply_tmp = pairmake ("EAP-Type", "SIM", T_OP_EQ)))
{
radlog(L_INFO, "rlm_sim_files: Adding EAP-Type: eap-sim");
pairadd (config_pairs, reply_tmp);
}
#if 0
DEBUG("rlm_sim_files: saw config");
debug_pair_list(*config_pairs);
DEBUG("rlm_sim_files: saw reply");
debug_pair_list(*reply_pairs);
#endif
return RLM_MODULE_OK;
}
static int sim_file_detach(void *instance)
{
struct sim_file_instance *inst = instance;
free(inst);
return 0;
}
module_t rlm_sim_files = {
RLM_MODULE_INIT,
"sim_files",
0,
sim_file_instantiate,
sim_file_detach,
{
NULL,
sim_file_authorize,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
},
};