Make sure first argument is an int when using %.*s to print e.g. chunks
[strongswan.git] / src / libcharon / plugins / tnc_pdp / tnc_pdp_connections.c
1 /*
2 * Copyright (C) 2012 Andreas Steffen
3 * HSR 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
16 #include "tnc_pdp_connections.h"
17
18 #include <utils/linked_list.h>
19 #include <debug.h>
20
21 typedef struct private_tnc_pdp_connections_t private_tnc_pdp_connections_t;
22 typedef struct entry_t entry_t;
23
24 /**
25 * Private data of tnc_pdp_connections_t
26 */
27 struct private_tnc_pdp_connections_t {
28
29 /**
30 * Implements tnc_pdp_connections_t interface
31 */
32 tnc_pdp_connections_t public;
33
34 /**
35 * List of TNC PEP RADIUS Connections
36 */
37 linked_list_t *list;
38 };
39
40 /**
41 * Data entry for a TNC PEP RADIUS connection
42 */
43 struct entry_t {
44
45 /**
46 * NAS identifier of PEP
47 */
48 chunk_t nas_id;
49
50 /**
51 * User name of TNC Client
52 */
53 chunk_t user_name;
54
55 /**
56 * EAP method state
57 */
58 eap_method_t *method;
59
60 /**
61 * IKE SA used for bus communication
62 */
63 ike_sa_t *ike_sa;
64 };
65
66 /**
67 * Free the memory allocated to a data entry
68 */
69 static void free_entry(entry_t *this)
70 {
71 this->method->destroy(this->method);
72 this->ike_sa->destroy(this->ike_sa);
73 free(this->nas_id.ptr);
74 free(this->user_name.ptr);
75 free(this);
76 }
77
78 /**
79 * Find a matching data entry
80 */
81 static bool equals_entry( entry_t *this, chunk_t nas_id, chunk_t user_name)
82 {
83 bool no_nas_id = !this->nas_id.ptr && !nas_id.ptr;
84
85 return (chunk_equals(this->nas_id, nas_id) || no_nas_id) &&
86 chunk_equals(this->user_name, user_name);
87 }
88
89 /**
90 * Find a matching data entry
91 */
92 static void dbg_nas_user(chunk_t nas_id, chunk_t user_name, bool not, char *op)
93 {
94 if (nas_id.len)
95 {
96 DBG1(DBG_CFG, "%s RADIUS connection for user '%.*s' NAS '%.*s'",
97 not ? "could not find" : op, (int)user_name.len,
98 user_name.ptr, (int)nas_id.len, nas_id.ptr);
99 }
100 else
101 {
102 DBG1(DBG_CFG, "%s RADIUS connection for user '%.*s'",
103 not ? "could not find" : op, (int)user_name.len,
104 user_name.ptr);
105 }
106 }
107
108 METHOD(tnc_pdp_connections_t, add, void,
109 private_tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name,
110 identification_t *peer, eap_method_t *method)
111 {
112 enumerator_t *enumerator;
113 entry_t *entry;
114 ike_sa_id_t *ike_sa_id;
115 ike_sa_t *ike_sa;
116 bool found = FALSE;
117
118 ike_sa_id = ike_sa_id_create(IKEV2_MAJOR_VERSION, 0, 0, FALSE);
119 ike_sa = ike_sa_create(ike_sa_id, FALSE, IKEV2);
120 ike_sa_id->destroy(ike_sa_id);
121 ike_sa->set_other_id(ike_sa, peer);
122
123 enumerator = this->list->create_enumerator(this->list);
124 while (enumerator->enumerate(enumerator, &entry))
125 {
126 if (equals_entry(entry, nas_id, user_name))
127 {
128 found = TRUE;
129 entry->method->destroy(entry->method);
130 entry->ike_sa->destroy(entry->ike_sa);
131 DBG1(DBG_CFG, "removed stale RADIUS connection");
132 entry->method = method;
133 entry->ike_sa = ike_sa;
134 break;
135 }
136 }
137 enumerator->destroy(enumerator);
138
139 if (!found)
140 {
141 entry = malloc_thing(entry_t);
142 entry->nas_id = chunk_clone(nas_id);
143 entry->user_name = chunk_clone(user_name);
144 entry->method = method;
145 entry->ike_sa = ike_sa;
146 this->list->insert_last(this->list, entry);
147 }
148 dbg_nas_user(nas_id, user_name, FALSE, "created");
149 }
150
151 METHOD(tnc_pdp_connections_t, remove_, void,
152 private_tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name)
153 {
154 enumerator_t *enumerator;
155 entry_t *entry;
156
157 enumerator = this->list->create_enumerator(this->list);
158 while (enumerator->enumerate(enumerator, &entry))
159 {
160 if (equals_entry(entry, nas_id, user_name))
161 {
162 free_entry(entry);
163 this->list->remove_at(this->list, enumerator);
164 dbg_nas_user(nas_id, user_name, FALSE, "removed");
165 break;
166 }
167 }
168 enumerator->destroy(enumerator);
169 }
170
171 METHOD(tnc_pdp_connections_t, get_state, eap_method_t*,
172 private_tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name,
173 ike_sa_t **ike_sa)
174 {
175 enumerator_t *enumerator;
176 entry_t *entry;
177 eap_method_t *found = NULL;
178
179 enumerator = this->list->create_enumerator(this->list);
180 while (enumerator->enumerate(enumerator, &entry))
181 {
182 if (equals_entry(entry, nas_id, user_name))
183 {
184 found = entry->method;
185 *ike_sa = entry->ike_sa;
186 break;
187 }
188 }
189 enumerator->destroy(enumerator);
190
191 dbg_nas_user(nas_id, user_name, !found, "found");
192 return found;
193 }
194
195 METHOD(tnc_pdp_connections_t, destroy, void,
196 private_tnc_pdp_connections_t *this)
197 {
198 this->list->destroy_function(this->list, (void*)free_entry);
199 free(this);
200 }
201
202 /*
203 * see header file
204 */
205 tnc_pdp_connections_t *tnc_pdp_connections_create(void)
206 {
207 private_tnc_pdp_connections_t *this;
208
209 INIT(this,
210 .public = {
211 .add = _add,
212 .remove = _remove_,
213 .get_state = _get_state,
214 .destroy = _destroy,
215 },
216 .list = linked_list_create(),
217 );
218
219 return &this->public;
220 }
221