]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
gpo: Enable user policy application
authorDavid Mulder <dmulder@suse.com>
Tue, 20 Jul 2021 15:13:06 +0000 (09:13 -0600)
committerJeremy Allison <jra@samba.org>
Fri, 13 Aug 2021 19:14:30 +0000 (19:14 +0000)
Signed-off-by: David Mulder <dmulder@suse.com>
Reviewed-by: Jeremy Allison <jra@samba.org>
python/samba/gpclass.py
python/samba/tests/gpo.py
python/samba/tests/gpo_member.py
source4/scripting/bin/samba-gpupdate

index 17d7d0c9243b2b514cd9de4427e32405cccc3c3e..1b8f825e47b257f4d567a6cde3d04bc2d7d10438 100644 (file)
@@ -19,6 +19,7 @@ import sys
 import os, shutil
 import errno
 import tdb
+import pwd
 sys.path.insert(0, "bin/python")
 from samba import NTSTATUSError
 from configparser import ConfigParser
@@ -294,11 +295,12 @@ class GPOStorage:
 class gp_ext(object):
     __metaclass__ = ABCMeta
 
-    def __init__(self, logger, lp, creds, store):
+    def __init__(self, logger, lp, creds, username, store):
         self.logger = logger
         self.lp = lp
         self.creds = creds
-        self.gp_db = store.get_gplog(creds.get_username())
+        self.username = username
+        self.gp_db = store.get_gplog(username)
 
     @abstractmethod
     def process_group_policy(self, deleted_gpo_list, changed_gpo_list):
@@ -364,11 +366,12 @@ def get_dc_hostname(creds, lp):
 ''' Fetch a list of GUIDs for applicable GPOs '''
 
 
-def get_gpo_list(dc_hostname, creds, lp):
+def get_gpo_list(dc_hostname, creds, lp, username):
     gpos = []
     ads = gpo.ADS_STRUCT(dc_hostname, lp, creds)
     if ads.connect():
-        gpos = ads.get_gpo_list(creds.get_username())
+        # username is DOM\\SAM, but get_gpo_list expects SAM
+        gpos = ads.get_gpo_list(username.split('\\')[-1])
     return gpos
 
 
@@ -433,10 +436,10 @@ def gpo_version(lp, path):
     return int(gpo.gpo_get_sysvol_gpt_version(gpt_path)[1])
 
 
-def apply_gp(lp, creds, logger, store, gp_extensions, force=False):
-    gp_db = store.get_gplog(creds.get_username())
+def apply_gp(lp, creds, logger, store, gp_extensions, username, target, force=False):
+    gp_db = store.get_gplog(username)
     dc_hostname = get_dc_hostname(creds, lp)
-    gpos = get_gpo_list(dc_hostname, creds, lp)
+    gpos = get_gpo_list(dc_hostname, creds, lp, username)
     del_gpos = get_deleted_gpos_list(gp_db, gpos)
     try:
         check_refresh_gpo_list(dc_hostname, lp, creds, gpos)
@@ -464,8 +467,12 @@ def apply_gp(lp, creds, logger, store, gp_extensions, force=False):
     store.start()
     for ext in gp_extensions:
         try:
-            ext = ext(logger, lp, creds, store)
-            ext.process_group_policy(del_gpos, changed_gpos)
+            ext = ext(logger, lp, creds, username, store)
+            if target == 'Computer':
+                ext.process_group_policy(del_gpos, changed_gpos)
+            else:
+                drop_privileges(creds.get_principal(), ext.process_group_policy,
+                                del_gpos, changed_gpos)
         except Exception as e:
             logger.error('Failed to apply extension  %s' % str(ext))
             logger.error('Message was: %s: %s' % (type(e).__name__, str(e)))
@@ -481,16 +488,20 @@ def apply_gp(lp, creds, logger, store, gp_extensions, force=False):
     store.commit()
 
 
-def unapply_gp(lp, creds, logger, store, gp_extensions):
-    gp_db = store.get_gplog(creds.get_username())
+def unapply_gp(lp, creds, logger, store, gp_extensions, username, target):
+    gp_db = store.get_gplog(username)
     gp_db.state(GPOSTATE.UNAPPLY)
     # Treat all applied gpos as deleted
     del_gpos = gp_db.get_applied_settings(gp_db.get_applied_guids())
     store.start()
     for ext in gp_extensions:
         try:
