[SCM] Samba Shared Repository - branch master updated

Douglas Bagnall dbagnall at samba.org
Thu Apr 12 09:28:02 UTC 2018


The branch, master has been updated
       via  09c2121 gpo: python chardet is not a dep of samba
       via  8e25e2f libgpo: gpo_copy_file() shouldn't explicitly call smb1
       via  6747553 param: Add python binding for lpcfg_cache_path
       via  477fd77 gpo: Create a gp_sec_ext module
       via  76cfbb6 gpo: Move implementation from samba_gpoupdate
       via  10b43aa gpo: Create base class gp_inf_ext
       via  dc41514 gpo: Move the file parse function to gp_ext
       via  1d47ab7 gpo: Move gp_sec_ext __init__ to base class
       via  cfd2d70 gpo: Rename the inf_to class to gp_ext_setter
      from  490756a Check "auth event notification" param in log_json

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 09c21214798ad435db488d206050d842b117166e
Author: David Mulder <dmulder at suse.com>
Date:   Wed Apr 11 12:45:40 2018 -0600

    gpo: python chardet is not a dep of samba
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    
    Autobuild-User(master): Douglas Bagnall <dbagnall at samba.org>
    Autobuild-Date(master): Thu Apr 12 11:27:03 CEST 2018 on sn-devel-144

commit 8e25e2f3408bda87e2acffa3fc464c32173bb814
Author: David Mulder <dmulder at suse.com>
Date:   Wed Apr 11 12:40:18 2018 -0600

    libgpo: gpo_copy_file() shouldn't explicitly call smb1
    
    Don't call cli_openx directly to open a file this
    calls smb1 code explicitly, which fails if we did
    a multi-protocol negotiate and negotiated smb2+.
    Use the higher level cli_open() instead.
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 6747553d1b40dc82b6aae6173dff7d2f89deb90d
Author: David Mulder <dmulder at suse.com>
Date:   Tue Apr 10 15:07:34 2018 -0600

    param: Add python binding for lpcfg_cache_path
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 477fd77c4d200f2c987caaf0c1740273c7a4e4a7
Author: David Mulder <dmulder at suse.com>
Date:   Mon Mar 12 09:44:38 2018 -0600

    gpo: Create a gp_sec_ext module
    
    Move the gp_sec_ext into it's own module,
    which is how new gp_ext's will be created.
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 76cfbb6e8cec87b7f1b069dfed06a572359eab0f
Author: David Mulder <dmulder at suse.com>
Date:   Thu Mar 29 08:32:02 2018 -0600

    gpo: Move implementation from samba_gpoupdate
    
    The implementation of group policy apply should
    not be in the application script. One reason is
    to implement user apply, we can call these
    functions via the python c-api, (passing creds
    via the command line will expose them via ps).
    Another reason for this is if some overrides
    the smb.conf "gpo update command" option, it
    would be useful to have these functions.
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 10b43aa1c9c1772af1485d93a8bdf53c31de211c
Author: David Mulder <dmulder at suse.com>
Date:   Thu Mar 29 08:25:05 2018 -0600

    gpo: Create base class gp_inf_ext
    
    Abstract the process of reading from an ini file,
    since other extensions will be reading gpos this
    way.
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit dc4151476923067b7659f42ca1f2c5f809cfef1e
Author: David Mulder <dmulder at suse.com>
Date:   Thu Mar 29 08:05:21 2018 -0600

    gpo: Move the file parse function to gp_ext
    
    A file will always be read from the sysvol the
    same way, but the data will be read differently.
    This patch moves the parse function to gp_ext,
    and requires subclasses to implement the read()
    function to interpret the data.
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 1d47ab7e2a49048f425d544b38bc980abb4f53ef
Author: David Mulder <dmulder at suse.com>
Date:   Thu Mar 29 09:07:53 2018 -0600

    gpo: Move gp_sec_ext __init__ to base class
    
    For this class to be extensible, the constructor
    should be available to subclasses.
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit cfd2d70889fdb07bba4d0bb05e59abe2128c84ee
Author: David Mulder <dmulder at suse.com>
Date:   Thu Mar 29 08:00:15 2018 -0600

    gpo: Rename the inf_to class to gp_ext_setter
    
    This class will be subclassed and used for more
    than just inf settings application.
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 libgpo/gpo_filesync.c                 |   2 +-
 python/samba/gp_sec_ext.py            | 153 +++++++++++++++++++
 python/samba/gpclass.py               | 274 ++++++++++++++--------------------
 source4/param/pyparam.c               |  25 ++++
 source4/scripting/bin/samba_gpoupdate |  79 +---------
 5 files changed, 296 insertions(+), 237 deletions(-)
 create mode 100644 python/samba/gp_sec_ext.py


