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