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