[Kolab-devel] Patch: Configuration and Tempfile Handling in Kolab::Conf

Stephan Buys list at codefusion.co.za
Thu Apr 29 22:38:24 CEST 2004


Hi,

Here is a lengthy patch that processes the config files the following way:

- read template into memory and substitue variables
- read original into memory
- compare both
- if no change, finished
- if change
- set permission on old conf file
- truncate old file
- write new conf file into truncated file
- close file
- restart daemon

This is, as far as I can tell, the most secure way to do things. I have rolled
this into CPAN already, the patch is included below.

If there are no objections I will commit this to HEAD tomorrow.

Regards,
-- 
Stephan 

--- Conf.pm     26 Apr 2004 15:47:26 -0000      1.7
+++ Conf.pm     29 Apr 2004 20:36:46 -0000
@@ -59,63 +59,67 @@ our $VERSION = '0.9';
 sub build {
     my $tmpl = shift;
     my $cfg = shift;
-    my $oldcfg = $cfg . '.old';
+    #my $oldcfg = $cfg . '.old';
     my $prefix = $Kolab::config{'prefix'};

-    my $tmpfile = $prefix . '/etc/kolab/.tmp';
-    copy($cfg, $oldcfg);
-    chown($Kolab::config{'kolab_uid'}, $Kolab::config{'kolab_gid'}, $oldcfg);
-    chmod(0600, $oldcfg) if ($oldcfg =~ /openldap/);
-
-    Kolab::log('T', "Creating new configuration file `$cfg' from template `$tmpl'");
-
-    my $template;
-    if (!($template = IO::File->new($tmpl, 'r'))) {
+    #my $tmpfile = $prefix . '/etc/kolab/.tmp';
+    #copy($cfg, $oldcfg);
+    #chown($Kolab::config{'kolab_uid'}, $Kolab::config{'kolab_gid'}, $oldcfg);
+    #chmod(0600, $oldcfg) if ($oldcfg =~ /openldap/);
+
+
+    my $TEMPLATE;
+    if (!($TEMPLATE = IO::File->new($tmpl, 'r'))) {
         Kolab::log('T', "Unable to open template file `$tmpl'", KOLAB_ERROR);
         exit(1);
     }
-    my $config;
-    if (!($config = IO::File->new($tmpfile, 'w+'))) {
-        Kolab::log('T', "Unable to open configuration file `$cfg'", KOLAB_ERROR);
-        exit(1);
-    }
+    my @tempfile = ();

-    my $skip = 0;
-    while (<$template>) {
-      if (/\@{3}if (\S+)\@{3}/) {
-       if ($Kolab::config{$1} && $Kolab::config{$1} ne "FALSE" ) {
-          # Keep text
-       } else {
-          # Skip text
-          $skip++;
+    #my $template;
+    #if (!($template = IO::File->new($tmpl, 'r'))) {
+    #    Kolab::log('T', "Unable to open template file `$tmpl'", KOLAB_ERROR);
+    #    exit(1);
+    #}
+    #my $config;
+    #if (!($config = IO::File->new($tmpfile, 'w+'))) {
+    #    Kolab::log('T', "Unable to open configuration file `$cfg'", KOLAB_ERROR);
+    #    exit(1);
+    #}
+
+    while (<$TEMPLATE>) {
+        if (/\@{3}(\S+)\@{3}/) {
+            if ($Kolab::config{$1}) {
+                s/\@{3}(\S+)\@{3}/$Kolab::config{$1}/g;
+            } else {
+                Kolab::log('T', "No configuration variable corresponding to `$1' exists", KOLAB_WARN);
+                s/\@{3}(\S+)\@{3}//g;
+            }
         }
-        s/\@{3}if (\S+)\@{3}//;
-      } elsif (/\@{3}endif\@{3}/) {
-        ( $skip > 0 ) && $skip--;
-        s/\@{3}endif\@{3}//;
-      } elsif (/\@{3}(\S+)\@{3}/) {
-       if ($Kolab::config{$1}) {
-         s/\@{3}(\S+)\@{3}/$Kolab::config{$1}/g;
-       } else {
-         Kolab::log('T', "No configuration variable corresponding to `$1' exists", KOLAB_WARN);
-         s/\@{3}(\S+)\@{3}//g;
-       }
-      }
-      ( $skip == 0 ) && print $config $_;
+        push (@tempfile, $_);
     }
+    $TEMPLATE->close;
+
+    my $CONFIGFILE;
+    if (!($CONFIGFILE = IO::File->new($cfg, 'r'))) {
+        Kolab::log('T', "Unable to open config file `$cfg'", KOLAB_ERROR);
+        exit(1);
+    }
+
+    my $configchanged = 0;
+
+    foreach my $line (@tempfile) {
+      my $configline = <$CONFIGFILE>;
+      $configchanged = 1 if ($configline ne $line)
+    }
+    $CONFIGFILE->close;
+    undef $CONFIGFILE;

-    $template->close;
-    $config->close;
-
-    move($tmpfile, $cfg);
-    chown($Kolab::config{'kolab_uid'}, $Kolab::config{'kolab_gid'}, $cfg);
-    chmod(0600, $cfg) if ($cfg =~ /openldap/);
-
-    if (-f $oldcfg) {
-        my $rc = `diff -q $cfg $oldcfg`;
-        chomp($rc);
-        if ($rc) {
-            if ($cfg =~ /postfix/) {
+    return 0 if ($configchanged ne 1);
+
+    if ($configchanged) {
+            Kolab::log('T', "`$cfg' change detected.", KOLAB_DEBUG);
+
+           if ($cfg =~ /postfix/) {
                 $Kolab::haschanged{'postfix'} = 1;
             } elsif ($cfg =~ /saslauthd/) {
                 $Kolab::haschanged{'saslauthd'} = 1;
@@ -127,17 +131,88 @@ sub build {
                 $Kolab::haschanged{'slapd'} = 1;
             } elsif ($cfg =~ /imapd/) {
                 $Kolab::haschanged{'imapd'} = 1;
-           } elsif ($cfg =~ /amavisd/) {
-                $Kolab::haschanged{'amavisd'} = 1;
-           } elsif ($cfg =~ /clamav/) {
-                $Kolab::haschanged{'clamav'} = 1;
-           }
-
-            Kolab::log('T', "`$cfg' change detected: $rc", KOLAB_DEBUG);
-        }
+            }
     }
-
+    Kolab::log('T', "Creating new configuration file `$cfg' from template `$tmpl'");
+
+    truncate($cfg,0);
+    my $perms;
+    #if ($cfg =~ /openldap/) { $perms = 0600; } else { $perms = 0644; };
+    if ($cfg =~ /openldap/) { chmod(0600,$cfg); };
+
+    my $NEWFILE;
+    if (!($NEWFILE = IO::File->new($cfg, 'w+', $perms))) {
+        Kolab::log('T', "Unable to open configuration file `$cfg'", KOLAB_ERROR);
+        exit(1);
+    }
+
+    foreach my $line (@tempfile) {
+       print $NEWFILE $line;
+    }
+    $NEWFILE->close;
+    chown($Kolab::config{'kolab_uid'}, $Kolab::config{'kolab_gid'}, $cfg);
+
     Kolab::log('T', "Finished creating configuration file `$cfg'");
+
+
+#   my $skip = 0;
+#   while (<$template>) {
+#     if (/\@{3}if (\S+)\@{3}/) {
+#       if ($Kolab::config{$1} && $Kolab::config{$1} ne "FALSE" ) {
+#         # Keep text
+#       } else {
+#         # Skip text
+#         $skip++;
+#       }
+#       s/\@{3}if (\S+)\@{3}//;
+#     } elsif (/\@{3}endif\@{3}/) {
+#       ( $skip > 0 ) && $skip--;
+#       s/\@{3}endif\@{3}//;
+#     } elsif (/\@{3}(\S+)\@{3}/) {
+#       if ($Kolab::config{$1}) {
+#         s/\@{3}(\S+)\@{3}/$Kolab::config{$1}/g;
+#       } else {
+#         Kolab::log('T', "No configuration variable corresponding to `$1' exists", KOLAB_WARN);
+#         s/\@{3}(\S+)\@{3}//g;
+#       }
+#     }
+#     ( $skip == 0 ) && print $config $_;
+#   }
+
+#    $template->close;
+#    $config->close;
+
+#    move($tmpfile, $cfg);
+#    chown($Kolab::config{'kolab_uid'}, $Kolab::config{'kolab_gid'}, $cfg);
+#    chmod(0600, $cfg) if ($cfg =~ /openldap/);
+
+#   if (-f $oldcfg) {
+#       my $rc = `diff -q $cfg $oldcfg`;
+#       chomp($rc);
+#       if ($rc) {
+#           if ($cfg =~ /postfix/) {
+#               $Kolab::haschanged{'postfix'} = 1;
+#           } elsif ($cfg =~ /saslauthd/) {
+#               $Kolab::haschanged{'saslauthd'} = 1;
+#           } elsif ($cfg =~ /apache/) {
+#               $Kolab::haschanged{'apache'} = 1;
+#           } elsif ($cfg =~ /proftpd/) {
+#               $Kolab::haschanged{'proftpd'} = 1;
+#           } elsif ($cfg =~ /openldap/) {
+#               $Kolab::haschanged{'slapd'} = 1;
+#           } elsif ($cfg =~ /imapd/) {
+#               $Kolab::haschanged{'imapd'} = 1;
+#           } elsif ($cfg =~ /amavisd/) {
+#               $Kolab::haschanged{'amavisd'} = 1;
+#           } elsif ($cfg =~ /clamav/) {
+#               $Kolab::haschanged{'clamav'} = 1;
+#           }
+
+#           Kolab::log('T', "`$cfg' change detected: $rc", KOLAB_DEBUG);
+#       }
+#   }
+
+#   Kolab::log('T', "Finished creating configuration file `$cfg'");
 }




More information about the devel mailing list