]> git.saurik.com Git - apple/ipsec.git/blame - ipsec-tools/racoon/localconf.c
ipsec-93.13.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
65#ifdef __APPLE__
66#include <CoreFoundation/CoreFoundation.h>
d1e348cf 67#if HAVE_SECURITY_FRAMEWORK
52b7d2ce 68#include <Security/Security.h>
d1e348cf
A
69#else
70typedef void * SecKeychainRef;
71#endif
52b7d2ce
A
72#endif
73
74struct localconf *lcconf;
75
76static void setdefault __P((void));
77
78void
79initlcconf()
80{
81 lcconf = racoon_calloc(1, sizeof(*lcconf));
82 if (lcconf == NULL)
83 errx(1, "failed to allocate local conf.");
84
85 setdefault();
86 lcconf->sock_vpncontrol = -1; /* not to be done during flush */
87 lcconf->racoon_conf = LC_DEFAULT_CF;
fd507379 88 TAILQ_INIT(&lcconf->saved_msg_queue);
52b7d2ce
A
89}
90
91void
92flushlcconf()
93{
94 int i;
95
96 setdefault();
97 clear_myaddr();
98 for (i = 0; i < LC_PATHTYPE_MAX; i++) {
99 if (lcconf->pathinfo[i]) {
100 racoon_free(lcconf->pathinfo[i]);
101 lcconf->pathinfo[i] = NULL;
102 }
103 }
104 for (i = 0; i < LC_IDENTTYPE_MAX; i++) {
105 if (lcconf->ident[i])
106 vfree(lcconf->ident[i]);
107 lcconf->ident[i] = NULL;
108 }
05434fec
A
109 if (lcconf->ext_nat_id) {
110 vfree(lcconf->ext_nat_id);
111 lcconf->ext_nat_id = NULL;
112 }
52b7d2ce
A
113}
114
115static void
116setdefault()
117{
118 lcconf->uid = 0;
119 lcconf->gid = 0;
120 lcconf->chroot = NULL;
121 lcconf->autograbaddr = 1;
122 lcconf->port_isakmp = PORT_ISAKMP;
123 lcconf->port_isakmp_natt = PORT_ISAKMP_NATT;
124 lcconf->default_af = AF_INET;
125 lcconf->pad_random = LC_DEFAULT_PAD_RANDOM;
126 lcconf->pad_randomlen = LC_DEFAULT_PAD_RANDOMLEN;
127 lcconf->pad_maxsize = LC_DEFAULT_PAD_MAXSIZE;
128 lcconf->pad_strict = LC_DEFAULT_PAD_STRICT;
129 lcconf->pad_excltail = LC_DEFAULT_PAD_EXCLTAIL;
130 lcconf->retry_counter = LC_DEFAULT_RETRY_COUNTER;
131 lcconf->retry_interval = LC_DEFAULT_RETRY_INTERVAL;
132 lcconf->count_persend = LC_DEFAULT_COUNT_PERSEND;
133 lcconf->secret_size = LC_DEFAULT_SECRETSIZE;
134 lcconf->retry_checkph1 = LC_DEFAULT_RETRY_CHECKPH1;
135 lcconf->wait_ph2complete = LC_DEFAULT_WAIT_PH2COMPLETE;
136 lcconf->strict_address = FALSE;
137 lcconf->complex_bundle = TRUE; /*XXX FALSE;*/
138 lcconf->gss_id_enc = LC_GSSENC_UTF16LE; /* Windows compatibility */
139 lcconf->natt_ka_interval = LC_DEFAULT_NATT_KA_INTERVAL;
140 lcconf->auto_exit_delay = 0;
141 lcconf->auto_exit_state &= ~LC_AUTOEXITSTATE_SET;
d1e348cf 142 lcconf->auto_exit_state |= LC_AUTOEXITSTATE_CLIENT; /* always auto exit as default */
52b7d2ce
A
143}
144
145/*
146 * get PSK by string.
147 */
148vchar_t *
149getpskbyname(id0)
150 vchar_t *id0;
151{
152 char *id;
153 vchar_t *key = NULL;
154
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
165 key = privsep_getpsk(id, id0->l - sizeof(struct ipsecdoi_id_b));
166
167end:
168 if (id)
169 racoon_free(id);
170 return key;
171}
172
d1e348cf 173#if defined(__APPLE__) && HAVE_KEYCHAIN
52b7d2ce
A
174/*
175 * get PSK from keyChain.
176 */
177vchar_t *
178getpskfromkeychain(const char *name, u_int8_t etype, int secrettype, vchar_t *id_p)
179{
180 SecKeychainRef keychain = NULL;
181 vchar_t *key = NULL;
182 void *cur_password = NULL;
183 UInt32 cur_password_len = 0;
184 OSStatus status;
185 char serviceName[] = "com.apple.net.racoon";
186
187 status = SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem);
188 if (status != noErr) {
189 plog(LLV_ERROR, LOCATION, NULL,
190 "failed to set system keychain domain.\n");
191 goto end;
192 }
193
194 status = SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem,
195 &keychain);
196 if (status != noErr) {
197 plog(LLV_ERROR, LOCATION, NULL,
198 "failed to get system keychain domain.\n");
199 goto end;
200 }
201
202 if (secrettype == SECRETTYPE_KEYCHAIN_BY_ID && etype == ISAKMP_ETYPE_AGG) {
203 /* try looking up based on peers id */
204
205 char* peer_id;
206 int idlen = id_p->l - sizeof(struct ipsecdoi_id_b);
207 u_int8_t id_type = ((struct ipsecdoi_id_b *)(id_p->v))->type;
208
209 switch (id_type) {
210 case IPSECDOI_ID_IPV4_ADDR:
211 case IPSECDOI_ID_IPV6_ADDR:
212 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
213 case IPSECDOI_ID_IPV4_ADDR_RANGE:
214 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
215 case IPSECDOI_ID_IPV6_ADDR_RANGE:
216 case IPSECDOI_ID_DER_ASN1_DN:
217 case IPSECDOI_ID_DER_ASN1_GN:
d1e348cf 218 goto no_id;
52b7d2ce
A
219 break;
220
221 case IPSECDOI_ID_FQDN:
222 case IPSECDOI_ID_USER_FQDN:
223 case IPSECDOI_ID_KEY_ID:
224 peer_id = racoon_malloc(idlen);
225 if (peer_id == NULL)
226 goto end;
227 memcpy(peer_id, id_p->v + sizeof(struct ipsecdoi_id_b), idlen);
228 *(peer_id + idlen) = '\0';
229 plog(LLV_ERROR, LOCATION, NULL,
230 "getting shared secret from keychain using %s.\n", peer_id);
231
232 break;
233 default:
234 goto end;
235 break;
236 }
237
238 status = SecKeychainFindGenericPassword(keychain,
239 strlen(serviceName),
240 serviceName,
241 idlen,
242 peer_id,
243 &cur_password_len,
244 &cur_password,
245 NULL);
246
d1e348cf
A
247 /* try find it using using only the peer id. */
248 if (status == errSecItemNotFound)
249 status = SecKeychainFindGenericPassword(keychain,
250 idlen,
251 peer_id,
252 0,
253 0,
254 &cur_password_len,
255 &cur_password,
256 NULL);
257
52b7d2ce
A
258 if (status == noErr)
259 goto end;
260 /* otherwise fall through to use the default value */
261 }
262
d1e348cf 263no_id:
52b7d2ce
A
264 /* use the value in remote config sharedsecret field
265 this is either the value specified for lookup or the
266 default when lookup by id fails.
267 */
268 status = SecKeychainFindGenericPassword(keychain,
269 strlen(serviceName),
270 serviceName,
271 strlen(name),
272 name,
273 &cur_password_len,
274 &cur_password,
275 NULL);
276
277 /* try find it using using only name. */
278 if (status == errSecItemNotFound)
279 status = SecKeychainFindGenericPassword(keychain,
280 strlen(name),
281 name,
282 0,
283 0,
284 &cur_password_len,
285 &cur_password,
286 NULL);
287
288 switch (status) {
289
290 case noErr :
291 goto end;
292 break;
293
294 case errSecItemNotFound :
295 break;
296
297 default :
298 plog(LLV_ERROR, LOCATION, NULL,
299 "failed to get preshared key from system keychain (error %d).\n", status);
300 }
301
302end:
303
304 if (cur_password) {
305 key = vmalloc(cur_password_len + 1);
306 if (key == NULL) {
307 plog(LLV_ERROR, LOCATION, NULL,
308 "failed to allocate key buffer.\n");
309 } else {
310 memcpy(key->v, cur_password, key->l);
311 key->v[cur_password_len] = 0;
312 }
313 free(cur_password);
314 }
315
316 if (keychain)
317 CFRelease(keychain);
318
319 return key;
320}
321#endif
322
323/*
324 * get PSK by address.
325 */
326vchar_t *
327getpskbyaddr(remote)
328 struct sockaddr *remote;
329{
330 vchar_t *key = NULL;
331 char addr[NI_MAXHOST], port[NI_MAXSERV];
332
333 GETNAMEINFO(remote, addr, port);
334
335 key = privsep_getpsk(addr, strlen(addr));
336
337 return key;
338}
339
340vchar_t *
341getpsk(str, len)
342 const char *str;
343 const int len;
344{
345 FILE *fp;
346 char buf[1024]; /* XXX how is variable length ? */
347 vchar_t *key = NULL;
348 char *p, *q;
349 size_t keylen;
350 char *k = NULL;
351
352 if (safefile(lcconf->pathinfo[LC_PATHTYPE_PSK], 1) == 0)
353 fp = fopen(lcconf->pathinfo[LC_PATHTYPE_PSK], "r");
354 else
355 fp = NULL;
356 if (fp == NULL) {
357 plog(LLV_ERROR, LOCATION, NULL,
358 "failed to open pre_share_key file %s\n",
359 lcconf->pathinfo[LC_PATHTYPE_PSK]);
360 return NULL;
361 }
362
363 while (fgets(buf, sizeof(buf), fp) != NULL) {
364 /* comment line */
365 if (buf[0] == '#')
366 continue;
367
368 /* search the end of 1st string. */
369 for (p = buf; *p != '\0' && !isspace((int)*p); p++)
370 ;
371 if (*p == '\0')
372 continue; /* no 2nd parameter */
373 *p = '\0';
374 /* search the 1st of 2nd string. */
375 while (isspace((int)*++p))
376 ;
377 if (*p == '\0')
378 continue; /* no 2nd parameter */
379 p--;
380 if (strncmp(buf, str, len) == 0 && buf[len] == '\0') {
381 p++;
382 keylen = 0;
383 for (q = p; *q != '\0' && *q != '\n'; q++)
384 keylen++;
385 *q = '\0';
386
387 /* fix key if hex string */
388 if (strncmp(p, "0x", 2) == 0) {
389 k = str2val(p + 2, 16, &keylen);
390 if (k == NULL) {
391 plog(LLV_ERROR, LOCATION, NULL,
392 "failed to get psk buffer.\n");
393 goto end;
394 }
395 p = k;
396 }
397
398 key = vmalloc(keylen);
399 if (key == NULL) {
400 plog(LLV_ERROR, LOCATION, NULL,
401 "failed to allocate key buffer.\n");
402 goto end;
403 }
404 memcpy(key->v, p, key->l);
405 if (k)
406 racoon_free(k);
407 goto end;
408 }
409 }
410
411end:
412 fclose(fp);
413 return key;
414}
415
416/*
417 * get a file name of a type specified.
418 */
419void
420getpathname(path, len, type, name)
421 char *path;
422 int len, type;
423 const char *name;
424{
425 snprintf(path, len, "%s%s%s",
426 name[0] == '/' ? "" : lcconf->pathinfo[type],
427 name[0] == '/' ? "" : "/",
428 name);
429
430 plog(LLV_DEBUG, LOCATION, NULL, "filename: %s\n", path);
431}
432
433#if 0 /* DELETEIT */
434static int lc_doi2idtype[] = {
435 -1,
436 -1,
437 LC_IDENTTYPE_FQDN,
438 LC_IDENTTYPE_USERFQDN,
439 -1,
440 -1,
441 -1,
442 -1,
443 -1,
444 LC_IDENTTYPE_CERTNAME,
445 -1,
446 LC_IDENTTYPE_KEYID,
447};
448
449/*
450 * convert DOI value to idtype
451 * OUT -1 : NG
452 * other: converted.
453 */
454int
455doi2idtype(idtype)
456 int idtype;
457{
458 if (ARRAYLEN(lc_doi2idtype) > idtype)
459 return lc_doi2idtype[idtype];
460 return -1;
461}
462#endif
463
464static int lc_sittype2doi[] = {
465 IPSECDOI_SIT_IDENTITY_ONLY,
466 IPSECDOI_SIT_SECRECY,
467 IPSECDOI_SIT_INTEGRITY,
468};
469
470/*
471 * convert sittype to DOI value.
472 * OUT -1 : NG
473 * other: converted.
474 */
475int
476sittype2doi(sittype)
477 int sittype;
478{
479 if (ARRAYLEN(lc_sittype2doi) > sittype)
480 return lc_sittype2doi[sittype];
481 return -1;
482}
483
484static int lc_doitype2doi[] = {
485 IPSEC_DOI,
486};
487
488/*
489 * convert doitype to DOI value.
490 * OUT -1 : NG
491 * other: converted.
492 */
493int
494doitype2doi(doitype)
495 int doitype;
496{
497 if (ARRAYLEN(lc_doitype2doi) > doitype)
498 return lc_doitype2doi[doitype];
499 return -1;
500}
501
d1e348cf
A
502
503