-            ext = ext(logger, lp, creds, store)
-            ext.process_group_policy(del_gpos, [])
+            ext = ext(logger, lp, creds, username, store)
+            if target == 'Computer':
+                ext.process_group_policy(del_gpos, [])
+            else:
+                drop_privileges(username, ext.process_group_policy,
+                                del_gpos, [])
         except Exception as e:
             logger.error('Failed to unapply extension  %s' % str(ext))
             logger.error('Message was: ' + str(e))
@@ -509,9 +520,9 @@ def __rsop_vals(vals, level=4):
     else:
         return vals
 
-def rsop(lp, creds, logger, store, gp_extensions, target):
+def rsop(lp, creds, logger, store, gp_extensions, username, target):
     dc_hostname = get_dc_hostname(creds, lp)
-    gpos = get_gpo_list(dc_hostname, creds, lp)
+    gpos = get_gpo_list(dc_hostname, creds, lp, username)
     check_refresh_gpo_list(dc_hostname, lp, creds, gpos)
 
     print('Resultant Set of Policy')
@@ -523,7 +534,7 @@ def rsop(lp, creds, logger, store, gp_extensions, target):
         print('GPO: %s' % gpo.display_name)
         print('='*term_width)
         for ext in gp_extensions:
-            ext = ext(logger, lp, creds, store)
+            ext = ext(logger, lp, creds, username, store)
             cse_name_m = re.findall("'([\w\.]+)'", str(type(ext)))
             if len(cse_name_m) > 0:
                 cse_name = cse_name_m[-1].split('.')[-1]
@@ -616,3 +627,45 @@ def unregister_gp_extension(guid, smb_conf=None):
     atomic_write_conf(lp, parser)
 
     return True
+
+
+def set_privileges(username, uid, gid):
+    '''
+    Set current process privileges
+    '''
+
+    os.setegid(gid)
+    os.seteuid(uid)
+
+
+def drop_privileges(username, func, *args):
+    '''
+    Run supplied function with privileges for specified username.
+    '''
+    current_uid = os.getuid()
+
+    if not current_uid == 0:
+        raise Exception('Not enough permissions to drop privileges')
+
+    user_uid = pwd.getpwnam(username).pw_uid
+    user_gid = pwd.getpwnam(username).pw_gid
+
+    # Drop privileges
+    set_privileges(username, user_uid, user_gid)
+
+    # We need to catch exception in order to be able to restore
+    # privileges later in this function
+    out = None
+    exc = None
+    try:
+        out = func(*args)
+    except Exception as e:
+        exc = e
+
+    # Restore privileges
+    set_privileges('root', current_uid, 0)
+
+    if exc:
+        raise exc
+
+    return out
index b5dc09543ad0c4926aef358210267413a8ac0212..52510e505952f541d06500d8a39798af10f02add 100644 (file)
@@ -478,7 +478,8 @@ class GPOTests(tests.TestCase):
         machine_creds.set_machine_account()
 
         # Initialize the group policy extension
-        ext = gp_krb_ext(logger, self.lp, machine_creds, store)
+        ext = gp_krb_ext(logger, self.lp, machine_creds,
+                         machine_creds.get_username(), store)
 
         ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
         if ads.connect():
@@ -532,7 +533,8 @@ class GPOTests(tests.TestCase):
         machine_creds.set_machine_account()
 
         # Initialize the group policy extension
-        ext = gp_scripts_ext(logger, self.lp, machine_creds, store)
+        ext = gp_scripts_ext(logger, self.lp, machine_creds,
+                             machine_creds.get_username(), store)
 
         ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
         if ads.connect():
@@ -590,7 +592,8 @@ class GPOTests(tests.TestCase):
         machine_creds.set_machine_account()
 
         # Initialize the group policy extension
-        ext = gp_sudoers_ext(logger, self.lp, machine_creds, store)
+        ext = gp_sudoers_ext(logger, self.lp, machine_creds,
+                             machine_creds.get_username(), store)
 
         ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
         if ads.connect():
@@ -641,7 +644,8 @@ class GPOTests(tests.TestCase):
         machine_creds.set_machine_account()
 
         # Initialize the group policy extension
