2 * Copyright (C) 2010 Tobias Brunner
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 "maemo_plugin.h"
22 #include <credentials/sets/mem_cred.h>
23 #include <processing/jobs/callback_job.h>
25 #define OSSO_CHARON_NAME "charon"
26 #define OSSO_CHARON_SERVICE "org.strongswan."OSSO_CHARON_NAME
27 #define OSSO_CHARON_OBJECT "/org/strongswan/"OSSO_CHARON_NAME
28 #define OSSO_CHARON_IFACE "org.strongswan."OSSO_CHARON_NAME
30 typedef struct private_maemo_plugin_t private_maemo_plugin_t
;
33 * private data of maemo plugin
35 struct private_maemo_plugin_t
{
38 * implements plugin interface
40 maemo_plugin_t
public;
48 * Glib main loop for a thread, handles DBUS calls
55 osso_context_t
*context
;
58 * Name of the current connection
64 static gboolean
initiate_connection(private_maemo_plugin_t
*this,
68 gchar
*hostname
= NULL
, *cacert
= NULL
, *username
= NULL
, *password
= NULL
;
69 identification_t
*gateway
= NULL
, *user
= NULL
;
72 child_cfg_t
*child_cfg
;
73 traffic_selector_t
*ts
;
76 lifetime_cfg_t lifetime
= {
78 .life
= 10800, /* 3h */
79 .rekey
= 10200, /* 2h50min */
80 .jitter
= 300 /* 5min */
86 DBG1(DBG_CFG
, "currently connected to '%s', disconnect first",
91 if (arguments
->len
!= 5)
93 DBG1(DBG_CFG
, "wrong number of arguments: %d", arguments
->len
);
97 for (i
= 0; i
< arguments
->len
; i
++)
99 osso_rpc_t
*arg
= &g_array_index(arguments
, osso_rpc_t
, i
);
100 if (arg
->type
!= DBUS_TYPE_STRING
)
102 DBG1(DBG_CFG
, "invalid argument [%d]: %d", i
, arg
->type
);
103 this->current
= (g_free(this->current
), NULL
);
109 this->current
= g_strdup(arg
->value
.s
);
111 case 1: /* hostname */
112 hostname
= arg
->value
.s
;
114 case 2: /* CA certificate path */
115 cacert
= arg
->value
.s
;
117 case 3: /* username */
118 username
= arg
->value
.s
;
120 case 4: /* password */
121 password
= arg
->value
.s
;
126 DBG1(DBG_CFG
, "received initiate for connection '%s'", this->current
);
128 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
129 BUILD_FROM_FILE
, cacert
, BUILD_END
);
132 this->creds
->add_cert(this->creds
, TRUE
, cert
);
136 DBG1(DBG_CFG
, "failed to load CA certificate");
138 /* if this is a server cert we could use the cert subject as id */
140 gateway
= identification_create_from_string(hostname
);
141 DBG1(DBG_CFG
, "using CA certificate, gateway identitiy '%Y'", gateway
);
144 shared_key_t
*shared_key
;
145 chunk_t secret
= chunk_create(password
, strlen(password
));
146 user
= identification_create_from_string(username
);
147 shared_key
= shared_key_create(SHARED_EAP
, chunk_clone(secret
));
148 this->creds
->add_shared(this->creds
, shared_key
, user
->clone(user
),
152 ike_cfg
= ike_cfg_create(TRUE
, FALSE
, "0.0.0.0", IKEV2_UDP_PORT
,
153 hostname
, IKEV2_UDP_PORT
);
154 ike_cfg
->add_proposal(ike_cfg
, proposal_create_default(PROTO_IKE
));
156 peer_cfg
= peer_cfg_create(this->current
, 2, ike_cfg
, CERT_SEND_IF_ASKED
,
157 UNIQUE_REPLACE
, 1, /* keyingtries */
158 36000, 0, /* rekey 10h, reauth none */
159 600, 600, /* jitter, over 10min */
160 TRUE
, 0, /* mobike, DPD */
161 host_create_from_string("0.0.0.0", 0) /* virt */,
162 NULL
, FALSE
, NULL
, NULL
); /* pool, mediation */
164 auth
= auth_cfg_create();
165 auth
->add(auth
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_EAP
);
166 auth
->add(auth
, AUTH_RULE_IDENTITY
, user
);
167 peer_cfg
->add_auth_cfg(peer_cfg
, auth
, TRUE
);
168 auth
= auth_cfg_create();
169 auth
->add(auth
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
170 auth
->add(auth
, AUTH_RULE_IDENTITY
, gateway
);
171 peer_cfg
->add_auth_cfg(peer_cfg
, auth
, FALSE
);
173 child_cfg
= child_cfg_create(this->current
, &lifetime
, NULL
/* updown */,
174 TRUE
, MODE_TUNNEL
, ACTION_NONE
, ACTION_NONE
,
175 FALSE
, 0, 0, NULL
, NULL
);
176 child_cfg
->add_proposal(child_cfg
, proposal_create_default(PROTO_ESP
));
177 ts
= traffic_selector_create_dynamic(0, 0, 65535);
178 child_cfg
->add_traffic_selector(child_cfg
, TRUE
, ts
);
179 ts
= traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE
, "0.0.0.0",
180 0, "255.255.255.255", 65535);
181 child_cfg
->add_traffic_selector(child_cfg
, FALSE
, ts
);
182 peer_cfg
->add_child_cfg(peer_cfg
, child_cfg
);
184 if (charon
->controller
->initiate(charon
->controller
, peer_cfg
, child_cfg
,
185 controller_cb_empty
, NULL
) != SUCCESS
)
187 DBG1(DBG_CFG
, "failed to initiate tunnel");
188 this->current
= (g_free(this->current
), NULL
);
194 static void disconnect(private_maemo_plugin_t
*this)
204 ike_sa
= charon
->ike_sa_manager
->checkout_by_name(charon
->ike_sa_manager
,
205 this->current
, FALSE
);
208 id
= ike_sa
->get_unique_id(ike_sa
);
209 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
210 charon
->controller
->terminate_ike(charon
->controller
, id
,
213 this->current
= (g_free(this->current
), NULL
);
217 * Callback for libosso dbus wrapper
219 static gint
dbus_req_handler(const gchar
*interface
, const gchar
*method
,
220 GArray
*arguments
, private_maemo_plugin_t
*this,
223 if (streq(method
, "Start"))
224 { /* void start (void), dummy function to start charon as root */
227 else if (streq(method
, "Connect"))
228 { /* bool connect (name, host, cert, user, pass) */
229 retval
->value
.b
= initiate_connection(this, arguments
);
230 retval
->type
= DBUS_TYPE_BOOLEAN
;
232 else if (streq(method
, "Disconnect"))
233 { /* void disconnect (void) */
244 * Main loop to handle D-BUS messages.
246 static job_requeue_t
run(private_maemo_plugin_t
*this)
248 this->loop
= g_main_loop_new(NULL
, FALSE
);
249 g_main_loop_run(this->loop
);
250 return JOB_REQUEUE_NONE
;
253 METHOD(plugin_t
, destroy
, void,
254 private_maemo_plugin_t
*this)
258 if (g_main_loop_is_running(this->loop
))
260 g_main_loop_quit(this->loop
);
262 g_main_loop_unref(this->loop
);
266 osso_deinitialize(this->context
);
268 lib
->credmgr
->remove_set(lib
->credmgr
, &this->creds
->set
);
269 this->creds
->destroy(this->creds
);
276 plugin_t
*maemo_plugin_create()
278 osso_return_t result
;
279 private_maemo_plugin_t
*this;
285 .creds
= mem_cred_create(),
288 lib
->credmgr
->add_set(lib
->credmgr
, &this->creds
->set
);
290 this->context
= osso_initialize(OSSO_CHARON_SERVICE
, "0.0.1", TRUE
, NULL
);
293 DBG1(DBG_CFG
, "failed to initialize OSSO context");
298 result
= osso_rpc_set_cb_f(this->context
,
302 (osso_rpc_cb_f
*)dbus_req_handler
,
304 if (result
!= OSSO_OK
)
306 DBG1(DBG_CFG
, "failed to set D-BUS callback (%d)", result
);
312 if (!g_thread_supported())
317 lib
->processor
->queue_job(lib
->processor
,
318 (job_t
*)callback_job_create((callback_job_cb_t
)run
, this, NULL
, NULL
));
320 return &this->public.plugin
;