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