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