setup.c revision cfc417e4c9268b46d71d2fe17aa9ad21bde23f39
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <unistd.h>
21#include <sys/param.h>
22#include <sys/types.h>
23#include <sys/socket.h>
24#include <netinet/in.h>
25#include <netinet/ip.h>
26#include <netdb.h>
27#include <fcntl.h>
28
29#include "config.h"
30#include "gcmalloc.h"
31#include "libpfkey.h"
32#include "var.h"
33#include "isakmp_var.h"
34#include "isakmp.h"
35#include "isakmp_xauth.h"
36#include "vmbuf.h"
37#include "crypto_openssl.h"
38#include "oakley.h"
39#include "ipsec_doi.h"
40#include "algorithm.h"
41#include "vendorid.h"
42#include "schedule.h"
43#include "pfkey.h"
44#include "nattraversal.h"
45#include "proposal.h"
46#include "sainfo.h"
47#include "localconf.h"
48#include "remoteconf.h"
49#include "sockmisc.h"
50#include "grabmyaddr.h"
51#include "plog.h"
52#include "admin.h"
53#include "privsep.h"
54#include "throttle.h"
55#include "misc.h"
56
57static struct localconf localconf;
58static struct sainfo sainfo;
59static char *pre_shared_key;
60
61static char *interface;
62static struct sockaddr *targets[2];
63static struct {
64    struct sockaddr *addr;
65    int fd;
66} sources[2];
67
68struct localconf *lcconf = &localconf;
69char *script_names[SCRIPT_MAX + 1];
70int f_local = 0;
71
72/*****************************************************************************/
73
74static void add_sainfo_algorithm(int class, int algorithm, int length)
75{
76    struct sainfoalg *p = calloc(1, sizeof(struct sainfoalg));
77    p->alg = algorithm;
78    p->encklen = length;
79
80    if (!sainfo.algs[class]) {
81        sainfo.algs[class] = p;
82    } else {
83        struct sainfoalg *q = sainfo.algs[class];
84        while (q->next) {
85            q = q->next;
86        }
87        q->next = p;
88    }
89}
90
91static void set_globals(char *interfaze, char *server)
92{
93    struct addrinfo hints = {
94        .ai_flags = AI_NUMERICSERV,
95#ifndef INET6
96        .ai_family = AF_INET,
97#else
98        .ai_family = AF_UNSPEC,
99#endif
100        .ai_socktype = SOCK_DGRAM,
101    };
102    struct addrinfo *info;
103
104    if (getaddrinfo(server, "500", &hints, &info) != 0) {
105        do_plog(LLV_ERROR, "Cannot resolve address: %s\n", server);
106        exit(1);
107    }
108    if (info->ai_next) {
109        do_plog(LLV_WARNING, "Found multiple addresses. Use the first one.\n");
110    }
111    targets[0] = dupsaddr(info->ai_addr);
112    freeaddrinfo(info);
113
114    interface = interfaze;
115    sources[0].addr = getlocaladdr(targets[0]);
116    if (!sources[0].addr) {
117        do_plog(LLV_ERROR, "Cannot get local address\n");
118        exit(1);
119    }
120    set_port(targets[0], 0);
121    set_port(sources[0].addr, 0);
122    sources[0].fd = -1;
123    sources[1].addr = dupsaddr(sources[0].addr);
124    sources[1].fd = -1;
125
126    localconf.port_isakmp = PORT_ISAKMP;
127    localconf.port_isakmp_natt = PORT_ISAKMP_NATT;
128    localconf.default_af = AF_INET;
129    localconf.pathinfo[LC_PATHTYPE_CERT] = "./";
130    localconf.pad_random = LC_DEFAULT_PAD_RANDOM;
131    localconf.pad_randomlen = LC_DEFAULT_PAD_RANDOM;
132    localconf.pad_strict = LC_DEFAULT_PAD_STRICT;
133    localconf.pad_excltail = LC_DEFAULT_PAD_EXCLTAIL;
134    localconf.retry_counter = 10;
135    localconf.retry_interval = 3;
136    localconf.count_persend = LC_DEFAULT_COUNT_PERSEND;
137    localconf.secret_size = LC_DEFAULT_SECRETSIZE;
138    localconf.retry_checkph1 = LC_DEFAULT_RETRY_CHECKPH1;
139    localconf.wait_ph2complete = LC_DEFAULT_WAIT_PH2COMPLETE;
140    localconf.natt_ka_interval = LC_DEFAULT_NATT_KA_INTERVAL;
141
142    sainfo.lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
143    sainfo.lifebyte = IPSECDOI_ATTR_SA_LD_KB_MAX;
144    add_sainfo_algorithm(algclass_ipsec_auth, IPSECDOI_ATTR_AUTH_HMAC_SHA1, 0);
145    add_sainfo_algorithm(algclass_ipsec_auth, IPSECDOI_ATTR_AUTH_HMAC_MD5, 0);
146    add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_3DES, 0);
147    add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_DES, 0);
148    add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_AES, 128);
149}
150
151/*****************************************************************************/
152
153static int policy_match(struct sadb_address *address)
154{
155    if (address) {
156        struct sockaddr *addr = PFKEY_ADDR_SADDR(address);
157        return cmpsaddr(addr, targets[0]) < CMPSADDR_MISMATCH ||
158                cmpsaddr(addr, targets[1]) < CMPSADDR_MISMATCH;
159    }
160    return 0;
161}
162
163/* flush; spdflush; */
164static void flush()
165{
166    struct sadb_msg *p;
167    int replies = 0;
168    int key = pfkey_open();
169
170    if (pfkey_send_dump(key, SADB_SATYPE_UNSPEC) <= 0 ||
171        pfkey_send_spddump(key) <= 0) {
172        do_plog(LLV_ERROR, "Cannot dump SAD and SPD\n");
173        exit(1);
174    }
175
176    for (p = NULL; replies < 2 && (p = pfkey_recv(key)) != NULL; free(p)) {
177        caddr_t q[SADB_EXT_MAX + 1];
178
179        if (p->sadb_msg_type != SADB_DUMP &&
180            p->sadb_msg_type != SADB_X_SPDDUMP) {
181            continue;
182        }
183        replies += !p->sadb_msg_seq;
184
185        if (p->sadb_msg_errno || pfkey_align(p, q) || pfkey_check(q)) {
186            continue;
187        }
188        if (policy_match((struct sadb_address *)q[SADB_EXT_ADDRESS_SRC]) ||
189            policy_match((struct sadb_address *)q[SADB_EXT_ADDRESS_DST])) {
190            p->sadb_msg_type = (p->sadb_msg_type == SADB_DUMP) ?
191                               SADB_DELETE : SADB_X_SPDDELETE;
192            p->sadb_msg_reserved = 0;
193            p->sadb_msg_seq = 0;
194            pfkey_send(key, p, PFKEY_UNUNIT64(p->sadb_msg_len));
195        }
196    }
197
198    pfkey_close(key);
199}
200
201/* flush; spdflush;
202 * spdadd src dst protocol -P out ipsec esp/transport//require; OR
203 * spdadd src any protocol -P out ipsec esp/tunnel/local-remote/require; */
204static void spdadd(struct sockaddr *src, struct sockaddr *dst,
205        int protocol, struct sockaddr *local, struct sockaddr *remote)
206{
207    struct __attribute__((packed)) {
208        struct sadb_x_policy p;
209        struct sadb_x_ipsecrequest q;
210        char addresses[sizeof(struct sockaddr_storage) * 2];
211    } policy;
212
213    struct sockaddr_storage any = {
214#ifndef __linux__
215        .ss_len = src->sa_len,
216#endif
217        .ss_family = src->sa_family,
218    };
219
220    int src_prefix = (src->sa_family == AF_INET) ? 32 : 128;
221    int dst_prefix = src_prefix;
222    int length = 0;
223    int key;
224
225    /* Fill default values. */
226    memset(&policy, 0, sizeof(policy));
227    policy.p.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
228    policy.p.sadb_x_policy_type = IPSEC_POLICY_IPSEC;
229    policy.p.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
230#ifdef HAVE_PFKEY_POLICY_PRIORITY
231    policy.p.sadb_x_policy_priority = PRIORITY_DEFAULT;
232#endif
233    policy.q.sadb_x_ipsecrequest_proto = IPPROTO_ESP;
234    policy.q.sadb_x_ipsecrequest_mode = IPSEC_MODE_TRANSPORT;
235    policy.q.sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE;
236
237    /* Deal with tunnel mode. */
238    if (!dst) {
239        policy.q.sadb_x_ipsecrequest_mode = IPSEC_MODE_TUNNEL;
240        dst = (struct sockaddr *)&any;
241        dst_prefix = 0;
242
243        length = sysdep_sa_len(local);
244        memcpy(policy.addresses, local, length);
245        memcpy(&policy.addresses[length], remote, length);
246        length += length;
247
248        /* Also use the source address to filter policies. */
249        targets[1] = dupsaddr(src);
250    }
251
252    /* Fix lengths. */
253    length += sizeof(policy.q);
254    policy.q.sadb_x_ipsecrequest_len = length;
255    length += sizeof(policy.p);
256    policy.p.sadb_x_policy_len = PFKEY_UNIT64(length);
257
258    /* Always do a flush before adding the new policy. */
259    flush();
260    key = pfkey_open();
261    if (pfkey_send_spdadd(key, src, src_prefix, dst, dst_prefix, protocol,
262            (caddr_t)&policy, length, 0) <= 0) {
263        do_plog(LLV_ERROR, "Cannot initialize SAD and SPD\n");
264        exit(1);
265    }
266    pfkey_close(key);
267    atexit(flush);
268}
269
270/*****************************************************************************/
271
272static void add_proposal(struct remoteconf *remoteconf,
273        int auth, int hash, int encryption, int length)
274{
275    struct isakmpsa *p = racoon_calloc(1, sizeof(struct isakmpsa));
276    p->prop_no = 1;
277    p->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
278    p->enctype = encryption;
279    p->encklen = length;
280    p->authmethod = auth;
281    p->hashtype = hash;
282    p->dh_group = OAKLEY_ATTR_GRP_DESC_MODP1024;
283    p->vendorid = VENDORID_UNKNOWN;
284
285    if (!remoteconf->proposal) {
286      p->trns_no = 1;
287      remoteconf->proposal = p;
288    } else {
289        struct isakmpsa *q = remoteconf->proposal;
290        while (q->next) {
291            q = q->next;
292        }
293        p->trns_no = q->trns_no + 1;
294        q->next = p;
295    }
296}
297
298static vchar_t *get_certificate(char *type, char *file)
299{
300    char path[PATH_MAX + 1];
301    vchar_t *certificate = NULL;
302
303    getpathname(path, sizeof(path), LC_PATHTYPE_CERT, file);
304    certificate = eay_get_x509cert(path);
305    if (!certificate) {
306        do_plog(LLV_ERROR, "Cannot load %s certificate\n", type);
307        exit(1);
308    }
309    return certificate;
310}
311
312static void set_certificates(struct remoteconf *remoteconf,
313        char *user_private_key, char *user_certificate, char *ca_certificate)
314{
315    remoteconf->myprivfile = user_private_key;
316    remoteconf->mycertfile = user_certificate;
317    if (user_certificate) {
318        remoteconf->mycert = get_certificate("user", user_certificate);
319    }
320    if (!ca_certificate[0]) {
321        remoteconf->verify_cert = FALSE;
322    } else {
323        remoteconf->cacertfile = ca_certificate;
324        remoteconf->cacert = get_certificate("CA", ca_certificate);
325    }
326    remoteconf->idvtype = IDTYPE_ASN1DN;
327}
328
329static vchar_t *strtovchar(char *string)
330{
331    vchar_t *vchar = string ? vmalloc(strlen(string) + 1) : NULL;
332    if (vchar) {
333        memcpy(vchar->v, string, vchar->l);
334    }
335    return vchar;
336}
337
338#ifdef ENABLE_HYBRID
339
340static void set_xauth_and_more(struct remoteconf *remoteconf,
341        char *username, char *password, char *phase1_up, char *script_arg)
342{
343    struct xauth_rmconf *xauth = racoon_calloc(1, sizeof(struct xauth_rmconf));
344    xauth->login = strtovchar(username);
345    xauth->pass = strtovchar(password);
346    remoteconf->xauth = xauth;
347    remoteconf->mode_cfg = TRUE;
348    remoteconf->script[SCRIPT_PHASE1_UP] = strtovchar(phase1_up);
349    script_names[SCRIPT_PHASE1_UP] = script_arg;
350}
351
352#endif
353
354void setup(int argc, char **argv)
355{
356    struct remoteconf *remoteconf = NULL;
357    int auth;
358
359    if (argc > 2) {
360        set_globals(argv[1], argv[2]);
361
362        /* Initialize everything else. */
363        eay_init();
364        initrmconf();
365        oakley_dhinit();
366        compute_vendorids();
367        sched_init();
368        if (pfkey_init() < 0 || isakmp_init() < 0) {
369            exit(1);
370        }
371#ifdef ENABLE_NATT
372        natt_keepalive_init();
373#endif
374
375        /* Create remote configuration. */
376        remoteconf = newrmconf();
377        remoteconf->etypes = racoon_calloc(1, sizeof(struct etypes));
378        remoteconf->etypes->type = ISAKMP_ETYPE_IDENT;
379        remoteconf->ike_frag = TRUE;
380        remoteconf->pcheck_level = PROP_CHECK_OBEY;
381        remoteconf->gen_policy = TRUE;
382        remoteconf->nat_traversal = TRUE;
383        remoteconf->remote = dupsaddr(targets[0]);
384        set_port(remoteconf->remote, localconf.port_isakmp);
385    }
386
387    /* Set authentication method and credentials. */
388    if (argc == 6 && !strcmp(argv[3], "udppsk")) {
389        pre_shared_key = argv[4];
390        remoteconf->idvtype = IDTYPE_ADDRESS;
391        auth = OAKLEY_ATTR_AUTH_METHOD_PSKEY;
392
393        set_port(targets[0], atoi(argv[5]));
394        spdadd(sources[0].addr, targets[0], IPPROTO_UDP, NULL, NULL);
395    } else if (argc == 8 && !strcmp(argv[3], "udprsa")) {
396        set_certificates(remoteconf, argv[4], argv[5], argv[6]);
397        auth = OAKLEY_ATTR_AUTH_METHOD_RSASIG;
398
399        set_port(targets[0], atoi(argv[7]));
400        spdadd(sources[0].addr, targets[0], IPPROTO_UDP, NULL, NULL);
401#ifdef ENABLE_HYBRID
402    } else if (argc == 10 && !strcmp(argv[3], "xauthpsk")) {
403        pre_shared_key = argv[5];
404        remoteconf->idvtype = IDTYPE_ADDRESS;
405        if (*argv[4]) {
406            remoteconf->idv = strtovchar(argv[4]);
407            /* We might want to add some heuristics to detect the type? */
408            remoteconf->idvtype = IDTYPE_KEYID;
409        }
410        set_xauth_and_more(remoteconf, argv[6], argv[7], argv[8], argv[9]);
411        auth = OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I;
412    } else if (argc == 11 && !strcmp(argv[3], "xauthrsa")) {
413        set_certificates(remoteconf, argv[4], argv[5], argv[6]);
414        set_xauth_and_more(remoteconf, argv[7], argv[8], argv[9], argv[10]);
415        auth = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I;
416    } else if (argc == 9 && !strcmp(argv[3], "hybridrsa")) {
417        set_certificates(remoteconf, NULL, NULL, argv[4]);
418        set_xauth_and_more(remoteconf, argv[5], argv[6], argv[7], argv[8]);
419        auth = OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I;
420#endif
421    } else {
422        printf("Usage: %s <interface> <server> [...], where [...] can be:\n"
423                " udppsk    <pre-shared-key> <port>\n"
424                " udprsa    <user-private-key> <user-cert> <ca-cert> <port>\n"
425#ifdef ENABLE_HYBRID
426                " xauthpsk  <identifier> <pre-shared-key>"
427                        " <username> <password> <phase1-up> <script-arg>\n"
428                " xauthrsa  <user-private-key> <user-cert> <ca-cert>"
429                        " <username> <password> <phase1-up> <script-arg>\n"
430                " hybridrsa <ca-cert>"
431                        " <username> <password> <phase1-up> <script-arg>\n"
432#endif
433                "", argv[0]);
434        exit(0);
435    }
436
437    /* Add proposals. */
438    add_proposal(remoteconf, auth,
439            OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_3DES, 0);
440    add_proposal(remoteconf, auth,
441            OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_3DES, 0);
442    add_proposal(remoteconf, auth,
443            OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_DES, 0);
444    add_proposal(remoteconf, auth,
445            OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_DES, 0);
446    add_proposal(remoteconf, auth,
447            OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_AES, 128);
448    add_proposal(remoteconf, auth,
449            OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_AES, 128);
450
451    /* Install remote configuration. */
452    insrmconf(remoteconf);
453
454    /* Create ISAKMP sockets. */
455    set_port(sources[0].addr, localconf.port_isakmp);
456    sources[0].fd = isakmp_open(sources[0].addr, FALSE);
457    if (sources[0].fd == -1) {
458        do_plog(LLV_ERROR, "Cannot create ISAKMP socket\n");
459        exit(1);
460    }
461#ifdef ENABLE_NATT
462    set_port(sources[1].addr, localconf.port_isakmp_natt);
463    sources[1].fd = isakmp_open(sources[1].addr, TRUE);
464    if (sources[1].fd == -1) {
465        do_plog(LLV_WARNING, "Cannot create ISAKMP socket for NAT-T\n");
466    }
467#endif
468
469    /* Start phase 1 negotiation for xauth. */
470    if (remoteconf->xauth) {
471        isakmp_ph1begin_i(remoteconf, remoteconf->remote, sources[0].addr);
472    }
473}
474
475/*****************************************************************************/
476
477/* localconf.h */
478
479vchar_t *getpskbyaddr(struct sockaddr *addr)
480{
481    return strtovchar(pre_shared_key);
482}
483
484vchar_t *getpskbyname(vchar_t *name)
485{
486    return NULL;
487}
488
489void getpathname(char *path, int length, int type, const char *name)
490{
491    if (pname) {
492        snprintf(path, length, pname, name);
493    } else {
494        strncpy(path, name, length);
495    }
496    path[length - 1] = '\0';
497}
498
499/* grabmyaddr.h */
500
501int myaddr_getsport(struct sockaddr *addr)
502{
503    return 0;
504}
505
506int myaddr_getfd(struct sockaddr *addr)
507{
508#ifdef ENABLE_NATT
509    if (sources[1].fd != -1 &&
510            cmpsaddr(addr, sources[1].addr) == CMPSADDR_MATCH) {
511        return sources[1].fd;
512    }
513#endif
514    if (cmpsaddr(addr, sources[0].addr) < CMPSADDR_MISMATCH) {
515        return sources[0].fd;
516    }
517    return -1;
518}
519
520/* privsep.h */
521
522int privsep_socket(int domain, int type, int protocol)
523{
524    int fd = socket(domain, type, protocol);
525    if ((domain == AF_INET || domain == AF_INET6) && setsockopt(
526            fd, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface))) {
527        do_plog(LLV_WARNING, "Cannot bind socket to %s\n", interface);
528    }
529    return fd;
530}
531
532int privsep_bind(int fd, const struct sockaddr *addr, socklen_t addrlen)
533{
534    return bind(fd, addr, addrlen);
535}
536
537vchar_t *privsep_eay_get_pkcs1privkey(char *file)
538{
539    return eay_get_pkcs1privkey(file);
540}
541
542static char *get_env(char * const *envp, char *key)
543{
544    int length = strlen(key);
545    while (*envp && (strncmp(*envp, key, length) || (*envp)[length] != '=')) {
546        ++envp;
547    }
548    return *envp ? &(*envp)[length + 1] : "";
549}
550
551static int skip_script = 0;
552extern void android_setenv(char ***envp);
553
554int privsep_script_exec(char *script, int name, char * const *envp)
555{
556    if (skip_script) {
557        do_plog(LLV_WARNING,
558                "Phase 1 is up again. This time skip executing the script.\n");
559    } else {
560        /* Racoon ignores INTERNAL_IP6_ADDRESS, so we only do IPv4. */
561        struct sockaddr *addr4 = str2saddr(get_env(envp, "INTERNAL_ADDR4"),
562                NULL);
563        struct sockaddr *local = str2saddr(get_env(envp, "LOCAL_ADDR"),
564                get_env(envp, "LOCAL_PORT"));
565        struct sockaddr *remote = str2saddr(get_env(envp, "REMOTE_ADDR"),
566                get_env(envp, "REMOTE_PORT"));
567
568        if (addr4 && local && remote) {
569#ifdef ANDROID_CHANGES
570            android_setenv((char ***)&envp);
571#endif
572            spdadd(addr4, NULL, IPPROTO_IP, local, remote);
573        } else {
574            do_plog(LLV_ERROR, "Cannot get parameters for SPD policy.\n");
575            exit(1);
576        }
577
578        skip_script = 1;
579        racoon_free(addr4);
580        racoon_free(local);
581        racoon_free(remote);
582        return script_exec(script, name, envp);
583    }
584    return 0;
585}
586
587int privsep_accounting_system(int port, struct sockaddr *addr,
588        char *user, int status)
589{
590    return 0;
591}
592
593int privsep_xauth_login_system(char *user, char *password)
594{
595    return -1;
596}
597
598/* misc.h */
599
600int racoon_hexdump(void *data, size_t length)
601{
602    return 0;
603}
604
605void close_on_exec(int fd)
606{
607    fcntl(fd, F_SETFD, FD_CLOEXEC);
608}
609
610/* sainfo.h */
611
612struct sainfo *getsainfo(const vchar_t *src, const vchar_t *dst,
613        const vchar_t *peer, const vchar_t *client, uint32_t remoteid)
614{
615    return &sainfo;
616}
617
618const char *sainfo2str(const struct sainfo *si)
619{
620    return "*";
621}
622
623/* throttle.h */
624
625int throttle_host(struct sockaddr *addr, int fail)
626{
627    return 0;
628}
629