2 conf.c -- configuration code
3 Copyright (C) 1998 Robert van der Meulen
4 1998-2001 Ivo Timmermans <itimmermans@bigfoot.com>
5 2000,2001 Guus Sliepen <guus@sliepen.warande.net>
6 2000 Cris van Pelt <tribbel@arise.dhs.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 $Id: conf.c,v 1.9.4.40 2001/01/17 01:30:05 zarq Exp $
35 #include <sys/types.h>
40 #include <utils.h> /* for cp */
43 #include "netutl.h" /* for strtoip */
47 config_t *config = NULL;
49 int timeout = 0; /* seconds before timeout */
50 char *confbase = NULL; /* directory in which all config files are */
51 char *netname = NULL; /* name of the vpn network */
53 /* Will be set if HUP signal is received. It will be processed when it is safe. */
57 These are all the possible configurable values
59 static internal_config_t hazahaza[] = {
60 /* Main configuration file keywords */
61 { "ConnectTo", config_connectto, TYPE_NAME },
62 { "Hostnames", config_hostnames, TYPE_BOOL },
63 { "Interface", config_interface, TYPE_NAME },
64 { "InterfaceIP", config_interfaceip, TYPE_IP },
65 { "KeyExpire", config_keyexpire, TYPE_INT },
66 { "MyVirtualIP", config_dummy, TYPE_IP },
67 { "MyOwnVPNIP", config_dummy, TYPE_IP },
68 { "Name", config_name, TYPE_NAME },
69 { "PingTimeout", config_pingtimeout, TYPE_INT },
70 { "PrivateKey", config_privatekey, TYPE_NAME },
71 { "PrivateKeyFile", config_privatekeyfile, TYPE_NAME },
72 { "TapDevice", config_tapdevice, TYPE_NAME },
73 { "VpnMask", config_dummy, TYPE_IP },
74 /* Host configuration file keywords */
75 { "Address", config_address, TYPE_NAME },
76 { "IndirectData", config_indirectdata, TYPE_BOOL },
77 { "Port", config_port, TYPE_INT },
78 { "PublicKey", config_publickey, TYPE_NAME },
79 { "PublicKeyFile", config_publickeyfile, TYPE_NAME },
80 { "RestrictAddress", config_restrictaddress, TYPE_BOOL },
81 { "RestrictHosts", config_restricthosts, TYPE_BOOL },
82 { "RestrictPort", config_restrictport, TYPE_BOOL },
83 { "RestrictSubnets", config_restrictsubnets, TYPE_BOOL },
84 { "Subnet", config_subnet, TYPE_IP }, /* Use IPv4 subnets only for now */
85 { "TCPonly", config_tcponly, TYPE_BOOL },
90 Add given value to the list of configs cfg
93 add_config_val(config_t **cfg, int argtype, char *val)
98 p = (config_t*)xmalloc(sizeof(*p));
104 p->data.val = strtol(val, &q, 0);
109 p->data.ptr = xmalloc(strlen(val) + 1);
110 strcpy(p->data.ptr, val);
113 p->data.ip = strtoip(val);
116 if(!strcasecmp("yes", val))
117 p->data.val = stupid_true;
118 else if(!strcasecmp("no", val))
119 p->data.val = stupid_false;
124 p->argtype = argtype;
142 Read exactly one line and strip the trailing newline if any. If the
143 file was on EOF, return NULL. Otherwise, return all the data in a
144 dynamically allocated buffer.
146 If line is non-NULL, it will be used as an initial buffer, to avoid
147 unnecessary mallocing each time this function is called. If buf is
148 given, and buf needs to be expanded, the var pointed to by buflen
151 char *readline(FILE *fp, char **buf, size_t *buflen)
153 char *newline = NULL;
155 char *line; /* The array that contains everything that has been read
157 char *idx; /* Read into this pointer, which points to an offset
159 size_t size, newsize; /* The size of the current array pointed to by
161 size_t maxlen; /* Maximum number of characters that may be read with
162 fgets. This is newsize - oldsize. */
167 if((buf != NULL) && (buflen != NULL))
175 line = xmalloc(size);
184 p = fgets(idx, maxlen, fp);
185 if(p == NULL) /* EOF or error */
190 /* otherwise: error; let the calling function print an error
191 message if applicable */
196 newline = strchr(p, '\n');
198 /* We haven't yet read everything to the end of the line */
201 line = xrealloc(line, newsize);
202 idx = &line[size - 1];
203 maxlen = newsize - size + 1;
208 *newline = '\0'; /* kill newline */
213 if((buf != NULL) && (buflen != NULL))
222 Parse a configuration file and put the results in the configuration tree
225 int read_config_file(config_t **base, const char *fname)
227 int err = -2; /* Parse error */
231 int i, lineno = 0, ignore = 0;
236 if((fp = fopen (fname, "r")) == NULL)
238 syslog(LOG_ERR, _("Cannot open config file %s: %m"), fname);
243 buffer = xmalloc(bufsize);
248 if((line = readline(fp, &buffer, &bufsize)) == NULL)
262 if((p = strtok(line, "\t =")) == NULL)
263 continue; /* no tokens on this line */
266 continue; /* comment: ignore */
268 if(!strcmp(p, "-----BEGIN"))
273 for(i = 0; hazahaza[i].name != NULL; i++)
274 if(!strcasecmp(hazahaza[i].name, p))
277 if(!hazahaza[i].name)
279 syslog(LOG_ERR, _("Invalid variable name `%s' on line %d while reading config file %s"),
284 if(((q = strtok(NULL, "\t\n\r =")) == NULL) || q[0] == '#')
286 syslog(LOG_ERR, _("No value for variable `%s' on line %d while reading config file %s"),
287 hazahaza[i].name, lineno, fname);
291 cfg = add_config_val(base, hazahaza[i].argtype, q);
294 syslog(LOG_ERR, _("Invalid value for variable `%s' on line %d while reading config file %s"),
295 hazahaza[i].name, lineno, fname);
299 cfg->which = hazahaza[i].which;
304 if(!strcmp(p, "-----END"))
314 int read_server_config()
319 asprintf(&fname, "%s/tinc.conf", confbase);
320 x = read_config_file(&config, fname);
321 if(x == -1) /* System error: complain */
323 syslog(LOG_ERR, _("Failed to read `%s': %m"),
332 Look up the value of the config option type
334 const config_t *get_config_val(config_t *p, which_t type)
337 for(; p != NULL; p = p->next)
345 Remove the complete configuration tree.
347 void clear_config(config_t **base)
351 for(p = *base; p != NULL; p = next)
354 if(p->data.ptr && (p->argtype == TYPE_NAME))
364 int isadir(const char* f)
371 return S_ISDIR(s.st_mode);
374 int is_safe_path(const char *file)
384 syslog(LOG_ERR, _("`%s' is not an absolute path"), file);
388 p = strrchr(file, '/');
390 if(p == file) /* It's in the root */
400 syslog(LOG_ERR, _("Couldn't stat `%s': %m"),
405 if(s.st_uid != geteuid())
407 syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"),
408 f, s.st_uid, geteuid());
412 if(S_ISLNK(s.st_mode))
414 syslog(LOG_WARNING, _("Warning: `%s' is a symlink"),
417 if(readlink(f, l, MAXBUFSIZE) < 0)
419 syslog(LOG_ERR, _("Unable to read symbolic link `%s': %m"), f);
431 if(lstat(f, &s) < 0 && errno != ENOENT)
433 syslog(LOG_ERR, _("Couldn't stat `%s': %m"),
441 if(s.st_uid != geteuid())
443 syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"),
444 f, s.st_uid, geteuid());
448 if(S_ISLNK(s.st_mode))
450 syslog(LOG_WARNING, _("Warning: `%s' is a symlink"),
453 if(readlink(f, l, MAXBUFSIZE) < 0)
455 syslog(LOG_ERR, _("Unable to read symbolic link `%s': %m"), f);
465 /* Accessible by others */
466 syslog(LOG_ERR, _("`%s' has unsecure permissions"),
474 FILE *ask_and_safe_open(const char* filename, const char* what, const char* mode)
480 /* Check stdin and stdout */
481 if(!isatty(0) || !isatty(1))
483 /* Argh, they are running us from a script or something. Write
484 the files to the current directory and let them burn in hell
486 fn = xstrdup(filename);
490 /* Ask for a file and/or directory name. */
491 fprintf(stdout, _("Please enter a file to save %s to [%s]: "),
495 if((fn = readline(stdin, NULL, NULL)) == NULL)
497 fprintf(stderr, _("Error while reading stdin: %m\n"));
502 /* User just pressed enter. */
503 fn = xstrdup(filename);
506 if((strchr(fn, '/') == NULL) || (fn[0] != '/'))
508 /* The directory is a relative path or a filename. */
511 directory = get_current_dir_name();
512 asprintf(&p, "%s/%s", directory, fn);
518 umask(0077); /* Disallow everything for group and other */
520 /* Open it first to keep the inode busy */
521 if((r = fopen(fn, mode)) == NULL)
523 fprintf(stderr, _("Error opening file `%s': %m\n"),
529 /* Then check the file for nasty attacks */
530 if(!is_safe_path(fn)) /* Do not permit any directories that are
531 readable or writeable by other users. */
533 fprintf(stderr, _("The file `%s' (or any of the leading directories) has unsafe permissions.\n"
534 "I will not create or overwrite this file.\n"),