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