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.41 2001/06/05 19:39:54 guus 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 },
86 { "Mode", config_mode, TYPE_NAME },
91 Add given value to the list of configs cfg
94 add_config_val(config_t **cfg, int argtype, char *val)
99 p = (config_t*)xmalloc(sizeof(*p));
105 p->data.val = strtol(val, &q, 0);
110 p->data.ptr = xmalloc(strlen(val) + 1);
111 strcpy(p->data.ptr, val);
114 p->data.ip = strtoip(val);
117 if(!strcasecmp("yes", val))
118 p->data.val = stupid_true;
119 else if(!strcasecmp("no", val))
120 p->data.val = stupid_false;
125 p->argtype = argtype;
143 Read exactly one line and strip the trailing newline if any. If the
144 file was on EOF, return NULL. Otherwise, return all the data in a
145 dynamically allocated buffer.
147 If line is non-NULL, it will be used as an initial buffer, to avoid
148 unnecessary mallocing each time this function is called. If buf is
149 given, and buf needs to be expanded, the var pointed to by buflen
152 char *readline(FILE *fp, char **buf, size_t *buflen)
154 char *newline = NULL;
156 char *line; /* The array that contains everything that has been read
158 char *idx; /* Read into this pointer, which points to an offset
160 size_t size, newsize; /* The size of the current array pointed to by
162 size_t maxlen; /* Maximum number of characters that may be read with
163 fgets. This is newsize - oldsize. */
168 if((buf != NULL) && (buflen != NULL))
176 line = xmalloc(size);
185 p = fgets(idx, maxlen, fp);
186 if(p == NULL) /* EOF or error */
191 /* otherwise: error; let the calling function print an error
192 message if applicable */
197 newline = strchr(p, '\n');
199 /* We haven't yet read everything to the end of the line */
202 line = xrealloc(line, newsize);
203 idx = &line[size - 1];
204 maxlen = newsize - size + 1;
209 *newline = '\0'; /* kill newline */
214 if((buf != NULL) && (buflen != NULL))
223 Parse a configuration file and put the results in the configuration tree
226 int read_config_file(config_t **base, const char *fname)
228 int err = -2; /* Parse error */
232 int i, lineno = 0, ignore = 0;
237 if((fp = fopen (fname, "r")) == NULL)
239 syslog(LOG_ERR, _("Cannot open config file %s: %m"), fname);
244 buffer = xmalloc(bufsize);
249 if((line = readline(fp, &buffer, &bufsize)) == NULL)
263 if((p = strtok(line, "\t =")) == NULL)
264 continue; /* no tokens on this line */
267 continue; /* comment: ignore */
269 if(!strcmp(p, "-----BEGIN"))
274 for(i = 0; hazahaza[i].name != NULL; i++)
275 if(!strcasecmp(hazahaza[i].name, p))
278 if(!hazahaza[i].name)
280 syslog(LOG_ERR, _("Invalid variable name `%s' on line %d while reading config file %s"),
285 if(((q = strtok(NULL, "\t\n\r =")) == NULL) || q[0] == '#')
287 syslog(LOG_ERR, _("No value for variable `%s' on line %d while reading config file %s"),
288 hazahaza[i].name, lineno, fname);
292 cfg = add_config_val(base, hazahaza[i].argtype, q);
295 syslog(LOG_ERR, _("Invalid value for variable `%s' on line %d while reading config file %s"),
296 hazahaza[i].name, lineno, fname);
300 cfg->which = hazahaza[i].which;
305 if(!strcmp(p, "-----END"))
315 int read_server_config()
320 asprintf(&fname, "%s/tinc.conf", confbase);
321 x = read_config_file(&config, fname);
322 if(x == -1) /* System error: complain */
324 syslog(LOG_ERR, _("Failed to read `%s': %m"),
333 Look up the value of the config option type
335 const config_t *get_config_val(config_t *p, which_t type)
338 for(; p != NULL; p = p->next)
346 Remove the complete configuration tree.
348 void clear_config(config_t **base)
352 for(p = *base; p != NULL; p = next)
355 if(p->data.ptr && (p->argtype == TYPE_NAME))
365 int isadir(const char* f)
372 return S_ISDIR(s.st_mode);
375 int is_safe_path(const char *file)
385 syslog(LOG_ERR, _("`%s' is not an absolute path"), file);
389 p = strrchr(file, '/');
391 if(p == file) /* It's in the root */
401 syslog(LOG_ERR, _("Couldn't stat `%s': %m"),
406 if(s.st_uid != geteuid())
408 syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"),
409 f, s.st_uid, geteuid());
413 if(S_ISLNK(s.st_mode))
415 syslog(LOG_WARNING, _("Warning: `%s' is a symlink"),
418 if(readlink(f, l, MAXBUFSIZE) < 0)
420 syslog(LOG_ERR, _("Unable to read symbolic link `%s': %m"), f);
432 if(lstat(f, &s) < 0 && errno != ENOENT)
434 syslog(LOG_ERR, _("Couldn't stat `%s': %m"),
442 if(s.st_uid != geteuid())
444 syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"),
445 f, s.st_uid, geteuid());
449 if(S_ISLNK(s.st_mode))
451 syslog(LOG_WARNING, _("Warning: `%s' is a symlink"),
454 if(readlink(f, l, MAXBUFSIZE) < 0)
456 syslog(LOG_ERR, _("Unable to read symbolic link `%s': %m"), f);
466 /* Accessible by others */
467 syslog(LOG_ERR, _("`%s' has unsecure permissions"),
475 FILE *ask_and_safe_open(const char* filename, const char* what, const char* mode)
481 /* Check stdin and stdout */
482 if(!isatty(0) || !isatty(1))
484 /* Argh, they are running us from a script or something. Write
485 the files to the current directory and let them burn in hell
487 fn = xstrdup(filename);
491 /* Ask for a file and/or directory name. */
492 fprintf(stdout, _("Please enter a file to save %s to [%s]: "),
496 if((fn = readline(stdin, NULL, NULL)) == NULL)
498 fprintf(stderr, _("Error while reading stdin: %m\n"));
503 /* User just pressed enter. */
504 fn = xstrdup(filename);
507 if((strchr(fn, '/') == NULL) || (fn[0] != '/'))
509 /* The directory is a relative path or a filename. */
512 directory = get_current_dir_name();
513 asprintf(&p, "%s/%s", directory, fn);
519 umask(0077); /* Disallow everything for group and other */
521 /* Open it first to keep the inode busy */
522 if((r = fopen(fn, mode)) == NULL)
524 fprintf(stderr, _("Error opening file `%s': %m\n"),
530 /* Then check the file for nasty attacks */
531 if(!is_safe_path(fn)) /* Do not permit any directories that are
532 readable or writeable by other users. */
534 fprintf(stderr, _("The file `%s' (or any of the leading directories) has unsafe permissions.\n"
535 "I will not create or overwrite this file.\n"),