2 * Copyright (C) 2008 Martin Willi
3 * 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 * Private data of an medcli_config_t object
29 struct private_medcli_config_t
{
34 medcli_config_t
public;
58 * create a traffic selector from a CIDR notation string
60 static traffic_selector_t
*ts_from_string(char *str
)
64 traffic_selector_t
*ts
;
66 ts
= traffic_selector_create_from_cidr(str
, 0, 0, 65535);
72 return traffic_selector_create_dynamic(0, 0, 65535);
75 METHOD(backend_t
, get_peer_cfg_by_name
, peer_cfg_t
*,
76 private_medcli_config_t
*this, char *name
)
79 peer_cfg_t
*peer_cfg
, *med_cfg
;
82 child_cfg_t
*child_cfg
;
84 char *address
, *local_net
, *remote_net
;
85 lifetime_cfg_t lifetime
= {
87 .life
= this->rekey
* 60 + this->rekey
,
93 /* query mediation server config:
94 * - build ike_cfg/peer_cfg for mediation connection on-the-fly
96 e
= this->db
->query(this->db
,
97 "SELECT Address, ClientConfig.KeyId, MediationServerConfig.KeyId "
98 "FROM MediationServerConfig JOIN ClientConfig",
99 DB_TEXT
, DB_BLOB
, DB_BLOB
);
100 if (!e
|| !e
->enumerate(e
, &address
, &me
, &other
))
105 ike_cfg
= ike_cfg_create(IKEV2
, FALSE
, FALSE
, "0.0.0.0",
106 charon
->socket
->get_port(charon
->socket
, FALSE
),
107 address
, IKEV2_UDP_PORT
, FRAGMENTATION_NO
, 0);
108 ike_cfg
->add_proposal(ike_cfg
, proposal_create_default(PROTO_IKE
));
109 med_cfg
= peer_cfg_create(
110 "mediation", ike_cfg
,
111 CERT_NEVER_SEND
, UNIQUE_REPLACE
,
112 1, this->rekey
*60, 0, /* keytries, rekey, reauth */
113 this->rekey
*5, this->rekey
*3, /* jitter, overtime */
114 TRUE
, FALSE
, TRUE
, /* mobike, aggressive, pull */
115 this->dpd
, 0, /* DPD delay, timeout */
116 TRUE
, NULL
, NULL
); /* mediation, med by, peer id */
119 auth
= auth_cfg_create();
120 auth
->add(auth
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
121 auth
->add(auth
, AUTH_RULE_IDENTITY
,
122 identification_create_from_encoding(ID_KEY_ID
, me
));
123 med_cfg
->add_auth_cfg(med_cfg
, auth
, TRUE
);
124 auth
= auth_cfg_create();
125 auth
->add(auth
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
126 auth
->add(auth
, AUTH_RULE_IDENTITY
,
127 identification_create_from_encoding(ID_KEY_ID
, other
));
128 med_cfg
->add_auth_cfg(med_cfg
, auth
, FALSE
);
130 /* query mediated config:
131 * - use any-any ike_cfg
132 * - build peer_cfg on-the-fly using med_cfg
135 e
= this->db
->query(this->db
,
136 "SELECT ClientConfig.KeyId, Connection.KeyId, "
137 "Connection.LocalSubnet, Connection.RemoteSubnet "
138 "FROM ClientConfig JOIN Connection "
139 "WHERE Active AND Alias = ?", DB_TEXT
, name
,
140 DB_BLOB
, DB_BLOB
, DB_TEXT
, DB_TEXT
);
141 if (!e
|| !e
->enumerate(e
, &me
, &other
, &local_net
, &remote_net
))
146 peer_cfg
= peer_cfg_create(
147 name
, this->ike
->get_ref(this->ike
),
148 CERT_NEVER_SEND
, UNIQUE_REPLACE
,
149 1, this->rekey
*60, 0, /* keytries, rekey, reauth */
150 this->rekey
*5, this->rekey
*3, /* jitter, overtime */
151 TRUE
, FALSE
, TRUE
, /* mobike, aggressive, pull */
152 this->dpd
, 0, /* DPD delay, timeout */
153 FALSE
, med_cfg
, /* mediation, med by */
154 identification_create_from_encoding(ID_KEY_ID
, other
));
156 auth
= auth_cfg_create();
157 auth
->add(auth
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
158 auth
->add(auth
, AUTH_RULE_IDENTITY
,
159 identification_create_from_encoding(ID_KEY_ID
, me
));
160 peer_cfg
->add_auth_cfg(peer_cfg
, auth
, TRUE
);
161 auth
= auth_cfg_create();
162 auth
->add(auth
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
163 auth
->add(auth
, AUTH_RULE_IDENTITY
,
164 identification_create_from_encoding(ID_KEY_ID
, other
));
165 peer_cfg
->add_auth_cfg(peer_cfg
, auth
, FALSE
);
167 child_cfg
= child_cfg_create(name
, &lifetime
, NULL
, TRUE
, MODE_TUNNEL
,
168 ACTION_NONE
, ACTION_NONE
, ACTION_NONE
, FALSE
,
169 0, 0, NULL
, NULL
, 0);
170 child_cfg
->add_proposal(child_cfg
, proposal_create_default(PROTO_ESP
));
171 child_cfg
->add_traffic_selector(child_cfg
, TRUE
, ts_from_string(local_net
));
172 child_cfg
->add_traffic_selector(child_cfg
, FALSE
, ts_from_string(remote_net
));
173 peer_cfg
->add_child_cfg(peer_cfg
, child_cfg
);
178 METHOD(backend_t
, create_ike_cfg_enumerator
, enumerator_t
*,
179 private_medcli_config_t
*this, host_t
*me
, host_t
*other
)
181 return enumerator_create_single(this->ike
, NULL
);
185 /** implements enumerator */
187 /** inner SQL enumerator */
189 /** currently enumerated peer config */
191 /** ike cfg to use in peer cfg */
199 METHOD(enumerator_t
, peer_enumerator_enumerate
, bool,
200 peer_enumerator_t
*this, peer_cfg_t
**cfg
)
202 char *name
, *local_net
, *remote_net
;
204 child_cfg_t
*child_cfg
;
206 lifetime_cfg_t lifetime
= {
208 .life
= this->rekey
* 60 + this->rekey
,
209 .rekey
= this->rekey
,
210 .jitter
= this->rekey
214 DESTROY_IF(this->current
);
215 if (!this->inner
->enumerate(this->inner
, &name
, &me
, &other
,
216 &local_net
, &remote_net
))
218 this->current
= NULL
;
221 this->current
= peer_cfg_create(
222 name
, this->ike
->get_ref(this->ike
),
223 CERT_NEVER_SEND
, UNIQUE_REPLACE
,
224 1, this->rekey
*60, 0, /* keytries, rekey, reauth */
225 this->rekey
*5, this->rekey
*3, /* jitter, overtime */
226 TRUE
, FALSE
, TRUE
, /* mobike, aggressive, pull */
227 this->dpd
, 0, /* DPD delay, timeout */
228 FALSE
, NULL
, NULL
); /* mediation, med by, peer id */
230 auth
= auth_cfg_create();
231 auth
->add(auth
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
232 auth
->add(auth
, AUTH_RULE_IDENTITY
,
233 identification_create_from_encoding(ID_KEY_ID
, me
));
234 this->current
->add_auth_cfg(this->current
, auth
, TRUE
);
235 auth
= auth_cfg_create();
236 auth
->add(auth
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
237 auth
->add(auth
, AUTH_RULE_IDENTITY
,
238 identification_create_from_encoding(ID_KEY_ID
, other
));
239 this->current
->add_auth_cfg(this->current
, auth
, FALSE
);
241 child_cfg
= child_cfg_create(name
, &lifetime
, NULL
, TRUE
, MODE_TUNNEL
,
242 ACTION_NONE
, ACTION_NONE
, ACTION_NONE
, FALSE
,
243 0, 0, NULL
, NULL
, 0);
244 child_cfg
->add_proposal(child_cfg
, proposal_create_default(PROTO_ESP
));
245 child_cfg
->add_traffic_selector(child_cfg
, TRUE
, ts_from_string(local_net
));
246 child_cfg
->add_traffic_selector(child_cfg
, FALSE
, ts_from_string(remote_net
));
247 this->current
->add_child_cfg(this->current
, child_cfg
);
248 *cfg
= this->current
;
252 METHOD(enumerator_t
, peer_enumerator_destroy
, void,
253 peer_enumerator_t
*this)
255 DESTROY_IF(this->current
);
256 this->inner
->destroy(this->inner
);
260 METHOD(backend_t
, create_peer_cfg_enumerator
, enumerator_t
*,
261 private_medcli_config_t
*this, identification_t
*me
,
262 identification_t
*other
)
264 peer_enumerator_t
*e
;
268 .enumerate
= (void*)_peer_enumerator_enumerate
,
269 .destroy
= _peer_enumerator_destroy
,
272 .rekey
= this->rekey
,
276 /* filter on IDs: NULL or ANY or matching KEY_ID */
277 e
->inner
= this->db
->query(this->db
,
278 "SELECT Alias, ClientConfig.KeyId, Connection.KeyId, "
279 "Connection.LocalSubnet, Connection.RemoteSubnet "
280 "FROM ClientConfig JOIN Connection "
282 "(? OR ClientConfig.KeyId = ?) AND (? OR Connection.KeyId = ?)",
283 DB_INT
, me
== NULL
|| me
->get_type(me
) == ID_ANY
,
284 DB_BLOB
, me
&& me
->get_type(me
) == ID_KEY_ID
?
285 me
->get_encoding(me
) : chunk_empty
,
286 DB_INT
, other
== NULL
|| other
->get_type(other
) == ID_ANY
,
287 DB_BLOB
, other
&& other
->get_type(other
) == ID_KEY_ID
?
288 other
->get_encoding(other
) : chunk_empty
,
289 DB_TEXT
, DB_BLOB
, DB_BLOB
, DB_TEXT
, DB_TEXT
);
299 * initiate a peer config
301 static job_requeue_t
initiate_config(peer_cfg_t
*peer_cfg
)
303 enumerator_t
*enumerator
;
304 child_cfg_t
*child_cfg
= NULL
;;
306 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
307 enumerator
->enumerate(enumerator
, &child_cfg
);
310 child_cfg
->get_ref(child_cfg
);
311 peer_cfg
->get_ref(peer_cfg
);
312 enumerator
->destroy(enumerator
);
313 charon
->controller
->initiate(charon
->controller
,
314 peer_cfg
, child_cfg
, NULL
, NULL
, 0);
318 enumerator
->destroy(enumerator
);
320 return JOB_REQUEUE_NONE
;
324 * schedule initiation of all "active" connections
326 static void schedule_autoinit(private_medcli_config_t
*this)
331 e
= this->db
->query(this->db
, "SELECT Alias FROM Connection WHERE Active",
335 while (e
->enumerate(e
, &name
))
337 peer_cfg_t
*peer_cfg
;
339 peer_cfg
= get_peer_cfg_by_name(this, name
);
342 /* schedule asynchronous initiation job */
343 lib
->processor
->queue_job(lib
->processor
,
344 (job_t
*)callback_job_create(
345 (callback_job_cb_t
)initiate_config
,
346 peer_cfg
, (void*)peer_cfg
->destroy
, NULL
));
353 METHOD(medcli_config_t
, destroy
, void,
354 private_medcli_config_t
*this)
356 this->ike
->destroy(this->ike
);
361 * Described in header.
363 medcli_config_t
*medcli_config_create(database_t
*db
)
365 private_medcli_config_t
*this;
370 .create_peer_cfg_enumerator
= _create_peer_cfg_enumerator
,
371 .create_ike_cfg_enumerator
= _create_ike_cfg_enumerator
,
372 .get_peer_cfg_by_name
= _get_peer_cfg_by_name
,
377 .rekey
= lib
->settings
->get_time(lib
->settings
, "medcli.rekey", 1200),
378 .dpd
= lib
->settings
->get_time(lib
->settings
, "medcli.dpd", 300),
379 .ike
= ike_cfg_create(IKEV2
, FALSE
, FALSE
, "0.0.0.0",
380 charon
->socket
->get_port(charon
->socket
, FALSE
),
381 "0.0.0.0", IKEV2_UDP_PORT
,
382 FRAGMENTATION_NO
, 0),
384 this->ike
->add_proposal(this->ike
, proposal_create_default(PROTO_IKE
));
386 schedule_autoinit(this);
388 return &this->public;