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.42 2001/07/24 20:03:40 guus Exp $
35 #include <sys/types.h>
41 #include <utils.h> /* for cp */
44 #include "netutl.h" /* for strtoip */
48 config_t *config = NULL;
50 int timeout = 0; /* seconds before timeout */
51 char *confbase = NULL; /* directory in which all config files are */
52 char *netname = NULL; /* name of the vpn network */
54 /* Will be set if HUP signal is received. It will be processed when it is safe. */
58 These are all the possible configurable values
60 static internal_config_t hazahaza[] = {
61 /* Main configuration file keywords */
62 { "ConnectTo", config_connectto, TYPE_NAME },
63 { "Hostnames", config_hostnames, TYPE_BOOL },
64 { "Interface", config_interface, TYPE_NAME },
65 { "InterfaceIP", config_interfaceip, TYPE_IP },
66 { "KeyExpire", config_keyexpire, TYPE_INT },
67 { "MyVirtualIP", config_dummy, TYPE_IP },
68 { "MyOwnVPNIP", config_dummy, TYPE_IP },
69 { "Name", config_name, TYPE_NAME },
70 { "PingTimeout", config_pingtimeout, TYPE_INT },
71 { "PrivateKey", config_privatekey, TYPE_NAME },
72 { "PrivateKeyFile", config_privatekeyfile, TYPE_NAME },
73 { "TapDevice", config_tapdevice, TYPE_NAME },
74 { "VpnMask", config_dummy, TYPE_IP },
75 /* Host configuration file keywords */
76 { "Address", config_address, TYPE_NAME },
77 { "IndirectData", config_indirectdata, TYPE_BOOL },
78 { "Port", config_port, TYPE_INT },
79 { "PublicKey", config_publickey, TYPE_NAME },
80 { "PublicKeyFile", config_publickeyfile, TYPE_NAME },
81 { "RestrictAddress", config_restrictaddress, TYPE_BOOL },
82 { "RestrictHosts", config_restricthosts, TYPE_BOOL },
83 { "RestrictPort", config_restrictport, TYPE_BOOL },
84 { "RestrictSubnets", config_restrictsubnets, TYPE_BOOL },
85 { "Subnet", config_subnet, TYPE_IP }, /* Use IPv4 subnets only for now */
86 { "TCPonly", config_tcponly, TYPE_BOOL },
87 { "Mode", config_mode, TYPE_NAME },
92 Add given value to the list of configs cfg
95 add_config_val(config_t **cfg, int argtype, char *val)
100 p = (config_t*)xmalloc(sizeof(*p));
106 p->data.val = strtol(val, &q, 0);
111 p->data.ptr = xmalloc(strlen(val) + 1);
112 strcpy(p->data.ptr, val);
115 p->data.ip = strtoip(val);
118 if(!strcasecmp("yes", val))
119 p->data.val = stupid_true;
120 else if(!strcasecmp("no", val))
121 p->data.val = stupid_false;
126 p->argtype = argtype;
144 Read exactly one line and strip the trailing newline if any. If the
145 file was on EOF, return NULL. Otherwise, return all the data in a
146 dynamically allocated buffer.
148 If line is non-NULL, it will be used as an initial buffer, to avoid
149 unnecessary mallocing each time this function is called. If buf is
150 given, and buf needs to be expanded, the var pointed to by buflen
153 char *readline(FILE *fp, char **buf, size_t *buflen)
155 char *newline = NULL;
157 char *line; /* The array that contains everything that has been read
159 char *idx; /* Read into this pointer, which points to an offset
161 size_t size, newsize; /* The size of the current array pointed to by
163 size_t maxlen; /* Maximum number of characters that may be read with
164 fgets. This is newsize - oldsize. */
169 if((buf != NULL) && (buflen != NULL))
177 line = xmalloc(size);
186 p = fgets(idx, maxlen, fp);
187 if(p == NULL) /* EOF or error */
192 /* otherwise: error; let the calling function print an error
193 message if applicable */
198 newline = strchr(p, '\n');
200 /* We haven't yet read everything to the end of the line */
203 line = xrealloc(line, newsize);
204 idx = &line[size - 1];
205 maxlen = newsize - size + 1;
210 *newline = '\0'; /* kill newline */
215 if((buf != NULL) && (buflen != NULL))
224 Parse a configuration file and put the results in the configuration tree
227 int read_config_file(config_t **base, const char *fname)
229 int err = -2; /* Parse error */
233 int i, lineno = 0, ignore = 0;
238 if((fp = fopen (fname, "r")) == NULL)
240 syslog(LOG_ERR, _("Cannot open config file %s: %m"), fname);
245 buffer = xmalloc(bufsize);
250 if((line = readline(fp, &buffer, &bufsize)) == NULL)
264 if((p = strtok(line, "\t =")) == NULL)
265 continue; /* no tokens on this line */
268 continue; /* comment: ignore */
270 if(!strcmp(p, "-----BEGIN"))
275 for(i = 0; hazahaza[i].name != NULL; i++)
276 if(!strcasecmp(hazahaza[i].name, p))
279 if(!hazahaza[i].name)
281 syslog(LOG_ERR, _("Invalid variable name `%s' on line %d while reading config file %s"),
286 if(((q = strtok(NULL, "\t\n\r =")) == NULL) || q[0] == '#')
288 syslog(LOG_ERR, _("No value for variable `%s' on line %d while reading config file %s"),
289 hazahaza[i].name, lineno, fname);
293 cfg = add_config_val(base, hazahaza[i].argtype, q);
296 syslog(LOG_ERR, _("Invalid value for variable `%s' on line %d while reading config file %s"),
297 hazahaza[i].name, lineno, fname);
301 cfg->which = hazahaza[i].which;
306 if(!strcmp(p, "-----END"))
316 int read_server_config()
321 asprintf(&fname, "%s/tinc.conf", confbase);
322 x = read_config_file(&config, fname);
323 if(x == -1) /* System error: complain */
325 syslog(LOG_ERR, _("Failed to read `%s': %m"),
334 Look up the value of the config option type
336 const config_t *get_config_val(config_t *p, which_t type)
339 for(; p != NULL; p = p->next)
347 Remove the complete configuration tree.
349 void clear_config(config_t **base)
353 for(p = *base; p != NULL; p = next)
356 if(p->data.ptr && (p->argtype == TYPE_NAME))
366 int isadir(const char* f)
373 return S_ISDIR(s.st_mode);
376 int is_safe_path(const char *file)
386 syslog(LOG_ERR, _("`%s' is not an absolute path"), file);
390 p = strrchr(file, '/');
392 if(p == file) /* It's in the root */
402 syslog(LOG_ERR, _("Couldn't stat `%s': %m"),
407 if(s.st_uid != geteuid())
409 syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"),
410 f, s.st_uid, geteuid());
414 if(S_ISLNK(s.st_mode))
416 syslog(LOG_WARNING, _("Warning: `%s' is a symlink"),
419 if(readlink(f, l, MAXBUFSIZE) < 0)
421 syslog(LOG_ERR, _("Unable to read symbolic link `%s': %m"), f);
433 if(lstat(f, &s) < 0 && errno != ENOENT)
435 syslog(LOG_ERR, _("Couldn't stat `%s': %m"),
443 if(s.st_uid != geteuid())
445 syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"),
446 f, s.st_uid, geteuid());
450 if(S_ISLNK(s.st_mode))
452 syslog(LOG_WARNING, _("Warning: `%s' is a symlink"),
455 if(readlink(f, l, MAXBUFSIZE) < 0)
457 syslog(LOG_ERR, _("Unable to read symbolic link `%s': %m"), f);
467 /* Accessible by others */
468 syslog(LOG_ERR, _("`%s' has unsecure permissions"),
476 FILE *ask_and_safe_open(const char* filename, const char* what, const char* mode)
482 /* Check stdin and stdout */
483 if(!isatty(0) || !isatty(1))
485 /* Argh, they are running us from a script or something. Write
486 the files to the current directory and let them burn in hell
488 fn = xstrdup(filename);
492 /* Ask for a file and/or directory name. */
493 fprintf(stdout, _("Please enter a file to save %s to [%s]: "),
497 if((fn = readline(stdin, NULL, NULL)) == NULL)
499 fprintf(stderr, _("Error while reading stdin: %s\n"), strerror(errno));
504 /* User just pressed enter. */
505 fn = xstrdup(filename);
508 if((strchr(fn, '/') == NULL) || (fn[0] != '/'))
510 /* The directory is a relative path or a filename. */
513 directory = get_current_dir_name();
514 asprintf(&p, "%s/%s", directory, fn);
520 umask(0077); /* Disallow everything for group and other */
522 /* Open it first to keep the inode busy */
523 if((r = fopen(fn, mode)) == NULL)
525 fprintf(stderr, _("Error opening file `%s': %s\n"),
526 fn, strerror(errno));
531 /* Then check the file for nasty attacks */
532 if(!is_safe_path(fn)) /* Do not permit any directories that are
533 readable or writeable by other users. */
535 fprintf(stderr, _("The file `%s' (or any of the leading directories) has unsafe permissions.\n"
536 "I will not create or overwrite this file.\n"),