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