Home | History | Annotate | Download | only in ipsec-tools
      1 /*
      2  * Copyright (C) 2009 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 <sys/types.h>
     21 #include <sys/socket.h>
     22 #include <netinet/in.h>
     23 #include <netinet/ip.h>
     24 #include <netdb.h>
     25 
     26 #include "config.h"
     27 #include "libpfkey.h"
     28 #include "var.h"
     29 #include "isakmp_var.h"
     30 #include "isakmp.h"
     31 #include "vmbuf.h"
     32 #include "oakley.h"
     33 #include "ipsec_doi.h"
     34 #include "algorithm.h"
     35 #include "vendorid.h"
     36 #include "proposal.h"
     37 #include "sainfo.h"
     38 #include "localconf.h"
     39 #include "remoteconf.h"
     40 #include "sockmisc.h"
     41 #include "grabmyaddr.h"
     42 #include "plog.h"
     43 #include "admin.h"
     44 #include "privsep.h"
     45 
     46 static struct myaddrs myaddrs[2];
     47 static struct etypes main_mode = { .type = ISAKMP_ETYPE_IDENT };
     48 static struct localconf localconf;
     49 static struct remoteconf remoteconf;
     50 static struct sainfo sainfo;
     51 static char *pre_shared_key;
     52 
     53 struct localconf *lcconf = &localconf;
     54 char *script_names[SCRIPT_MAX + 1];
     55 
     56 static void set_default()
     57 {
     58     localconf.myaddrs = &myaddrs[0];
     59     localconf.port_isakmp = PORT_ISAKMP;
     60     localconf.port_isakmp_natt = PORT_ISAKMP_NATT;
     61     localconf.default_af = AF_INET;
     62     localconf.pad_random = LC_DEFAULT_PAD_RANDOM;
     63     localconf.pad_randomlen = LC_DEFAULT_PAD_RANDOM;
     64     localconf.pad_strict = LC_DEFAULT_PAD_STRICT;
     65     localconf.pad_excltail = LC_DEFAULT_PAD_EXCLTAIL;
     66     localconf.retry_counter = 10;
     67     localconf.retry_interval = 3;
     68     localconf.count_persend = LC_DEFAULT_COUNT_PERSEND;
     69     localconf.secret_size = LC_DEFAULT_SECRETSIZE;
     70     localconf.retry_checkph1 = LC_DEFAULT_RETRY_CHECKPH1;
     71     localconf.wait_ph2complete = LC_DEFAULT_WAIT_PH2COMPLETE;
     72     localconf.natt_ka_interval = LC_DEFAULT_NATT_KA_INTERVAL;
     73     localconf.pathinfo[LC_PATHTYPE_CERT] = "/";
     74 
     75     remoteconf.etypes = &main_mode;
     76     remoteconf.doitype = IPSEC_DOI;
     77     remoteconf.sittype = IPSECDOI_SIT_IDENTITY_ONLY;
     78     remoteconf.idvtype = IDTYPE_ADDRESS;
     79     remoteconf.nonce_size = DEFAULT_NONCE_SIZE;
     80 
     81     remoteconf.ike_frag = TRUE;
     82     remoteconf.esp_frag = IP_MAXPACKET;
     83     remoteconf.ini_contact = TRUE;
     84     remoteconf.pcheck_level = PROP_CHECK_OBEY;
     85     remoteconf.verify_identifier = FALSE;
     86     remoteconf.verify_cert = TRUE;
     87     remoteconf.getcert_method = ISAKMP_GETCERT_PAYLOAD;
     88     remoteconf.certtype = ISAKMP_CERT_X509SIGN;
     89     remoteconf.getcacert_method = ISAKMP_GETCERT_LOCALFILE;
     90     remoteconf.cacerttype = ISAKMP_CERT_X509SIGN;
     91     remoteconf.send_cert = TRUE;
     92     remoteconf.send_cr = TRUE;
     93     remoteconf.gen_policy = TRUE;
     94     remoteconf.retry_counter = LC_DEFAULT_RETRY_COUNTER;
     95     remoteconf.retry_interval = LC_DEFAULT_RETRY_INTERVAL;
     96     remoteconf.nat_traversal = TRUE;
     97     remoteconf.rsa_private = genlist_init();
     98     remoteconf.rsa_public = genlist_init();
     99     remoteconf.dpd = TRUE;
    100     remoteconf.dpd_interval = 0;
    101     remoteconf.dpd_retry = 5;
    102     remoteconf.dpd_maxfails = 5;
    103 
    104     sainfo.lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
    105     sainfo.lifebyte = IPSECDOI_ATTR_SA_LD_KB_MAX;
    106 }
    107 
    108 static void set_address(char *server, char *port)
    109 {
    110     struct addrinfo hints = {
    111         .ai_flags = AI_NUMERICSERV,
    112 #ifndef INET6
    113         .ai_family = AF_INET,
    114 #else
    115         .ai_family = AF_UNSPEC,
    116 #endif
    117         .ai_socktype = SOCK_DGRAM,
    118     };
    119     struct addrinfo *r;
    120 
    121     if (getaddrinfo(server, port, &hints, &r) != 0) {
    122         do_plog(LLV_ERROR, "Cannot resolve server address\n");
    123         exit(1);
    124     }
    125     if (r->ai_next) {
    126         do_plog(LLV_WARNING, "Multiple server address found\n");
    127     }
    128     remoteconf.remote = dupsaddr(r->ai_addr);
    129     freeaddrinfo(r);
    130 
    131     myaddrs[0].addr = getlocaladdr(remoteconf.remote);
    132     if (!myaddrs[0].addr) {
    133         do_plog(LLV_ERROR, "Cannot get local address\n");
    134         exit(1);
    135     }
    136 }
    137 
    138 static void add_proposal(int auth, int hash, int encryption, int length)
    139 {
    140     struct isakmpsa *p = calloc(1, sizeof(struct isakmpsa));
    141     p->prop_no = 1;
    142     p->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
    143     p->enctype = encryption;
    144     p->encklen = length;
    145     p->authmethod = auth;
    146     p->hashtype = hash;
    147     p->dh_group = OAKLEY_ATTR_GRP_DESC_MODP1024;
    148     p->vendorid = VENDORID_UNKNOWN;
    149     p->rmconf = &remoteconf;
    150 
    151     if (!remoteconf.proposal) {
    152       p->trns_no = 1;
    153       remoteconf.proposal = p;
    154     } else {
    155         struct isakmpsa *q = remoteconf.proposal;
    156         while (q->next) {
    157             q = q->next;
    158         }
    159         p->trns_no = q->trns_no + 1;
    160         q->next = p;
    161     }
    162 }
    163 
    164 static void add_sainfo_algorithm(int class, int algorithm, int length)
    165 {
    166     struct sainfoalg *p = calloc(1, sizeof(struct sainfoalg));
    167     p->alg = algorithm;
    168     p->encklen = length;
    169 
    170     if (!sainfo.algs[class]) {
    171         sainfo.algs[class] = p;
    172     } else {
    173         struct sainfoalg *q = sainfo.algs[class];
    174         while (q->next) {
    175             q = q->next;
    176         }
    177         q->next = p;
    178     }
    179 }
    180 
    181 /* flush; spdflush; */
    182 static void flush()
    183 {
    184     int key = pfkey_open();
    185     if (key != -1) {
    186         pfkey_send_flush(key, SADB_SATYPE_UNSPEC);
    187         pfkey_send_spdflush(key);
    188         pfkey_close(key);
    189     }
    190 }
    191 
    192 /* flush; spdflush;
    193  * spdadd local remote udp -P out ipsec esp/transport//require; */
    194 static void spdadd(struct sockaddr *local, struct sockaddr *remote)
    195 {
    196     struct __attribute__((packed)) {
    197         struct sadb_x_policy p;
    198         struct sadb_x_ipsecrequest q;
    199     } policy;
    200     int mask = (local->sa_family == AF_INET) ? sizeof(struct in_addr) * 8 :
    201                sizeof(struct in6_addr) * 8;
    202     int key = pfkey_open();
    203     if (key == -1) {
    204         do_plog(LLV_ERROR, "Cannot create KEY socket\n");
    205         exit(1);
    206     }
    207 
    208     memset(&policy, 0, sizeof(policy));
    209     policy.p.sadb_x_policy_len = PFKEY_UNIT64(sizeof(policy));
    210     policy.p.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
    211     policy.p.sadb_x_policy_type = IPSEC_POLICY_IPSEC;
    212     policy.p.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
    213 #ifdef HAVE_PFKEY_POLICY_PRIORITY
    214     policy.p.sadb_x_policy_priority = PRIORITY_DEFAULT;
    215 #endif
    216     policy.q.sadb_x_ipsecrequest_len = sizeof(struct sadb_x_ipsecrequest);
    217     policy.q.sadb_x_ipsecrequest_proto = IPPROTO_ESP;
    218     policy.q.sadb_x_ipsecrequest_mode = IPSEC_MODE_TRANSPORT;
    219     policy.q.sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE;
    220 
    221     if (pfkey_send_flush(key, SADB_SATYPE_UNSPEC) <= 0 ||
    222         pfkey_send_spdflush(key) <= 0 ||
    223         pfkey_send_spdadd(key, local, mask, remote, mask, IPPROTO_UDP,
    224                           (caddr_t)&policy, sizeof(policy), 0) <= 0) {
    225         do_plog(LLV_ERROR, "Cannot initialize SA and SPD\n");
    226         exit(1);
    227     }
    228     pfkey_close(key);
    229     atexit(flush);
    230 }
    231 
    232 void setup(int argc, char **argv)
    233 {
    234     int auth;
    235     if (argc != 4 && argc != 6) {
    236         printf("Usage: %s server port pre-shared-key\n"
    237                "       %s server port my-private-key my-cert ca-cert\n",
    238                argv[0], argv[0]);
    239         exit(0);
    240     }
    241     set_default();
    242 
    243     /* Set local address and remote address. */
    244     set_address(argv[1], argv[2]);
    245 
    246     /* Initialize SA and SPD. */
    247     spdadd(myaddrs[0].addr, remoteconf.remote);
    248 
    249     /* Set local port and remote port. */
    250     set_port(myaddrs[0].addr, localconf.port_isakmp);
    251     set_port(remoteconf.remote, localconf.port_isakmp);
    252 #ifdef ENABLE_NATT
    253     myaddrs[0].next = &myaddrs[1];
    254     myaddrs[1].addr = dupsaddr(myaddrs[0].addr);
    255     set_port(myaddrs[1].addr, localconf.port_isakmp_natt);
    256     myaddrs[1].udp_encap = 1;
    257 #endif
    258 
    259     /* Set authentication method. */
    260     if (argc == 4) {
    261         pre_shared_key = argv[3];
    262         auth = OAKLEY_ATTR_AUTH_METHOD_PSKEY;
    263     } else {
    264         remoteconf.idvtype = IDTYPE_ASN1DN;
    265         remoteconf.myprivfile = argv[3];
    266         remoteconf.mycertfile = argv[4];
    267         remoteconf.cacertfile = argv[5];
    268         auth = OAKLEY_ATTR_AUTH_METHOD_RSASIG;
    269     }
    270 
    271     /* Create proposals. */
    272     add_proposal(auth, OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_3DES, 0);
    273     add_proposal(auth, OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_3DES, 0);
    274     add_proposal(auth, OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_DES, 0);
    275     add_proposal(auth, OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_DES, 0);
    276     add_proposal(auth, OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_AES, 128);
    277     add_proposal(auth, OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_AES, 128);
    278 
    279     /* Create sainfo algorithms. */
    280     add_sainfo_algorithm(algclass_ipsec_auth, IPSECDOI_ATTR_AUTH_HMAC_SHA1, 0);
    281     add_sainfo_algorithm(algclass_ipsec_auth, IPSECDOI_ATTR_AUTH_HMAC_MD5, 0);
    282     add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_3DES, 0);
    283     add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_DES, 0);
    284     add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_AES, 128);
    285 }
    286 
    287 /* localconf.h */
    288 
    289 vchar_t *getpskbyaddr(struct sockaddr *addr)
    290 {
    291     return privsep_getpsk(pre_shared_key, strlen(pre_shared_key));
    292 }
    293 
    294 vchar_t *getpskbyname(vchar_t *name)
    295 {
    296     return NULL;
    297 }
    298 
    299 void getpathname(char *path, int length, int type, const char *name)
    300 {
    301     strncpy(path, name, length);
    302 }
    303 
    304 /* remoteconf.h */
    305 
    306 struct remoteconf *getrmconf(struct sockaddr *addr)
    307 {
    308     return cmpsaddrwop(addr, remoteconf.remote) ? NULL : &remoteconf;
    309 }
    310 
    311 struct isakmpsa *dupisakmpsa(struct isakmpsa *sa)
    312 {
    313     struct isakmpsa *p = NULL;
    314     if (sa && (p = malloc(sizeof(struct isakmpsa)))) {
    315         *p = *sa;
    316         p->next = NULL;
    317         if (sa->dhgrp) {
    318             oakley_setdhgroup(sa->dh_group, &p->dhgrp);
    319         }
    320     }
    321     return p;
    322 }
    323 
    324 void delisakmpsa(struct isakmpsa *sa)
    325 {
    326     while (sa) {
    327         struct isakmpsa *p = sa->next;
    328         if (sa->dhgrp) {
    329             oakley_dhgrp_free(sa->dhgrp);
    330         }
    331         free(sa);
    332         sa = p;
    333     }
    334 }
    335 
    336 struct etypes *check_etypeok(struct remoteconf *rmconf, uint8_t etype)
    337 {
    338     struct etypes *p = rmconf->etypes;
    339     while (p && etype != p->type) {
    340         p = p->next;
    341     }
    342     return p;
    343 }
    344 
    345 struct remoteconf *foreachrmconf(rmconf_func_t function, void *data)
    346 {
    347     return (*function)(&remoteconf, data);
    348 }
    349 
    350 /* sainfo.h */
    351 
    352 struct sainfo *getsainfo(const vchar_t *src, const vchar_t *dst,
    353                          const vchar_t *peer, int remoteid)
    354 {
    355     return &sainfo;
    356 }
    357 
    358 const char *sainfo2str(const struct sainfo *si)
    359 {
    360     return "*";
    361 }
    362