blob: 6dd0b276428a72d90ca9395eab54a6022e63c46a [file] [log] [blame]
Chia-chi Yeh837a1c72009-06-26 09:40:31 +08001/*
Chia-chi Yehe9fc3762011-07-07 03:20:34 -07002 * Copyright (C) 2011 The Android Open Source Project
Chia-chi Yeh837a1c72009-06-26 09:40:31 +08003 *
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>
Chia-chi Yehf8a6a762011-07-04 17:21:23 -070020#include <unistd.h>
Chia-chi Yeh8f3b3882011-07-07 13:43:20 -070021#include <sys/param.h>
Chia-chi Yeh837a1c72009-06-26 09:40:31 +080022#include <sys/types.h>
23#include <sys/socket.h>
Chia-chi Yehc4549542009-07-22 06:46:14 +080024#include <netinet/in.h>
Chia-chi Yeh837a1c72009-06-26 09:40:31 +080025#include <netinet/ip.h>
Chia-chi Yeh7197eb72009-07-13 16:43:29 +080026#include <netdb.h>
Chia-chi Yehf8a6a762011-07-04 17:21:23 -070027#include <fcntl.h>
Chia-chi Yeh837a1c72009-06-26 09:40:31 +080028
29#include "config.h"
Chia-chi Yehf8a6a762011-07-04 17:21:23 -070030#include "gcmalloc.h"
Chia-chi Yeh837a1c72009-06-26 09:40:31 +080031#include "libpfkey.h"
32#include "var.h"
33#include "isakmp_var.h"
34#include "isakmp.h"
Chia-chi Yehdbbbd5f2011-07-12 13:21:42 -070035#include "isakmp_xauth.h"
Chia-chi Yeh837a1c72009-06-26 09:40:31 +080036#include "vmbuf.h"
Chia-chi Yehf8a6a762011-07-04 17:21:23 -070037#include "crypto_openssl.h"
Chia-chi Yeh837a1c72009-06-26 09:40:31 +080038#include "oakley.h"
39#include "ipsec_doi.h"
40#include "algorithm.h"
41#include "vendorid.h"
Chia-chi Yehf8a6a762011-07-04 17:21:23 -070042#include "schedule.h"
43#include "pfkey.h"
44#include "nattraversal.h"
Chia-chi Yeh837a1c72009-06-26 09:40:31 +080045#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"
Chia-chi Yehbd5fa3c2009-07-07 16:24:13 +080052#include "admin.h"
53#include "privsep.h"
Chia-chi Yeh514ffe22011-07-07 13:52:27 -070054#include "throttle.h"
Chia-chi Yehf8a6a762011-07-04 17:21:23 -070055#include "misc.h"
Chia-chi Yeh837a1c72009-06-26 09:40:31 +080056
Chia-chi Yeh837a1c72009-06-26 09:40:31 +080057static struct localconf localconf;
Chia-chi Yeh837a1c72009-06-26 09:40:31 +080058static struct sainfo sainfo;
59static char *pre_shared_key;
Chia-chi Yehf8a6a762011-07-04 17:21:23 -070060
61static char *interface;
Chia-chi Yehb0d8f172011-07-12 15:14:38 -070062static struct sockaddr *targets[2];
Chia-chi Yehf8a6a762011-07-04 17:21:23 -070063static struct {
64 struct sockaddr *addr;
65 int fd;
Chia-chi Yehb0d8f172011-07-12 15:14:38 -070066} sources[2];
Chia-chi Yeh837a1c72009-06-26 09:40:31 +080067
68struct localconf *lcconf = &localconf;
69char *script_names[SCRIPT_MAX + 1];
Chia-chi Yehf8a6a762011-07-04 17:21:23 -070070int f_local = 0;
Chia-chi Yeh837a1c72009-06-26 09:40:31 +080071
Chia-chi Yehf8a6a762011-07-04 17:21:23 -070072/*****************************************************************************/
Chia-chi Yeh837a1c72009-06-26 09:40:31 +080073
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
Chia-chi Yehf8a6a762011-07-04 17:21:23 -070091static 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
Chia-chi Yehb0d8f172011-07-12 15:14:38 -0700104 if (getaddrinfo(server, "500", &hints, &info) != 0) {
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700105 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 }
Chia-chi Yehb0d8f172011-07-12 15:14:38 -0700111 targets[0] = dupsaddr(info->ai_addr);
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700112 freeaddrinfo(info);
113
114 interface = interfaze;
Chia-chi Yehb0d8f172011-07-12 15:14:38 -0700115 sources[0].addr = getlocaladdr(targets[0]);
116 if (!sources[0].addr) {
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700117 do_plog(LLV_ERROR, "Cannot get local address\n");
118 exit(1);
119 }
Chia-chi Yehb0d8f172011-07-12 15:14:38 -0700120 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;
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700125
126 localconf.port_isakmp = PORT_ISAKMP;
127 localconf.port_isakmp_natt = PORT_ISAKMP_NATT;
128 localconf.default_af = AF_INET;
Chia-chi Yehe9fc3762011-07-07 03:20:34 -0700129 localconf.pathinfo[LC_PATHTYPE_CERT] = "./";
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700130 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);
Chia-chi Yehf82b8262011-07-13 18:07:54 -0700146 add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_AES, 256);
147 add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_AES, 128);
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700148 add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_3DES, 0);
149 add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_DES, 0);
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700150}
151
152/*****************************************************************************/
153
154static int policy_match(struct sadb_address *address)
Chia-chi Yeh3473d8e2011-05-31 13:26:30 -0700155{
156 if (address) {
Chia-chi Yehb0d8f172011-07-12 15:14:38 -0700157 struct sockaddr *addr = PFKEY_ADDR_SADDR(address);
158 return cmpsaddr(addr, targets[0]) < CMPSADDR_MISMATCH ||
159 cmpsaddr(addr, targets[1]) < CMPSADDR_MISMATCH;
Chia-chi Yeh3473d8e2011-05-31 13:26:30 -0700160 }
161 return 0;
162}
163
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800164/* flush; spdflush; */
165static void flush()
166{
Chia-chi Yeh3473d8e2011-05-31 13:26:30 -0700167 struct sadb_msg *p;
168 int replies = 0;
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800169 int key = pfkey_open();
Chia-chi Yeh3473d8e2011-05-31 13:26:30 -0700170
171 if (pfkey_send_dump(key, SADB_SATYPE_UNSPEC) <= 0 ||
172 pfkey_send_spddump(key) <= 0) {
Chia-chi Yehb0d8f172011-07-12 15:14:38 -0700173 do_plog(LLV_ERROR, "Cannot dump SAD and SPD\n");
Chia-chi Yeh3473d8e2011-05-31 13:26:30 -0700174 exit(1);
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800175 }
Chia-chi Yeh3473d8e2011-05-31 13:26:30 -0700176
177 for (p = NULL; replies < 2 && (p = pfkey_recv(key)) != NULL; free(p)) {
178 caddr_t q[SADB_EXT_MAX + 1];
179
180 if (p->sadb_msg_type != SADB_DUMP &&
181 p->sadb_msg_type != SADB_X_SPDDUMP) {
182 continue;
183 }
184 replies += !p->sadb_msg_seq;
185
186 if (p->sadb_msg_errno || pfkey_align(p, q) || pfkey_check(q)) {
187 continue;
188 }
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700189 if (policy_match((struct sadb_address *)q[SADB_EXT_ADDRESS_SRC]) ||
190 policy_match((struct sadb_address *)q[SADB_EXT_ADDRESS_DST])) {
Chia-chi Yeh3473d8e2011-05-31 13:26:30 -0700191 p->sadb_msg_type = (p->sadb_msg_type == SADB_DUMP) ?
192 SADB_DELETE : SADB_X_SPDDELETE;
193 p->sadb_msg_reserved = 0;
194 p->sadb_msg_seq = 0;
195 pfkey_send(key, p, PFKEY_UNUNIT64(p->sadb_msg_len));
196 }
197 }
198
199 pfkey_close(key);
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800200}
201
Chia-chi Yeh2871f2f2011-08-09 19:19:20 -0700202/* spdadd src dst protocol -P out ipsec esp/transport//require;
203 * spdadd dst src protocol -P in ipsec esp/transport//require;
204 * or
205 * spdadd src any protocol -P out ipsec esp/tunnel/local-remote/require;
206 * spdadd any src protocol -P in ipsec esp/tunnel/remote-local/require; */
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700207static void spdadd(struct sockaddr *src, struct sockaddr *dst,
208 int protocol, struct sockaddr *local, struct sockaddr *remote)
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800209{
210 struct __attribute__((packed)) {
211 struct sadb_x_policy p;
212 struct sadb_x_ipsecrequest q;
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700213 char addresses[sizeof(struct sockaddr_storage) * 2];
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800214 } policy;
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800215
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700216 struct sockaddr_storage any = {
217#ifndef __linux__
218 .ss_len = src->sa_len,
219#endif
220 .ss_family = src->sa_family,
221 };
222
223 int src_prefix = (src->sa_family == AF_INET) ? 32 : 128;
224 int dst_prefix = src_prefix;
225 int length = 0;
226 int key;
227
Chia-chi Yeh2871f2f2011-08-09 19:19:20 -0700228 /* Fill values for outbound policy. */
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800229 memset(&policy, 0, sizeof(policy));
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800230 policy.p.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
231 policy.p.sadb_x_policy_type = IPSEC_POLICY_IPSEC;
232 policy.p.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
233#ifdef HAVE_PFKEY_POLICY_PRIORITY
234 policy.p.sadb_x_policy_priority = PRIORITY_DEFAULT;
235#endif
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800236 policy.q.sadb_x_ipsecrequest_proto = IPPROTO_ESP;
237 policy.q.sadb_x_ipsecrequest_mode = IPSEC_MODE_TRANSPORT;
238 policy.q.sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE;
239
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700240 /* Deal with tunnel mode. */
241 if (!dst) {
Chia-chi Yeh2871f2f2011-08-09 19:19:20 -0700242 int size = sysdep_sa_len(local);
243 memcpy(policy.addresses, local, size);
244 memcpy(&policy.addresses[size], remote, size);
245 length += size + size;
246
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700247 policy.q.sadb_x_ipsecrequest_mode = IPSEC_MODE_TUNNEL;
248 dst = (struct sockaddr *)&any;
249 dst_prefix = 0;
250
Chia-chi Yehb0d8f172011-07-12 15:14:38 -0700251 /* Also use the source address to filter policies. */
252 targets[1] = dupsaddr(src);
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700253 }
254
255 /* Fix lengths. */
256 length += sizeof(policy.q);
257 policy.q.sadb_x_ipsecrequest_len = length;
258 length += sizeof(policy.p);
259 policy.p.sadb_x_policy_len = PFKEY_UNIT64(length);
260
Chia-chi Yeh2871f2f2011-08-09 19:19:20 -0700261 /* Always do a flush before adding new policies. */
Chia-chi Yeh3473d8e2011-05-31 13:26:30 -0700262 flush();
Chia-chi Yeh2871f2f2011-08-09 19:19:20 -0700263
264 /* Set outbound policy. */
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700265 key = pfkey_open();
266 if (pfkey_send_spdadd(key, src, src_prefix, dst, dst_prefix, protocol,
267 (caddr_t)&policy, length, 0) <= 0) {
Chia-chi Yeh2871f2f2011-08-09 19:19:20 -0700268 do_plog(LLV_ERROR, "Cannot set outbound policy\n");
Chia-chi Yeh7197eb72009-07-13 16:43:29 +0800269 exit(1);
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800270 }
Chia-chi Yeh2871f2f2011-08-09 19:19:20 -0700271
272 /* Flip values for inbound policy. */
273 policy.p.sadb_x_policy_dir = IPSEC_DIR_INBOUND;
274 if (!dst_prefix) {
275 int size = sysdep_sa_len(local);
276 memcpy(policy.addresses, remote, size);
277 memcpy(&policy.addresses[size], local, size);
278 }
279
280 /* Set inbound policy. */
281 if (pfkey_send_spdadd(key, dst, dst_prefix, src, src_prefix, protocol,
282 (caddr_t)&policy, length, 0) <= 0) {
283 do_plog(LLV_ERROR, "Cannot set inbound policy\n");
284 exit(1);
285 }
286
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800287 pfkey_close(key);
Chia-chi Yehc4549542009-07-22 06:46:14 +0800288 atexit(flush);
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800289}
290
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700291/*****************************************************************************/
292
293static void add_proposal(struct remoteconf *remoteconf,
294 int auth, int hash, int encryption, int length)
295{
296 struct isakmpsa *p = racoon_calloc(1, sizeof(struct isakmpsa));
297 p->prop_no = 1;
298 p->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
299 p->enctype = encryption;
300 p->encklen = length;
301 p->authmethod = auth;
302 p->hashtype = hash;
303 p->dh_group = OAKLEY_ATTR_GRP_DESC_MODP1024;
304 p->vendorid = VENDORID_UNKNOWN;
305
306 if (!remoteconf->proposal) {
307 p->trns_no = 1;
308 remoteconf->proposal = p;
309 } else {
310 struct isakmpsa *q = remoteconf->proposal;
311 while (q->next) {
312 q = q->next;
313 }
314 p->trns_no = q->trns_no + 1;
315 q->next = p;
316 }
317}
318
Chia-chi Yeh71076532011-08-08 12:20:14 -0700319static vchar_t *strtovchar(char *string)
320{
321 vchar_t *vchar = string ? vmalloc(strlen(string) + 1) : NULL;
322 if (vchar) {
323 memcpy(vchar->v, string, vchar->l);
324 }
325 return vchar;
326}
327
328static void set_pre_shared_key(struct remoteconf *remoteconf,
329 char *identifier, char *key)
330{
331 pre_shared_key = key;
332 if (identifier[0]) {
333 remoteconf->idv = strtovchar(identifier);
334 remoteconf->idv->l -= 1;
335 remoteconf->etypes->type = ISAKMP_ETYPE_AGG;
336
337 remoteconf->idvtype = IDTYPE_KEYID;
338 if (strchr(identifier, '.')) {
339 remoteconf->idvtype = IDTYPE_FQDN;
340 if (strchr(identifier, '@')) {
341 remoteconf->idvtype = IDTYPE_USERFQDN;
342 }
343 }
344 }
345}
346
Chia-chi Yehdbbbd5f2011-07-12 13:21:42 -0700347static vchar_t *get_certificate(char *type, char *file)
348{
349 char path[PATH_MAX + 1];
350 vchar_t *certificate = NULL;
351
352 getpathname(path, sizeof(path), LC_PATHTYPE_CERT, file);
353 certificate = eay_get_x509cert(path);
354 if (!certificate) {
355 do_plog(LLV_ERROR, "Cannot load %s certificate\n", type);
356 exit(1);
357 }
358 return certificate;
359}
360
361static void set_certificates(struct remoteconf *remoteconf,
362 char *user_private_key, char *user_certificate, char *ca_certificate)
363{
364 remoteconf->myprivfile = user_private_key;
365 remoteconf->mycertfile = user_certificate;
366 if (user_certificate) {
Chia-chi Yeh71076532011-08-08 12:20:14 -0700367 remoteconf->idvtype = IDTYPE_ASN1DN;
Chia-chi Yehdbbbd5f2011-07-12 13:21:42 -0700368 remoteconf->mycert = get_certificate("user", user_certificate);
369 }
370 if (!ca_certificate[0]) {
371 remoteconf->verify_cert = FALSE;
372 } else {
373 remoteconf->cacertfile = ca_certificate;
374 remoteconf->cacert = get_certificate("CA", ca_certificate);
375 }
Chia-chi Yehdbbbd5f2011-07-12 13:21:42 -0700376}
377
378#ifdef ENABLE_HYBRID
379
380static void set_xauth_and_more(struct remoteconf *remoteconf,
381 char *username, char *password, char *phase1_up, char *script_arg)
382{
383 struct xauth_rmconf *xauth = racoon_calloc(1, sizeof(struct xauth_rmconf));
Chia-chi Yeh10700972011-07-12 18:06:57 -0700384 xauth->login = strtovchar(username);
385 xauth->pass = strtovchar(password);
Chia-chi Yehdbbbd5f2011-07-12 13:21:42 -0700386 remoteconf->xauth = xauth;
387 remoteconf->mode_cfg = TRUE;
388 remoteconf->script[SCRIPT_PHASE1_UP] = strtovchar(phase1_up);
389 script_names[SCRIPT_PHASE1_UP] = script_arg;
390}
391
392#endif
393
Chia-chi Yeh7197eb72009-07-13 16:43:29 +0800394void setup(int argc, char **argv)
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800395{
Chia-chi Yehdbbbd5f2011-07-12 13:21:42 -0700396 struct remoteconf *remoteconf = NULL;
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800397 int auth;
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800398
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700399 if (argc > 2) {
400 set_globals(argv[1], argv[2]);
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800401
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700402 /* Initialize everything else. */
403 eay_init();
404 initrmconf();
405 oakley_dhinit();
406 compute_vendorids();
407 sched_init();
408 if (pfkey_init() < 0 || isakmp_init() < 0) {
409 exit(1);
410 }
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800411#ifdef ENABLE_NATT
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700412 natt_keepalive_init();
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800413#endif
414
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700415 /* Create remote configuration. */
416 remoteconf = newrmconf();
417 remoteconf->etypes = racoon_calloc(1, sizeof(struct etypes));
418 remoteconf->etypes->type = ISAKMP_ETYPE_IDENT;
Chia-chi Yeh71076532011-08-08 12:20:14 -0700419 remoteconf->idvtype = IDTYPE_ADDRESS;
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700420 remoteconf->ike_frag = TRUE;
Chia-chi Yehf82b8262011-07-13 18:07:54 -0700421 remoteconf->pcheck_level = PROP_CHECK_CLAIM;
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700422 remoteconf->gen_policy = TRUE;
423 remoteconf->nat_traversal = TRUE;
Chia-chi Yeh71076532011-08-08 12:20:14 -0700424 remoteconf->dh_group = OAKLEY_ATTR_GRP_DESC_MODP1024;
425 oakley_setdhgroup(remoteconf->dh_group, &remoteconf->dhgrp);
Chia-chi Yehb0d8f172011-07-12 15:14:38 -0700426 remoteconf->remote = dupsaddr(targets[0]);
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700427 set_port(remoteconf->remote, localconf.port_isakmp);
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800428 }
429
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700430 /* Set authentication method and credentials. */
Chia-chi Yeh71076532011-08-08 12:20:14 -0700431 if (argc == 7 && !strcmp(argv[3], "udppsk")) {
432 set_pre_shared_key(remoteconf, argv[4], argv[5]);
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700433 auth = OAKLEY_ATTR_AUTH_METHOD_PSKEY;
Chia-chi Yehdbbbd5f2011-07-12 13:21:42 -0700434
Chia-chi Yeh71076532011-08-08 12:20:14 -0700435 set_port(targets[0], atoi(argv[6]));
Chia-chi Yehb0d8f172011-07-12 15:14:38 -0700436 spdadd(sources[0].addr, targets[0], IPPROTO_UDP, NULL, NULL);
Chia-chi Yehdbbbd5f2011-07-12 13:21:42 -0700437 } else if (argc == 8 && !strcmp(argv[3], "udprsa")) {
438 set_certificates(remoteconf, argv[4], argv[5], argv[6]);
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700439 auth = OAKLEY_ATTR_AUTH_METHOD_RSASIG;
Chia-chi Yehdbbbd5f2011-07-12 13:21:42 -0700440
Chia-chi Yehb0d8f172011-07-12 15:14:38 -0700441 set_port(targets[0], atoi(argv[7]));
442 spdadd(sources[0].addr, targets[0], IPPROTO_UDP, NULL, NULL);
Chia-chi Yehdbbbd5f2011-07-12 13:21:42 -0700443#ifdef ENABLE_HYBRID
444 } else if (argc == 10 && !strcmp(argv[3], "xauthpsk")) {
Chia-chi Yeh71076532011-08-08 12:20:14 -0700445 set_pre_shared_key(remoteconf, argv[4], argv[5]);
Chia-chi Yehdbbbd5f2011-07-12 13:21:42 -0700446 set_xauth_and_more(remoteconf, argv[6], argv[7], argv[8], argv[9]);
447 auth = OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I;
448 } else if (argc == 11 && !strcmp(argv[3], "xauthrsa")) {
449 set_certificates(remoteconf, argv[4], argv[5], argv[6]);
450 set_xauth_and_more(remoteconf, argv[7], argv[8], argv[9], argv[10]);
451 auth = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I;
452 } else if (argc == 9 && !strcmp(argv[3], "hybridrsa")) {
453 set_certificates(remoteconf, NULL, NULL, argv[4]);
454 set_xauth_and_more(remoteconf, argv[5], argv[6], argv[7], argv[8]);
455 auth = OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I;
456#endif
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700457 } else {
Chia-chi Yehdbbbd5f2011-07-12 13:21:42 -0700458 printf("Usage: %s <interface> <server> [...], where [...] can be:\n"
Chia-chi Yeh71076532011-08-08 12:20:14 -0700459 " udppsk <identifier> <pre-shared-key> <port>\n"
Chia-chi Yehdbbbd5f2011-07-12 13:21:42 -0700460 " udprsa <user-private-key> <user-cert> <ca-cert> <port>\n"
461#ifdef ENABLE_HYBRID
462 " xauthpsk <identifier> <pre-shared-key>"
463 " <username> <password> <phase1-up> <script-arg>\n"
464 " xauthrsa <user-private-key> <user-cert> <ca-cert>"
465 " <username> <password> <phase1-up> <script-arg>\n"
466 " hybridrsa <ca-cert>"
467 " <username> <password> <phase1-up> <script-arg>\n"
468#endif
469 "", argv[0]);
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700470 exit(0);
471 }
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800472
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700473 /* Add proposals. */
474 add_proposal(remoteconf, auth,
Chia-chi Yehf82b8262011-07-13 18:07:54 -0700475 OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_AES, 256);
476 add_proposal(remoteconf, auth,
477 OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_AES, 256);
478 add_proposal(remoteconf, auth,
479 OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_AES, 128);
480 add_proposal(remoteconf, auth,
481 OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_AES, 128);
482 add_proposal(remoteconf, auth,
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700483 OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_3DES, 0);
484 add_proposal(remoteconf, auth,
485 OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_3DES, 0);
486 add_proposal(remoteconf, auth,
487 OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_DES, 0);
488 add_proposal(remoteconf, auth,
489 OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_DES, 0);
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700490
491 /* Install remote configuration. */
492 insrmconf(remoteconf);
493
494 /* Create ISAKMP sockets. */
Chia-chi Yehb0d8f172011-07-12 15:14:38 -0700495 set_port(sources[0].addr, localconf.port_isakmp);
496 sources[0].fd = isakmp_open(sources[0].addr, FALSE);
497 if (sources[0].fd == -1) {
Chia-chi Yeh0ed32712011-07-12 14:06:46 -0700498 do_plog(LLV_ERROR, "Cannot create ISAKMP socket\n");
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700499 exit(1);
500 }
501#ifdef ENABLE_NATT
Chia-chi Yehb0d8f172011-07-12 15:14:38 -0700502 set_port(sources[1].addr, localconf.port_isakmp_natt);
503 sources[1].fd = isakmp_open(sources[1].addr, TRUE);
504 if (sources[1].fd == -1) {
Chia-chi Yeh0ed32712011-07-12 14:06:46 -0700505 do_plog(LLV_WARNING, "Cannot create ISAKMP socket for NAT-T\n");
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700506 }
507#endif
Chia-chi Yehdbbbd5f2011-07-12 13:21:42 -0700508
509 /* Start phase 1 negotiation for xauth. */
510 if (remoteconf->xauth) {
Chia-chi Yehb0d8f172011-07-12 15:14:38 -0700511 isakmp_ph1begin_i(remoteconf, remoteconf->remote, sources[0].addr);
Chia-chi Yehdbbbd5f2011-07-12 13:21:42 -0700512 }
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800513}
514
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700515/*****************************************************************************/
516
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800517/* localconf.h */
518
519vchar_t *getpskbyaddr(struct sockaddr *addr)
520{
Chia-chi Yehdbbbd5f2011-07-12 13:21:42 -0700521 return strtovchar(pre_shared_key);
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800522}
523
524vchar_t *getpskbyname(vchar_t *name)
525{
526 return NULL;
527}
528
529void getpathname(char *path, int length, int type, const char *name)
530{
Chia-chi Yeh8f3b3882011-07-07 13:43:20 -0700531 if (pname) {
532 snprintf(path, length, pname, name);
Chia-chi Yehe9fc3762011-07-07 03:20:34 -0700533 } else {
534 strncpy(path, name, length);
535 }
Chia-chi Yehfd76ec52011-07-07 12:28:27 -0700536 path[length - 1] = '\0';
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800537}
538
Chia-chi Yeh514ffe22011-07-07 13:52:27 -0700539/* grabmyaddr.h */
540
541int myaddr_getsport(struct sockaddr *addr)
542{
543 return 0;
544}
545
546int myaddr_getfd(struct sockaddr *addr)
547{
548#ifdef ENABLE_NATT
Chia-chi Yehb0d8f172011-07-12 15:14:38 -0700549 if (sources[1].fd != -1 &&
550 cmpsaddr(addr, sources[1].addr) == CMPSADDR_MATCH) {
551 return sources[1].fd;
Chia-chi Yeh514ffe22011-07-07 13:52:27 -0700552 }
553#endif
Chia-chi Yehb0d8f172011-07-12 15:14:38 -0700554 if (cmpsaddr(addr, sources[0].addr) < CMPSADDR_MISMATCH) {
555 return sources[0].fd;
Chia-chi Yeh514ffe22011-07-07 13:52:27 -0700556 }
557 return -1;
558}
559
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700560/* privsep.h */
561
562int privsep_socket(int domain, int type, int protocol)
563{
564 int fd = socket(domain, type, protocol);
565 if ((domain == AF_INET || domain == AF_INET6) && setsockopt(
566 fd, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface))) {
Chia-chi Yeh0ed32712011-07-12 14:06:46 -0700567 do_plog(LLV_WARNING, "Cannot bind socket to %s\n", interface);
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700568 }
569 return fd;
570}
571
572int privsep_bind(int fd, const struct sockaddr *addr, socklen_t addrlen)
573{
574 return bind(fd, addr, addrlen);
575}
576
577vchar_t *privsep_eay_get_pkcs1privkey(char *file)
578{
579 return eay_get_pkcs1privkey(file);
580}
581
Chia-chi Yehe4b12472011-07-12 17:14:47 -0700582static char *get_env(char * const *envp, char *key)
583{
584 int length = strlen(key);
585 while (*envp && (strncmp(*envp, key, length) || (*envp)[length] != '=')) {
586 ++envp;
587 }
588 return *envp ? &(*envp)[length + 1] : "";
589}
590
Chia-chi Yehcfc417e2011-07-13 14:05:22 -0700591static int skip_script = 0;
Chia-chi Yeha9a07ac2011-07-19 18:29:16 -0700592extern const char *android_hook(char **envp);
Chia-chi Yeh10700972011-07-12 18:06:57 -0700593
Chia-chi Yehdbbbd5f2011-07-12 13:21:42 -0700594int privsep_script_exec(char *script, int name, char * const *envp)
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700595{
Chia-chi Yehcfc417e2011-07-13 14:05:22 -0700596 if (skip_script) {
597 do_plog(LLV_WARNING,
598 "Phase 1 is up again. This time skip executing the script.\n");
Chia-chi Yehe4b12472011-07-12 17:14:47 -0700599 } else {
Chia-chi Yehcfc417e2011-07-13 14:05:22 -0700600 /* Racoon ignores INTERNAL_IP6_ADDRESS, so we only do IPv4. */
601 struct sockaddr *addr4 = str2saddr(get_env(envp, "INTERNAL_ADDR4"),
602 NULL);
603 struct sockaddr *local = str2saddr(get_env(envp, "LOCAL_ADDR"),
604 get_env(envp, "LOCAL_PORT"));
605 struct sockaddr *remote = str2saddr(get_env(envp, "REMOTE_ADDR"),
606 get_env(envp, "REMOTE_PORT"));
Chia-chi Yehe4b12472011-07-12 17:14:47 -0700607
Chia-chi Yehcfc417e2011-07-13 14:05:22 -0700608 if (addr4 && local && remote) {
609#ifdef ANDROID_CHANGES
Chia-chi Yeha9a07ac2011-07-19 18:29:16 -0700610 if (pname) {
611 script = (char *)android_hook((char **)envp);
612 }
Chia-chi Yehcfc417e2011-07-13 14:05:22 -0700613#endif
614 spdadd(addr4, NULL, IPPROTO_IP, local, remote);
615 } else {
616 do_plog(LLV_ERROR, "Cannot get parameters for SPD policy.\n");
617 exit(1);
618 }
619
620 skip_script = 1;
621 racoon_free(addr4);
622 racoon_free(local);
623 racoon_free(remote);
624 return script_exec(script, name, envp);
625 }
626 return 0;
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700627}
628
Chia-chi Yeh514ffe22011-07-07 13:52:27 -0700629int privsep_accounting_system(int port, struct sockaddr *addr,
630 char *user, int status)
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700631{
632 return 0;
633}
634
Chia-chi Yeh514ffe22011-07-07 13:52:27 -0700635int privsep_xauth_login_system(char *user, char *password)
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700636{
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700637 return -1;
638}
639
Chia-chi Yeh0ed32712011-07-12 14:06:46 -0700640/* misc.h */
641
642int racoon_hexdump(void *data, size_t length)
643{
644 return 0;
645}
646
647void close_on_exec(int fd)
648{
649 fcntl(fd, F_SETFD, FD_CLOEXEC);
650}
651
652/* sainfo.h */
653
654struct sainfo *getsainfo(const vchar_t *src, const vchar_t *dst,
655 const vchar_t *peer, const vchar_t *client, uint32_t remoteid)
656{
657 return &sainfo;
658}
659
660const char *sainfo2str(const struct sainfo *si)
661{
662 return "*";
663}
664
Chia-chi Yeh514ffe22011-07-07 13:52:27 -0700665/* throttle.h */
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700666
Chia-chi Yeh514ffe22011-07-07 13:52:27 -0700667int throttle_host(struct sockaddr *addr, int fail)
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700668{
669 return 0;
670}