]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/frontends/android/jni/libandroidbridge/backend/android_service.c
Merge branch 'pt-tls'
[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 {
e88b529a
TB
170 if (errno == EBADF)
171 { /* the TUN device got closed just before calling select(), retry */
172 return JOB_REQUEUE_FAIR;
173 }
2483f6a4
TB
174 DBG1(DBG_DMN, "select on TUN device failed: %s", strerror(errno));
175 return JOB_REQUEUE_NONE;
176 }
d7d2a5ec
TB
177 else if (len == 0)
178 { /* timeout, check again right away */
179 return JOB_REQUEUE_DIRECT;
180 }
2483f6a4
TB
181
182 raw = chunk_alloc(TUN_DEFAULT_MTU);
183 len = read(tunfd, raw.ptr, raw.len);
184 if (len < 0)
185 {
186 DBG1(DBG_DMN, "reading from TUN device failed: %s", strerror(errno));
187 chunk_free(&raw);
188 return JOB_REQUEUE_FAIR;
189 }
190 raw.len = len;
191
192 packet = ip_packet_create(raw);
193 if (packet)
194 {
195 ipsec->processor->queue_outbound(ipsec->processor, packet);
196 }
197 else
198 {
199 DBG1(DBG_DMN, "invalid IP packet read from TUN device");
200 }
201 return JOB_REQUEUE_DIRECT;
202}
203
30ba2ff7
TB
204/**
205 * Add a route to the TUN device builder
206 */
207static bool add_route(vpnservice_builder_t *builder, host_t *net,
208 u_int8_t prefix)
209{
210 /* if route is 0.0.0.0/0, split it into two routes 0.0.0.0/1 and
211 * 128.0.0.0/1 because otherwise it would conflict with the current default
212 * route */
213 if (net->is_anyaddr(net) && prefix == 0)
214 {
215 bool success;
216
217 success = add_route(builder, net, 1);
218 net = host_create_from_string("128.0.0.0", 0);
219 success = success && add_route(builder, net, 1);
220 net->destroy(net);
221 return success;
222 }
223 return builder->add_route(builder, net, prefix);
224}
225
226/**
227 * Generate and set routes from installed IPsec policies
228 */
229static bool add_routes(vpnservice_builder_t *builder, child_sa_t *child_sa)
230{
231 traffic_selector_t *src_ts, *dst_ts;
232 enumerator_t *enumerator;
233 bool success = TRUE;
234
235 enumerator = child_sa->create_policy_enumerator(child_sa);
236 while (success && enumerator->enumerate(enumerator, &src_ts, &dst_ts))
237 {
238 host_t *net;
239 u_int8_t prefix;
240
241 dst_ts->to_subnet(dst_ts, &net, &prefix);
242 success = add_route(builder, net, prefix);
243 net->destroy(net);
244 }
245 enumerator->destroy(enumerator);
246 return success;
247}
248
a2993d72 249/**
2483f6a4
TB
250 * Setup a new TUN device for the supplied SAs, also queues a job that
251 * reads packets from this device.
a2993d72
TB
252 * Additional information such as DNS servers are gathered in appropriate
253 * listeners asynchronously. To be sure every required bit of information is
254 * available this should be called after the CHILD_SA has been established.
255 */
256static bool setup_tun_device(private_android_service_t *this,
257 ike_sa_t *ike_sa, child_sa_t *child_sa)
258{
259 vpnservice_builder_t *builder;
101d26ba 260 enumerator_t *enumerator;
d7d2a5ec 261 bool vip_found = FALSE, already_registered = FALSE;
62e6630b 262 host_t *vip;
a2993d72
TB
263 int tunfd;
264
265 DBG1(DBG_DMN, "setting up TUN device for CHILD_SA %s{%u}",
266 child_sa->get_name(child_sa), child_sa->get_reqid(child_sa));
101d26ba
MW
267
268 builder = charonservice->get_vpnservice_builder(charonservice);
269
270 enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE);
271 while (enumerator->enumerate(enumerator, &vip))
272 {
273 if (!vip->is_anyaddr(vip))
274 {
275 if (!builder->add_address(builder, vip))
276 {
277 break;
278 }
279 vip_found = TRUE;
280 }
281 }
282 enumerator->destroy(enumerator);
283
284 if (!vip_found)
62e6630b
TB
285 {
286 DBG1(DBG_DMN, "setting up TUN device failed, no virtual IP found");
287 return FALSE;
288 }
101d26ba 289 if (!add_routes(builder, child_sa) ||
62e6630b 290 !builder->set_mtu(builder, TUN_DEFAULT_MTU))
a2993d72
TB
291 {
292 return FALSE;
293 }
294
295 tunfd = builder->establish(builder);
296 if (tunfd == -1)
297 {
298 return FALSE;
299 }
300
301 this->lock->write_lock(this->lock);
d7d2a5ec
TB
302 if (this->tunfd > 0)
303 { /* close previously opened TUN device */
304 close(this->tunfd);
305 already_registered = true;
306 }
a2993d72
TB
307 this->tunfd = tunfd;
308 this->lock->unlock(this->lock);
309
310 DBG1(DBG_DMN, "successfully created TUN device");
3b3cf0c8 311
d7d2a5ec
TB
312 if (!already_registered)
313 {
314 charon->receiver->add_esp_cb(charon->receiver,
3b3cf0c8 315 (receiver_esp_cb_t)receiver_esp_cb, NULL);
d7d2a5ec 316 ipsec->processor->register_inbound(ipsec->processor,
d9531100 317 (ipsec_inbound_cb_t)deliver_plain, this);
d7d2a5ec 318 ipsec->processor->register_outbound(ipsec->processor,
3b3cf0c8
TB
319 (ipsec_outbound_cb_t)send_esp, NULL);
320
d7d2a5ec
TB
321 lib->processor->queue_job(lib->processor,
322 (job_t*)callback_job_create((callback_job_cb_t)handle_plain, this,
2483f6a4 323 NULL, (callback_job_cancel_t)return_false));
d7d2a5ec 324 }
a2993d72
TB
325 return TRUE;
326}
327
328/**
329 * Close the current tun device
330 */
331static void close_tun_device(private_android_service_t *this)
332{
333 int tunfd;
334
335 this->lock->write_lock(this->lock);
336 if (this->tunfd < 0)
337 { /* already closed (or never created) */
338 this->lock->unlock(this->lock);
339 return;
340 }
341 tunfd = this->tunfd;
342 this->tunfd = -1;
343 this->lock->unlock(this->lock);
3b3cf0c8
TB
344
345 ipsec->processor->unregister_outbound(ipsec->processor,
346 (ipsec_outbound_cb_t)send_esp);
d9531100
TB
347 ipsec->processor->unregister_inbound(ipsec->processor,
348 (ipsec_inbound_cb_t)deliver_plain);
3b3cf0c8
TB
349 charon->receiver->del_esp_cb(charon->receiver,
350 (receiver_esp_cb_t)receiver_esp_cb);
a2993d72
TB
351 close(tunfd);
352}
353
66211196
TB
354METHOD(listener_t, child_updown, bool,
355 private_android_service_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
356 bool up)
357{
358 if (this->ike_sa == ike_sa)
359 {
360 if (up)
361 {
362 /* disable the hooks registered to catch initiation failures */
363 this->public.listener.ike_updown = NULL;
a2993d72
TB
364 if (!setup_tun_device(this, ike_sa, child_sa))
365 {
366 DBG1(DBG_DMN, "failed to setup TUN device");
367 charonservice->update_status(charonservice,
368 CHARONSERVICE_GENERIC_ERROR);
369 return FALSE;
370
371 }
66211196
TB
372 charonservice->update_status(charonservice,
373 CHARONSERVICE_CHILD_STATE_UP);
374 }
375 else
376 {
d7d2a5ec
TB
377 if (ike_sa->has_condition(ike_sa, COND_REAUTHENTICATING))
378 { /* we ignore this during reauthentication */
379 return TRUE;
380 }
a2993d72 381 close_tun_device(this);
66211196
TB
382 charonservice->update_status(charonservice,
383 CHARONSERVICE_CHILD_STATE_DOWN);
384 return FALSE;
385 }
386 }
387 return TRUE;
388}
389
390METHOD(listener_t, ike_updown, bool,
391 private_android_service_t *this, ike_sa_t *ike_sa, bool up)
392{
393 /* this callback is only registered during initiation, so if the IKE_SA
394 * goes down we assume an authentication error */
395 if (this->ike_sa == ike_sa && !up)
396 {
397 charonservice->update_status(charonservice,
398 CHARONSERVICE_AUTH_ERROR);
399 return FALSE;
400 }
401 return TRUE;
402}
403
66211196
TB
404METHOD(listener_t, alert, bool,
405 private_android_service_t *this, ike_sa_t *ike_sa, alert_t alert,
406 va_list args)
407{
408 if (this->ike_sa == ike_sa)
409 {
410 switch (alert)
411 {
412 case ALERT_PEER_ADDR_FAILED:
413 charonservice->update_status(charonservice,
414 CHARONSERVICE_LOOKUP_ERROR);
415 break;
416 case ALERT_PEER_AUTH_FAILED:
417 charonservice->update_status(charonservice,
418 CHARONSERVICE_PEER_AUTH_ERROR);
419 break;
272ce5b5 420 case ALERT_PEER_INIT_UNREACHABLE:
2b6088c7
TB
421 this->lock->read_lock(this->lock);
422 if (this->tunfd < 0)
423 { /* only handle this if we are not reestablishing the SA */
424 charonservice->update_status(charonservice,
425 CHARONSERVICE_UNREACHABLE_ERROR);
426 }
427 this->lock->unlock(this->lock);
272ce5b5 428 break;
66211196
TB
429 default:
430 break;
431 }
432 }
433 return TRUE;
434}
435
436METHOD(listener_t, ike_rekey, bool,
437 private_android_service_t *this, ike_sa_t *old, ike_sa_t *new)
438{
439 if (this->ike_sa == old)
440 {
441 this->ike_sa = new;
442 }
443 return TRUE;
444}
445
d7d2a5ec
TB
446METHOD(listener_t, ike_reestablish, bool,
447 private_android_service_t *this, ike_sa_t *old, ike_sa_t *new)
448{
449 if (this->ike_sa == old)
450 {
451 this->ike_sa = new;
272ce5b5 452 /* re-register hook to detect initiation failures */
d7d2a5ec 453 this->public.listener.ike_updown = _ike_updown;
d7d2a5ec
TB
454 /* the TUN device will be closed when the new CHILD_SA is established */
455 }
456 return TRUE;
457}
458
66211196
TB
459static job_requeue_t initiate(private_android_service_t *this)
460{
461 identification_t *gateway, *user;
462 ike_cfg_t *ike_cfg;
463 peer_cfg_t *peer_cfg;
464 child_cfg_t *child_cfg;
465 traffic_selector_t *ts;
466 ike_sa_t *ike_sa;
467 auth_cfg_t *auth;
468 lifetime_cfg_t lifetime = {
469 .time = {
470 .life = 10800, /* 3h */
471 .rekey = 10200, /* 2h50min */
472 .jitter = 300 /* 5min */
473 }
474 };
475
9fc7cc6f 476 ike_cfg = ike_cfg_create(IKEV2, TRUE, TRUE, "0.0.0.0", FALSE,
66211196 477 charon->socket->get_port(charon->socket, FALSE),
365d9a6f 478 this->gateway, FALSE, IKEV2_UDP_PORT,
306a269e 479 FRAGMENTATION_NO, 0);
66211196
TB
480 ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
481
1fdd62ff 482 peer_cfg = peer_cfg_create("android", ike_cfg, CERT_SEND_IF_ASKED,
8658e87b 483 UNIQUE_REPLACE, 0, /* keyingtries */
66211196
TB
484 36000, 0, /* rekey 10h, reauth none */
485 600, 600, /* jitter, over 10min */
486 TRUE, FALSE, /* mobike, aggressive */
487 0, 0, /* DPD delay, timeout */
497ce2cf 488 FALSE, NULL, NULL); /* mediation */
101d26ba 489 peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
66211196 490
c89cc226
TB
491 /* local auth config */
492 if (streq("ikev2-eap", this->type))
493 {
494 auth = auth_cfg_create();
495 auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
496 user = identification_create_from_string(this->username);
497 auth->add(auth, AUTH_RULE_IDENTITY, user);
498
499 this->creds->add_username_password(this->creds, this->username,
500 this->password);
501 memwipe(this->password, strlen(this->password));
502 peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
503 }
504 else if (streq("ikev2-cert", this->type))
505 {
506 certificate_t *cert;
507 identification_t *id;
66211196 508
c89cc226
TB
509 cert = this->creds->load_user_certificate(this->creds);
510 if (!cert)
511 {
512 peer_cfg->destroy(peer_cfg);
513 charonservice->update_status(charonservice,
514 CHARONSERVICE_GENERIC_ERROR);
515 return JOB_REQUEUE_NONE;
516
517 }
518 auth = auth_cfg_create();
519 auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
520 auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert);
521 id = cert->get_subject(cert);
522 auth->add(auth, AUTH_RULE_IDENTITY, id->clone(id));
523 peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
524 }
525
526 /* remote auth config */
66211196
TB
527 auth = auth_cfg_create();
528 auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
529 gateway = identification_create_from_string(this->gateway);
530 auth->add(auth, AUTH_RULE_IDENTITY, gateway);
e596d0ef 531 auth->add(auth, AUTH_RULE_IDENTITY_LOOSE, TRUE);
66211196
TB
532 peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
533
534 child_cfg = child_cfg_create("android", &lifetime, NULL, TRUE, MODE_TUNNEL,
8658e87b
TB
535 ACTION_NONE, ACTION_RESTART, ACTION_RESTART,
536 FALSE, 0, 0, NULL, NULL, 0);
e3d98f2c
TB
537 /* create an ESP proposal with the algorithms currently supported by
538 * libipsec, no PFS for now */
539 child_cfg->add_proposal(child_cfg, proposal_create_from_string(PROTO_ESP,
540 "aes128-aes192-aes256-sha1-sha256-sha384-sha512"));
b00806cf
TB
541 ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE, "0.0.0.0",
542 0, "255.255.255.255", 65535);
66211196
TB
543 child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
544 ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE, "0.0.0.0",
545 0, "255.255.255.255", 65535);
546 child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
547 peer_cfg->add_child_cfg(peer_cfg, child_cfg);
548
549 /* get us an IKE_SA */
550 ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
551 peer_cfg);
552 if (!ike_sa)
553 {
554 peer_cfg->destroy(peer_cfg);
555 charonservice->update_status(charonservice,
556 CHARONSERVICE_GENERIC_ERROR);
557 return JOB_REQUEUE_NONE;
558 }
559 if (!ike_sa->get_peer_cfg(ike_sa))
560 {
561 ike_sa->set_peer_cfg(ike_sa, peer_cfg);
562 }
563 peer_cfg->destroy(peer_cfg);
564
565 /* store the IKE_SA so we can track its progress */
566 this->ike_sa = ike_sa;
567
568 /* get an additional reference because initiate consumes one */
569 child_cfg->get_ref(child_cfg);
570 if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS)
571 {
572 DBG1(DBG_CFG, "failed to initiate tunnel");
573 charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
574 ike_sa);
575 return JOB_REQUEUE_NONE;
576 }
577 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
578 return JOB_REQUEUE_NONE;
579}
580
581METHOD(android_service_t, destroy, void,
582 private_android_service_t *this)
583{
584 charon->bus->remove_listener(charon->bus, &this->public.listener);
a2993d72
TB
585 /* make sure the tun device is actually closed */
586 close_tun_device(this);
587 this->lock->destroy(this->lock);
c89cc226 588 free(this->type);
66211196 589 free(this->gateway);
c89cc226
TB
590 free(this->username);
591 if (this->password)
592 {
593 memwipe(this->password, strlen(this->password));
594 free(this->password);
595 }
66211196
TB
596 free(this);
597}
598
599/**
600 * See header
601 */
c89cc226 602android_service_t *android_service_create(android_creds_t *creds, char *type,
38bbca58
TB
603 char *gateway, char *username,
604 char *password)
66211196
TB
605{
606 private_android_service_t *this;
607
608 INIT(this,
609 .public = {
610 .listener = {
611 .ike_rekey = _ike_rekey,
d7d2a5ec 612 .ike_reestablish = _ike_reestablish,
66211196 613 .ike_updown = _ike_updown,
66211196
TB
614 .child_updown = _child_updown,
615 .alert = _alert,
616 },
617 .destroy = _destroy,
618 },
a2993d72 619 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
66211196 620 .username = username,
c89cc226 621 .password = password,
66211196 622 .gateway = gateway,
c89cc226
TB
623 .creds = creds,
624 .type = type,
a2993d72 625 .tunfd = -1,
66211196
TB
626 );
627
628 charon->bus->add_listener(charon->bus, &this->public.listener);
629
630 lib->processor->queue_job(lib->processor,
631 (job_t*)callback_job_create((callback_job_cb_t)initiate, this,
632 NULL, NULL));
633 return &this->public;
634}