diff options
| author | Andrew Tridgell <tridge@samba.org> | 2009-09-18 14:12:02 -0700 | 
|---|---|---|
| committer | Andrew Tridgell <tridge@samba.org> | 2009-09-18 14:12:02 -0700 | 
| commit | 716ddc2a897eacd08aed7ff4bee165e418ff63cc (patch) | |
| tree | 9f400d977baa55edc70fa39e1346fb2dda975a27 /source4/scripting | |
| parent | c6d58efa4b1ad5ff4a9e0f224b8a9789d8f82faf (diff) | |
| parent | c2139e8e5646a8558d70c1ca4ce2d755497de8e1 (diff) | |
| download | samba-716ddc2a897eacd08aed7ff4bee165e418ff63cc.tar.gz samba-716ddc2a897eacd08aed7ff4bee165e418ff63cc.tar.bz2 samba-716ddc2a897eacd08aed7ff4bee165e418ff63cc.zip  | |
Merge branch 'master' of /home/tridge/samba/git/combined
Diffstat (limited to 'source4/scripting')
| -rwxr-xr-x | source4/scripting/bin/fullschema | 2 | ||||
| -rwxr-xr-x | source4/scripting/bin/minschema | 2 | ||||
| -rwxr-xr-x | source4/scripting/bin/reorgldb.py | 60 | ||||
| -rw-r--r-- | source4/scripting/python/samba/idmap.py | 2 | ||||
| -rw-r--r-- | source4/scripting/python/samba/provision.py | 13 | ||||
| -rw-r--r-- | source4/scripting/python/samba/samdb.py | 90 | 
6 files changed, 123 insertions, 46 deletions
diff --git a/source4/scripting/bin/fullschema b/source4/scripting/bin/fullschema index 4c73100492..4a01b6aed0 100755 --- a/source4/scripting/bin/fullschema +++ b/source4/scripting/bin/fullschema @@ -1,6 +1,6 @@  #!/usr/bin/python  #  -#  work out the minimal schema for a set of objectclasses  +# Works out the full schema  #  import base64 diff --git a/source4/scripting/bin/minschema b/source4/scripting/bin/minschema index c860495e96..43f7816116 100755 --- a/source4/scripting/bin/minschema +++ b/source4/scripting/bin/minschema @@ -1,6 +1,6 @@  #!/usr/bin/python  #  -#  work out the minimal schema for a set of objectclasses  +# Works out the minimal schema for a set of objectclasses  #  import base64 diff --git a/source4/scripting/bin/reorgldb.py b/source4/scripting/bin/reorgldb.py new file mode 100755 index 0000000000..571363fdc7 --- /dev/null +++ b/source4/scripting/bin/reorgldb.py @@ -0,0 +1,60 @@ +#!/usr/bin/python +# +# Copyright (C) Matthieu Patou <mat@matws.net> 2009 +# This script realize an offline reorganisation of an LDB +# file it helps to reduce (sometime drastically) the +# size of LDB files. +import sys +import optparse +import os +sys.path.insert(0, "bin/python") + +import samba +from samba.credentials import DONT_USE_KERBEROS +from samba.auth import system_session +from samba import Ldb, substitute_var, valid_netbios_name, check_all_substituted +from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError +import ldb +import samba.getopt as options +from samba.samdb import SamDB +from samba import param +from samba.provision import ProvisionPaths, ProvisionNames,provision_paths_from_lp, Schema + +parser = optparse.OptionParser("provision [options]") +sambaopts = options.SambaOptions(parser) +parser.add_option_group(sambaopts) +parser.add_option_group(options.VersionOptions(parser)) +credopts = options.CredentialsOptions(parser) +parser.add_option_group(credopts) +parser.add_option("--database", type="string", metavar="FILE", +        help="LDB to reorganize") +opts = parser.parse_args()[0] +lp = sambaopts.get_loadparm() +smbconf = lp.configfile + +if not opts.database: +	print "Parameter database is mandatory" +	sys.exit(1) +creds = credopts.get_credentials(lp) +creds.set_kerberos_state(DONT_USE_KERBEROS) +session = system_session() +empty = ldb.Message() +newname="%s.new"%(opts.database) +if os.path.exists(newname): +	os.remove(newname) +old_ldb = Ldb(opts.database, session_info=session, credentials=creds,lp=lp) +new_ldb = Ldb(newname,session_info=session, credentials=creds,lp=lp) + +new_ldb.transaction_start() +res = old_ldb.search(expression="(dn=*)",base="", scope=SCOPE_SUBTREE) +for i in range(0,len(res)): +	if str(res[i].dn) == "@BASEINFO": +		continue +	if str(res[i].dn).startswith("@INDEX:"): +		continue +	delta = new_ldb.msg_diff(empty,res[i]) +	delta.dn = res[i].dn +	delta.remove("distinguishedName") +	new_ldb.add(delta) + +new_ldb.transaction_commit() diff --git a/source4/scripting/python/samba/idmap.py b/source4/scripting/python/samba/idmap.py index acc98a56e8..ad209f42de 100644 --- a/source4/scripting/python/samba/idmap.py +++ b/source4/scripting/python/samba/idmap.py @@ -34,7 +34,7 @@ class IDmapDB(samba.Ldb):      def __init__(self, url=None, lp=None, modules_dir=None, session_info=None,                   credentials=None, flags=0, options=None): -        """Opens the IDmap Database. +        """Opens the IDMap Database          For parameter meanings see the super class (samba.Ldb)          """ diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index 4840efcb63..065677fa68 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -44,7 +44,7 @@ from credentials import Credentials, DONT_USE_KERBEROS  from auth import system_session, admin_session  from samba import version, Ldb, substitute_var, valid_netbios_name  from samba import check_all_substituted -from samba import DS_DOMAIN_FUNCTION_2008_R2, DS_DC_FUNCTION_2008_R2 +from samba import DS_DOMAIN_FUNCTION_2000, DS_DC_FUNCTION_2008_R2  from samba.samdb import SamDB  from samba.idmap import IDmapDB  from samba.dcerpc import security @@ -835,8 +835,8 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,      :note: This will wipe the main SAM database file!      """ -    domainFunctionality = DS_DOMAIN_FUNCTION_2008_R2 -    forestFunctionality = DS_DOMAIN_FUNCTION_2008_R2 +    domainFunctionality = DS_DOMAIN_FUNCTION_2000 +    forestFunctionality = DS_DOMAIN_FUNCTION_2000      domainControllerFunctionality = DS_DC_FUNCTION_2008_R2      # Also wipes the database @@ -978,6 +978,7 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,                  "DOMAINDN": names.domaindn})          message("Setting up sam.ldb data")          setup_add_ldif(samdb, setup_path("provision.ldif"), { +            "CREATTIME": str(int(time.time()) * 1e7), # seconds -> ticks              "DOMAINDN": names.domaindn,              "NETBIOSNAME": names.netbiosname,              "DEFAULTSITE": names.sitename, @@ -1005,10 +1006,10 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,                                  policyguid_dc=policyguid_dc,                                  setup_path=setup_path,                                  domainControllerFunctionality=domainControllerFunctionality) -                # add the NTDSGUID based SPNs +                  ntds_dn = "CN=NTDS Settings,CN=%s,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,%s" % (names.hostname, names.domaindn) -                names.ntdsguid = samdb.searchone(basedn=ntds_dn, attribute="objectGUID", -                                                 expression="", scope=SCOPE_BASE) +                names.ntdsguid = samdb.searchone(basedn=ntds_dn, +                  attribute="objectGUID", expression="", scope=SCOPE_BASE)                  assert isinstance(names.ntdsguid, str)      except: diff --git a/source4/scripting/python/samba/samdb.py b/source4/scripting/python/samba/samdb.py index a58d6c5b12..ef2a0b1644 100644 --- a/source4/scripting/python/samba/samdb.py +++ b/source4/scripting/python/samba/samdb.py @@ -37,7 +37,7 @@ class SamDB(samba.Ldb):      def __init__(self, url=None, lp=None, modules_dir=None, session_info=None,                   credentials=None, flags=0, options=None): -        """Opens the Sam Database. +        """Opens the SAM Database          For parameter meanings see the super class (samba.Ldb)          """ @@ -55,13 +55,25 @@ class SamDB(samba.Ldb):          super(SamDB, self).connect(url=self.lp.private_path(url), flags=flags,                  options=options) -    def enable_account(self, user_dn): -        """Enable an account. +    def domain_dn(self): +        # find the DNs for the domain +        res = self.search(base="", +                          scope=ldb.SCOPE_BASE, +                          expression="(defaultNamingContext=*)", +                          attrs=["defaultNamingContext"]) +        assert(len(res) == 1 and res[0]["defaultNamingContext"] is not None) +        return res[0]["defaultNamingContext"][0] + +    def enable_account(self, filter): +        """Enables an account -        :param user_dn: Dn of the account to enable. +        :param filter: LDAP filter to find the user (eg samccountname=name)          """ -        res = self.search(user_dn, ldb.SCOPE_BASE, None, ["userAccountControl"]) -        assert len(res) == 1 +        res = self.search(base=self.domain_dn(), scope=ldb.SCOPE_SUBTREE, +                          expression=filter, attrs=["userAccountControl"]) +        assert(len(res) == 1) +        user_dn = res[0].dn +          userAccountControl = int(res[0]["userAccountControl"][0])          if (userAccountControl & 0x2):              userAccountControl = userAccountControl & ~0x2 # remove disabled bit @@ -76,11 +88,16 @@ userAccountControl: %u  """ % (user_dn, userAccountControl)          self.modify_ldif(mod) -    def force_password_change_at_next_login(self, user_dn): -        """Force a password change at next login +    def force_password_change_at_next_login(self, filter): +        """Forces a password change at next login -        :param user_dn: Dn of the account to force password change on +        :param filter: LDAP filter to find the user (eg samccountname=name)          """ +        res = self.search(base=self.domain_dn(), scope=ldb.SCOPE_SUBTREE, +                          expression=filter, attrs=[]) +        assert(len(res) == 1) +        user_dn = res[0].dn +          mod = """  dn: %s  changetype: modify @@ -89,17 +106,12 @@ pwdLastSet: 0  """ % (user_dn)          self.modify_ldif(mod) -    def domain_dn(self): -        # find the DNs for the domain -        res = self.search(base="", -                          scope=ldb.SCOPE_BASE, -                          expression="(defaultNamingContext=*)",  -                          attrs=["defaultNamingContext"]) -        assert(len(res) == 1 and res[0]["defaultNamingContext"] is not None) -        return res[0]["defaultNamingContext"][0] -      def newuser(self, username, unixname, password, force_password_change_at_next_login=False): -        """add a new user record. +        """Adds a new user + +        Note: This call uses the "userPassword" attribute to set the password. +        This works correctly on SAMBA 4 DCs and on Windows DCs with +        "2003 Native" or higer domain function level.          :param username: Name of the new user.          :param unixname: Name of the unix user to map to. @@ -110,11 +122,8 @@ pwdLastSet: 0          try:              user_dn = "CN=%s,CN=Users,%s" % (username, self.domain_dn()) -            # -            #  the new user record. note the reliance on the samdb module to  -            #  fill in a sid, guid etc -            # -            #  now the real work +            # The new user record. Note the reliance on the SAMLDB module which +            # fills in the default informations              self.add({"dn": user_dn,                   "sAMAccountName": username,                  "userPassword": password, @@ -130,30 +139,34 @@ pwdLastSet: 0                  idmap = IDmapDB(lp=self.lp)                  user = pwd.getpwnam(unixname) +                  # setup ID mapping for this UID -                                  idmap.setup_name_mapping(user_sid, idmap.TYPE_UID, user[2])              except KeyError:                  pass              if force_password_change_at_next_login: -                self.force_password_change_at_next_login(user_dn) +                self.force_password_change_at_next_login("(dn=" + user_dn + ")")              #  modify the userAccountControl to remove the disabled bit -            self.enable_account(user_dn) +            self.enable_account("(dn=" + user_dn + ")")          except:              self.transaction_cancel()              raise          self.transaction_commit()      def setpassword(self, filter, password, force_password_change_at_next_login=False): -        """Set a password on a user record +        """Sets the password for a user +        Note: This call uses the "userPassword" attribute to set the password. +        This works correctly on SAMBA 4 DCs and on Windows DCs with +        "2003 Native" or higer domain function level. +          :param filter: LDAP filter to find the user (eg samccountname=name)          :param password: Password for the user +        :param force_password_change_at_next_login: Force password change          """ -        # connect to the sam           self.transaction_start()          try:              res = self.search(base=self.domain_dn(), scope=ldb.SCOPE_SUBTREE, @@ -174,24 +187,27 @@ userPassword:: %s                  self.force_password_change_at_next_login(user_dn)              #  modify the userAccountControl to remove the disabled bit -            self.enable_account(user_dn) +            self.enable_account(filter)          except:              self.transaction_cancel()              raise          self.transaction_commit() -    def setexpiry(self, user, expiry_seconds, noexpiry): -        """Set the account expiry for a user +    def setexpiry(self, filter, expiry_seconds, noexpiry=False): +        """Sets the account expiry for a user +        :param filter: LDAP filter to find the user (eg samccountname=name)          :param expiry_seconds: expiry time from now in seconds          :param noexpiry: if set, then don't expire password          """          self.transaction_start()          try:              res = self.search(base=self.domain_dn(), scope=ldb.SCOPE_SUBTREE, -                              expression=("(samAccountName=%s)" % user), +                              expression=filter,                                attrs=["userAccountControl", "accountExpires"])              assert len(res) == 1 +            user_dn = res[0].dn +              userAccountControl = int(res[0]["userAccountControl"][0])              accountExpires     = int(res[0]["accountExpires"][0])              if noexpiry: @@ -201,16 +217,16 @@ userPassword:: %s                  userAccountControl = userAccountControl & ~0x10000                  accountExpires = glue.unix2nttime(expiry_seconds + int(time.time())) -            mod = """ +            setexp = """  dn: %s  changetype: modify  replace: userAccountControl  userAccountControl: %u  replace: accountExpires  accountExpires: %u -""" % (res[0].dn, userAccountControl, accountExpires) -            # now change the database -            self.modify_ldif(mod) +""" % (user_dn, userAccountControl, accountExpires) + +            self.modify_ldif(setexp)          except:              self.transaction_cancel()              raise  | 
