python/samba/netcmd/schema.py: samdb schema update now
[nivanova/samba-autobuild/.git] / python / samba / samdb.py
index 348bd212256f5c79b96938950bc6fd9df945f8cb..7184fcfa4b0f6da3990eed19c24d926628f3fc99 100644 (file)
@@ -27,6 +27,7 @@ import ldb
 import time
 import base64
 import os
+import re
 from samba import dsdb, dsdb_dns
 from samba.ndr import ndr_unpack, ndr_pack
 from samba.dcerpc import drsblobs, misc
@@ -37,6 +38,9 @@ from samba.dcerpc import security
 __docformat__ = "restructuredText"
 
 
+def get_default_backend_store():
+    return "tdb"
+
 class SamDB(samba.Ldb):
     """The SAM database."""
 
@@ -86,6 +90,10 @@ class SamDB(samba.Ldb):
         '''return the domain DN'''
         return str(self.get_default_basedn())
 
+    def schema_dn(self):
+        '''return the schema partition dn'''
+        return str(self.get_schema_basedn())
+
     def disable_account(self, search_filter):
         """Disables an account
 
@@ -486,6 +494,65 @@ member: %s
         else:
             self.transaction_commit()
 
+    def newcomputer(self, computername, computerou=None, description=None,
+                    prepare_oldjoin=False, ip_address_list=None,
+                    service_principal_name_list=None):
+        """Adds a new user with additional parameters
+
+        :param computername: Name of the new computer
+        :param computerou: Object container for new computer
+        :param description: Description of the new computer
+        :param prepare_oldjoin: Preset computer password for oldjoin mechanism
+        :param ip_address_list: ip address list for DNS A or AAAA record
+        :param service_principal_name_list: string list of servicePincipalName
+        """
+
+        cn = re.sub(r"\$$", "", computername)
+        if cn.count('$'):
+            raise Exception('Illegal computername "%s"' % computername)
+        samaccountname = "%s$" % cn
+
+        computercontainer_dn = "CN=Computers,%s" % self.domain_dn()
+        if computerou:
+            computercontainer_dn = self.normalize_dn_in_domain(computerou)
+
+        computer_dn = "CN=%s,%s" % (cn, computercontainer_dn)
+
+        ldbmessage = {"dn": computer_dn,
+                      "sAMAccountName": samaccountname,
+                      "objectClass": "computer",
+                      }
+
+        if description is not None:
+            ldbmessage["description"] = description
+
+        if service_principal_name_list:
+            ldbmessage["servicePrincipalName"] = service_principal_name_list
+
+        accountcontrol = str(dsdb.UF_WORKSTATION_TRUST_ACCOUNT |
+                             dsdb.UF_ACCOUNTDISABLE)
+        if prepare_oldjoin:
+            accountcontrol = str(dsdb.UF_WORKSTATION_TRUST_ACCOUNT)
+        ldbmessage["userAccountControl"] = accountcontrol
+
+        if ip_address_list:
+            ldbmessage['dNSHostName'] = '{}.{}'.format(
+                cn, self.domain_dns_name())
+
+        self.transaction_start()
+        try:
+            self.add(ldbmessage)
+
+            if prepare_oldjoin:
+                password = cn.lower()
+                self.setpassword(("(distinguishedName=%s)" %
+                                  ldb.binary_encode(computer_dn)),
+                                 password, False)
+        except:
+            self.transaction_cancel()
+            raise
+        else:
+            self.transaction_commit()
 
     def deleteuser(self, username):
         """Deletes a user
@@ -526,7 +593,11 @@ member: %s
             if len(res) > 1:
                 raise Exception('Matched %u multiple users with filter "%s"' % (len(res), search_filter))
             user_dn = res[0].dn
-            pw = text_type(b'"' + password.encode('utf-8') + b'"', 'utf-8').encode('utf-16-le')
+            if not isinstance(password, text_type):
+                pw = password.decode('utf-8')
+            else:
+                pw = password
+            pw = ('"' + pw + '"').encode('utf-16-le')
             setpw = """
 dn: %s
 changetype: modify
@@ -691,6 +762,15 @@ accountExpires: %u
     def set_schema_from_ldb(self, ldb_conn, write_indices_and_attributes=True):
         dsdb._dsdb_set_schema_from_ldb(self, ldb_conn, write_indices_and_attributes)
 
+    def set_schema_update_now(self):
+        ldif = """
+dn:
+changetype: modify
+add: schemaUpdateNow
+schemaUpdateNow: 1
+"""
+        self.modify_ldif(ldif)
+
     def dsdb_DsReplicaAttribute(self, ldb, ldap_display_name, ldif_elements):
         '''convert a list of attribute values to a DRSUAPI DsReplicaAttribute'''
         return dsdb._dsdb_DsReplicaAttribute(ldb, ldap_display_name, ldif_elements)