Home | History | Annotate | Download | only in ipsec-tools
      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 
     57 static struct localconf localconf;
     58 static struct sainfo sainfo;
     59 static char *pre_shared_key;
     60 
     61 static struct sockaddr *targets[2];
     62 static struct sockaddr *source;
     63 static struct myaddrs myaddrs[2];
     64 
     65 struct localconf *lcconf = &localconf;
     66 int f_local = 0;
     67 
     68 /*****************************************************************************/
     69 
     70 static void add_sainfo_algorithm(int class, int algorithm, int length)
     71 {
     72     struct sainfoalg *p = calloc(1, sizeof(struct sainfoalg));
     73     p->alg = algorithm;
     74     p->encklen = length;
     75 
     76     if (!sainfo.algs[class]) {
     77         sainfo.algs[class] = p;
     78     } else {
     79         struct sainfoalg *q = sainfo.algs[class];
     80         while (q->next) {
     81             q = q->next;
     82         }
     83         q->next = p;
     84     }
     85 }
     86 
     87 static void set_globals(char *server)
     88 {
     89     struct addrinfo hints = {
     90         .ai_flags = AI_NUMERICSERV,
     91 #ifndef INET6
     92         .ai_family = AF_INET,
     93 #else
     94         .ai_family = AF_UNSPEC,
     95 #endif
     96         .ai_socktype = SOCK_DGRAM,
     97     };
     98     struct addrinfo *info;
     99 
    100     if (getaddrinfo(server, "500", &hints, &info) != 0) {
    101         do_plog(LLV_ERROR, "Cannot resolve address: %s\n", server);
    102         exit(1);
    103     }
    104     if (info->ai_next) {
    105         do_plog(LLV_WARNING, "Found multiple addresses. Use the first one.\n");
    106     }
    107     targets[0] = dupsaddr(info->ai_addr);
    108     freeaddrinfo(info);
    109 
    110     source = getlocaladdr(targets[0]);
    111     if (!source) {
    112         do_plog(LLV_ERROR, "Cannot get local address\n");
    113         exit(1);
    114     }
    115     set_port(targets[0], 0);
    116     set_port(source, 0);
    117 
    118     myaddrs[0].addr = dupsaddr(source);
    119     set_port(myaddrs[0].addr, PORT_ISAKMP);
    120     myaddrs[0].sock = -1;
    121 #ifdef ENABLE_NATT
    122     myaddrs[0].next = &myaddrs[1];
    123     myaddrs[1].addr = dupsaddr(myaddrs[0].addr);
    124     set_port(myaddrs[1].addr, PORT_ISAKMP_NATT);
    125     myaddrs[1].sock = -1;
    126     myaddrs[1].udp_encap = 1;
    127 #endif
    128 
    129     localconf.myaddrs = &myaddrs[0];
    130     localconf.port_isakmp = PORT_ISAKMP;
    131     localconf.port_isakmp_natt = PORT_ISAKMP_NATT;
    132     localconf.default_af = AF_INET;
    133     localconf.pathinfo[LC_PATHTYPE_CERT] = "./";
    134     localconf.pad_random = LC_DEFAULT_PAD_RANDOM;
    135     localconf.pad_randomlen = LC_DEFAULT_PAD_RANDOM;
    136     localconf.pad_strict = LC_DEFAULT_PAD_STRICT;
    137     localconf.pad_excltail = LC_DEFAULT_PAD_EXCLTAIL;
    138     localconf.retry_counter = 10;
    139     localconf.retry_interval = 3;
    140     localconf.count_persend = LC_DEFAULT_COUNT_PERSEND;
    141     localconf.secret_size = LC_DEFAULT_SECRETSIZE;
    142     localconf.retry_checkph1 = LC_DEFAULT_RETRY_CHECKPH1;
    143     localconf.wait_ph2complete = LC_DEFAULT_WAIT_PH2COMPLETE;
    144     localconf.natt_ka_interval = LC_DEFAULT_NATT_KA_INTERVAL;
    145 
    146     sainfo.lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
    147     sainfo.lifebyte = IPSECDOI_ATTR_SA_LD_KB_MAX;
    148     add_sainfo_algorithm(algclass_ipsec_auth, IPSECDOI_ATTR_AUTH_HMAC_SHA1, 0);
    149     add_sainfo_algorithm(algclass_ipsec_auth, IPSECDOI_ATTR_AUTH_HMAC_MD5, 0);
    150     add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_AES, 256);
    151     add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_AES, 128);
    152     add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_3DES, 0);
    153     add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_DES, 0);
    154 
    155     memset(script_names, 0, sizeof(script_names));
    156 }
    157 
    158 /*****************************************************************************/
    159 
    160 static int policy_match(struct sadb_address *address)
    161 {
    162     if (address) {
    163         struct sockaddr *addr = PFKEY_ADDR_SADDR(address);
    164         return !cmpsaddrwop(addr, targets[0]) || !cmpsaddrwop(addr, targets[1]);
    165     }
    166     return 0;
    167 }
    168 
    169 /* flush; spdflush; */
    170 static void flush()
    171 {
    172     struct sadb_msg *p;
    173     int replies = 0;
    174     int key = pfkey_open();
    175 
    176     if (pfkey_send_dump(key, SADB_SATYPE_UNSPEC) <= 0 ||
    177         pfkey_send_spddump(key) <= 0) {
    178         do_plog(LLV_ERROR, "Cannot dump SAD and SPD\n");
    179         exit(1);
    180     }
    181 
    182     for (p = NULL; replies < 2 && (p = pfkey_recv(key)) != NULL; free(p)) {
    183         caddr_t q[SADB_EXT_MAX + 1];
    184 
    185         if (p->sadb_msg_type != SADB_DUMP &&
    186             p->sadb_msg_type != SADB_X_SPDDUMP) {
    187             continue;
    188         }
    189         replies += !p->sadb_msg_seq;
    190 
    191         if (p->sadb_msg_errno || pfkey_align(p, q) || pfkey_check(q)) {
    192             continue;
    193         }
    194         if (policy_match((struct sadb_address *)q[SADB_EXT_ADDRESS_SRC]) ||
    195             policy_match((struct sadb_address *)q[SADB_EXT_ADDRESS_DST])) {
    196             p->sadb_msg_type = (p->sadb_msg_type == SADB_DUMP) ?
    197                                SADB_DELETE : SADB_X_SPDDELETE;
    198             p->sadb_msg_reserved = 0;
    199             p->sadb_msg_seq = 0;
    200             pfkey_send(key, p, PFKEY_UNUNIT64(p->sadb_msg_len));
    201         }
    202     }
    203 
    204     pfkey_close(key);
    205 }
    206 
    207 /* spdadd src dst protocol -P out ipsec esp/transport//require;
    208  * spdadd dst src protocol -P in  ipsec esp/transport//require;
    209  * or
    210  * spdadd src any protocol -P out ipsec esp/tunnel/local-remote/require;
    211  * spdadd any src protocol -P in  ipsec esp/tunnel/remote-local/require; */
    212 static void spdadd(struct sockaddr *src, struct sockaddr *dst,
    213         int protocol, struct sockaddr *local, struct sockaddr *remote)
    214 {
    215     struct __attribute__((packed)) {
    216         struct sadb_x_policy p;
    217         struct sadb_x_ipsecrequest q;
    218         char addresses[sizeof(struct sockaddr_storage) * 2];
    219     } policy;
    220 
    221     struct sockaddr_storage any = {
    222 #ifndef __linux__
    223         .ss_len = src->sa_len,
    224 #endif
    225         .ss_family = src->sa_family,
    226     };
    227 
    228     int src_prefix = (src->sa_family == AF_INET) ? 32 : 128;
    229     int dst_prefix = src_prefix;
    230     int length = 0;
    231     int key;
    232 
    233     /* Fill values for outbound policy. */
    234     memset(&policy, 0, sizeof(policy));
    235     policy.p.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
    236     policy.p.sadb_x_policy_type = IPSEC_POLICY_IPSEC;
    237     policy.p.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
    238 #ifdef HAVE_PFKEY_POLICY_PRIORITY
    239     policy.p.sadb_x_policy_priority = PRIORITY_DEFAULT;
    240 #endif
    241     policy.q.sadb_x_ipsecrequest_proto = IPPROTO_ESP;
    242     policy.q.sadb_x_ipsecrequest_mode = IPSEC_MODE_TRANSPORT;
    243     policy.q.sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE;
    244 
    245     /* Deal with tunnel mode. */
    246     if (!dst) {
    247         int size = sysdep_sa_len(local);
    248         memcpy(policy.addresses, local, size);
    249         memcpy(&policy.addresses[size], remote, size);
    250         length += size + size;
    251 
    252         policy.q.sadb_x_ipsecrequest_mode = IPSEC_MODE_TUNNEL;
    253         dst = (struct sockaddr *)&any;
    254         dst_prefix = 0;
    255 
    256         /* Also use the source address to filter policies. */
    257         targets[1] = dupsaddr(src);
    258     }
    259 
    260     /* Fix lengths. */
    261     length += sizeof(policy.q);
    262     policy.q.sadb_x_ipsecrequest_len = length;
    263     length += sizeof(policy.p);
    264     policy.p.sadb_x_policy_len = PFKEY_UNIT64(length);
    265 
    266     /* Always do a flush before adding new policies. */
    267     flush();
    268 
    269     /* Set outbound policy. */
    270     key = pfkey_open();
    271     if (pfkey_send_spdadd(key, src, src_prefix, dst, dst_prefix, protocol,
    272             (caddr_t)&policy, length, 0) <= 0) {
    273         do_plog(LLV_ERROR, "Cannot set outbound policy\n");
    274         exit(1);
    275     }
    276 
    277     /* Flip values for inbound policy. */
    278     policy.p.sadb_x_policy_dir = IPSEC_DIR_INBOUND;
    279     if (!dst_prefix) {
    280         int size = sysdep_sa_len(local);
    281         memcpy(policy.addresses, remote, size);
    282         memcpy(&policy.addresses[size], local, size);
    283     }
    284 
    285     /* Set inbound policy. */
    286     if (pfkey_send_spdadd(key, dst, dst_prefix, src, src_prefix, protocol,
    287             (caddr_t)&policy, length, 0) <= 0) {
    288         do_plog(LLV_ERROR, "Cannot set inbound policy\n");
    289         exit(1);
    290     }
    291 
    292     pfkey_close(key);
    293     atexit(flush);
    294 }
    295 
    296 /*****************************************************************************/
    297 
    298 static void add_proposal(struct remoteconf *remoteconf,
    299         int auth, int hash, int encryption, int length)
    300 {
    301     struct isakmpsa *p = racoon_calloc(1, sizeof(struct isakmpsa));
    302     p->prop_no = 1;
    303     p->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
    304     p->enctype = encryption;
    305     p->encklen = length;
    306     p->authmethod = auth;
    307     p->hashtype = hash;
    308     p->dh_group = OAKLEY_ATTR_GRP_DESC_MODP1024;
    309     p->vendorid = VENDORID_UNKNOWN;
    310     p->rmconf = remoteconf;
    311 
    312     if (!remoteconf->proposal) {
    313       p->trns_no = 1;
    314       remoteconf->proposal = p;
    315     } else {
    316         struct isakmpsa *q = remoteconf->proposal;
    317         while (q->next) {
    318             q = q->next;
    319         }
    320         p->trns_no = q->trns_no + 1;
    321         q->next = p;
    322     }
    323 }
    324 
    325 static vchar_t *strtovchar(char *string)
    326 {
    327     vchar_t *vchar = string ? vmalloc(strlen(string) + 1) : NULL;
    328     if (vchar) {
    329         memcpy(vchar->v, string, vchar->l);
    330         vchar->l -= 1;
    331     }
    332     return vchar;
    333 }
    334 
    335 static void set_pre_shared_key(struct remoteconf *remoteconf,
    336         char *identifier, char *key)
    337 {
    338     pre_shared_key = key;
    339     if (identifier[0]) {
    340         remoteconf->idv = strtovchar(identifier);
    341         remoteconf->etypes->type = ISAKMP_ETYPE_AGG;
    342 
    343         remoteconf->idvtype = IDTYPE_KEYID;
    344         if (strchr(identifier, '.')) {
    345             remoteconf->idvtype = IDTYPE_FQDN;
    346             if (strchr(identifier, '@')) {
    347                 remoteconf->idvtype = IDTYPE_USERFQDN;
    348             }
    349         }
    350     }
    351 }
    352 
    353 static void set_certificates(struct remoteconf *remoteconf,
    354         char *user_private_key, char *user_certificate,
    355         char *ca_certificate, char *server_certificate)
    356 {
    357     remoteconf->myprivfile = user_private_key;
    358     remoteconf->mycertfile = user_certificate;
    359     if (user_certificate) {
    360         remoteconf->idvtype = IDTYPE_ASN1DN;
    361     }
    362     if (!ca_certificate[0]) {
    363         remoteconf->verify_cert = FALSE;
    364     } else {
    365         remoteconf->cacertfile = ca_certificate;
    366     }
    367     if (server_certificate[0]) {
    368         remoteconf->peerscertfile = server_certificate;
    369         remoteconf->getcert_method = ISAKMP_GETCERT_LOCALFILE;
    370     }
    371 }
    372 
    373 #ifdef ENABLE_HYBRID
    374 
    375 static void set_xauth_and_more(struct remoteconf *remoteconf,
    376         char *username, char *password, char *phase1_up, char *script_arg)
    377 {
    378     struct xauth_rmconf *xauth = racoon_calloc(1, sizeof(struct xauth_rmconf));
    379     xauth->login = strtovchar(username);
    380     xauth->login->l += 1;
    381     xauth->pass = strtovchar(password);
    382     xauth->pass->l += 1;
    383     remoteconf->xauth = xauth;
    384     remoteconf->mode_cfg = TRUE;
    385     remoteconf->script[SCRIPT_PHASE1_UP] = strtovchar(phase1_up);
    386     script_names[SCRIPT_PHASE1_UP] = script_arg;
    387 }
    388 
    389 #endif
    390 
    391 extern void monitor_fd(int fd, void (*callback)(int));
    392 
    393 void add_isakmp_handler(int fd, const char *interface)
    394 {
    395     if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
    396             interface, strlen(interface))) {
    397         do_plog(LLV_WARNING, "Cannot bind socket to %s\n", interface);
    398     }
    399     monitor_fd(fd, (void *)isakmp_handler);
    400 }
    401 
    402 void setup(int argc, char **argv)
    403 {
    404     struct remoteconf *remoteconf = NULL;
    405     int auth;
    406 
    407     if (argc > 2) {
    408         set_globals(argv[2]);
    409 
    410         /* Initialize everything else. */
    411         eay_init();
    412         initrmconf();
    413         oakley_dhinit();
    414         compute_vendorids();
    415         sched_init();
    416         if (pfkey_init() < 0 || isakmp_init() < 0) {
    417             exit(1);
    418         }
    419         monitor_fd(localconf.sock_pfkey, (void *)pfkey_handler);
    420         add_isakmp_handler(myaddrs[0].sock, argv[1]);
    421 #ifdef ENABLE_NATT
    422         add_isakmp_handler(myaddrs[1].sock, argv[1]);
    423         natt_keepalive_init();
    424 #endif
    425 
    426         /* Create remote configuration. */
    427         remoteconf = newrmconf();
    428         remoteconf->etypes = racoon_calloc(1, sizeof(struct etypes));
    429         remoteconf->etypes->type = ISAKMP_ETYPE_IDENT;
    430         remoteconf->idvtype = IDTYPE_ADDRESS;
    431         remoteconf->ike_frag = TRUE;
    432         remoteconf->pcheck_level = PROP_CHECK_CLAIM;
    433         remoteconf->certtype = ISAKMP_CERT_X509SIGN;
    434         remoteconf->gen_policy = TRUE;
    435         remoteconf->nat_traversal = TRUE;
    436         remoteconf->dh_group = OAKLEY_ATTR_GRP_DESC_MODP1024;
    437         remoteconf->script[SCRIPT_PHASE1_UP] = strtovchar("");
    438         remoteconf->script[SCRIPT_PHASE1_DOWN] = strtovchar("");
    439         oakley_setdhgroup(remoteconf->dh_group, &remoteconf->dhgrp);
    440         remoteconf->remote = dupsaddr(targets[0]);
    441     }
    442 
    443     /* Set authentication method and credentials. */
    444     if (argc == 7 && !strcmp(argv[3], "udppsk")) {
    445         set_pre_shared_key(remoteconf, argv[4], argv[5]);
    446         auth = OAKLEY_ATTR_AUTH_METHOD_PSKEY;
    447 
    448         set_port(targets[0], atoi(argv[6]));
    449         spdadd(source, targets[0], IPPROTO_UDP, NULL, NULL);
    450     } else if (argc == 9 && !strcmp(argv[3], "udprsa")) {
    451         set_certificates(remoteconf, argv[4], argv[5], argv[6], argv[7]);
    452         auth = OAKLEY_ATTR_AUTH_METHOD_RSASIG;
    453 
    454         set_port(targets[0], atoi(argv[8]));
    455         spdadd(source, targets[0], IPPROTO_UDP, NULL, NULL);
    456 #ifdef ENABLE_HYBRID
    457     } else if (argc == 10 && !strcmp(argv[3], "xauthpsk")) {
    458         set_pre_shared_key(remoteconf, argv[4], argv[5]);
    459         set_xauth_and_more(remoteconf, argv[6], argv[7], argv[8], argv[9]);
    460         auth = OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I;
    461     } else if (argc == 12 && !strcmp(argv[3], "xauthrsa")) {
    462         set_certificates(remoteconf, argv[4], argv[5], argv[6], argv[7]);
    463         set_xauth_and_more(remoteconf, argv[8], argv[9], argv[10], argv[11]);
    464         auth = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I;
    465     } else if (argc == 10 && !strcmp(argv[3], "hybridrsa")) {
    466         set_certificates(remoteconf, NULL, NULL, argv[4], argv[5]);
    467         set_xauth_and_more(remoteconf, argv[6], argv[7], argv[8], argv[9]);
    468         auth = OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I;
    469 #endif
    470     } else {
    471         printf("Usage: %s <interface> <server> [...], where [...] can be:\n"
    472                 " udppsk    <identifier> <pre-shared-key> <port>; \n"
    473                 " udprsa    <user-private-key> <user-certificate> \\\n"
    474                 "           <ca-certificate> <server-certificate> <port>;\n"
    475 #ifdef ENABLE_HYBRID
    476                 " xauthpsk  <identifier> <pre-shared-key> \\\n"
    477                 "           <username> <password> <phase1-up> <script-arg>;\n"
    478                 " xauthrsa  <user-private-key> <user-certificate> \\\n"
    479                 "           <ca-certificate> <server-certificate> \\\n"
    480                 "           <username> <password> <phase1-up> <script-arg>;\n"
    481                 " hybridrsa <ca-certificate> <server-certificate> \\\n"
    482                 "           <username> <password> <phase1-up> <script-arg>;\n"
    483 #endif
    484                 "", argv[0]);
    485         exit(0);
    486     }
    487 
    488     /* Add proposals. */
    489     add_proposal(remoteconf, auth,
    490             OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_AES, 256);
    491     add_proposal(remoteconf, auth,
    492             OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_AES, 256);
    493     add_proposal(remoteconf, auth,
    494             OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_AES, 128);
    495     add_proposal(remoteconf, auth,
    496             OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_AES, 128);
    497     add_proposal(remoteconf, auth,
    498             OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_3DES, 0);
    499     add_proposal(remoteconf, auth,
    500             OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_3DES, 0);
    501     add_proposal(remoteconf, auth,
    502             OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_DES, 0);
    503     add_proposal(remoteconf, auth,
    504             OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_DES, 0);
    505 
    506     /* Install remote configuration. */
    507     insrmconf(remoteconf);
    508 
    509     /* Start phase 1 negotiation for xauth. */
    510     if (remoteconf->xauth) {
    511         isakmp_ph1begin_i(remoteconf, remoteconf->remote, source);
    512     }
    513 }
    514 
    515 /*****************************************************************************/
    516 
    517 /* localconf.h */
    518 
    519 vchar_t *getpskbyaddr(struct sockaddr *addr)
    520 {
    521     return strtovchar(pre_shared_key);
    522 }
    523 
    524 vchar_t *getpskbyname(vchar_t *name)
    525 {
    526     return NULL;
    527 }
    528 
    529 void getpathname(char *path, int length, int type, const char *name)
    530 {
    531     if (pname) {
    532         snprintf(path, length, pname, name);
    533     } else {
    534         strncpy(path, name, length);
    535     }
    536     path[length - 1] = '\0';
    537 }
    538 
    539 /* grabmyaddr.h */
    540 
    541 int myaddr_getsport(struct sockaddr *addr)
    542 {
    543     return 0;
    544 }
    545 
    546 int getsockmyaddr(struct sockaddr *addr)
    547 {
    548 #ifdef ENABLE_NATT
    549     if (!cmpsaddrstrict(addr, myaddrs[1].addr)) {
    550         return myaddrs[1].sock;
    551     }
    552 #endif
    553     if (!cmpsaddrwop(addr, myaddrs[0].addr)) {
    554         return myaddrs[0].sock;
    555     }
    556     return -1;
    557 }
    558 
    559 /* privsep.h */
    560 
    561 int privsep_pfkey_open()
    562 {
    563     return pfkey_open();
    564 }
    565 
    566 void privsep_pfkey_close(int key)
    567 {
    568     pfkey_close(key);
    569 }
    570 
    571 vchar_t *privsep_eay_get_pkcs1privkey(char *file)
    572 {
    573     return eay_get_pkcs1privkey(file);
    574 }
    575 
    576 static char *get_env(char * const *envp, char *key)
    577 {
    578     int length = strlen(key);
    579     while (*envp && (strncmp(*envp, key, length) || (*envp)[length] != '=')) {
    580         ++envp;
    581     }
    582     return *envp ? &(*envp)[length + 1] : "";
    583 }
    584 
    585 static int skip_script = 0;
    586 extern const char *android_hook(char **envp);
    587 
    588 int privsep_script_exec(char *script, int name, char * const *envp)
    589 {
    590     if (skip_script) {
    591         return 0;
    592     }
    593     skip_script = 1;
    594 
    595     if (name == SCRIPT_PHASE1_DOWN) {
    596         exit(1);
    597     }
    598     if (script_names[SCRIPT_PHASE1_UP]) {
    599         /* Racoon ignores INTERNAL_IP6_ADDRESS, so we only do IPv4. */
    600         struct sockaddr *addr4 = str2saddr(get_env(envp, "INTERNAL_ADDR4"),
    601                 NULL);
    602         struct sockaddr *local = str2saddr(get_env(envp, "LOCAL_ADDR"),
    603                 get_env(envp, "LOCAL_PORT"));
    604         struct sockaddr *remote = str2saddr(get_env(envp, "REMOTE_ADDR"),
    605                 get_env(envp, "REMOTE_PORT"));
    606 
    607         if (addr4 && local && remote) {
    608 #ifdef ANDROID_CHANGES
    609             if (pname) {
    610                 script = (char *)android_hook((char **)envp);
    611             }
    612 #endif
    613             spdadd(addr4, NULL, IPPROTO_IP, local, remote);
    614         } else {
    615             do_plog(LLV_ERROR, "Cannot get parameters for SPD policy.\n");
    616             exit(1);
    617         }
    618 
    619         racoon_free(addr4);
    620         racoon_free(local);
    621         racoon_free(remote);
    622         return script_exec(script, name, envp);
    623     }
    624     return 0;
    625 }
    626 
    627 int privsep_accounting_system(int port, struct sockaddr *addr,
    628         char *user, int status)
    629 {
    630     return 0;
    631 }
    632 
    633 int privsep_xauth_login_system(char *user, char *password)
    634 {
    635     return -1;
    636 }
    637 
    638 /* misc.h */
    639 
    640 int racoon_hexdump(void *data, size_t length)
    641 {
    642     return 0;
    643 }
    644 
    645 /* sainfo.h */
    646 
    647 struct sainfo *getsainfo(const vchar_t *src, const vchar_t *dst,
    648         const vchar_t *peer, int remoteid)
    649 {
    650     return &sainfo;
    651 }
    652 
    653 const char *sainfo2str(const struct sainfo *si)
    654 {
    655     return "*";
    656 }
    657 
    658 /* throttle.h */
    659 
    660 int throttle_host(struct sockaddr *addr, int fail)
    661 {
    662     return 0;
    663 }
    664