-        ext = vgp_sudoers_ext(logger, self.lp, machine_creds, store)
+        ext = vgp_sudoers_ext(logger, self.lp, machine_creds,
+                              machine_creds.get_username(), store)
 
         ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
         if ads.connect():
@@ -734,7 +738,8 @@ class GPOTests(tests.TestCase):
         machine_creds.guess(self.lp)
         machine_creds.set_machine_account()
 
-        ext = gp_inf_ext(logger, self.lp, machine_creds, store)
+        ext = gp_inf_ext(logger, self.lp, machine_creds,
+                         machine_creds.get_username(), store)
         test_data = '[Kerberos Policy]\nMaxTicketAge = 99\n'
 
         with NamedTemporaryFile() as f:
@@ -819,7 +824,8 @@ class GPOTests(tests.TestCase):
             self.assertTrue(ret, 'Could not create the target %s' %
                                  (reg_pol % g.name))
             for ext in gp_extensions:
-                ext = ext(logger, self.lp, machine_creds, store)
+                ext = ext(logger, self.lp, machine_creds,
+                          machine_creds.get_username(), store)
                 ret = ext.rsop(g)
                 self.assertEquals(len(ret.keys()), 1,
                                   'A single policy should have been displayed')
@@ -918,7 +924,8 @@ class GPOTests(tests.TestCase):
         remove = []
         with TemporaryDirectory() as dname:
             for ext in gp_extensions:
-                ext = ext(logger, self.lp, machine_creds, store)
+                ext = ext(logger, self.lp, machine_creds,
+                          machine_creds.get_username(), store)
                 if type(ext) == gp_krb_ext:
                     ext.process_group_policy([], gpos)
                     ret = store.get_int('kdc:user_ticket_lifetime')
@@ -994,7 +1001,8 @@ class GPOTests(tests.TestCase):
             lp = LoadParm(f.name)
 
             # Initialize the group policy extension
-            ext = gp_smb_conf_ext(logger, lp, machine_creds, store)
+            ext = gp_smb_conf_ext(logger, lp, machine_creds,
+                                  machine_creds.get_username(), store)
             ext.process_group_policy([], gpos)
             lp = LoadParm(f.name)
 
@@ -1041,7 +1049,8 @@ class GPOTests(tests.TestCase):
         machine_creds.set_machine_account()
 
         # Initialize the group policy extension
-        ext = gp_msgs_ext(logger, self.lp, machine_creds, store)
+        ext = gp_msgs_ext(logger, self.lp, machine_creds,
+                          machine_creds.get_username(), store)
 
         ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
         if ads.connect():
@@ -1104,7 +1113,8 @@ class GPOTests(tests.TestCase):
         machine_creds.set_machine_account()
 
         # Initialize the group policy extension
-        ext = vgp_symlink_ext(logger, self.lp, machine_creds, store)
+        ext = vgp_symlink_ext(logger, self.lp, machine_creds,
+                              machine_creds.get_username(), store)
 
         ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
         if ads.connect():
@@ -1181,7 +1191,8 @@ class GPOTests(tests.TestCase):
         machine_creds.set_machine_account()
 
         # Initialize the group policy extension
-        ext = vgp_files_ext(logger, self.lp, machine_creds, store)
+        ext = vgp_files_ext(logger, self.lp, machine_creds,
+                            machine_creds.get_username(), store)
 
         ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
         if ads.connect():
@@ -1265,7 +1276,8 @@ class GPOTests(tests.TestCase):
         machine_creds.set_machine_account()
 
         # Initialize the group policy extension
-        ext = vgp_openssh_ext(logger, self.lp, machine_creds, store)
+        ext = vgp_openssh_ext(logger, self.lp, machine_creds,
+                              machine_creds.get_username(), store)
 
         ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
         if ads.connect():
@@ -1335,7 +1347,8 @@ class GPOTests(tests.TestCase):
         machine_creds.set_machine_account()
 
         # Initialize the group policy extension
-        ext = vgp_startup_scripts_ext(logger, self.lp, machine_creds, store)
+        ext = vgp_startup_scripts_ext(logger, self.lp, machine_creds,
+                                      machine_creds.get_username(), store)
 
         ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
         if ads.connect():
@@ -1451,7 +1464,8 @@ class GPOTests(tests.TestCase):
         machine_creds.set_machine_account()
 
         # Initialize the group policy extension
