netcmd: Fix --kerberos=yes and --no-secrets domain backups
authorTim Beale <timbeale@catalyst.net.nz>
Thu, 9 Aug 2018 04:20:10 +0000 (16:20 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 15 Aug 2018 08:19:09 +0000 (10:19 +0200)
The --kerberos=yes and --no-secrets options didn't work in combination
for domain backups. The problem was creds.get_username() might not
necessarily match the kerberos user (such as in the selftest
environment). If this was the case, then trying to reset the admin
password failed (because the creds.get_username() didn't exist in
the DB).

Because the admin user always has a fixed RID, we can work out the
administrator based on its object SID, instead of relying on the
username in the creds.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13566

Signed-off-by: Tim Beale <timbeale@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
Autobuild-Date(master): Wed Aug 15 10:19:09 CEST 2018 on sn-devel-144

python/samba/netcmd/domain_backup.py

index cf2327e5bbb18c01b646c5d1ee16e8c8f4be5f46..ae04ec1d2c42b77992a266eff84ad0a74ed2b411 100644 (file)
@@ -33,7 +33,7 @@ from samba.auth import system_session
 from samba.join import DCJoinContext, join_clone, DCCloneAndRenameContext
 from samba.dcerpc.security import dom_sid
 from samba.netcmd import Option, CommandError
-from samba.dcerpc import misc
+from samba.dcerpc import misc, security
 from samba import Ldb
 from fsmo import cmd_fsmo_seize
 from samba.provision import make_smbconf
@@ -158,16 +158,25 @@ def check_targetdir(logger, targetdir):
 
 # For '--no-secrets' backups, this sets the Administrator user's password to a
 # randomly-generated value. This is similar to the provision behaviour
-def set_admin_password(logger, samdb, username):
+def set_admin_password(logger, samdb):
     """Sets a randomly generated password for the backup DB's admin user"""
 
+    # match the admin user by RID
+    domainsid = samdb.get_domain_sid()
+    match_admin = "(objectsid={}-{})".format(domainsid,
+                                             security.DOMAIN_RID_ADMINISTRATOR)
+    search_expr = "(&(objectClass=user){})".format(match_admin)
+
+    # retrieve the admin username (just in case it's been renamed)
+    res = samdb.search(base=samdb.domain_dn(), scope=ldb.SCOPE_SUBTREE,
+                       expression=search_expr)
+    username = str(res[0]['samaccountname'])
+
     adminpass = samba.generate_random_password(12, 32)
     logger.info("Setting %s password in backup to: %s" % (username, adminpass))
     logger.info("Run 'samba-tool user setpassword %s' after restoring DB" %
                 username)
-    samdb.setpassword("(&(objectClass=user)(sAMAccountName=%s))"
-                      % ldb.binary_encode(username), adminpass,
-                      force_change_at_next_login=False,
+    samdb.setpassword(search_expr, adminpass, force_change_at_next_login=False,
                       username=username)
 
 
@@ -250,7 +259,7 @@ class cmd_domain_backup_online(samba.netcmd.Command):
 
         # ensure the admin user always has a password set (same as provision)
         if no_secrets:
-            set_admin_password(logger, samdb, creds.get_username())
+            set_admin_password(logger, samdb)
 
         # Add everything in the tmpdir to the backup tar file
         backup_file = backup_filepath(targetdir, realm, time_str)
@@ -762,7 +771,7 @@ class cmd_domain_backup_rename(samba.netcmd.Command):
 
         # ensure the admin user always has a password set (same as provision)
         if no_secrets:
-            set_admin_password(logger, samdb, creds.get_username())
+            set_admin_password(logger, samdb)
 
         # Add everything in the tmpdir to the backup tar file
         backup_file = backup_filepath(targetdir, new_dns_realm, time_str)