2 * rlm_sim_files.c authorization: Find a SIM user in the "simtriplets"
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * Copyright 2004 Michael Richardson <mcr@sandelman.ottawa.on.ca>
22 * Copyright 2006 The FreeRADIUS server project
24 * (Adapted from rlm_files/rlm_files.c )
28 * this is an authorization-only module that walks the file every time.
30 * this is an example of getting data for rlm_eap_sim from an external
33 * in a real system, this would be replaced with a lookup to the SS7
34 * network, but those interfaces are distinctly non-standard, and might
35 * even be totally proprietary
42 * The triplets file contains records of the form:
45 * 232420100000015,30000000000000000000000000000000,30112233,445566778899AABB
47 * there must be *three* entries for every IMSI for it to be considered valid.
49 * Lines starting with # are ignored.
51 * Conveniently, this file format is produced by XXXX.
57 #include <freeradius-devel/ident.h>
60 #include <freeradius-devel/autoconf.h>
71 #include <freeradius-devel/radiusd.h>
72 #include <freeradius-devel/modules.h>
73 #include "../rlm_eap/libeap/eap_sim.h"
75 struct sim_file_instance {
80 static const CONF_PARSER module_config[] = {
81 { "simtriplets", PW_TYPE_STRING_PTR,
82 offsetof(struct sim_file_instance, file),
83 NULL, "${raddbdir}/simtriplets.dat" },
85 { NULL, -1, 0, NULL, NULL }
89 * (Re-)read the "users" file into memory.
91 static int sim_file_instantiate(CONF_SECTION *conf, void **instance)
93 struct sim_file_instance *inst;
95 inst = rad_malloc(sizeof *inst);
99 memset(inst, 0, sizeof(*inst));
101 if (cf_section_parse(conf, inst, module_config) < 0) {
111 * Find the named user in the database. Create the
112 * set of attribute-value pairs to check and reply with
113 * for this user from the database. The main code only
114 * needs to check the password, the rest is done here.
116 static int sim_file_authorize(void *instance, REQUEST *request)
118 VALUE_PAIR *namepair;
119 VALUE_PAIR *reply_tmp;
121 struct sim_file_instance *inst = instance;
122 VALUE_PAIR **reply_pairs;
123 VALUE_PAIR **config_pairs;
125 char tripbuf[sizeof("232420100000015,30000000000000000000000000000000,30112233,445566778899AABB")*2];
126 char imsi[128], chal[256], kc[128], sres[128];
131 reply_pairs = &request->reply->vps;
132 config_pairs = &request->config_items;
135 * Grab the canonical user name.
137 namepair = request->username;
138 name = namepair ? (char *) namepair->vp_strvalue : "NONE";
140 triplets = fopen(inst->file, "r");
142 if(triplets == NULL) {
143 radlog(L_ERR, "can not open %s: %s",
144 inst->file, strerror(errno));
145 return RLM_MODULE_NOTFOUND;
151 while(fgets(tripbuf, sizeof(tripbuf), triplets) == tripbuf
156 VALUE_PAIR *r, *k, *s;
159 if(tripbuf[0]=='#') continue;
163 chal[0]='0'; chal[1]='x';
164 kc[0]='0'; kc[1]='x';
165 sres[0]='0'; sres[1]='x';
171 strncat(imsi, f, sizeof(imsi));
175 if(strcmp(imsi, name) != 0)
185 strncat(chal+2, f, sizeof(chal)-2);
193 strncat(sres+2, f, sizeof(sres)-2);
197 f = strsep(&l, ",\n");
201 strncat(kc+2, f, sizeof(kc)-2);
207 radlog(L_ERR, "invalid number of fields %d at line %d",
209 /* complain about malformed line */
214 r = paircreate(ATTRIBUTE_EAP_SIM_RAND1 + imsicount, PW_TYPE_OCTETS);
215 r = pairparsevalue(r, chal);
216 pairadd(reply_pairs, r);
218 k = paircreate(ATTRIBUTE_EAP_SIM_KC1 + imsicount, PW_TYPE_OCTETS);
219 k = pairparsevalue(k, kc);
220 rad_assert(k != NULL);
221 pairadd(reply_pairs, k);
223 s = paircreate(ATTRIBUTE_EAP_SIM_SRES1 + imsicount, PW_TYPE_OCTETS);
224 s = pairparsevalue(s, sres);
225 pairadd(reply_pairs, s);
233 DEBUG("rlm_sim_files: "
234 "insufficient number of challenges for imsi %s: %d\n",
236 return RLM_MODULE_NOTFOUND;
239 DEBUG("rlm_sim_files: "
240 "authorized user/imsi %s\n", name);
243 * EAP module will also grab based upon presence of EAP packet
244 * and it will add the Autz-Type entry.
247 if((reply_tmp = pairmake ("EAP-Type", "SIM", T_OP_EQ)))
249 radlog(L_INFO, "rlm_sim_files: Adding EAP-Type: eap-sim");
250 pairadd (config_pairs, reply_tmp);
254 DEBUG("rlm_sim_files: saw config");
255 vp_printlist(stdout, *config_pairs);
257 DEBUG("rlm_sim_files: saw reply");
258 vp_printlist(stdout, *reply_pairs);
261 return RLM_MODULE_OK;
268 static int sim_file_detach(void *instance)
270 struct sim_file_instance *inst = instance;
277 /* globally exported name */
278 module_t rlm_sim_files = {
281 0, /* type: reserved */
282 sim_file_instantiate, /* instantiation */
283 sim_file_detach, /* detach */
285 NULL, /* authentication */
286 sim_file_authorize, /* authorization */
287 NULL, /* preaccounting */
288 NULL, /* accounting */
289 NULL, /* checksimul */
290 NULL, /* pre-proxy */
291 NULL, /* post-proxy */