2 * Copyright (C) 2008 Martin Willi
3 * HSR Hochschule fuer Technik Rapperswil
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>.
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
19 #include "medcli_config.h"
22 #include <processing/jobs/callback_job.h>
24 typedef struct private_medcli_config_t private_medcli_config_t
;
27 * Name of the mediation connection
29 #define MEDIATION_CONN_NAME "medcli-mediation"
32 * Private data of an medcli_config_t object
34 struct private_medcli_config_t
{
39 medcli_config_t
public;
63 * create a traffic selector from a CIDR notation string
65 static traffic_selector_t
*ts_from_string(char *str
)
69 traffic_selector_t
*ts
;
71 ts
= traffic_selector_create_from_cidr(str
, 0, 0, 65535);
77 return traffic_selector_create_dynamic(0, 0, 65535);
81 * Build a mediation config
83 static peer_cfg_t
*build_mediation_config(private_medcli_config_t
*this,
84 peer_cfg_create_t
*defaults
)
90 ike_cfg_create_t ike
= {
93 .local_port
= charon
->socket
->get_port(charon
->socket
, FALSE
),
94 .remote_port
= IKEV2_UDP_PORT
,
97 peer_cfg_create_t peer
= *defaults
;
100 /* query mediation server config:
101 * - build ike_cfg/peer_cfg for mediation connection on-the-fly
103 e
= this->db
->query(this->db
,
104 "SELECT Address, ClientConfig.KeyId, MediationServerConfig.KeyId "
105 "FROM MediationServerConfig JOIN ClientConfig",
106 DB_TEXT
, DB_BLOB
, DB_BLOB
);
107 if (!e
|| !e
->enumerate(e
, &ike
.remote
, &me
, &other
))
112 ike_cfg
= ike_cfg_create(&ike
);
113 ike_cfg
->add_proposal(ike_cfg
, proposal_create_default(PROTO_IKE
));
114 ike_cfg
->add_proposal(ike_cfg
, proposal_create_default_aead(PROTO_IKE
));
116 peer
.mediation
= TRUE
;
117 med_cfg
= peer_cfg_create(MEDIATION_CONN_NAME
, ike_cfg
, &peer
);
120 auth
= auth_cfg_create();
121 auth
->add(auth
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
122 auth
->add(auth
, AUTH_RULE_IDENTITY
,
123 identification_create_from_encoding(ID_KEY_ID
, me
));
124 med_cfg
->add_auth_cfg(med_cfg
, auth
, TRUE
);
125 auth
= auth_cfg_create();
126 auth
->add(auth
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
127 auth
->add(auth
, AUTH_RULE_IDENTITY
,
128 identification_create_from_encoding(ID_KEY_ID
, other
));
129 med_cfg
->add_auth_cfg(med_cfg
, auth
, FALSE
);
133 METHOD(backend_t
, get_peer_cfg_by_name
, peer_cfg_t
*,
134 private_medcli_config_t
*this, char *name
)
138 peer_cfg_t
*peer_cfg
;
139 child_cfg_t
*child_cfg
;
141 char *local_net
, *remote_net
;
142 peer_cfg_create_t peer
= {
143 .cert_policy
= CERT_NEVER_SEND
,
144 .unique
= UNIQUE_REPLACE
,
146 .rekey_time
= this->rekey
* 60,
147 .jitter_time
= this->rekey
* 5,
148 .over_time
= this->rekey
* 3,
151 child_cfg_create_t child
= {
154 .life
= this->rekey
* 60 + this->rekey
,
155 .rekey
= this->rekey
,
156 .jitter
= this->rekey
162 if (streq(name
, "medcli-mediation"))
164 return build_mediation_config(this, &peer
);
167 /* query mediated config:
168 * - use any-any ike_cfg
169 * - build peer_cfg on-the-fly using med_cfg
172 e
= this->db
->query(this->db
,
173 "SELECT ClientConfig.KeyId, Connection.KeyId, "
174 "Connection.LocalSubnet, Connection.RemoteSubnet "
175 "FROM ClientConfig JOIN Connection "
176 "WHERE Active AND Alias = ?", DB_TEXT
, name
,
177 DB_BLOB
, DB_BLOB
, DB_TEXT
, DB_TEXT
);
178 if (!e
|| !e
->enumerate(e
, &me
, &other
, &local_net
, &remote_net
))
183 peer
.mediated_by
= MEDIATION_CONN_NAME
;
184 peer
.peer_id
= identification_create_from_encoding(ID_KEY_ID
, other
);
185 peer_cfg
= peer_cfg_create(name
, this->ike
->get_ref(this->ike
), &peer
);
187 auth
= auth_cfg_create();
188 auth
->add(auth
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
189 auth
->add(auth
, AUTH_RULE_IDENTITY
,
190 identification_create_from_encoding(ID_KEY_ID
, me
));
191 peer_cfg
->add_auth_cfg(peer_cfg
, auth
, TRUE
);
192 auth
= auth_cfg_create();
193 auth
->add(auth
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
194 auth
->add(auth
, AUTH_RULE_IDENTITY
,
195 identification_create_from_encoding(ID_KEY_ID
, other
));
196 peer_cfg
->add_auth_cfg(peer_cfg
, auth
, FALSE
);
198 child_cfg
= child_cfg_create(name
, &child
);
199 child_cfg
->add_proposal(child_cfg
, proposal_create_default(PROTO_ESP
));
200 child_cfg
->add_proposal(child_cfg
, proposal_create_default_aead(PROTO_ESP
));
201 child_cfg
->add_traffic_selector(child_cfg
, TRUE
, ts_from_string(local_net
));
202 child_cfg
->add_traffic_selector(child_cfg
, FALSE
, ts_from_string(remote_net
));
203 peer_cfg
->add_child_cfg(peer_cfg
, child_cfg
);
208 METHOD(backend_t
, create_ike_cfg_enumerator
, enumerator_t
*,
209 private_medcli_config_t
*this, host_t
*me
, host_t
*other
)
211 return enumerator_create_single(this->ike
, NULL
);
215 /** implements enumerator */
217 /** inner SQL enumerator */
219 /** currently enumerated peer config */
221 /** ike cfg to use in peer cfg */
229 METHOD(enumerator_t
, peer_enumerator_enumerate
, bool,
230 peer_enumerator_t
*this, va_list args
)
232 char *name
, *local_net
, *remote_net
;
235 child_cfg_t
*child_cfg
;
237 peer_cfg_create_t peer
= {
238 .cert_policy
= CERT_NEVER_SEND
,
239 .unique
= UNIQUE_REPLACE
,
241 .rekey_time
= this->rekey
* 60,
242 .jitter_time
= this->rekey
* 5,
243 .over_time
= this->rekey
* 3,
246 child_cfg_create_t child
= {
249 .life
= this->rekey
* 60 + this->rekey
,
250 .rekey
= this->rekey
,
251 .jitter
= this->rekey
257 VA_ARGS_VGET(args
, cfg
);
259 DESTROY_IF(this->current
);
260 if (!this->inner
->enumerate(this->inner
, &name
, &me
, &other
,
261 &local_net
, &remote_net
))
263 this->current
= NULL
;
266 this->current
= peer_cfg_create(name
, this->ike
->get_ref(this->ike
), &peer
);
268 auth
= auth_cfg_create();
269 auth
->add(auth
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
270 auth
->add(auth
, AUTH_RULE_IDENTITY
,
271 identification_create_from_encoding(ID_KEY_ID
, me
));
272 this->current
->add_auth_cfg(this->current
, auth
, TRUE
);
273 auth
= auth_cfg_create();
274 auth
->add(auth
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
275 auth
->add(auth
, AUTH_RULE_IDENTITY
,
276 identification_create_from_encoding(ID_KEY_ID
, other
));
277 this->current
->add_auth_cfg(this->current
, auth
, FALSE
);
279 child_cfg
= child_cfg_create(name
, &child
);
280 child_cfg
->add_proposal(child_cfg
, proposal_create_default(PROTO_ESP
));
281 child_cfg
->add_proposal(child_cfg
, proposal_create_default_aead(PROTO_ESP
));
282 child_cfg
->add_traffic_selector(child_cfg
, TRUE
, ts_from_string(local_net
));
283 child_cfg
->add_traffic_selector(child_cfg
, FALSE
, ts_from_string(remote_net
));
284 this->current
->add_child_cfg(this->current
, child_cfg
);
285 *cfg
= this->current
;
289 METHOD(enumerator_t
, peer_enumerator_destroy
, void,
290 peer_enumerator_t
*this)
292 DESTROY_IF(this->current
);
293 this->inner
->destroy(this->inner
);
297 METHOD(backend_t
, create_peer_cfg_enumerator
, enumerator_t
*,
298 private_medcli_config_t
*this, identification_t
*me
,
299 identification_t
*other
)
301 peer_enumerator_t
*e
;
305 .enumerate
= enumerator_enumerate_default
,
306 .venumerate
= _peer_enumerator_enumerate
,
307 .destroy
= _peer_enumerator_destroy
,
310 .rekey
= this->rekey
,
314 /* filter on IDs: NULL or ANY or matching KEY_ID */
315 e
->inner
= this->db
->query(this->db
,
316 "SELECT Alias, ClientConfig.KeyId, Connection.KeyId, "
317 "Connection.LocalSubnet, Connection.RemoteSubnet "
318 "FROM ClientConfig JOIN Connection "
320 "(? OR ClientConfig.KeyId = ?) AND (? OR Connection.KeyId = ?)",
321 DB_INT
, me
== NULL
|| me
->get_type(me
) == ID_ANY
,
322 DB_BLOB
, me
&& me
->get_type(me
) == ID_KEY_ID
?
323 me
->get_encoding(me
) : chunk_empty
,
324 DB_INT
, other
== NULL
|| other
->get_type(other
) == ID_ANY
,
325 DB_BLOB
, other
&& other
->get_type(other
) == ID_KEY_ID
?
326 other
->get_encoding(other
) : chunk_empty
,
327 DB_TEXT
, DB_BLOB
, DB_BLOB
, DB_TEXT
, DB_TEXT
);
337 * initiate a peer config
339 static job_requeue_t
initiate_config(peer_cfg_t
*peer_cfg
)
341 enumerator_t
*enumerator
;
342 child_cfg_t
*child_cfg
= NULL
;;
344 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
345 enumerator
->enumerate(enumerator
, &child_cfg
);
348 child_cfg
->get_ref(child_cfg
);
349 peer_cfg
->get_ref(peer_cfg
);
350 enumerator
->destroy(enumerator
);
351 charon
->controller
->initiate(charon
->controller
,
352 peer_cfg
, child_cfg
, NULL
, NULL
, 0, FALSE
);
356 enumerator
->destroy(enumerator
);
358 return JOB_REQUEUE_NONE
;
362 * schedule initiation of all "active" connections
364 static void schedule_autoinit(private_medcli_config_t
*this)
369 e
= this->db
->query(this->db
, "SELECT Alias FROM Connection WHERE Active",
373 while (e
->enumerate(e
, &name
))
375 peer_cfg_t
*peer_cfg
;
377 peer_cfg
= get_peer_cfg_by_name(this, name
);
380 /* schedule asynchronous initiation job */
381 lib
->processor
->queue_job(lib
->processor
,
382 (job_t
*)callback_job_create(
383 (callback_job_cb_t
)initiate_config
,
384 peer_cfg
, (void*)peer_cfg
->destroy
, NULL
));
391 METHOD(medcli_config_t
, destroy
, void,
392 private_medcli_config_t
*this)
394 this->ike
->destroy(this->ike
);
399 * Described in header.
401 medcli_config_t
*medcli_config_create(database_t
*db
)
403 private_medcli_config_t
*this;
404 ike_cfg_create_t ike
= {
407 .local_port
= charon
->socket
->get_port(charon
->socket
, FALSE
),
409 .remote_port
= IKEV2_UDP_PORT
,
416 .create_peer_cfg_enumerator
= _create_peer_cfg_enumerator
,
417 .create_ike_cfg_enumerator
= _create_ike_cfg_enumerator
,
418 .get_peer_cfg_by_name
= _get_peer_cfg_by_name
,
423 .rekey
= lib
->settings
->get_time(lib
->settings
, "medcli.rekey", 1200),
424 .dpd
= lib
->settings
->get_time(lib
->settings
, "medcli.dpd", 300),
425 .ike
= ike_cfg_create(&ike
),
427 this->ike
->add_proposal(this->ike
, proposal_create_default(PROTO_IKE
));
428 this->ike
->add_proposal(this->ike
, proposal_create_default_aead(PROTO_IKE
));
430 schedule_autoinit(this);
432 return &this->public;