reintegrated two-sim branch providing SIM card plugin API
[strongswan.git] / src / charon / plugins / eap_sim_file / eap_sim_file_triplets.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 *
15 * $Id$
16 */
17
18 #include "eap_sim_file_triplets.h"
19
20 #include <stdio.h>
21 #include <errno.h>
22
23 #include <daemon.h>
24 #include <utils/linked_list.h>
25 #include <utils/mutex.h>
26
27 typedef struct private_eap_sim_file_triplets_t private_eap_sim_file_triplets_t;
28
29 /**
30 * Private data of an eap_sim_file_triplets_t object.
31 */
32 struct private_eap_sim_file_triplets_t {
33
34 /**
35 * Public eap_sim_file_triplets_t interface.
36 */
37 eap_sim_file_triplets_t public;
38
39 /**
40 * List of triplets, as triplet_t
41 */
42 linked_list_t *triplets;
43
44 /**
45 * mutex to lock triplets list
46 */
47 mutex_t *mutex;
48 };
49
50 /**
51 * A single triplet
52 */
53 typedef struct {
54 identification_t *imsi;
55 char rand[RAND_LEN];
56 char sres[SRES_LEN];
57 char kc[KC_LEN];
58 } triplet_t;
59
60 /**
61 * Destroy a triplet
62 */
63 static void triplet_destroy(triplet_t *this)
64 {
65 this->imsi->destroy(this->imsi);
66 free(this);
67 }
68
69 /**
70 * triplet enumerator
71 */
72 typedef struct {
73 /** implements enumerator */
74 enumerator_t public;
75 /** inner enumerator */
76 enumerator_t *inner;
77 /** current enumerating triplet */
78 triplet_t *current;
79 /** back ptr */
80 private_eap_sim_file_triplets_t *this;
81 } triplet_enumerator_t;
82
83 /**
84 * destroy a triplet enumerator
85 */
86 static void enumerator_destroy(triplet_enumerator_t *e)
87 {
88 if (e->current)
89 {
90 /* We assume that the current element is used on invocation if destroy.
91 * We move that triplet to the end to avoid handout of the same triplet
92 * next time. */
93 e->this->triplets->remove_at(e->this->triplets, e->inner);
94 e->this->triplets->insert_last(e->this->triplets, e->current);
95 }
96 e->inner->destroy(e->inner);
97 e->this->mutex->unlock(e->this->mutex);
98 free(e);
99 }
100
101 /**
102 * enumerate through triplets
103 */
104 static bool enumerator_enumerate(triplet_enumerator_t *e, identification_t **imsi,
105 char **rand, char **sres, char **kc)
106 {
107 triplet_t *triplet;
108
109 if (e->inner->enumerate(e->inner, &triplet))
110 {
111 e->current = triplet;
112 *imsi = triplet->imsi;
113 *rand = triplet->rand;
114 *sres = triplet->sres;
115 *kc = triplet->kc;
116 return TRUE;
117 }
118 e->current = NULL;
119 return FALSE;
120 }
121
122 /**
123 * Implementation of eap_sim_file_triplets_t.create_enumerator
124 */
125 static enumerator_t* create_enumerator(private_eap_sim_file_triplets_t *this)
126 {
127 triplet_enumerator_t *enumerator = malloc_thing(triplet_enumerator_t);
128
129 this->mutex->lock(this->mutex);
130 enumerator->public.enumerate = (void*)enumerator_enumerate;
131 enumerator->public.destroy = (void*)enumerator_destroy;
132 enumerator->inner = this->triplets->create_enumerator(this->triplets);
133 enumerator->current = NULL;
134 enumerator->this = this;
135
136 return &enumerator->public;
137 }
138
139 /**
140 * convert to token into the array
141 */
142 static void parse_token(char *to, char *from, size_t len)
143 {
144 chunk_t chunk;
145
146 chunk = chunk_create(from, min(strlen(from), len * 2));
147 chunk = chunk_from_hex(chunk, NULL);
148 memset(to, 0, len);
149 memcpy(to + len - chunk.len, chunk.ptr, chunk.len);
150 free(chunk.ptr);
151 }
152
153 /**
154 * Read the triplets from the file
155 */
156 static void read_triplets(private_eap_sim_file_triplets_t *this, char *path)
157 {
158 char line[512];
159 FILE *file;
160 int i, nr = 0;
161
162 file = fopen(path, "r");
163 if (file == NULL)
164 {
165 DBG1(DBG_CFG, "opening triplet file %s failed: %s",
166 path, strerror(errno));
167 return;
168 }
169
170 /* read line by line */
171 while (fgets(line, sizeof(line), file))
172 {
173 triplet_t *triplet;
174 enumerator_t *enumerator;
175 char *token;
176
177 nr++;
178 /* skip comments, empty lines */
179 switch (line[0])
180 {
181 case '\n':
182 case '\r':
183 case '#':
184 case '\0':
185 continue;
186 default:
187 break;
188 }
189 triplet = malloc_thing(triplet_t);
190 memset(triplet, 0, sizeof(triplet_t));
191
192 i = 0;
193 enumerator = enumerator_create_token(line, ",", " \n\r#");
194 while (enumerator->enumerate(enumerator, &token))
195 {
196 switch (i++)
197 {
198 case 0: /* IMSI */
199 triplet->imsi = identification_create_from_encoding(ID_EAP,
200 chunk_create(token, strlen(token)));
201 continue;
202 case 1: /* rand */
203 parse_token(triplet->rand, token, RAND_LEN);
204 continue;
205 case 2: /* sres */
206 parse_token(triplet->sres, token, SRES_LEN);
207 continue;
208 case 3: /* kc */
209 parse_token(triplet->kc, token, KC_LEN);
210 continue;
211 default:
212 break;;
213 }
214 break;
215 }
216 enumerator->destroy(enumerator);
217 if (i < 4)
218 {
219 DBG1(DBG_CFG, "error in triplet file, line %d", nr);
220 triplet_destroy(triplet);
221 continue;
222 }
223
224 DBG1(DBG_CFG, "triplet: imsi %D\nrand %b\nsres %b\nkc %b",
225 triplet->imsi, triplet->rand, RAND_LEN,
226 triplet->sres, SRES_LEN, triplet->kc, KC_LEN);
227
228 this->triplets->insert_last(this->triplets, triplet);
229 }
230 fclose(file);
231
232 DBG1(DBG_CFG, "read %d triplets from %s",
233 this->triplets->get_count(this->triplets), path);
234 }
235
236 /**
237 * Implementation of eap_sim_file_triplets_t.destroy.
238 */
239 static void destroy(private_eap_sim_file_triplets_t *this)
240 {
241 this->triplets->destroy_function(this->triplets, (void*)triplet_destroy);
242 this->mutex->destroy(this->mutex);
243 free(this);
244 }
245
246 /**
247 * See header
248 */
249 eap_sim_file_triplets_t *eap_sim_file_triplets_create(char *file)
250 {
251 private_eap_sim_file_triplets_t *this = malloc_thing(private_eap_sim_file_triplets_t);
252
253 this->public.create_enumerator = (enumerator_t*(*)(eap_sim_file_triplets_t*))create_enumerator;
254 this->public.destroy = (void(*)(eap_sim_file_triplets_t*))destroy;
255
256 this->triplets = linked_list_create();
257 this->mutex = mutex_create(MUTEX_DEFAULT);
258
259 read_triplets(this, file);
260
261 return &this->public;
262 }
263