-        ext = vgp_motd_ext(logger, self.lp, machine_creds, store)
+        ext = vgp_motd_ext(logger, self.lp, machine_creds,
+                           machine_creds.get_username(), store)
 
         ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
         if ads.connect():
@@ -1500,7 +1514,8 @@ class GPOTests(tests.TestCase):
         machine_creds.set_machine_account()
 
         # Initialize the group policy extension
-        ext = vgp_issue_ext(logger, self.lp, machine_creds, store)
+        ext = vgp_issue_ext(logger, self.lp, machine_creds,
+                            machine_creds.get_username(), store)
 
         ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
         if ads.connect():
@@ -1551,7 +1566,8 @@ class GPOTests(tests.TestCase):
         machine_creds.set_machine_account()
 
         # Initialize the group policy extension
-        ext = vgp_access_ext(logger, self.lp, machine_creds, store)
+        ext = vgp_access_ext(logger, self.lp, machine_creds,
+                             machine_creds.get_username(), store)
 
         ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
         if ads.connect():
@@ -1679,7 +1695,8 @@ class GPOTests(tests.TestCase):
         machine_creds.set_machine_account()
 
         # Initialize the group policy extension
-        ext = gp_gnome_settings_ext(logger, self.lp, machine_creds, store)
+        ext = gp_gnome_settings_ext(logger, self.lp, machine_creds,
+                                    machine_creds.get_username(), store)
 
         ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
         if ads.connect():
@@ -1901,7 +1918,8 @@ class GPOTests(tests.TestCase):
         machine_creds.set_machine_account()
 
         # Initialize the group policy extension
-        ext = gp_cert_auto_enroll_ext(logger, self.lp, machine_creds, store)
+        ext = gp_cert_auto_enroll_ext(logger, self.lp, machine_creds,
+                                      machine_creds.get_username(), store)
 
         ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
         if ads.connect():
index 3d614f53d04d8f1617c5f54755e81f6c6b5d0a15..18e8cb9715f85ce6ffce74962f98b5385827a591 100644 (file)
@@ -39,6 +39,7 @@ class GPOTests(tests.TestCase):
         cache_dir = self.lp.get('cache directory')
         store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb'))
         try:
-            gp_access_ext(logger, self.lp, self.creds, store)
+            gp_access_ext(logger, self.lp, self.creds,
+                          self.creds.get_username(), store)
         except Exception:
             self.fail('Initializing gp_access_ext should not require ad-dc')
index df784e7744aef5323eec4d6537b9891f75ac61f6..4d13f9dae10acfd90240fe76b1618b2950eb4575 100755 (executable)
@@ -46,6 +46,7 @@ from samba.vgp_startup_scripts_ext import vgp_startup_scripts_ext
 from samba.vgp_access_ext import vgp_access_ext
 from samba.gp_gnome_settings_ext import gp_gnome_settings_ext
 from samba.gp_cert_auto_enroll_ext import gp_cert_auto_enroll_ext
+from samba.credentials import Credentials
 import logging
 
 if __name__ == "__main__":
@@ -73,6 +74,15 @@ if __name__ == "__main__":
     lp = sambaopts.get_loadparm()
 
     creds = credopts.get_credentials(lp, fallback_machine=True)
+    # Apply policy to the command line specified user
+    if opts.target == 'Computer':
+        username = creds.get_username()
+    elif opts.target == 'User':
+        username = '%s\\%s' % (creds.get_domain(), creds.get_username())
+    # Always supply the machine creds for fetching the gpo list
+    creds = Credentials()
+    creds.guess(lp)
+    creds.set_machine_account(lp)
 
     # Set up logging
     logger = logging.getLogger('samba-gpupdate')
@@ -116,9 +126,11 @@ if __name__ == "__main__":
         gp_extensions.extend(user_exts)
 
     if opts.rsop:
-        rsop(lp, creds, logger, store, gp_extensions, opts.target)
+        rsop(lp, creds, logger, store, gp_extensions, username, opts.target)
     elif not opts.unapply:
-        apply_gp(lp, creds, logger, store, gp_extensions, opts.force)
+        apply_gp(lp, creds, logger, store, gp_extensions, username,
+                 opts.target, opts.force)
     else:
-        unapply_gp(lp, creds, logger, store, gp_extensions)
+        unapply_gp(lp, creds, logger, store, gp_extensions, username,
+                   opts.target)