setup.c revision 03177458c167f55b5289d738aae210a64b87e92d
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 "vmbuf.h"
36#include "crypto_openssl.h"
37#include "oakley.h"
38#include "ipsec_doi.h"
39#include "algorithm.h"
40#include "vendorid.h"
41#include "schedule.h"
42#include "pfkey.h"
43#include "nattraversal.h"
44#include "proposal.h"
45#include "sainfo.h"
46#include "localconf.h"
47#include "remoteconf.h"
48#include "sockmisc.h"
49#include "grabmyaddr.h"
50#include "plog.h"
51#include "admin.h"
52#include "privsep.h"
53#include "throttle.h"
54#include "misc.h"
55
56static struct localconf localconf;
57static struct sainfo sainfo;
58static char *pre_shared_key;
59
60static char *interface;
61static struct sockaddr *target;
62static struct {
63    struct sockaddr *addr;
64    int fd;
65} myaddrs[2];
66
67struct localconf *lcconf = &localconf;
68char *script_names[SCRIPT_MAX + 1];
69int f_local = 0;
70
71/*****************************************************************************/
72
73static void add_sainfo_algorithm(int class, int algorithm, int length)
74{
75    struct sainfoalg *p = calloc(1, sizeof(struct sainfoalg));
76    p->alg = algorithm;
77    p->encklen = length;
78
79    if (!sainfo.algs[class]) {
80        sainfo.algs[class] = p;
81    } else {
82        struct sainfoalg *q = sainfo.algs[class];
83        while (q->next) {
84            q = q->next;
85        }
86        q->next = p;
87    }
88}
89
90static void set_globals(char *interfaze, char *server)
91{
92    struct addrinfo hints = {
93        .ai_flags = AI_NUMERICSERV,
94#ifndef INET6
95        .ai_family = AF_INET,
96#else
97        .ai_family = AF_UNSPEC,
98#endif
99        .ai_socktype = SOCK_DGRAM,
100    };
101    struct addrinfo *info;
102
103    if (getaddrinfo(server, "80", &hints, &info) != 0) {
104        do_plog(LLV_ERROR, "Cannot resolve address: %s\n", server);
105        exit(1);
106    }
107    if (info->ai_next) {
108        do_plog(LLV_WARNING, "Found multiple addresses. Use the first one.\n");
109    }
110    target = dupsaddr(info->ai_addr);
111    freeaddrinfo(info);
112
113    interface = interfaze;
114    myaddrs[0].addr = getlocaladdr(target);
115    if (!myaddrs[0].addr) {
116        do_plog(LLV_ERROR, "Cannot get local address\n");
117        exit(1);
118    }
119    set_port(target, 0);
120    set_port(myaddrs[0].addr, 0);
121    myaddrs[0].fd = -1;
122    myaddrs[1].addr = dupsaddr(myaddrs[0].addr);
123    myaddrs[1].fd = -1;
124
125    localconf.port_isakmp = PORT_ISAKMP;
126    localconf.port_isakmp_natt = PORT_ISAKMP_NATT;
127    localconf.default_af = AF_INET;
128    localconf.pathinfo[LC_PATHTYPE_CERT] = "./";
129    localconf.pad_random = LC_DEFAULT_PAD_RANDOM;
130    localconf.pad_randomlen = LC_DEFAULT_PAD_RANDOM;
131    localconf.pad_strict = LC_DEFAULT_PAD_STRICT;
132    localconf.pad_excltail = LC_DEFAULT_PAD_EXCLTAIL;
133    localconf.retry_counter = 10;
134    localconf.retry_interval = 3;
135    localconf.count_persend = LC_DEFAULT_COUNT_PERSEND;
136    localconf.secret_size = LC_DEFAULT_SECRETSIZE;
137    localconf.retry_checkph1 = LC_DEFAULT_RETRY_CHECKPH1;
138    localconf.wait_ph2complete = LC_DEFAULT_WAIT_PH2COMPLETE;
139    localconf.natt_ka_interval = LC_DEFAULT_NATT_KA_INTERVAL;
140
141    sainfo.lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
142    sainfo.lifebyte = IPSECDOI_ATTR_SA_LD_KB_MAX;
143    add_sainfo_algorithm(algclass_ipsec_auth, IPSECDOI_ATTR_AUTH_HMAC_SHA1, 0);
144    add_sainfo_algorithm(algclass_ipsec_auth, IPSECDOI_ATTR_AUTH_HMAC_MD5, 0);
145    add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_3DES, 0);
146    add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_DES, 0);
147    add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_AES, 128);
148}
149
150/*****************************************************************************/
151
152static int policy_match(struct sadb_address *address)
153{
154    if (address) {
155        return cmpsaddr(PFKEY_ADDR_SADDR(address), target) < CMPSADDR_MISMATCH;
156    }
157    return 0;
158}
159
160/* flush; spdflush; */
161static void flush()
162{
163    struct sadb_msg *p;
164    int replies = 0;
165    int key = pfkey_open();
166
167    if (pfkey_send_dump(key, SADB_SATYPE_UNSPEC) <= 0 ||
168        pfkey_send_spddump(key) <= 0) {
169        do_plog(LLV_ERROR, "Cannot dump SAD and SPD");
170        exit(1);
171    }
172
173    for (p = NULL; replies < 2 && (p = pfkey_recv(key)) != NULL; free(p)) {
174        caddr_t q[SADB_EXT_MAX + 1];
175
176        if (p->sadb_msg_type != SADB_DUMP &&
177            p->sadb_msg_type != SADB_X_SPDDUMP) {
178            continue;
179        }
180        replies += !p->sadb_msg_seq;
181
182        if (p->sadb_msg_errno || pfkey_align(p, q) || pfkey_check(q)) {
183            continue;
184        }
185        if (policy_match((struct sadb_address *)q[SADB_EXT_ADDRESS_SRC]) ||
186            policy_match((struct sadb_address *)q[SADB_EXT_ADDRESS_DST])) {
187            p->sadb_msg_type = (p->sadb_msg_type == SADB_DUMP) ?
188                               SADB_DELETE : SADB_X_SPDDELETE;
189            p->sadb_msg_reserved = 0;
190            p->sadb_msg_seq = 0;
191            pfkey_send(key, p, PFKEY_UNUNIT64(p->sadb_msg_len));
192        }
193    }
194
195    pfkey_close(key);
196}
197
198/* flush; spdflush;
199 * spdadd src dst protocol -P out ipsec esp/transport//require; OR
200 * spdadd src any protocol -P out ipsec esp/tunnel/local-remote/require; */
201static void spdadd(struct sockaddr *src, struct sockaddr *dst,
202        int protocol, struct sockaddr *local, struct sockaddr *remote)
203{
204    struct __attribute__((packed)) {
205        struct sadb_x_policy p;
206        struct sadb_x_ipsecrequest q;
207        char addresses[sizeof(struct sockaddr_storage) * 2];
208    } policy;
209
210    struct sockaddr_storage any = {
211#ifndef __linux__
212        .ss_len = src->sa_len,
213#endif
214        .ss_family = src->sa_family,
215    };
216
217    int src_prefix = (src->sa_family == AF_INET) ? 32 : 128;
218    int dst_prefix = src_prefix;
219    int length = 0;
220    int key;
221
222    /* Fill default values. */
223    memset(&policy, 0, sizeof(policy));
224    policy.p.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
225    policy.p.sadb_x_policy_type = IPSEC_POLICY_IPSEC;
226    policy.p.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
227#ifdef HAVE_PFKEY_POLICY_PRIORITY
228    policy.p.sadb_x_policy_priority = PRIORITY_DEFAULT;
229#endif
230    policy.q.sadb_x_ipsecrequest_proto = IPPROTO_ESP;
231    policy.q.sadb_x_ipsecrequest_mode = IPSEC_MODE_TRANSPORT;
232    policy.q.sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE;
233
234    /* Deal with tunnel mode. */
235    if (!dst) {
236        policy.q.sadb_x_ipsecrequest_mode = IPSEC_MODE_TUNNEL;
237        dst = (struct sockaddr *)&any;
238        dst_prefix = 0;
239
240        length = sysdep_sa_len(local);
241        memcpy(policy.addresses, local, length);
242        memcpy(&policy.addresses[length], remote, length);
243        length += length;
244
245        /* Use the source address to flush policies. */
246        racoon_free(target);
247        target = dupsaddr(src);
248    }
249
250    /* Fix lengths. */
251    length += sizeof(policy.q);
252    policy.q.sadb_x_ipsecrequest_len = length;
253    length += sizeof(policy.p);
254    policy.p.sadb_x_policy_len = PFKEY_UNIT64(length);
255
256    /* Always do a flush before adding the new policy. */
257    flush();
258    key = pfkey_open();
259    if (pfkey_send_spdadd(key, src, src_prefix, dst, dst_prefix, protocol,
260            (caddr_t)&policy, length, 0) <= 0) {
261        do_plog(LLV_ERROR, "Cannot initialize SAD and SPD\n");
262        exit(1);
263    }
264    pfkey_close(key);
265    atexit(flush);
266}
267
268/*****************************************************************************/
269
270static void add_proposal(struct remoteconf *remoteconf,
271        int auth, int hash, int encryption, int length)
272{
273    struct isakmpsa *p = racoon_calloc(1, sizeof(struct isakmpsa));
274    p->prop_no = 1;
275    p->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
276    p->enctype = encryption;
277    p->encklen = length;
278    p->authmethod = auth;
279    p->hashtype = hash;
280    p->dh_group = OAKLEY_ATTR_GRP_DESC_MODP1024;
281    p->vendorid = VENDORID_UNKNOWN;
282
283    if (!remoteconf->proposal) {
284      p->trns_no = 1;
285      remoteconf->proposal = p;
286    } else {
287        struct isakmpsa *q = remoteconf->proposal;
288        while (q->next) {
289            q = q->next;
290        }
291        p->trns_no = q->trns_no + 1;
292        q->next = p;
293    }
294}
295
296void setup(int argc, char **argv)
297{
298    struct remoteconf *remoteconf;
299    int auth;
300
301    if (argc > 2) {
302        set_globals(argv[1], argv[2]);
303
304        /* Initialize everything else. */
305        eay_init();
306        initrmconf();
307        oakley_dhinit();
308        compute_vendorids();
309        sched_init();
310        if (pfkey_init() < 0 || isakmp_init() < 0) {
311            exit(1);
312        }
313#ifdef ENABLE_NATT
314        natt_keepalive_init();
315#endif
316
317        /* Create remote configuration. */
318        remoteconf = newrmconf();
319        remoteconf->etypes = racoon_calloc(1, sizeof(struct etypes));
320        remoteconf->etypes->type = ISAKMP_ETYPE_IDENT;
321        remoteconf->ike_frag = TRUE;
322        remoteconf->pcheck_level = PROP_CHECK_OBEY;
323        remoteconf->gen_policy = TRUE;
324        remoteconf->nat_traversal = TRUE;
325        remoteconf->remote = dupsaddr(target);
326        set_port(remoteconf->remote, localconf.port_isakmp);
327    }
328
329    /* Set authentication method and credentials. */
330    if (argc == 6 && !strcmp(argv[3], "udppsk")) {
331        set_port(target, atoi(argv[4]));
332        spdadd(myaddrs[0].addr, target, IPPROTO_UDP, NULL, NULL);
333        pre_shared_key = argv[5];
334        remoteconf->idvtype = IDTYPE_ADDRESS;
335        auth = OAKLEY_ATTR_AUTH_METHOD_PSKEY;
336    } else if (argc == 8 && !strcmp(argv[3], "udprsa")) {
337        char path[PATH_MAX + 1];
338        set_port(target, atoi(argv[4]));
339        spdadd(myaddrs[0].addr, target, IPPROTO_UDP, NULL, NULL);
340        remoteconf->myprivfile = argv[5];
341        remoteconf->mycertfile = argv[6];
342        getpathname(path, sizeof(path), LC_PATHTYPE_CERT, argv[6]);
343        remoteconf->mycert = eay_get_x509cert(path);
344        if (!remoteconf->mycert) {
345            do_plog(LLV_ERROR, "Cannot load user certificate\n");
346            exit(1);
347        }
348        if (!*argv[7]) {
349            remoteconf->verify_cert = FALSE;
350        } else {
351            remoteconf->cacertfile = argv[7];
352            getpathname(path, sizeof(path), LC_PATHTYPE_CERT, argv[7]);
353            remoteconf->cacert = eay_get_x509cert(path);
354            if (!remoteconf->cacert) {
355                do_plog(LLV_ERROR, "Cannot load CA certificate\n");
356                exit(1);
357            }
358        }
359        remoteconf->idvtype = IDTYPE_ASN1DN;
360        auth = OAKLEY_ATTR_AUTH_METHOD_RSASIG;
361    } else {
362        printf("Usage: %s <interface> <server> [...],\n"
363               "    where [...] can be:\n"
364               "    udppsk <port> <pre-shared-key>\n"
365               "    udprsa <port> <user-private-key> <user-cert> <ca-cert>\n",
366               argv[0]);
367        exit(0);
368    }
369
370    /* Add proposals. */
371    add_proposal(remoteconf, auth,
372            OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_3DES, 0);
373    add_proposal(remoteconf, auth,
374            OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_3DES, 0);
375    add_proposal(remoteconf, auth,
376            OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_DES, 0);
377    add_proposal(remoteconf, auth,
378            OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_DES, 0);
379    add_proposal(remoteconf, auth,
380            OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_AES, 128);
381    add_proposal(remoteconf, auth,
382            OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_AES, 128);
383
384    /* Install remote configuration. */
385    insrmconf(remoteconf);
386
387    /* Create ISAKMP sockets. */
388    set_port(myaddrs[0].addr, localconf.port_isakmp);
389    myaddrs[0].fd = isakmp_open(myaddrs[0].addr, FALSE);
390    if (myaddrs[0].fd == -1) {
391        do_plog(LLV_ERROR, "Cannot create ISAKMP socket");
392        exit(1);
393    }
394#ifdef ENABLE_NATT
395    set_port(myaddrs[1].addr, localconf.port_isakmp_natt);
396    myaddrs[1].fd = isakmp_open(myaddrs[1].addr, TRUE);
397    if (myaddrs[1].fd == -1) {
398        do_plog(LLV_WARNING, "Cannot create ISAKMP socket for NAT-T");
399    }
400#endif
401}
402
403/*****************************************************************************/
404
405/* localconf.h */
406
407vchar_t *getpskbyaddr(struct sockaddr *addr)
408{
409    vchar_t *p = NULL;
410    if (pre_shared_key && (p = vmalloc(strlen(pre_shared_key)))) {
411        memcpy(p->v, pre_shared_key, p->l);
412    }
413    return p;
414}
415
416vchar_t *getpskbyname(vchar_t *name)
417{
418    return NULL;
419}
420
421void getpathname(char *path, int length, int type, const char *name)
422{
423    if (pname) {
424        snprintf(path, length, pname, name);
425    } else {
426        strncpy(path, name, length);
427    }
428    path[length - 1] = '\0';
429}
430
431/* grabmyaddr.h */
432
433int myaddr_getsport(struct sockaddr *addr)
434{
435    return 0;
436}
437
438int myaddr_getfd(struct sockaddr *addr)
439{
440#ifdef ENABLE_NATT
441    if (myaddrs[1].fd != -1 &&
442            cmpsaddr(addr, myaddrs[1].addr) == CMPSADDR_MATCH) {
443        return myaddrs[1].fd;
444    }
445#endif
446    if (cmpsaddr(addr, myaddrs[0].addr) < CMPSADDR_MISMATCH) {
447        return myaddrs[0].fd;
448    }
449    return -1;
450}
451
452/* misc.h */
453
454int racoon_hexdump(void *data, size_t length)
455{
456    return 0;
457}
458
459void close_on_exec(int fd)
460{
461    fcntl(fd, F_SETFD, FD_CLOEXEC);
462}
463
464/* sainfo.h */
465
466struct sainfo *getsainfo(const vchar_t *src, const vchar_t *dst,
467        const vchar_t *peer, const vchar_t *client, uint32_t remoteid)
468{
469    return &sainfo;
470}
471
472const char *sainfo2str(const struct sainfo *si)
473{
474    return "*";
475}
476
477/* privsep.h */
478
479int privsep_socket(int domain, int type, int protocol)
480{
481    int fd = socket(domain, type, protocol);
482    if ((domain == AF_INET || domain == AF_INET6) && setsockopt(
483            fd, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface))) {
484        do_plog(LLV_WARNING, "Cannot bind socket to %s", interface);
485    }
486    return fd;
487}
488
489int privsep_bind(int fd, const struct sockaddr *addr, socklen_t addrlen)
490{
491    return bind(fd, addr, addrlen);
492}
493
494vchar_t *privsep_eay_get_pkcs1privkey(char *file)
495{
496    return eay_get_pkcs1privkey(file);
497}
498
499int privsep_script_exec(char *script, int name, char * const *environ)
500{
501    return 0;
502}
503
504int privsep_accounting_system(int port, struct sockaddr *addr,
505        char *user, int status)
506{
507    return 0;
508}
509
510int privsep_xauth_login_system(char *user, char *password)
511{
512    return -1;
513}
514
515/* throttle.h */
516
517int throttle_host(struct sockaddr *addr, int fail)
518{
519    return 0;
520}
521