2 * This program is is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License, version 2 if the
4 * License as published by the Free Software Foundation.
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 * @file rlm_sim_files.c
20 * @brief Parses simtriplets files to provide a data src for eap_sim.
22 * This is an authorization-only module that walks the file every time.
24 * This is an example of getting data for rlm_eap_sim from an external
27 * In a real system, this would be replaced with a lookup to the SS7
28 * network, but those interfaces are distinctly non-standard, and might
29 * even be totally proprietary.
31 * The triplets file contains records of the form:
34 232420100000015,30000000000000000000000000000000,30112233,445566778899AABB
37 * There must be *three* entries for every IMSI for it to be considered valid.
38 * Lines starting with # are ignored.
40 * Conveniently, this file format is produced by XXXX.
42 * @copyright 2004 Michael Richardson <mcr@sandelman.ottawa.on.ca>
43 * @copyright 2006 The FreeRADIUS server project
45 #include <freeradius-devel/ident.h>
48 #include <freeradius-devel/radiusd.h>
49 #include <freeradius-devel/modules.h>
50 #include <freeradius-devel/rad_assert.h>
57 #include "../rlm_eap/libeap/eap_sim.h"
59 struct sim_file_instance {
64 static const CONF_PARSER module_config[] = {
65 { "simtriplets", PW_TYPE_STRING_PTR,
66 offsetof(struct sim_file_instance, file),
67 NULL, "${raddbdir}/simtriplets.dat" },
69 { NULL, -1, 0, NULL, NULL }
73 * (Re-)read the "users" file into memory.
75 static int sim_file_instantiate(CONF_SECTION *conf, void **instance)
77 struct sim_file_instance *inst;
79 *instance = inst = talloc_zero(conf, struct sim_file_instance);
82 if (cf_section_parse(conf, inst, module_config) < 0) {
90 * Find the named user in the database. Create the
91 * set of attribute-value pairs to check and reply with
92 * for this user from the database. The main code only
93 * needs to check the password, the rest is done here.
95 static rlm_rcode_t sim_file_authorize(void *instance, REQUEST *request)
98 VALUE_PAIR *reply_tmp;
100 struct sim_file_instance *inst = instance;
101 VALUE_PAIR **reply_pairs;
102 VALUE_PAIR **config_pairs;
104 char tripbuf[sizeof("232420100000015,30000000000000000000000000000000,30112233,445566778899AABB")*2];
105 char imsi[128], chal[256], kc[128], sres[128];
110 reply_pairs = &request->reply->vps;
111 config_pairs = &request->config_items;
114 * Grab the canonical user name.
116 namepair = request->username;
117 name = namepair ? (char *) namepair->vp_strvalue : "NONE";
119 triplets = fopen(inst->file, "r");
121 if(triplets == NULL) {
122 radlog(L_ERR, "can not open %s: %s",
123 inst->file, strerror(errno));
124 return RLM_MODULE_NOTFOUND;
130 while(fgets(tripbuf, sizeof(tripbuf), triplets) == tripbuf
135 VALUE_PAIR *r, *k, *s;
138 if(tripbuf[0]=='#') continue;
142 chal[0]='0'; chal[1]='x';
143 kc[0]='0'; kc[1]='x';
144 sres[0]='0'; sres[1]='x';
149 strlcpy(imsi, f, sizeof(imsi));
153 if(strcmp(imsi, name) != 0)
162 strlcpy(chal + 2, f, sizeof(chal) - 2);
169 strlcpy(sres + 2, f, sizeof(sres) - 2);
173 f = strsep(&l, ",\n");
176 strlcpy(kc + 2, f, sizeof(kc) - 2);
182 radlog(L_ERR, "invalid number of fields %d at line %d",
184 /* complain about malformed line */
189 r = paircreate(ATTRIBUTE_EAP_SIM_RAND1 + imsicount, 0);
190 pairparsevalue(r, chal);
191 pairadd(reply_pairs, r);
193 k = paircreate(ATTRIBUTE_EAP_SIM_KC1 + imsicount, 0);
194 pairparsevalue(k, kc);
195 rad_assert(k != NULL);
196 pairadd(reply_pairs, k);
198 s = paircreate(ATTRIBUTE_EAP_SIM_SRES1 + imsicount, 0);
199 pairparsevalue(s, sres);
200 pairadd(reply_pairs, s);
208 DEBUG("rlm_sim_files: "
209 "insufficient number of challenges for imsi %s: %d\n",
211 return RLM_MODULE_NOTFOUND;
214 DEBUG("rlm_sim_files: "
215 "authorized user/imsi %s\n", name);
218 * EAP module will also grab based upon presence of EAP packet
219 * and it will add the Autz-Type entry.
222 if((reply_tmp = pairmake ("EAP-Type", "SIM", T_OP_EQ)))
224 radlog(L_INFO, "rlm_sim_files: Adding EAP-Type: eap-sim");
225 pairadd (config_pairs, reply_tmp);
229 DEBUG("rlm_sim_files: saw config");
230 debug_pair_list(*config_pairs);
232 DEBUG("rlm_sim_files: saw reply");
233 debug_pair_list(*reply_pairs);
236 return RLM_MODULE_OK;
240 /* globally exported name */
241 module_t rlm_sim_files = {
244 0, /* type: reserved */
245 sim_file_instantiate, /* instantiation */
248 NULL, /* authentication */
249 sim_file_authorize, /* authorization */
250 NULL, /* preaccounting */
251 NULL, /* accounting */
252 NULL, /* checksimul */
253 NULL, /* pre-proxy */
254 NULL, /* post-proxy */