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