Changeset truncated at 500 lines:

diff --git a/libgpo/gpo_filesync.c b/libgpo/gpo_filesync.c
index 6e3efda..bf0bb53 100644
--- a/libgpo/gpo_filesync.c
+++ b/libgpo/gpo_filesync.c
@@ -50,7 +50,7 @@ NTSTATUS gpo_copy_file(TALLOC_CTX *mem_ctx,
 	int read_size = io_bufsize;
 	off_t nread = 0;
 
-	result = cli_openx(cli, nt_path, O_RDONLY, DENY_NONE, &fnum);
+	result = cli_open(cli, nt_path, O_RDONLY, DENY_NONE, &fnum);
 	if (!NT_STATUS_IS_OK(result)) {
 		goto out;
 	}
diff --git a/python/samba/gp_sec_ext.py b/python/samba/gp_sec_ext.py
new file mode 100644
index 0000000..bbd385f
--- /dev/null
+++ b/python/samba/gp_sec_ext.py
@@ -0,0 +1,153 @@
+# gp_sec_ext kdc gpo policy
+# Copyright (C) Luke Morrison <luc785 at .hotmail.com> 2013
+# Copyright (C) David Mulder <dmulder at suse.com> 2018
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import os.path
+from gpclass import gp_ext_setter, gp_inf_ext
+
+class inf_to_kdc_tdb(gp_ext_setter):
+    def mins_to_hours(self):
+        return '%d' % (int(self.val)/60)
+
+    def days_to_hours(self):
+        return '%d' % (int(self.val)*24)
+
+    def set_kdc_tdb(self, val):
+        old_val = self.gp_db.gpostore.get(self.attribute)
+        self.logger.info('%s was changed from %s to %s' % (self.attribute,
+                                                           old_val, val))
+        if val is not None:
+            self.gp_db.gpostore.store(self.attribute, val)
+            self.gp_db.store(str(self), self.attribute, old_val)
+        else:
+            self.gp_db.gpostore.delete(self.attribute)
+            self.gp_db.delete(str(self), self.attribute)
+
+    def mapper(self):
+        return { 'kdc:user_ticket_lifetime': (self.set_kdc_tdb, self.explicit),
+                 'kdc:service_ticket_lifetime': (self.set_kdc_tdb,
+                                                 self.mins_to_hours),
+                 'kdc:renewal_lifetime': (self.set_kdc_tdb,
+                                          self.days_to_hours),
+               }
+
+    def __str__(self):
+        return 'Kerberos Policy'
+
+class inf_to_ldb(gp_ext_setter):
+    '''This class takes the .inf file parameter (essentially a GPO file mapped
+    to a GUID), hashmaps it to the Samba parameter, which then uses an ldb
+    object to update the parameter to Samba4. Not registry oriented whatsoever.
+    '''
+
+    def ch_minPwdAge(self, val):
+        old_val = self.ldb.get_minPwdAge()
+        self.logger.info('KDC Minimum Password age was changed from %s to %s' \
+                         % (old_val, val))
+        self.gp_db.store(str(self), self.attribute, old_val)
+        self.ldb.set_minPwdAge(val)
+
+    def ch_maxPwdAge(self, val):
+        old_val = self.ldb.get_maxPwdAge()
+        self.logger.info('KDC Maximum Password age was changed from %s to %s' \
+                         % (old_val, val))
+        self.gp_db.store(str(self), self.attribute, old_val)
+        self.ldb.set_maxPwdAge(val)
+
+    def ch_minPwdLength(self, val):
+        old_val = self.ldb.get_minPwdLength()
+        self.logger.info(
+            'KDC Minimum Password length was changed from %s to %s' \
+             % (old_val, val))
+        self.gp_db.store(str(self), self.attribute, old_val)
+        self.ldb.set_minPwdLength(val)
+
+    def ch_pwdProperties(self, val):
+        old_val = self.ldb.get_pwdProperties()
+        self.logger.info('KDC Password Properties were changed from %s to %s' \
+                         % (old_val, val))
+        self.gp_db.store(str(self), self.attribute, old_val)
+        self.ldb.set_pwdProperties(val)
+
+    def days2rel_nttime(self):
+        seconds = 60
+        minutes = 60
+        hours = 24
+        sam_add = 10000000
+        val = (self.val)
+        val = int(val)
+        return  str(-(val * seconds * minutes * hours * sam_add))
+
+    def mapper(self):
+        '''ldap value : samba setter'''
+        return { "minPwdAge" : (self.ch_minPwdAge, self.days2rel_nttime),
+                 "maxPwdAge" : (self.ch_maxPwdAge, self.days2rel_nttime),
+                 # Could be none, but I like the method assignment in
+                 # update_samba
+                 "minPwdLength" : (self.ch_minPwdLength, self.explicit),
+                 "pwdProperties" : (self.ch_pwdProperties, self.explicit),
+
+               }
+
+    def __str__(self):
+        return 'System Access'
+
+class gp_sec_ext(gp_inf_ext):
+    '''This class does the following two things:
+        1) Identifies the GPO if it has a certain kind of filepath,
+        2) Finally parses it.
+    '''
+
+    count = 0
+
+    def __str__(self):
+        return "Security GPO extension"
+
+    def list(self, rootpath):
+        return os.path.join(rootpath,
+            "MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf")
+
+    def listmachpol(self, rootpath):
+        return os.path.join(rootpath, "Machine/Registry.pol")
+
+    def listuserpol(self, rootpath):
+        return os.path.join(rootpath, "User/Registry.pol")
+
+    def apply_map(self):
+        return {"System Access": {"MinimumPasswordAge": ("minPwdAge",
+                                                         inf_to_ldb),
+                                  "MaximumPasswordAge": ("maxPwdAge",
+                                                         inf_to_ldb),
+                                  "MinimumPasswordLength": ("minPwdLength",
+                                                            inf_to_ldb),
+                                  "PasswordComplexity": ("pwdProperties",
+                                                         inf_to_ldb),
+                                 },
+                "Kerberos Policy": {"MaxTicketAge": (
+                                        "kdc:user_ticket_lifetime",
+                                        inf_to_kdc_tdb
+                                    ),
+                                    "MaxServiceAge": (
+                                        "kdc:service_ticket_lifetime",
+                                        inf_to_kdc_tdb
+                                    ),
+                                    "MaxRenewAge": (
+                                        "kdc:renewal_lifetime",
+                                        inf_to_kdc_tdb
+                                    ),
+                                   }
+               }
+
diff --git a/python/samba/gpclass.py b/python/samba/gpclass.py
index 33c9001..0966611 100644
--- a/python/samba/gpclass.py
+++ b/python/samba/gpclass.py
@@ -25,6 +25,10 @@ from StringIO import StringIO
 from abc import ABCMeta, abstractmethod
 import xml.etree.ElementTree as etree
 import re
+from samba.net import Net
+from samba.dcerpc import nbt
+from samba import smb
+import samba.gpo as gpo
 
 try:
     from enum import Enum
@@ -286,6 +290,9 @@ class GPOStorage:
 class gp_ext(object):
     __metaclass__ = ABCMeta
 
+    def __init__(self, logger):
+        self.logger = logger
+
     @abstractmethod
     def list(self, rootpath):
         pass
@@ -295,14 +302,41 @@ class gp_ext(object):
         pass
 
     @abstractmethod
-    def parse(self, afile, ldb, conn, gp_db, lp):
+    def read(self, policy):
         pass
 
+    def parse(self, afile, ldb, conn, gp_db, lp):
+        self.ldb = ldb
+        self.gp_db = gp_db
+        self.lp = lp
+
+        # Fixing the bug where only some Linux Boxes capitalize MACHINE
+        try:
+            blist = afile.split('/')
+            idx = afile.lower().split('/').index('machine')
+            for case in [
+                            blist[idx].upper(),
+                            blist[idx].capitalize(),
+                            blist[idx].lower()
+                        ]:
+                bfile = '/'.join(blist[:idx]) + '/' + case + '/' + \
+                    '/'.join(blist[idx+1:])
+                try:
+                    return self.read(conn.loadfile(bfile.replace('/', '\\')))
+                except NTSTATUSError:
+                    continue
+        except ValueError:
+            try:
+                return self.read(conn.loadfile(afile.replace('/', '\\')))
+            except Exception as e:
+                self.logger.error(str(e))
+                return None
+
     @abstractmethod
     def __str__(self):
         pass
 
-class inf_to():
+class gp_ext_setter():
     __metaclass__ = ABCMeta
 
     def __init__(self, logger, ldb, gp_db, lp, attribute, val):
@@ -328,148 +362,19 @@ class inf_to():
     def __str__(self):
         pass
 
-class inf_to_kdc_tdb(inf_to):
-    def mins_to_hours(self):
-        return '%d' % (int(self.val)/60)
-
-    def days_to_hours(self):
-        return '%d' % (int(self.val)*24)
-
-    def set_kdc_tdb(self, val):
-        old_val = self.gp_db.gpostore.get(self.attribute)
-        self.logger.info('%s was changed from %s to %s' % (self.attribute,
-                                                           old_val, val))
-        if val is not None:
-            self.gp_db.gpostore.store(self.attribute, val)
-            self.gp_db.store(str(self), self.attribute, old_val)
-        else:
-            self.gp_db.gpostore.delete(self.attribute)
-            self.gp_db.delete(str(self), self.attribute)
-
-    def mapper(self):
-        return { 'kdc:user_ticket_lifetime': (self.set_kdc_tdb, self.explicit),
-                 'kdc:service_ticket_lifetime': (self.set_kdc_tdb,
-                                                 self.mins_to_hours),
-                 'kdc:renewal_lifetime': (self.set_kdc_tdb,
-                                          self.days_to_hours),
-               }
-
-    def __str__(self):
-        return 'Kerberos Policy'
-
-class inf_to_ldb(inf_to):
-    '''This class takes the .inf file parameter (essentially a GPO file mapped
-    to a GUID), hashmaps it to the Samba parameter, which then uses an ldb
-    object to update the parameter to Samba4. Not registry oriented whatsoever.
-    '''
-
-    def ch_minPwdAge(self, val):
-        old_val = self.ldb.get_minPwdAge()
-        self.logger.info('KDC Minimum Password age was changed from %s to %s' \
-                         % (old_val, val))
-        self.gp_db.store(str(self), self.attribute, old_val)
-        self.ldb.set_minPwdAge(val)
-
-    def ch_maxPwdAge(self, val):
-        old_val = self.ldb.get_maxPwdAge()
-        self.logger.info('KDC Maximum Password age was changed from %s to %s' \
-                         % (old_val, val))
-        self.gp_db.store(str(self), self.attribute, old_val)
-        self.ldb.set_maxPwdAge(val)
-
-    def ch_minPwdLength(self, val):
-        old_val = self.ldb.get_minPwdLength()
-        self.logger.info(
-            'KDC Minimum Password length was changed from %s to %s' \
-             % (old_val, val))
-        self.gp_db.store(str(self), self.attribute, old_val)
-        self.ldb.set_minPwdLength(val)
-
-    def ch_pwdProperties(self, val):
-        old_val = self.ldb.get_pwdProperties()
-        self.logger.info('KDC Password Properties were changed from %s to %s' \
-                         % (old_val, val))
-        self.gp_db.store(str(self), self.attribute, old_val)
-        self.ldb.set_pwdProperties(val)
-
-    def days2rel_nttime(self):
-        seconds = 60
-        minutes = 60
-        hours = 24
-        sam_add = 10000000
-        val = (self.val)
-        val = int(val)
-        return  str(-(val * seconds * minutes * hours * sam_add))
-
-    def mapper(self):
-        '''ldap value : samba setter'''
-        return { "minPwdAge" : (self.ch_minPwdAge, self.days2rel_nttime),
-                 "maxPwdAge" : (self.ch_maxPwdAge, self.days2rel_nttime),
-                 # Could be none, but I like the method assignment in
-                 # update_samba
-                 "minPwdLength" : (self.ch_minPwdLength, self.explicit),
-                 "pwdProperties" : (self.ch_pwdProperties, self.explicit),
-
-               }
-
-    def __str__(self):
-        return 'System Access'
-
-
-class gp_sec_ext(gp_ext):
-    '''This class does the following two things:
-        1) Identifies the GPO if it has a certain kind of filepath,
-        2) Finally parses it.
-    '''
-
-    count = 0
-
-    def __init__(self, logger):
-        self.logger = logger
-
-    def __str__(self):
-        return "Security GPO extension"
-
+class gp_inf_ext(gp_ext):
+    @abstractmethod
     def list(self, rootpath):
-        return os.path.join(rootpath,
-                            "MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf")
-
-    def listmachpol(self, rootpath):
-        return os.path.join(rootpath, "Machine/Registry.pol")
-
-    def listuserpol(self, rootpath):
-        return os.path.join(rootpath, "User/Registry.pol")
+        pass
 
+    @abstractmethod
     def apply_map(self):
-        return {"System Access": {"MinimumPasswordAge": ("minPwdAge",
-                                                         inf_to_ldb),
-                                  "MaximumPasswordAge": ("maxPwdAge",
-                                                         inf_to_ldb),
-                                  "MinimumPasswordLength": ("minPwdLength",
-                                                            inf_to_ldb),
-                                  "PasswordComplexity": ("pwdProperties",
-                                                         inf_to_ldb),
-                                 },
-                "Kerberos Policy": {"MaxTicketAge": (
-                                        "kdc:user_ticket_lifetime",
-                                        inf_to_kdc_tdb
-                                    ),
-                                    "MaxServiceAge": (
-                                        "kdc:service_ticket_lifetime",
-                                        inf_to_kdc_tdb
-                                    ),
-                                    "MaxRenewAge": (
-                                        "kdc:renewal_lifetime",
-                                        inf_to_kdc_tdb
-                                    ),
-                                   }
-               }
-
-    def read_inf(self, path, conn):
+        pass
+
+    def read(self, policy):
         ret = False
         inftable = self.apply_map()
 
-        policy = conn.loadfile(path.replace('/', '\\'))
         current_section = None
 
         # So here we would declare a boolean,
@@ -499,27 +404,78 @@ class gp_sec_ext(gp_ext):
                     self.gp_db.commit()
         return ret
 
-    def parse(self, afile, ldb, conn, gp_db, lp):
-        self.ldb = ldb
-        self.gp_db = gp_db
-        self.lp = lp
+    @abstractmethod
+    def __str__(self):
+        pass
 
-        # Fixing the bug where only some Linux Boxes capitalize MACHINE
-        if afile.endswith('inf'):
+''' Fetch the hostname of a writable DC '''
+def get_dc_hostname(creds, lp):
+    net = Net(creds=creds, lp=lp)
+    cldap_ret = net.finddc(domain=lp.get('realm'), flags=(nbt.NBT_SERVER_LDAP |
+        nbt.NBT_SERVER_DS))
+    return cldap_ret.pdc_dns_name
+
+''' Fetch a list of GUIDs for applicable GPOs '''
+def get_gpo_list(dc_hostname, creds, lp):
+    gpos = []
+    ads = gpo.ADS_STRUCT(dc_hostname, lp, creds)
+    if ads.connect():
+        gpos = ads.get_gpo_list(creds.get_username())
+    return gpos
+
+def apply_gp(lp, creds, test_ldb, logger, store, gp_extensions):
+    gp_db = store.get_gplog(creds.get_username())
+    dc_hostname = get_dc_hostname(creds, lp)
+    try:
+        conn =  smb.SMB(dc_hostname, 'sysvol', lp=lp, creds=creds)
+    except:
+        logger.error('Error connecting to \'%s\' using SMB' % dc_hostname)
+        raise
+    gpos = get_gpo_list(dc_hostname, creds, lp)
+
+    for gpo_obj in gpos:
+        guid = gpo_obj.name
+        if guid == 'Local Policy':
+            continue
+        path = os.path.join(lp.get('realm').lower(), 'Policies', guid)
+        local_path = os.path.join(lp.get("path", "sysvol"), path)
+        version = int(gpo.gpo_get_sysvol_gpt_version(local_path)[1])
+        if version != store.get_int(guid):
+            logger.info('GPO %s has changed' % guid)
+            gp_db.state(GPOSTATE.APPLY)
+        else:
+            gp_db.state(GPOSTATE.ENFORCE)
+        gp_db.set_guid(guid)
+        store.start()
+        for ext in gp_extensions:
             try:
-                blist = afile.split('/')
-                idx = afile.lower().split('/').index('machine')
-                for case in [blist[idx].upper(), blist[idx].capitalize(),
-                             blist[idx].lower()]:
-                    bfile = '/'.join(blist[:idx]) + '/' + case + '/' + \
-                            '/'.join(blist[idx+1:])
-                    try:
-                        return self.read_inf(bfile, conn)
-                    except NTSTATUSError:
-                        continue
-            except ValueError:
-                try:
-                    return self.read_inf(afile, conn)
-                except:
-                    return None
+                ext.parse(ext.list(path), test_ldb, conn, gp_db, lp)
+            except Exception as e:
+                logger.error('Failed to parse gpo %s for extension %s' % \
+                    (guid, str(ext)))
+                logger.error('Message was: ' + str(e))
+                store.cancel()
+                continue
+        store.store(guid, '%i' % version)
+        store.commit()
+
+def unapply_log(gp_db):
+    while True:
+        item = gp_db.apply_log_pop()
+        if item:
+            yield item
+        else:
+            break
+
+def unapply_gp(lp, creds, test_ldb, logger, store, gp_extensions):
+    gp_db = store.get_gplog(creds.get_username())
+    gp_db.state(GPOSTATE.UNAPPLY)
+    for gpo_guid in unapply_log(gp_db):
+        gp_db.set_guid(gpo_guid)
+        unapply_attributes = gp_db.list(gp_extensions)
+        for attr in unapply_attributes:
+            attr_obj = attr[-1](logger, test_ldb, gp_db, lp, attr[0], attr[1])
+            attr_obj.mapper()[attr[0]][0](attr[1]) # Set the old value
+            gp_db.delete(str(attr_obj), attr[0])
+        gp_db.commit()
 
diff --git a/source4/param/pyparam.c b/source4/param/pyparam.c
index f16c2c0..18d7017 100644
--- a/source4/param/pyparam.c


-- 
Samba Shared Repository



More information about the samba-cvs mailing list