[389-devel] Please Review: (529258) Make upgrade remove obsolete schema from 99user.ldif

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




>From 0b45b3d488471cd6b55c425271154c6f49830dd8 Mon Sep 17 00:00:00 2001
From: Nathan Kinder <nkinder@xxxxxxxxxx>
Date: Wed, 28 Oct 2009 18:18:49 -0700
Subject: [PATCH] Bug 529258 - Make upgrade remove obsolete schema from 99user.ldif

Due to a previously fixed bug (bz 474254), standard schema may
have been duplicated in 99user.ldif.  When running an upgrade, we
need to check the 99user.ldif file to see if any obsolete standard
schema is defined there and remove it.

This patch makes upgrade backup the original 99user.ldif, and
scans it to see if any of the obsolete attributeTypes or
objectClasses attributes that we are removing from the standard
schema exist in 99user.ldif.  We trim the obsolete definitions
and write out a new 99user.ldif with the proper permissions.
---
 ldap/admin/src/scripts/60upgradeschemafiles.pl |  137 +++++++++++++++++++++++-
 ldap/admin/src/scripts/setup-ds.res.in         |    2 +
 2 files changed, 138 insertions(+), 1 deletions(-)

diff --git a/ldap/admin/src/scripts/60upgradeschemafiles.pl b/ldap/admin/src/scripts/60upgradeschemafiles.pl
index c1b1bb7..0cf4a98 100644
--- a/ldap/admin/src/scripts/60upgradeschemafiles.pl
+++ b/ldap/admin/src/scripts/60upgradeschemafiles.pl
@@ -1,4 +1,5 @@
 
