]> git.saurik.com Git - apple/ipsec.git/blame - ipsec-tools/racoon/localconf.c
ipsec-164.9.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / localconf.c
CommitLineData
52b7d2ce
A
1/* $KAME: localconf.c,v 1.33 2001/08/09 07:32:19 sakane Exp $ */
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include "config.h"
33
34#include <sys/types.h>
35#include <sys/param.h>
36
37#include <stdlib.h>
38#include <stdio.h>
39#include <string.h>
40#include <errno.h>
41#include <ctype.h>
42#include <err.h>
43
44#include "var.h"
45#include "misc.h"
46#include "vmbuf.h"
47#include "plog.h"
48#include "debug.h"
49
50#include "localconf.h"
51#include "algorithm.h"
52#include "admin.h"
53#include "privsep.h"
54#include "isakmp_var.h"
55#include "isakmp.h"
56#include "ipsec_doi.h"
57#include "grabmyaddr.h"
58#include "vendorid.h"
59#include "str2val.h"
60#include "safefile.h"
61#include "admin.h"
62#include "gcmalloc.h"
63#include "session.h"
64
52b7d2ce 65#include <CoreFoundation/CoreFoundation.h>
d1e348cf 66#if HAVE_SECURITY_FRAMEWORK
52b7d2ce 67#include <Security/Security.h>
d1e348cf
A
68#else
69typedef void * SecKeychainRef;
70#endif
52b7d2ce
A
71
72struct localconf *lcconf;
73
74static void setdefault __P((void));
75
76void
77initlcconf()
78{
79 lcconf = racoon_calloc(1, sizeof(*lcconf));
80 if (lcconf == NULL)
81 errx(1, "failed to allocate local conf.");
82
83 setdefault();
84 lcconf->sock_vpncontrol = -1; /* not to be done during flush */
85 lcconf->racoon_conf = LC_DEFAULT_CF;
fd507379 86 TAILQ_INIT(&lcconf->saved_msg_queue);
52b7d2ce
A
87}
88
89void
90flushlcconf()
91{
92 int i;
93
94 setdefault();
95 clear_myaddr();
96 for (i = 0; i < LC_PATHTYPE_MAX; i++) {
97 if (lcconf->pathinfo[i]) {
98 racoon_free(lcconf->pathinfo[i]);
99 lcconf->pathinfo[i] = NULL;
100 }
101 }
102 for (i = 0; i < LC_IDENTTYPE_MAX; i++) {
103 if (lcconf->ident[i])
104 vfree(lcconf->ident[i]);
105 lcconf->ident[i] = NULL;
106 }
05434fec
A
107 if (lcconf->ext_nat_id) {
108 vfree(lcconf->ext_nat_id);
109 lcconf->ext_nat_id = NULL;
110 }
52b7d2ce
A
111}
112
113static void
114setdefault()
115{
116 lcconf->uid = 0;
117 lcconf->gid = 0;
118 lcconf->chroot = NULL;
119 lcconf->autograbaddr = 1;
120 lcconf->port_isakmp = PORT_ISAKMP;
121 lcconf->port_isakmp_natt = PORT_ISAKMP_NATT;
122 lcconf->default_af = AF_INET;
123 lcconf->pad_random = LC_DEFAULT_PAD_RANDOM;
124 lcconf->pad_randomlen = LC_DEFAULT_PAD_RANDOMLEN;
125 lcconf->pad_maxsize = LC_DEFAULT_PAD_MAXSIZE;
126 lcconf->pad_strict = LC_DEFAULT_PAD_STRICT;
127 lcconf->pad_excltail = LC_DEFAULT_PAD_EXCLTAIL;
128 lcconf->retry_counter = LC_DEFAULT_RETRY_COUNTER;
129 lcconf->retry_interval = LC_DEFAULT_RETRY_INTERVAL;
130 lcconf->count_persend = LC_DEFAULT_COUNT_PERSEND;
131 lcconf->secret_size = LC_DEFAULT_SECRETSIZE;
132 lcconf->retry_checkph1 = LC_DEFAULT_RETRY_CHECKPH1;
133 lcconf->wait_ph2complete = LC_DEFAULT_WAIT_PH2COMPLETE;
134 lcconf->strict_address = FALSE;
135 lcconf->complex_bundle = TRUE; /*XXX FALSE;*/
136 lcconf->gss_id_enc = LC_GSSENC_UTF16LE; /* Windows compatibility */
137 lcconf->natt_ka_interval = LC_DEFAULT_NATT_KA_INTERVAL;
138 lcconf->auto_exit_delay = 0;
139 lcconf->auto_exit_state &= ~LC_AUTOEXITSTATE_SET;
d1e348cf 140 lcconf->auto_exit_state |= LC_AUTOEXITSTATE_CLIENT; /* always auto exit as default */
52b7d2ce
A
141}
142
143/*
144 * get PSK by string.
145 */
146vchar_t *
147getpskbyname(id0)
148 vchar_t *id0;
149{
150 char *id;
151 vchar_t *key = NULL;
152
e8d9021d
A
153 plog(LLV_DEBUG, LOCATION, NULL, "Getting pre-shared key by name.\n");
154
52b7d2ce
A
155 id = racoon_calloc(1, 1 + id0->l - sizeof(struct ipsecdoi_id_b));
156 if (id == NULL) {
157 plog(LLV_ERROR, LOCATION, NULL,
158 "failed to get psk buffer.\n");
159 goto end;
160 }
161 memcpy(id, id0->v + sizeof(struct ipsecdoi_id_b),
162 id0->l - sizeof(struct ipsecdoi_id_b));
163 id[id0->l - sizeof(struct ipsecdoi_id_b)] = '\0';
164
e8d9021d 165#ifdef HAVE_OPENSSL
52b7d2ce 166 key = privsep_getpsk(id, id0->l - sizeof(struct ipsecdoi_id_b));
e8d9021d
A
167#else
168 key = getpsk(id, id0->l - sizeof(struct ipsecdoi_id_b));
169#endif
52b7d2ce
A
170
171end:
172 if (id)
173 racoon_free(id);
174 return key;
175}
176
e8d9021d 177#if HAVE_KEYCHAIN
52b7d2ce
A
178/*
179 * get PSK from keyChain.
180 */
181vchar_t *
182getpskfromkeychain(const char *name, u_int8_t etype, int secrettype, vchar_t *id_p)
183{
184 SecKeychainRef keychain = NULL;
185 vchar_t *key = NULL;
186 void *cur_password = NULL;
187 UInt32 cur_password_len = 0;
188 OSStatus status;
189 char serviceName[] = "com.apple.net.racoon";
190
e8d9021d
A
191 plog(LLV_DEBUG, LOCATION, NULL, "Getting pre-shared key from keychain.\n");
192
52b7d2ce
A
193 status = SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem);
194 if (status != noErr) {
195 plog(LLV_ERROR, LOCATION, NULL,
196 "failed to set system keychain domain.\n");
197 goto end;
198 }
199
200 status = SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem,
201 &keychain);
202 if (status != noErr) {
203 plog(LLV_ERROR, LOCATION, NULL,
204 "failed to get system keychain domain.\n");
205 goto end;
206 }
207
208 if (secrettype == SECRETTYPE_KEYCHAIN_BY_ID && etype == ISAKMP_ETYPE_AGG) {
209 /* try looking up based on peers id */
210
e8d9021d 211 char* peer_id = NULL;
52b7d2ce
A
212 int idlen = id_p->l - sizeof(struct ipsecdoi_id_b);
213 u_int8_t id_type = ((struct ipsecdoi_id_b *)(id_p->v))->type;
214
215 switch (id_type) {
216 case IPSECDOI_ID_IPV4_ADDR:
217 case IPSECDOI_ID_IPV6_ADDR:
218 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
219 case IPSECDOI_ID_IPV4_ADDR_RANGE:
220 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
221 case IPSECDOI_ID_IPV6_ADDR_RANGE:
222 case IPSECDOI_ID_DER_ASN1_DN:
223 case IPSECDOI_ID_DER_ASN1_GN:
d1e348cf 224 goto no_id;
52b7d2ce
A
225 break;
226
227 case IPSECDOI_ID_FQDN:
228 case IPSECDOI_ID_USER_FQDN:
229 case IPSECDOI_ID_KEY_ID:
e8d9021d 230 peer_id = racoon_malloc(1 + idlen);
52b7d2ce
A
231 if (peer_id == NULL)
232 goto end;
233 memcpy(peer_id, id_p->v + sizeof(struct ipsecdoi_id_b), idlen);
234 *(peer_id + idlen) = '\0';
235 plog(LLV_ERROR, LOCATION, NULL,
236 "getting shared secret from keychain using %s.\n", peer_id);
237
238 break;
239 default:
240 goto end;
241 break;
242 }
243
244 status = SecKeychainFindGenericPassword(keychain,
245 strlen(serviceName),
246 serviceName,
247 idlen,
248 peer_id,
249 &cur_password_len,
250 &cur_password,
251 NULL);
252
d1e348cf
A
253 /* try find it using using only the peer id. */
254 if (status == errSecItemNotFound)
255 status = SecKeychainFindGenericPassword(keychain,
256 idlen,
257 peer_id,
258 0,
259 0,
260 &cur_password_len,
261 &cur_password,
262 NULL);
e8d9021d
A
263 if (peer_id)
264 racoon_free(peer_id);
52b7d2ce
A
265 if (status == noErr)
266 goto end;
267 /* otherwise fall through to use the default value */
268 }
269
d1e348cf 270no_id:
52b7d2ce
A
271 /* use the value in remote config sharedsecret field
272 this is either the value specified for lookup or the
273 default when lookup by id fails.
274 */
275 status = SecKeychainFindGenericPassword(keychain,
276 strlen(serviceName),
277 serviceName,
278 strlen(name),
279 name,
280 &cur_password_len,
281 &cur_password,
282 NULL);
283
284 /* try find it using using only name. */
285 if (status == errSecItemNotFound)
286 status = SecKeychainFindGenericPassword(keychain,
287 strlen(name),
288 name,
289 0,
290 0,
291 &cur_password_len,
292 &cur_password,
293 NULL);
294
295 switch (status) {
296
297 case noErr :
298 goto end;
299 break;
300
301 case errSecItemNotFound :
302 break;
303
304 default :
305 plog(LLV_ERROR, LOCATION, NULL,
306 "failed to get preshared key from system keychain (error %d).\n", status);
307 }
308
309end:
310
311 if (cur_password) {
e8d9021d 312 key = vmalloc(cur_password_len);
52b7d2ce
A
313 if (key == NULL) {
314 plog(LLV_ERROR, LOCATION, NULL,
315 "failed to allocate key buffer.\n");
e8d9021d
A
316 } else
317 memcpy(key->v, cur_password, cur_password_len);
52b7d2ce
A
318 free(cur_password);
319 }
320
321 if (keychain)
322 CFRelease(keychain);
323
324 return key;
325}
326#endif
327
328/*
329 * get PSK by address.
330 */
331vchar_t *
332getpskbyaddr(remote)
85f41bec 333 struct sockaddr_storage *remote;
52b7d2ce
A
334{
335 vchar_t *key = NULL;
336 char addr[NI_MAXHOST], port[NI_MAXSERV];
337
e8d9021d
A
338 plog(LLV_DEBUG, LOCATION, NULL, "Getting pre-shared key by addr.\n");
339
85f41bec 340 GETNAMEINFO((struct sockaddr *)remote, addr, port);
52b7d2ce 341
e8d9021d 342#ifdef HAVE_OPENSSL
52b7d2ce 343 key = privsep_getpsk(addr, strlen(addr));
e8d9021d
A
344#else
345 key = getpsk(addr, strlen(addr));
346#endif
52b7d2ce
A
347
348 return key;
349}
350
351vchar_t *
352getpsk(str, len)
353 const char *str;
354 const int len;
355{
356 FILE *fp;
357 char buf[1024]; /* XXX how is variable length ? */
358 vchar_t *key = NULL;
359 char *p, *q;
360 size_t keylen;
361 char *k = NULL;
e8d9021d
A
362
363 plog(LLV_DEBUG, LOCATION, NULL, "Getting pre-shared key from file.\n");
52b7d2ce
A
364
365 if (safefile(lcconf->pathinfo[LC_PATHTYPE_PSK], 1) == 0)
366 fp = fopen(lcconf->pathinfo[LC_PATHTYPE_PSK], "r");
367 else
368 fp = NULL;
369 if (fp == NULL) {
370 plog(LLV_ERROR, LOCATION, NULL,
371 "failed to open pre_share_key file %s\n",
372 lcconf->pathinfo[LC_PATHTYPE_PSK]);
373 return NULL;
374 }
375
376 while (fgets(buf, sizeof(buf), fp) != NULL) {
377 /* comment line */
378 if (buf[0] == '#')
379 continue;
380
381 /* search the end of 1st string. */
382 for (p = buf; *p != '\0' && !isspace((int)*p); p++)
383 ;
384 if (*p == '\0')
385 continue; /* no 2nd parameter */
386 *p = '\0';
387 /* search the 1st of 2nd string. */
388 while (isspace((int)*++p))
389 ;
390 if (*p == '\0')
391 continue; /* no 2nd parameter */
392 p--;
393 if (strncmp(buf, str, len) == 0 && buf[len] == '\0') {
394 p++;
395 keylen = 0;
396 for (q = p; *q != '\0' && *q != '\n'; q++)
397 keylen++;
398 *q = '\0';
399
400 /* fix key if hex string */
401 if (strncmp(p, "0x", 2) == 0) {
402 k = str2val(p + 2, 16, &keylen);
403 if (k == NULL) {
404 plog(LLV_ERROR, LOCATION, NULL,
405 "failed to get psk buffer.\n");
406 goto end;
407 }
408 p = k;
409 }
410
411 key = vmalloc(keylen);
412 if (key == NULL) {
413 plog(LLV_ERROR, LOCATION, NULL,
414 "failed to allocate key buffer.\n");
415 goto end;
416 }
417 memcpy(key->v, p, key->l);
418 if (k)
419 racoon_free(k);
420 goto end;
421 }
422 }
423
424end:
425 fclose(fp);
426 return key;
427}
428
429/*
430 * get a file name of a type specified.
431 */
432void
433getpathname(path, len, type, name)
434 char *path;
435 int len, type;
436 const char *name;
437{
438 snprintf(path, len, "%s%s%s",
439 name[0] == '/' ? "" : lcconf->pathinfo[type],
440 name[0] == '/' ? "" : "/",
441 name);
442
443 plog(LLV_DEBUG, LOCATION, NULL, "filename: %s\n", path);
444}
445
446#if 0 /* DELETEIT */
447static int lc_doi2idtype[] = {
448 -1,
449 -1,
450 LC_IDENTTYPE_FQDN,
451 LC_IDENTTYPE_USERFQDN,
452 -1,
453 -1,
454 -1,
455 -1,
456 -1,
457 LC_IDENTTYPE_CERTNAME,
458 -1,
459 LC_IDENTTYPE_KEYID,
460};
461
462/*
463 * convert DOI value to idtype
464 * OUT -1 : NG
465 * other: converted.
466 */
467int
468doi2idtype(idtype)
469 int idtype;
470{
471 if (ARRAYLEN(lc_doi2idtype) > idtype)
472 return lc_doi2idtype[idtype];
473 return -1;
474}
475#endif
476
477static int lc_sittype2doi[] = {
478 IPSECDOI_SIT_IDENTITY_ONLY,
479 IPSECDOI_SIT_SECRECY,
480 IPSECDOI_SIT_INTEGRITY,
481};
482
483/*
484 * convert sittype to DOI value.
485 * OUT -1 : NG
486 * other: converted.
487 */
488int
489sittype2doi(sittype)
490 int sittype;
491{
492 if (ARRAYLEN(lc_sittype2doi) > sittype)
493 return lc_sittype2doi[sittype];
494 return -1;
495}
496
497static int lc_doitype2doi[] = {
498 IPSEC_DOI,
499};
500
501/*
502 * convert doitype to DOI value.
503 * OUT -1 : NG
504 * other: converted.
505 */
506int
507doitype2doi(doitype)
508 int doitype;
509{
510 if (ARRAYLEN(lc_doitype2doi) > doitype)
511 return lc_doitype2doi[doitype];
512 return -1;
513}
514
d1e348cf
A
515
516