1 /*        $NetBSD: localconf.c,v 1.12 2025/03/08 16:39:08 christos Exp $        */
2 
3 /*        $KAME: localconf.c,v 1.33 2001/08/09 07:32:19 sakane Exp $  */
4 
5 /*
6  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the project nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include "config.h"
35 
36 #include <sys/types.h>
37 #include <sys/param.h>
38 
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <errno.h>
43 #include <ctype.h>
44 #include <err.h>
45 
46 #include "var.h"
47 #include "misc.h"
48 #include "vmbuf.h"
49 #include "plog.h"
50 #include "debug.h"
51 
52 #include "localconf.h"
53 #include "algorithm.h"
54 #include "admin.h"
55 #include "privsep.h"
56 #include "isakmp_var.h"
57 #include "isakmp.h"
58 #include "ipsec_doi.h"
59 #include "grabmyaddr.h"
60 #include "vendorid.h"
61 #include "str2val.h"
62 #include "safefile.h"
63 #include "admin.h"
64 #include "gcmalloc.h"
65 
66 struct localconf *lcconf = NULL;
67 
68 static void setdefault(void);
69 
70 void
initlcconf()71 initlcconf()
72 {
73           if (lcconf == NULL) {
74                     lcconf = racoon_calloc(1, sizeof(*lcconf));
75                     if (lcconf == NULL)
76                               errx(1, "failed to allocate local conf.");
77 
78                     // Important: assure all pointers within lcconf to be NULL.
79                     memset(lcconf, 0, sizeof(*lcconf));
80           }
81 
82           setdefault();
83           lcconf->racoon_conf = __UNCONST(LC_DEFAULT_CF);
84 }
85 
86 void
lcconf_setchroot(char * chroot)87 lcconf_setchroot(char* chroot)
88 {
89           if (lcconf->chroot) {
90                     racoon_free(lcconf->chroot);
91                     lcconf->chroot = NULL;
92           }
93           lcconf->chroot = chroot;
94 }
95 
96 int
lcconf_setpath(char * path,unsigned int path_type)97 lcconf_setpath(char* path, unsigned int path_type)
98 {
99           if (path_type >= LC_PATHTYPE_MAX)
100                     return -1;
101 
102           if (lcconf->pathinfo[path_type])
103                     racoon_free(lcconf->pathinfo[path_type]);
104 
105           lcconf->pathinfo[path_type] = path;
106 
107           return 0;
108 }
109 
110 void
flushlcconf()111 flushlcconf()
112 {
113           int i;
114 
115           setdefault();
116           myaddr_flush();
117 
118           for (i = 0; i < LC_PATHTYPE_MAX; i++) {
119                     if (lcconf->pathinfo[i]) {
120                               racoon_free(lcconf->pathinfo[i]);
121                               lcconf->pathinfo[i] = NULL;
122                     }
123           }
124 }
125 
126 static void
setdefault()127 setdefault()
128 {
129           lcconf->uid = 0;
130           lcconf->gid = 0;
131 
132           {
133                     int i = 0;
134                     for (; i < LC_PATHTYPE_MAX; i++) {
135                               if (lcconf->pathinfo[i]) {
136                                         racoon_free(lcconf->pathinfo[i]);
137                                         lcconf->pathinfo[i] = NULL;
138                               }
139                     }
140           }
141 
142           lcconf_setchroot(NULL);
143 
144           lcconf->port_isakmp = PORT_ISAKMP;
145           lcconf->port_isakmp_natt = PORT_ISAKMP_NATT;
146           lcconf->default_af = AF_INET;
147           lcconf->pad_random = LC_DEFAULT_PAD_RANDOM;
148           lcconf->pad_randomlen = LC_DEFAULT_PAD_RANDOMLEN;
149           lcconf->pad_maxsize = LC_DEFAULT_PAD_MAXSIZE;
150           lcconf->pad_strict = LC_DEFAULT_PAD_STRICT;
151           lcconf->pad_excltail = LC_DEFAULT_PAD_EXCLTAIL;
152           lcconf->retry_counter = LC_DEFAULT_RETRY_COUNTER;
153           lcconf->retry_interval = LC_DEFAULT_RETRY_INTERVAL;
154           lcconf->count_persend = LC_DEFAULT_COUNT_PERSEND;
155           lcconf->secret_size = LC_DEFAULT_SECRETSIZE;
156           lcconf->retry_checkph1 = LC_DEFAULT_RETRY_CHECKPH1;
157           lcconf->wait_ph2complete = LC_DEFAULT_WAIT_PH2COMPLETE;
158           lcconf->strict_address = FALSE;
159           lcconf->complex_bundle = TRUE; /*XXX FALSE;*/
160           lcconf->gss_id_enc = LC_GSSENC_UTF16LE; /* Windows compatibility */
161           lcconf->natt_ka_interval = LC_DEFAULT_NATT_KA_INTERVAL;
162           lcconf->pfkey_buffer_size = LC_DEFAULT_PFKEY_BUFFER_SIZE;
163 }
164 
165 /*
166  * get PSK by string.
167  */
168 vchar_t *
getpskbyname(vchar_t * id0)169 getpskbyname(vchar_t *id0)
170 {
171           char *id;
172           vchar_t *key = NULL;
173 
174           id = racoon_calloc(1, 1 + id0->l - sizeof(struct ipsecdoi_id_b));
175           if (id == NULL) {
176                     plog(LLV_ERROR, LOCATION, NULL,
177                               "failed to get psk buffer.\n");
178                     goto end;
179           }
180           memcpy(id, id0->v + sizeof(struct ipsecdoi_id_b),
181                     id0->l - sizeof(struct ipsecdoi_id_b));
182           id[id0->l - sizeof(struct ipsecdoi_id_b)] = '\0';
183 
184           key = privsep_getpsk(id, id0->l - sizeof(struct ipsecdoi_id_b));
185 
186 end:
187           if (id)
188                     racoon_free(id);
189           return key;
190 }
191 
192 /*
193  * get PSK by address.
194  */
195 vchar_t *
getpskbyaddr(struct sockaddr * remote)196 getpskbyaddr(struct sockaddr *remote)
197 {
198           vchar_t *key = NULL;
199           char addr[NI_MAXHOST], port[NI_MAXSERV];
200 
201           GETNAMEINFO(remote, addr, port);
202 
203           key = privsep_getpsk(addr, strlen(addr));
204 
205           return key;
206 }
207 
208 vchar_t *
getpsk(const char * str,const int len)209 getpsk(const char *str, const int len)
210 {
211           FILE *fp;
212           char buf[1024];     /* XXX how is variable length ? */
213           vchar_t *key = NULL;
214           char *p, *q;
215           size_t keylen;
216           char *k = NULL;
217 
218           if (safefile(lcconf->pathinfo[LC_PATHTYPE_PSK], 1) == 0)
219                     fp = fopen(lcconf->pathinfo[LC_PATHTYPE_PSK], "r");
220           else
221                     fp = NULL;
222           if (fp == NULL) {
223                     plog(LLV_ERROR, LOCATION, NULL,
224                               "failed to open pre_share_key file %s\n",
225                               lcconf->pathinfo[LC_PATHTYPE_PSK]);
226                     return NULL;
227           }
228 
229           while (fgets(buf, sizeof(buf), fp) != NULL) {
230                     /* comment line */
231                     if (buf[0] == '#')
232                               continue;
233 
234                     /* search the end of 1st string. */
235                     for (p = buf; *p != '\0' && !isspace((unsigned char)*p); p++)
236                               continue;
237                     if (*p == '\0')
238                               continue; /* no 2nd parameter */
239                     *p = '\0';
240                     /* search the 1st of 2nd string. */
241                     while (isspace((unsigned char)*++p))
242                               continue;
243                     if (*p == '\0')
244                               continue; /* no 2nd parameter */
245                     p--;
246                     if (
247 #ifdef ENABLE_WILDCARD_MATCH
248                         strncmp(buf, "*", 2) == 0 ||
249 #endif
250                         (strncmp(buf, str, len) == 0 && buf[len] == '\0')) {
251                               p++;
252                               keylen = 0;
253                               for (q = p; *q != '\0' && *q != '\n'; q++)
254                                         keylen++;
255                               *q = '\0';
256 
257                               /* fix key if hex string */
258                               if (strncmp(p, "0x", 2) == 0) {
259                                         k = str2val(p + 2, 16, &keylen);
260                                         if (k == NULL) {
261                                                   plog(LLV_ERROR, LOCATION, NULL,
262                                                             "failed to get psk buffer.\n");
263                                                   goto end;
264                                         }
265                                         p = k;
266                               }
267 
268                               key = vmalloc(keylen);
269                               if (key == NULL) {
270                                         plog(LLV_ERROR, LOCATION, NULL,
271                                                   "failed to allocate key buffer.\n");
272                                         goto end;
273                               }
274                               memcpy(key->v, p, key->l);
275                               if (k)
276                                         racoon_free(k);
277                               goto end;
278                     }
279           }
280 
281 end:
282           fclose(fp);
283           return key;
284 }
285 
286 /*
287  * get a file name of a type specified.
288  */
289 void
getpathname(char * path,int len,int type,const char * name)290 getpathname(char *path, int len, int type, const char *name)
291 {
292           snprintf(path, len, "%s%s%s",
293                     name[0] == '/' ? "" : lcconf->pathinfo[type],
294                     name[0] == '/' ? "" : "/",
295                     name);
296 
297           plog(LLV_DEBUG, LOCATION, NULL, "filename: %s\n", path);
298 }
299 
300 #if 0 /* DELETEIT */
301 static int lc_doi2idtype[] = {
302           -1,
303           -1,
304           LC_IDENTTYPE_FQDN,
305           LC_IDENTTYPE_USERFQDN,
306           -1,
307           -1,
308           -1,
309           -1,
310           -1,
311           LC_IDENTTYPE_CERTNAME,
312           -1,
313           LC_IDENTTYPE_KEYID,
314 };
315 
316 /*
317  * convert DOI value to idtype
318  * OUT    -1   : NG
319  *        other: converted.
320  */
321 int
322 doi2idtype(idtype)
323           int idtype;
324 {
325           if (ARRAYLEN(lc_doi2idtype) > idtype)
326                     return lc_doi2idtype[idtype];
327           return -1;
328 }
329 #endif
330 
331 static int lc_sittype2doi[] = {
332           IPSECDOI_SIT_IDENTITY_ONLY,
333           IPSECDOI_SIT_SECRECY,
334           IPSECDOI_SIT_INTEGRITY,
335 };
336 
337 /*
338  * convert sittype to DOI value.
339  * OUT    -1   : NG
340  *        other: converted.
341  */
342 int
sittype2doi(int sittype)343 sittype2doi(int sittype)
344 {
345           if (ARRAYLEN(lc_sittype2doi) > sittype)
346                     return lc_sittype2doi[sittype];
347           return -1;
348 }
349 
350 static int lc_doitype2doi[] = {
351           IPSEC_DOI,
352 };
353 
354 /*
355  * convert doitype to DOI value.
356  * OUT    -1   : NG
357  *        other: converted.
358  */
359 int
doitype2doi(int doitype)360 doitype2doi(int doitype)
361 {
362           if (ARRAYLEN(lc_doitype2doi) > doitype)
363                     return lc_doitype2doi[doitype];
364           return -1;
365 }
366 
367 
368 
369 static void
saverestore_params(int f)370 saverestore_params(int f)
371 {
372           static uint16_t s_port_isakmp;
373 
374           /* 0: save, 1: restore */
375           if (f) {
376                     lcconf->port_isakmp = s_port_isakmp;
377           } else {
378                     s_port_isakmp = lcconf->port_isakmp;
379           }
380 }
381 
382 void
restore_params()383 restore_params()
384 {
385           saverestore_params(1);
386 }
387 
388 void
save_params()389 save_params()
390 {
391           saverestore_params(0);
392 }
393