+use Mozilla::LDAP::LDIF;
 use DSCreate qw(installSchema);
 
 sub runinst {
@@ -12,6 +13,14 @@ sub runinst {
     # them with newer versions
     my @toremove = qw(00core.ldif 01core389.ldif 01common.ldif 02common.ldif 05rfc2247.ldif 10presence.ldif 28pilot.ldif 30ns-common.ldif 50ns-directory.ldif 60mozilla.ldif);
 
+    # these hashes will be used to check for obsolete schema
+    # in 99user.ldif
+    my %attrsbyname;
+    my %attrsbyoid;
+    my %objclassesbyname;
+    my %objclassesbyoid;
+    my $userschemaentry;
+
     # make a backup directory to store the deleted schema, then
     # don't really delete it, just move it to that directory
     my $mode = (stat($inf->{slapd}->{schema_dir}))[2];
@@ -36,7 +45,126 @@ sub runinst {
         }
     }
 
-    if (@errs) { # errors backing up schema
+    # Remove obsolete schema from 99user.ldif. Compare by name and OID.
+    if (!open( OLDUSERSCHEMA, $inf->{slapd}->{schema_dir} . "/99user.ldif")) {
+        push @errs, ["error_reading_schema_file", $inf->{slapd}->{schema_dir} . "/99user.ldif", $!];
+    } else {
+        my $olduserschema = new Mozilla::LDAP::LDIF(*OLDUSERSCHEMA);
+
+        # Find the cn=schema entry.
+        while ($userschemaentry = readOneEntry $olduserschema) {
+            my $dn = $userschemaentry->getDN();
+            # The only entry should be cn=schema, but best to play it safe.
+            next if ($dn ne "cn=schema");
+
+            # create the attributeTypes hashes (name->value, oid->value)
+            my @attrtypes = $userschemaentry->getValues("attributeTypes");
+            foreach my $attrtype (@attrtypes) {
+                # parse out the attribute name and oid
+                if ($attrtype =~ /^\(\s*([\d\.]+)\s+NAME\s+'(\w+)'/) {
+                    # normalize the attribute name
+                    $attrsbyname{lc "$2"} = "$attrtype";
+                    $attrsbyoid{"$1"} = "$attrtype";
+                }
+            }
+
+            # create the objectClasses hashes (name->value, oid->value)
+            my @objclasses = $userschemaentry->getValues("objectClasses");
+            foreach my $objclass (@objclasses) {
+                # parse out the objectclass name and oid
+                if ($objclass =~ /^\(\s*([\d\.]+)\s+NAME\s+'(\w+)'/) {
+                    # normalize the objectclass name
+                    $objclassesbyname{lc "$2"} = "$objclass";
+                    $objclassesbyoid{"$1"} = "$objclass";
+                }
+            }
+
+            # We found the cn=schema entry, so there's no need
+            # to look for more entries.
+            last;
+        }
+
+        close OLDUSERSCHEMA;
+    }
+
+    for my $file (@toremove) {
+        my $fullname = "$bakdir/$file";
+
+        next if (! -f $fullname); # does not exist - skip - already (re)moved
+
+        if (!open( OBSOLETESCHEMA, "$fullname")) {
+            push @errs, ["error_reading_schema_file", $fullname, $!];
+        } else {
+            my $obsoleteschema = new Mozilla::LDAP::LDIF(*OBSOLETESCHEMA);
+
+            # Find the cn=schema entry.
+            while (my $entry = readOneEntry $obsoleteschema) {
+                my $dn = $entry->getDN();
+                # The only entry should be cn=schema, but best to play it safe.
+                next if ($dn ne "cn=schema");
+
+                # Check if any of the attributeTypes in this file
+                # are defined in 99user.ldif and remove them if so.
+                my @attrtypes = $entry->getValues("attributeTypes");
+                foreach $attrtype (@attrtypes) {
+                    # parse out the attribute name and oid
+                    if ($attrtype =~ /^\(\s*([\d\.]+)\s+NAME\s+'(\w+)'/) {
+                        # normalize the attribute name
+                        if ($attrsbyname{lc "$2"}) {
+                            $userschemaentry->removeValue("attributeTypes", $attrsbyname{lc "$2"});
+                        } elsif ($attrsbyoid{"$1"}) {
+                            $userschemaentry->removeValue("attributeTypes", $attrsbyoid{"$1"});
+                        }
+                    }
+                }
+
+                # Check if any of the objectClasses in this file
+                # are defined in 99user.ldif and remove them if so.
+                my @objclasses = $entry->getValues("objectClasses");
+                foreach $objclass (@objclasses) {
+                    # parse out the objectclass name and oid
+                    if ($objclass =~ /^\(\s*([\d\.]+)\s+NAME\s+'(\w+)'/) {
+                        # normalize the objectclass name
+                        if ($objclassesbyname{lc "$2"}) {
+                            $userschemaentry->removeValue("objectClasses", $objclassesbyname{lc "$2"});
+                        } elsif ($objclassesbyoid{"$1"}) {
+                            $userschemaentry->removeValue("objectClasses", $objclassesbyoid{"$1"});
+                        }
+                    }
+                }
+            }
+
+            close OBSOLETESCHEMA;
+        }
+    }
+
+    # Backup the original 99user.ldif
+    $! = 0; # clear
+    rename $inf->{slapd}->{schema_dir} . "/99user.ldif", "$bakdir/99user.ldif";
+    if ($!) {
+        push @errs, ["error_renaming_schema", $inf->{slapd}->{schema_dir} . "/99user.ldif", "$bakdir/99user.ldif", $!];
+    }
+
+    # Write the new 99user.ldif
+    if (!open ( NEWUSERSCHEMA, ">" . $inf->{slapd}->{schema_dir} . "/99user.ldif")) {
+        push @errs, ["error_writing_schema_file", $inf->{slapd}->{schema_dir} . "/99user.ldif", $!];
+    } else {
+        my $newuserschema = new Mozilla::LDAP::LDIF(*NEWUSERSCHEMA);
+        writeOneEntry $newuserschema $userschemaentry;
+        close NEWUSERSCHEMA;
+
+        # Set permissions based off of the original 99user.ldif.
+        my @stat = stat("$bakdir/99user.ldif");
+        my $mode = $stat[2];
+        my $uid = $stat[4];
+        my $gid = $stat[5];
+        chmod $mode, $inf->{slapd}->{schema_dir} . "/99user.ldif";
+        chown $uid, $gid, $inf->{slapd}->{schema_dir} . "/99user.ldif";
+    }
+
+    # If we've encountered any errors up to this point, restore
+    # the original schema.
+    if (@errs) {
         # restore the original schema files
         for my $file (@toremove) {
             my $oldname = "$bakdir/$file";
@@ -45,6 +173,13 @@ sub runinst {
             next if (-f $newname); # not removed
             rename $oldname, $newname;
         }
+
+        # Restore 99user.ldif. We overwrite whatever is there since
+        # it is possible that we have modifed it.
+        if (-f "$bakdir/99user.ldif") {
+                rename "$bakdir/99user.ldif", $inf->{slapd}->{schema_dir} . "/99user.ldif";
+        }
+
         return @errs;
     }
 
diff --git a/ldap/admin/src/scripts/setup-ds.res.in b/ldap/admin/src/scripts/setup-ds.res.in
index 57e7654..af9080d 100644
--- a/ldap/admin/src/scripts/setup-ds.res.in
+++ b/ldap/admin/src/scripts/setup-ds.res.in
@@ -176,7 +176,9 @@ update_admin_dialog = Please specify the authentication data for '%s'\n\n
 update_admin_id_prompt = Full DN of administrative user
 update_admin_pwd_prompt = Password for this user
 error_renaming_schema = Could not rename schema file '%s' tp '%s'.  Error: %s\n
+error_reading_schema_file = Schema file '%s' does not exist or is not readable.  Error: %s\n
 error_reading_schema_dir = Schema directory '%s' does not exist or is not readable\n
+error_writing_schema_file = Schema file '%s' could not be opened for writing.  Error: %s\n
 error_online_update = Could not open a connection to the server at %s port %s as '%s'.\
 Please make sure the server is up and running before using online mode,\
 or use offline mode.\n\n
-- 
1.6.2.5

--
389-devel mailing list
389-devel@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/fedora-directory-devel

[Index of Archives]     [Fedora Directory Announce]     [Fedora Users]     [Older Fedora Users Mail]     [Fedora Advisory Board]     [Fedora Security]     [Fedora Devel Java]     [Fedora Desktop]     [ATA RAID]     [Fedora Marketing]     [Fedora Mentors]     [Fedora Package Review]     [Fedora Art]     [Fedora Music]     [Fedora Packaging]     [CentOS]     [Fedora SELinux]     [Big List of Linux Books]     [KDE Users]     [Fedora Art]     [Fedora Docs]

  Powered by Linux