]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/frontends/android/jni/libandroidbridge/backend/android_service.c
android: Use a shorter timeout for retransmits
[thirdparty/strongswan.git] / src / frontends / android / jni / libandroidbridge / backend / android_service.c
CommitLineData
66211196
TB
1/*
2 * Copyright (C) 2010-2012 Tobias Brunner
3 * Copyright (C) 2012 Giuliano Grassi
4 * Copyright (C) 2012 Ralf Sager
5 * Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
2483f6a4 18#include <errno.h>
d9531100
TB
19#include <unistd.h>
20
66211196
TB
21#include "android_service.h"
22#include "../charonservice.h"
a2993d72 23#include "../vpnservice_builder.h"
66211196
TB
24
25#include <daemon.h>
26#include <library.h>
3b3cf0c8 27#include <ipsec.h>
66211196 28#include <processing/jobs/callback_job.h>
a2993d72 29#include <threading/rwlock.h>
2483f6a4 30#include <threading/thread.h>
66211196
TB
31
32typedef struct private_android_service_t private_android_service_t;
33
a2993d72
TB
34#define TUN_DEFAULT_MTU 1400
35
66211196
TB
36/**
37 * private data of Android service
38 */
39struct private_android_service_t {
40
41 /**
42 * public interface
43 */
44 android_service_t public;
45
c89cc226
TB
46 /**
47 * credential set
48 */
49 android_creds_t *creds;
50
66211196
TB
51 /**
52 * current IKE_SA
53 */
54 ike_sa_t *ike_sa;
55
c89cc226
TB
56 /**
57 * the type of VPN
58 */
59 char *type;
60
66211196
TB
61 /**
62 * gateway
63 */
64 char *gateway;
65
66 /**
67 * username
68 */
69 char *username;
70
c89cc226
TB
71 /**
72 * password
73 */
74 char *password;
75
a2993d72
TB
76 /**
77 * lock to safely access the TUN device fd
78 */
79 rwlock_t *lock;
80
81 /**
82 * TUN device file descriptor
83 */
84 int tunfd;
85
66211196
TB
86};
87
3b3cf0c8
TB
88/**
89 * Outbound callback
90 */
91static void send_esp(void *data, esp_packet_t *packet)
92{
93 charon->sender->send_no_marker(charon->sender, (packet_t*)packet);
94}
95
d9531100
TB
96/**
97 * Inbound callback
98 */
99static void deliver_plain(private_android_service_t *this,
100 ip_packet_t *packet)
101{
102 chunk_t encoding;
103 ssize_t len;
104
105 encoding = packet->get_encoding(packet);
106
107 this->lock->read_lock(this->lock);
108 if (this->tunfd < 0)
109 { /* the TUN device is already closed */
110 this->lock->unlock(this->lock);
111 packet->destroy(packet);
112 return;
113 }
114 len = write(this->tunfd, encoding.ptr, encoding.len);
115 this->lock->unlock(this->lock);
116
117 if (len < 0 || len != encoding.len)
118 {
119 DBG1(DBG_DMN, "failed to write packet to TUN device: %s",
120 strerror(errno));
121 }
122 packet->destroy(packet);
123}
124
3b3cf0c8
TB
125/**
126 * Receiver callback
127 */
128static void receiver_esp_cb(void *data, packet_t *packet)
129{
130 esp_packet_t *esp_packet;
131
132 esp_packet = esp_packet_create_from_packet(packet);
133 ipsec->processor->queue_inbound(ipsec->processor, esp_packet);
134}
135
2483f6a4
TB
136/**
137 * Job handling outbound plaintext packets
138 */
139static job_requeue_t handle_plain(private_android_service_t *this)
140{
141 ip_packet_t *packet;
142 chunk_t raw;
143 fd_set set;
144 ssize_t len;
145 int tunfd;
146 bool old;
d7d2a5ec
TB
147 timeval_t tv = {
148 /* check every second if tunfd is still valid */
149 .tv_sec = 1,
150 };
2483f6a4
TB
151
152 FD_ZERO(&set);
153
154 this->lock->read_lock(this->lock);
155 if (this->tunfd < 0)
156 { /* the TUN device is already closed */
157 this->lock->unlock(this->lock);
158 return JOB_REQUEUE_NONE;
159 }
160 tunfd = this->tunfd;
161 FD_SET(tunfd, &set);
162 this->lock->unlock(this->lock);
163
164 old = thread_cancelability(TRUE);
d7d2a5ec 165 len = select(tunfd + 1, &set, NULL, NULL, &tv);
2483f6a4
TB
166 thread_cancelability(old);
167
168 if (len < 0)
169 {
170 DBG1(DBG_DMN, "select on TUN device failed: %s", strerror(errno));
171 return JOB_REQUEUE_NONE;
172 }
d7d2a5ec
TB
173 else if (len == 0)
174 { /* timeout, check again right away */
175 return JOB_REQUEUE_DIRECT;
176 }
2483f6a4
TB
177
178 raw = chunk_alloc(TUN_DEFAULT_MTU);
179 len = read(tunfd, raw.ptr, raw.len);
180 if (len < 0)
181 {
182 DBG1(DBG_DMN, "reading from TUN device failed: %s", strerror(errno));
183 chunk_free(&raw);
184 return JOB_REQUEUE_FAIR;
185 }
186 raw.len = len;
187
188 packet = ip_packet_create(raw);
189 if (packet)
190 {
191 ipsec->processor->queue_outbound(ipsec->processor, packet);
192 }
193 else
194 {
195 DBG1(DBG_DMN, "invalid IP packet read from TUN device");
196 }
197 return JOB_REQUEUE_DIRECT;
198}
199
30ba2ff7
TB
200/**
201 * Add a route to the TUN device builder
202 */
203static bool add_route(vpnservice_builder_t *builder, host_t *net,
204 u_int8_t prefix)
205{
206 /* if route is 0.0.0.0/0, split it into two routes 0.0.0.0/1 and
207 * 128.0.0.0/1 because otherwise it would conflict with the current default
208 * route */
209 if (net->is_anyaddr(net) && prefix == 0)
210 {
211 bool success;
212
213 success = add_route(builder, net, 1);
214 net = host_create_from_string("128.0.0.0", 0);
215 success = success && add_route(builder, net, 1);
216 net->destroy(net);
217 return success;
218 }
219 return builder->add_route(builder, net, prefix);
220}
221
222/**
223 * Generate and set routes from installed IPsec policies
224 */
225static bool add_routes(vpnservice_builder_t *builder, child_sa_t *child_sa)
226{
227 traffic_selector_t *src_ts, *dst_ts;
228 enumerator_t *enumerator;
229 bool success = TRUE;
230
231 enumerator = child_sa->create_policy_enumerator(child_sa);
232 while (success && enumerator->enumerate(enumerator, &src_ts, &dst_ts))
233 {
234 host_t *net;
235 u_int8_t prefix;
236
237 dst_ts->to_subnet(dst_ts, &net, &prefix);
238 success = add_route(builder, net, prefix);
239 net->destroy(net);
240 }
241 enumerator->destroy(enumerator);
242 return success;
243}
244
a2993d72 245/**
2483f6a4
TB
246 * Setup a new TUN device for the supplied SAs, also queues a job that
247 * reads packets from this device.
a2993d72
TB
248 * Additional information such as DNS servers are gathered in appropriate
249 * listeners asynchronously. To be sure every required bit of information is
250 * available this should be called after the CHILD_SA has been established.
251 */
252static bool setup_tun_device(private_android_service_t *this,
253 ike_sa_t *ike_sa, child_sa_t *child_sa)
254{
255 vpnservice_builder_t *builder;
101d26ba 256 enumerator_t *enumerator;
d7d2a5ec 257 bool vip_found = FALSE, already_registered = FALSE;
62e6630b 258 host_t *vip;
a2993d72
TB
259 int tunfd;
260
261 DBG1(DBG_DMN, "setting up TUN device for CHILD_SA %s{%u}",
262 child_sa->get_name(child_sa), child_sa->get_reqid(child_sa));
101d26ba
MW
263
264 builder = charonservice->get_vpnservice_builder(charonservice);
265
266 enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE);
267 while (enumerator->enumerate(enumerator, &vip))
268 {
269 if (!vip->is_anyaddr(vip))
270 {
271 if (!builder->add_address(builder, vip))
272 {
273 break;
274 }
275 vip_found = TRUE;
276 }
277 }
278 enumerator->destroy(enumerator);
279
280 if (!vip_found)
62e6630b
TB
281 {
282 DBG1(DBG_DMN, "setting up TUN device failed, no virtual IP found");
283 return FALSE;
284 }
101d26ba 285 if (!add_routes(builder, child_sa) ||
62e6630b 286 !builder->set_mtu(builder, TUN_DEFAULT_MTU))
a2993d72
TB
287 {
288 return FALSE;
289 }
290
291 tunfd = builder->establish(builder);
292 if (tunfd == -1)
293 {
294 return FALSE;
295 }
296
297 this->lock->write_lock(this->lock);
d7d2a5ec
TB
298 if (this->tunfd > 0)
299 { /* close previously opened TUN device */
300 close(this->tunfd);
301 already_registered = true;
302 }
a2993d72
TB
303 this->tunfd = tunfd;
304 this->lock->unlock(this->lock);
305
306 DBG1(DBG_DMN, "successfully created TUN device");
3b3cf0c8 307
d7d2a5ec
TB
308 if (!already_registered)
309 {
310 charon->receiver->add_esp_cb(charon->receiver,
3b3cf0c8 311 (receiver_esp_cb_t)receiver_esp_cb, NULL);
d7d2a5ec 312 ipsec->processor->register_inbound(ipsec->processor,
d9531100 313 (ipsec_inbound_cb_t)deliver_plain, this);
d7d2a5ec 314 ipsec->processor->register_outbound(ipsec->processor,
3b3cf0c8
TB
315 (ipsec_outbound_cb_t)send_esp, NULL);
316
d7d2a5ec
TB
317 lib->processor->queue_job(lib->processor,
318 (job_t*)callback_job_create((callback_job_cb_t)handle_plain, this,
2483f6a4 319 NULL, (callback_job_cancel_t)return_false));
d7d2a5ec 320 }
a2993d72
TB
321 return TRUE;
322}
323
324/**
325 * Close the current tun device
326 */
327static void close_tun_device(private_android_service_t *this)
328{
329 int tunfd;
330
331 this->lock->write_lock(this->lock);
332 if (this->tunfd < 0)
333 { /* already closed (or never created) */
334 this->lock->unlock(this->lock);
335 return;
336 }
337 tunfd = this->tunfd;
338 this->tunfd = -1;
339 this->lock->unlock(this->lock);
3b3cf0c8
TB
340
341 ipsec->processor->unregister_outbound(ipsec->processor,
342 (ipsec_outbound_cb_t)send_esp);
d9531100
TB
343 ipsec->processor->unregister_inbound(ipsec->processor,
344 (ipsec_inbound_cb_t)deliver_plain);
3b3cf0c8
TB
345 charon->receiver->del_esp_cb(charon->receiver,
346 (receiver_esp_cb_t)receiver_esp_cb);
a2993d72
TB
347 close(tunfd);
348}
349
66211196
TB
350METHOD(listener_t, child_updown, bool,
351 private_android_service_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
352 bool up)
353{
354 if (this->ike_sa == ike_sa)
355 {
356 if (up)
357 {
358 /* disable the hooks registered to catch initiation failures */
359 this->public.listener.ike_updown = NULL;
a2993d72
TB
360 if (!setup_tun_device(this, ike_sa, child_sa))
361 {
362 DBG1(DBG_DMN, "failed to setup TUN device");
363 charonservice->update_status(charonservice,
364 CHARONSERVICE_GENERIC_ERROR);
365 return FALSE;
366
367 }
66211196
TB
368 charonservice->update_status(charonservice,
369 CHARONSERVICE_CHILD_STATE_UP);
370 }
371 else
372 {
d7d2a5ec
TB
373 if (ike_sa->has_condition(ike_sa, COND_REAUTHENTICATING))
374 { /* we ignore this during reauthentication */
375 return TRUE;
376 }
a2993d72 377 close_tun_device(this);
66211196
TB
378 charonservice->update_status(charonservice,
379 CHARONSERVICE_CHILD_STATE_DOWN);
380 return FALSE;
381 }
382 }
383 return TRUE;
384}
385
386METHOD(listener_t, ike_updown, bool,
387 private_android_service_t *this, ike_sa_t *ike_sa, bool up)
388{
389 /* this callback is only registered during initiation, so if the IKE_SA
390 * goes down we assume an authentication error */
391 if (this->ike_sa == ike_sa && !up)
392 {
393 charonservice->update_status(charonservice,
394 CHARONSERVICE_AUTH_ERROR);
395 return FALSE;
396 }
397 return TRUE;
398}
399
66211196
TB
400METHOD(listener_t, alert, bool,
401 private_android_service_t *this, ike_sa_t *ike_sa, alert_t alert,
402 va_list args)
403{
404 if (this->ike_sa == ike_sa)
405 {
406 switch (alert)
407 {
408 case ALERT_PEER_ADDR_FAILED:
409 charonservice->update_status(charonservice,
410 CHARONSERVICE_LOOKUP_ERROR);
411 break;
412 case ALERT_PEER_AUTH_FAILED:
413 charonservice->update_status(charonservice,
414 CHARONSERVICE_PEER_AUTH_ERROR);
415 break;
272ce5b5
TB
416 case ALERT_PEER_INIT_UNREACHABLE:
417 charonservice->update_status(charonservice,
418 CHARONSERVICE_UNREACHABLE_ERROR);
419 break;
66211196
TB
420 default:
421 break;
422 }
423 }
424 return TRUE;
425}
426
427METHOD(listener_t, ike_rekey, bool,
428 private_android_service_t *this, ike_sa_t *old, ike_sa_t *new)
429{
430 if (this->ike_sa == old)
431 {
432 this->ike_sa = new;
433 }
434 return TRUE;
435}
436
d7d2a5ec
TB
437METHOD(listener_t, ike_reestablish, bool,
438 private_android_service_t *this, ike_sa_t *old, ike_sa_t *new)
439{
440 if (this->ike_sa == old)
441 {
442 this->ike_sa = new;
272ce5b5 443 /* re-register hook to detect initiation failures */
d7d2a5ec 444 this->public.listener.ike_updown = _ike_updown;
d7d2a5ec
TB
445 /* the TUN device will be closed when the new CHILD_SA is established */
446 }
447 return TRUE;
448}
449
66211196
TB
450static job_requeue_t initiate(private_android_service_t *this)
451{
452 identification_t *gateway, *user;
453 ike_cfg_t *ike_cfg;
454 peer_cfg_t *peer_cfg;
455 child_cfg_t *child_cfg;
456 traffic_selector_t *ts;
457 ike_sa_t *ike_sa;
458 auth_cfg_t *auth;
459 lifetime_cfg_t lifetime = {
460 .time = {
461 .life = 10800, /* 3h */
462 .rekey = 10200, /* 2h50min */
463 .jitter = 300 /* 5min */
464 }
465 };
466
38bbca58 467 ike_cfg = ike_cfg_create(TRUE, TRUE, "0.0.0.0", FALSE,
66211196
TB
468 charon->socket->get_port(charon->socket, FALSE),
469 this->gateway, FALSE, IKEV2_UDP_PORT);
470 ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
471
472 peer_cfg = peer_cfg_create("android", IKEV2, ike_cfg, CERT_SEND_IF_ASKED,
8658e87b 473 UNIQUE_REPLACE, 0, /* keyingtries */
66211196
TB
474 36000, 0, /* rekey 10h, reauth none */
475 600, 600, /* jitter, over 10min */
476 TRUE, FALSE, /* mobike, aggressive */
477 0, 0, /* DPD delay, timeout */
497ce2cf 478 FALSE, NULL, NULL); /* mediation */
101d26ba 479 peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
66211196 480
c89cc226
TB
481 /* local auth config */
482 if (streq("ikev2-eap", this->type))
483 {
484 auth = auth_cfg_create();
485 auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
486 user = identification_create_from_string(this->username);
487 auth->add(auth, AUTH_RULE_IDENTITY, user);
488
489 this->creds->add_username_password(this->creds, this->username,
490 this->password);
491 memwipe(this->password, strlen(this->password));
492 peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
493 }
494 else if (streq("ikev2-cert", this->type))
495 {
496 certificate_t *cert;
497 identification_t *id;
66211196 498
c89cc226
TB
499 cert = this->creds->load_user_certificate(this->creds);
500 if (!cert)
501 {
502 peer_cfg->destroy(peer_cfg);
503 charonservice->update_status(charonservice,
504 CHARONSERVICE_GENERIC_ERROR);
505 return JOB_REQUEUE_NONE;
506
507 }
508 auth = auth_cfg_create();
509 auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
510 auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert);
511 id = cert->get_subject(cert);
512 auth->add(auth, AUTH_RULE_IDENTITY, id->clone(id));
513 peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
514 }
515
516 /* remote auth config */
66211196
TB
517 auth = auth_cfg_create();
518 auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
519 gateway = identification_create_from_string(this->gateway);
520 auth->add(auth, AUTH_RULE_IDENTITY, gateway);
e596d0ef 521 auth->add(auth, AUTH_RULE_IDENTITY_LOOSE, TRUE);
66211196
TB
522 peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
523
524 child_cfg = child_cfg_create("android", &lifetime, NULL, TRUE, MODE_TUNNEL,
8658e87b
TB
525 ACTION_NONE, ACTION_RESTART, ACTION_RESTART,
526 FALSE, 0, 0, NULL, NULL, 0);
e3d98f2c
TB
527 /* create an ESP proposal with the algorithms currently supported by
528 * libipsec, no PFS for now */
529 child_cfg->add_proposal(child_cfg, proposal_create_from_string(PROTO_ESP,
530 "aes128-aes192-aes256-sha1-sha256-sha384-sha512"));
b00806cf
TB
531 ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE, "0.0.0.0",
532 0, "255.255.255.255", 65535);
66211196
TB
533 child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
534 ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE, "0.0.0.0",
535 0, "255.255.255.255", 65535);
536 child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
537 peer_cfg->add_child_cfg(peer_cfg, child_cfg);
538
539 /* get us an IKE_SA */
540 ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
541 peer_cfg);
542 if (!ike_sa)
543 {
544 peer_cfg->destroy(peer_cfg);
545 charonservice->update_status(charonservice,
546 CHARONSERVICE_GENERIC_ERROR);
547 return JOB_REQUEUE_NONE;
548 }
549 if (!ike_sa->get_peer_cfg(ike_sa))
550 {
551 ike_sa->set_peer_cfg(ike_sa, peer_cfg);
552 }
553 peer_cfg->destroy(peer_cfg);
554
555 /* store the IKE_SA so we can track its progress */
556 this->ike_sa = ike_sa;
557
558 /* get an additional reference because initiate consumes one */
559 child_cfg->get_ref(child_cfg);
560 if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS)
561 {
562 DBG1(DBG_CFG, "failed to initiate tunnel");
563 charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
564 ike_sa);
565 return JOB_REQUEUE_NONE;
566 }
567 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
568 return JOB_REQUEUE_NONE;
569}
570
571METHOD(android_service_t, destroy, void,
572 private_android_service_t *this)
573{
574 charon->bus->remove_listener(charon->bus, &this->public.listener);
a2993d72
TB
575 /* make sure the tun device is actually closed */
576 close_tun_device(this);
577 this->lock->destroy(this->lock);
c89cc226 578 free(this->type);
66211196 579 free(this->gateway);
c89cc226
TB
580 free(this->username);
581 if (this->password)
582 {
583 memwipe(this->password, strlen(this->password));
584 free(this->password);
585 }
66211196
TB
586 free(this);
587}
588
589/**
590 * See header
591 */
c89cc226 592android_service_t *android_service_create(android_creds_t *creds, char *type,
38bbca58
TB
593 char *gateway, char *username,
594 char *password)
66211196
TB
595{
596 private_android_service_t *this;
597
598 INIT(this,
599 .public = {
600 .listener = {
601 .ike_rekey = _ike_rekey,
d7d2a5ec 602 .ike_reestablish = _ike_reestablish,
66211196 603 .ike_updown = _ike_updown,
66211196
TB
604 .child_updown = _child_updown,
605 .alert = _alert,
606 },
607 .destroy = _destroy,
608 },
a2993d72 609 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
66211196 610 .username = username,
c89cc226 611 .password = password,
66211196 612 .gateway = gateway,
c89cc226
TB
613 .creds = creds,
614 .type = type,
a2993d72 615 .tunfd = -1,
66211196
TB
616 );
617
618 charon->bus->add_listener(charon->bus, &this->public.listener);
619
620 lib->processor->queue_job(lib->processor,
621 (job_t*)callback_job_create((callback_job_cb_t)initiate, this,
622 NULL, NULL));
623 return &this->public;
624}