2 read_conf.c -- read the configuration files
3 Copyright (C) 1998 Robert van der Meulen
4 1998-2002 Ivo Timmermans <ivo@o2w.nl>
5 2000-2002 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: read_conf.c,v 1.1 2002/04/28 12:46:26 zarq Exp $
34 #include <sys/types.h>
39 #include <utils.h> /* for cp */
43 #include "netutl.h" /* for str2address */
49 Read exactly one line and strip the trailing newline if any. If the
50 file was on EOF, return NULL. Otherwise, return all the data in a
51 dynamically allocated buffer.
53 If line is non-NULL, it will be used as an initial buffer, to avoid
54 unnecessary mallocing each time this function is called. If buf is
55 given, and buf needs to be expanded, the var pointed to by buflen
58 char *readline(FILE *fp, char **buf, size_t *buflen)
62 char *line; /* The array that contains everything that has been read
64 char *idx; /* Read into this pointer, which points to an offset
66 size_t size, newsize; /* The size of the current array pointed to by
68 size_t maxlen; /* Maximum number of characters that may be read with
69 fgets. This is newsize - oldsize. */
74 if((buf != NULL) && (buflen != NULL))
91 p = fgets(idx, maxlen, fp);
92 if(p == NULL) /* EOF or error */
97 /* otherwise: error; let the calling function print an error
98 message if applicable */
103 newline = strchr(p, '\n');
105 /* We haven't yet read everything to the end of the line */
108 line = xrealloc(line, newsize);
109 idx = &line[size - 1];
110 maxlen = newsize - size + 1;
115 *newline = '\0'; /* kill newline */
120 if((buf != NULL) && (buflen != NULL))
129 Parse a configuration file and put the results in the configuration tree
132 int read_config_file(avl_tree_t *config_tree, const char *fname)
134 int err = -2; /* Parse error */
137 char *variable, *value;
138 int lineno = 0, ignore = 0;
143 if((fp = fopen (fname, "r")) == NULL)
145 syslog(LOG_ERR, _("Cannot open config file %s: %s"), fname, strerror(errno));
150 buffer = xmalloc(bufsize);
154 if((line = readline(fp, &buffer, &bufsize)) == NULL)
168 if((variable = strtok(line, "\t =")) == NULL)
169 continue; /* no tokens on this line */
171 if(variable[0] == '#')
172 continue; /* comment: ignore */
174 if(!strcmp(variable, "-----BEGIN"))
179 if(((value = strtok(NULL, "\t\n\r =")) == NULL) || value[0] == '#')
181 syslog(LOG_ERR, _("No value for variable `%s' on line %d while reading config file %s"),
182 variable, lineno, fname);
187 cfg->variable = xstrdup(variable);
188 cfg->value = xstrdup(value);
189 cfg->file = xstrdup(fname);
192 config_add(config_tree, cfg);
195 if(!strcmp(variable, "-----END"))
205 int read_server_config()
210 asprintf(&fname, "%s/tinc.conf", confbase);
211 x = read_config_file(config_tree, fname);
212 if(x == -1) /* System error: complain */
214 syslog(LOG_ERR, _("Failed to read `%s': %s"), fname, strerror(errno));
221 int isadir(const char* f)
228 return S_ISDIR(s.st_mode);
231 int is_safe_path(const char *file)
241 syslog(LOG_ERR, _("`%s' is not an absolute path"), file);
245 p = strrchr(file, '/');
247 if(p == file) /* It's in the root */
257 syslog(LOG_ERR, _("Couldn't stat `%s': %s"), f, strerror(errno));
261 if(s.st_uid != geteuid())
263 syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"),
264 f, s.st_uid, geteuid());
268 if(S_ISLNK(s.st_mode))
270 syslog(LOG_WARNING, _("Warning: `%s' is a symlink"),
273 if(readlink(f, l, MAXBUFSIZE) < 0)
275 syslog(LOG_ERR, _("Unable to read symbolic link `%s': %s"), f, strerror(errno));
287 if(lstat(f, &s) < 0 && errno != ENOENT)
289 syslog(LOG_ERR, _("Couldn't stat `%s': %s"), f, strerror(errno));
296 if(s.st_uid != geteuid())
298 syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"),
299 f, s.st_uid, geteuid());
303 if(S_ISLNK(s.st_mode))
305 syslog(LOG_WARNING, _("Warning: `%s' is a symlink"),
308 if(readlink(f, l, MAXBUFSIZE) < 0)
310 syslog(LOG_ERR, _("Unable to read symbolic link `%s': %s"), f, strerror(errno));
320 /* Accessible by others */
321 syslog(LOG_ERR, _("`%s' has unsecure permissions"),
329 FILE *ask_and_safe_open(const char* filename, const char* what, const char* mode)
335 /* Check stdin and stdout */
336 if(!isatty(0) || !isatty(1))
338 /* Argh, they are running us from a script or something. Write
339 the files to the current directory and let them burn in hell
341 fn = xstrdup(filename);
345 /* Ask for a file and/or directory name. */
346 fprintf(stdout, _("Please enter a file to save %s to [%s]: "),
350 if((fn = readline(stdin, NULL, NULL)) == NULL)
352 fprintf(stderr, _("Error while reading stdin: %s\n"), strerror(errno));
357 /* User just pressed enter. */
358 fn = xstrdup(filename);
361 if((strchr(fn, '/') == NULL) || (fn[0] != '/'))
363 /* The directory is a relative path or a filename. */
366 directory = get_current_dir_name();
367 asprintf(&p, "%s/%s", directory, fn);
373 umask(0077); /* Disallow everything for group and other */
375 /* Open it first to keep the inode busy */
376 if((r = fopen(fn, mode)) == NULL)
378 fprintf(stderr, _("Error opening file `%s': %s\n"),
379 fn, strerror(errno));
384 /* Then check the file for nasty attacks */
385 if(!is_safe_path(fn)) /* Do not permit any directories that are
386 readable or writeable by other users. */
388 fprintf(stderr, _("The file `%s' (or any of the leading directories) has unsafe permissions.\n"
389 "I will not create or overwrite this file.\n"),
401 int read_connection_config(connection_t *c)
406 asprintf(&fname, "%s/hosts/%s", confbase, c->name);
407 x = read_config_file(c->config_tree, fname);