Adding "conf.d" configuration dir support.
[tinc] / src / conf.c
index b895b7f..e2b6442 100644 (file)
@@ -2,7 +2,7 @@
     conf.c -- configuration code
     Copyright (C) 1998 Robert van der Meulen
                   1998-2005 Ivo Timmermans
-                  2000-2010 Guus Sliepen <guus@tinc-vpn.org>
+                  2000-2012 Guus Sliepen <guus@tinc-vpn.org>
                   2010-2011 Julien Muchembled <jm@jmuchemb.eu>
                  2000 Cris van Pelt
 
@@ -26,6 +26,7 @@
 #include "avl_tree.h"
 #include "connection.h"
 #include "conf.h"
+#include "list.h"
 #include "logger.h"
 #include "netutl.h"                            /* for str2address */
 #include "protocol.h"
@@ -377,6 +378,30 @@ bool read_server_config(void) {
        xasprintf(&fname, "%s/tinc.conf", confbase);
        x = read_config_file(config_tree, fname);
 
+       // We will try to read the conf files in the "conf.d" dir
+       if (x) {
+               char * dname;
+               xasprintf(&dname, "%s/conf.d", confbase);
+               DIR *dir = opendir (dname);
+               // If we can find this dir
+               if (dir) { 
+                       struct dirent *ep;
+                       // We list all the files in it
+                       while (x && (ep = readdir (dir))) {
+                               size_t l = strlen(ep->d_name);
+                               // And we try to read the ones that end with ".conf"
+                               if (l > 5 && !strcmp(".conf", & ep->d_name[ l - 5 ])) {
+                                       free(fname);
+                                       xasprintf(&fname, "%s/%s", dname, ep->d_name);
+                                       logger(LOG_DEBUG, "Reading conf file \"%s\"", fname);
+                                       x = read_config_file(config_tree, fname);
+                               }
+                       }
+                       closedir (dir);
+               }
+               free(dname);
+       }
+
        if(!x) {                                /* System error: complain */
                logger(LOG_ERR, "Failed to read `%s': %s", fname, strerror(errno));
        }
@@ -399,6 +424,70 @@ bool read_connection_config(connection_t *c) {
        return x;
 }
 
+static void disable_old_keys(const char *filename) {
+       char tmpfile[PATH_MAX] = "";
+       char buf[1024];
+       bool disabled = false;
+       FILE *r, *w;
+
+       r = fopen(filename, "r");
+       if(!r)
+               return;
+
+       snprintf(tmpfile, sizeof tmpfile, "%s.tmp", filename);
+
+       w = fopen(tmpfile, "w");
+
+       while(fgets(buf, sizeof buf, r)) {
+               if(!strncmp(buf, "-----BEGIN RSA", 14)) {       
+                       buf[11] = 'O';
+                       buf[12] = 'L';
+                       buf[13] = 'D';
+                       disabled = true;
+               }
+               else if(!strncmp(buf, "-----END RSA", 12)) {    
+                       buf[ 9] = 'O';
+                       buf[10] = 'L';
+                       buf[11] = 'D';
+                       disabled = true;
+               }
+               if(w && fputs(buf, w) < 0) {
+                       disabled = false;
+                       break;
+               }
+       }
+
+       if(w)
+               fclose(w);
+       fclose(r);
+
+       if(!w && disabled) {
+               fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n");
+               return;
+       }
+
+       if(disabled) {
+#ifdef HAVE_MINGW
+               // We cannot atomically replace files on Windows.
+               char bakfile[PATH_MAX] = "";
+               snprintf(bakfile, sizeof bakfile, "%s.bak", filename);
+               if(rename(filename, bakfile) || rename(tmpfile, filename)) {
+                       rename(bakfile, filename);
+#else
+               if(rename(tmpfile, filename)) {
+#endif
+                       fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n");
+               } else  {
+#ifdef HAVE_MINGW
+                       unlink(bakfile);
+#endif
+                       fprintf(stderr, "Warning: old key(s) found and disabled.\n");
+               }
+       }
+
+       unlink(tmpfile);
+}
+
 FILE *ask_and_open(const char *filename, const char *what) {
        FILE *r;
        char *directory;
@@ -446,9 +535,11 @@ FILE *ask_and_open(const char *filename, const char *what) {
 
        umask(0077);                            /* Disallow everything for group and other */
 
+       disable_old_keys(fn);
+
        /* Open it first to keep the inode busy */
 
-       r = fopen(fn, "r+") ?: fopen(fn, "w+");
+       r = fopen(fn, "a");
 
        if(!r) {
                fprintf(stderr, "Error opening file `%s': %s\n",
@@ -459,42 +550,4 @@ FILE *ask_and_open(const char *filename, const char *what) {
        return r;
 }
 
-bool disable_old_keys(FILE *f) {
-       char buf[100];
-       long pos;
-       bool disabled = false;
-
-       rewind(f);
-       pos = ftell(f);
 
-       if(pos < 0)
-               return false;
-
-       while(fgets(buf, sizeof buf, f)) {
-               if(!strncmp(buf, "-----BEGIN RSA", 14)) {       
-                       buf[11] = 'O';
-                       buf[12] = 'L';
-                       buf[13] = 'D';
-                       if(fseek(f, pos, SEEK_SET))
-                               break;
-                       if(fputs(buf, f) <= 0)
-                               break;
-                       disabled = true;
-               }
-               else if(!strncmp(buf, "-----END RSA", 12)) {    
-                       buf[ 9] = 'O';
-                       buf[10] = 'L';
-                       buf[11] = 'D';
-                       if(fseek(f, pos, SEEK_SET))
-                               break;
-                       if(fputs(buf, f) <= 0)
-                               break;
-                       disabled = true;
-               }
-               pos = ftell(f);
-               if(pos < 0)
-                       break;
-       }
-
-       return disabled;
-}