2007-12-17 10:20:20 +03:00
# Unix SMB/CIFS implementation.
2010-06-20 03:28:39 +04:00
# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2010
2009-09-19 23:57:41 +04:00
# Copyright (C) Matthias Dieter Wallnoefer 2009
2007-12-17 10:20:20 +03:00
#
# Based on the original in EJS:
2008-01-25 03:02:13 +03:00
# Copyright (C) Andrew Tridgell <tridge@samba.org> 2005
2011-10-21 20:05:07 +04:00
# Copyright (C) Giampaolo Lauria <lauria2@yahoo.com> 2011
2010-11-28 05:34:47 +03:00
#
2007-12-17 10:20:20 +03:00
# 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.
2010-11-28 05:34:47 +03:00
#
2007-12-17 10:20:20 +03:00
# 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.
2010-11-28 05:34:47 +03:00
#
2007-12-17 10:20:20 +03:00
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
2007-12-30 03:14:15 +03:00
""" Convenience functions for using the SAM. """
2007-12-17 10:20:20 +03:00
import samba
2007-12-18 04:21:14 +03:00
import ldb
2008-08-30 01:32:44 +04:00
import time
2009-03-12 07:20:25 +03:00
import base64
2011-08-05 07:09:35 +04:00
import os
2017-12-07 23:38:28 +03:00
import re
2015-09-22 03:11:04 +03:00
from samba import dsdb , dsdb_dns
2010-06-22 20:03:15 +04:00
from samba . ndr import ndr_unpack , ndr_pack
2010-11-28 05:34:47 +03:00
from samba . dcerpc import drsblobs , misc
2011-08-05 05:17:06 +04:00
from samba . common import normalise_int32
2018-01-30 20:52:11 +03:00
from samba . compat import text_type
2018-02-26 19:04:00 +03:00
from samba . dcerpc import security
2007-12-17 10:20:20 +03:00
2008-05-22 19:42:18 +04:00
__docformat__ = " restructuredText "
2010-11-28 05:34:47 +03:00
2018-03-20 04:38:19 +03:00
def get_default_backend_store ( ) :
return " tdb "
2007-12-17 10:20:20 +03:00
class SamDB ( samba . Ldb ) :
2007-12-30 03:14:15 +03:00
""" The SAM database. """
2008-04-14 13:51:02 +04:00
2010-06-22 20:03:15 +04:00
hash_oid_name = { }
2015-05-25 19:17:55 +03:00
hash_well_known = { }
2010-06-22 20:03:15 +04:00
2009-08-15 17:20:09 +04:00
def __init__ ( self , url = None , lp = None , modules_dir = None , session_info = None ,
2018-01-08 21:43:18 +03:00
credentials = None , flags = ldb . FLG_DONT_CREATE_DB ,
options = None , global_schema = True ,
2010-09-19 06:28:05 +04:00
auto_connect = True , am_rodc = None ) :
2008-04-14 13:51:02 +04:00
self . lp = lp
2010-04-20 05:48:51 +04:00
if not auto_connect :
url = None
elif url is None and lp is not None :
2011-06-02 09:43:40 +04:00
url = lp . samdb_url ( )
2009-08-15 17:20:09 +04:00
2011-08-03 05:31:45 +04:00
self . url = url
2009-08-15 17:20:09 +04:00
super ( SamDB , self ) . __init__ ( url = url , lp = lp , modules_dir = modules_dir ,
2010-11-28 05:34:47 +03:00
session_info = session_info , credentials = credentials , flags = flags ,
options = options )
2009-08-15 17:20:09 +04:00
2010-04-07 14:11:12 +04:00
if global_schema :
2010-06-20 17:22:49 +04:00
dsdb . _dsdb_set_global_schema ( self )
2008-04-14 13:51:02 +04:00
2010-09-19 06:28:05 +04:00
if am_rodc is not None :
dsdb . _dsdb_set_am_rodc ( self , am_rodc )
2010-05-17 13:49:37 +04:00
2009-08-15 17:20:09 +04:00
def connect ( self , url = None , flags = 0 , options = None ) :
2011-09-02 08:42:50 +04:00
''' connect to the database '''
2011-08-05 07:09:35 +04:00
if self . lp is not None and not os . path . exists ( url ) :
2010-04-20 05:48:51 +04:00
url = self . lp . private_path ( url )
2011-08-03 05:31:45 +04:00
self . url = url
2010-04-20 05:48:51 +04:00
super ( SamDB , self ) . connect ( url = url , flags = flags ,
2009-08-15 17:20:09 +04:00
options = options )
2007-12-18 04:21:14 +03:00
2010-09-19 07:22:23 +04:00
def am_rodc ( self ) :
2011-09-02 08:42:50 +04:00
''' return True if we are an RODC '''
2010-09-19 07:22:23 +04:00
return dsdb . _am_rodc ( self )
2011-12-07 02:56:31 +04:00
def am_pdc ( self ) :
''' return True if we are an PDC emulator '''
return dsdb . _am_pdc ( self )
2009-09-18 22:16:05 +04:00
def domain_dn ( self ) :
2011-09-02 08:42:50 +04:00
''' return the domain DN '''
2010-11-15 08:41:59 +03:00
return str ( self . get_default_basedn ( ) )
2009-09-18 22:16:05 +04:00
2011-11-08 23:59:19 +04:00
def disable_account ( self , search_filter ) :
""" Disables an account
: param search_filter : LDAP filter to find the user ( eg
samccountname = name )
"""
2011-11-15 02:54:29 +04:00
flags = samba . dsdb . UF_ACCOUNTDISABLE
2011-11-08 23:59:19 +04:00
self . toggle_userAccountFlags ( search_filter , flags , on = True )
2010-09-29 02:55:22 +04:00
def enable_account ( self , search_filter ) :
2009-09-18 22:16:05 +04:00
""" Enables an account
2010-11-28 05:34:47 +03:00
: param search_filter : LDAP filter to find the user ( eg
samccountname = name )
2007-12-17 10:20:20 +03:00
"""
2011-06-24 18:37:26 +04:00
flags = samba . dsdb . UF_ACCOUNTDISABLE | samba . dsdb . UF_PASSWD_NOTREQD
self . toggle_userAccountFlags ( search_filter , flags , on = False )
2011-10-21 20:05:07 +04:00
def toggle_userAccountFlags ( self , search_filter , flags , flags_str = None ,
on = True , strict = False ) :
2012-03-07 02:31:55 +04:00
""" Toggle_userAccountFlags
2011-06-24 18:37:26 +04:00
: param search_filter : LDAP filter to find the user ( eg
samccountname = name )
2012-03-07 02:31:55 +04:00
: param flags : samba . dsdb . UF_ * flags
: param on : on = True ( default ) = > set , on = False = > unset
: param strict : strict = False ( default ) ignore if no action is needed
2011-06-24 18:37:26 +04:00
strict = True raises an Exception if . . .
"""
2009-09-18 22:16:05 +04:00
res = self . search ( base = self . domain_dn ( ) , scope = ldb . SCOPE_SUBTREE ,
2010-09-29 02:55:22 +04:00
expression = search_filter , attrs = [ " userAccountControl " ] )
2011-06-01 08:41:51 +04:00
if len ( res ) == 0 :
2011-10-21 20:05:07 +04:00
raise Exception ( " Unable to find account where ' %s ' " % search_filter )
2009-09-18 22:16:05 +04:00
assert ( len ( res ) == 1 )
2011-06-24 18:37:26 +04:00
account_dn = res [ 0 ] . dn
old_uac = int ( res [ 0 ] [ " userAccountControl " ] [ 0 ] )
if on :
if strict and ( old_uac & flags ) :
2011-10-21 20:05:07 +04:00
error = " Account flag(s) ' %s ' already set " % flags_str
2011-06-24 18:37:26 +04:00
raise Exception ( error )
new_uac = old_uac | flags
else :
if strict and not ( old_uac & flags ) :
2011-10-21 20:05:07 +04:00
error = " Account flag(s) ' %s ' already unset " % flags_str
2011-06-24 18:37:26 +04:00
raise Exception ( error )
2009-09-18 22:16:05 +04:00
2011-06-24 18:37:26 +04:00
new_uac = old_uac & ~ flags
if old_uac == new_uac :
return
2008-03-28 04:08:54 +03:00
2007-12-17 10:20:20 +03:00
mod = """
dn : % s
changetype : modify
2011-06-24 18:37:26 +04:00
delete : userAccountControl
userAccountControl : % u
add : userAccountControl
2007-12-17 10:20:20 +03:00
userAccountControl : % u
2011-06-24 18:37:26 +04:00
""" % (account_dn, old_uac, new_uac)
2007-12-30 03:14:15 +03:00
self . modify_ldif ( mod )
2010-11-28 05:34:47 +03:00
2010-09-29 02:55:22 +04:00
def force_password_change_at_next_login ( self , search_filter ) :
2009-09-18 22:16:05 +04:00
""" Forces a password change at next login
2010-11-28 05:34:47 +03:00
: param search_filter : LDAP filter to find the user ( eg
samccountname = name )
2009-06-18 06:38:04 +04:00
"""
2009-09-18 22:16:05 +04:00
res = self . search ( base = self . domain_dn ( ) , scope = ldb . SCOPE_SUBTREE ,
2010-09-29 02:55:22 +04:00
expression = search_filter , attrs = [ ] )
2011-06-01 08:46:04 +04:00
if len ( res ) == 0 :
raise Exception ( ' Unable to find user " %s " ' % search_filter )
2009-09-18 22:16:05 +04:00
assert ( len ( res ) == 1 )
user_dn = res [ 0 ] . dn
2009-06-18 06:38:04 +04:00
mod = """
dn : % s
changetype : modify
replace : pwdLastSet
pwdLastSet : 0
""" % (user_dn)
self . modify_ldif ( mod )
2010-06-07 20:10:28 +04:00
def newgroup ( self , groupname , groupou = None , grouptype = None ,
2014-10-18 02:34:35 +04:00
description = None , mailaddress = None , notes = None , sd = None ,
gidnumber = None , nisdomain = None ) :
2010-06-07 20:10:28 +04:00
""" Adds a new group with additional parameters
: param groupname : Name of the new group
: param grouptype : Type of the new group
: param description : Description of the new group
: param mailaddress : Email address of the new group
: param notes : Notes of the new group
2014-10-18 02:34:35 +04:00
: param gidnumber : GID Number of the new group
: param nisdomain : NIS Domain Name of the new group
2010-11-24 18:17:15 +03:00
: param sd : security descriptor of the object
2010-06-07 20:10:28 +04:00
"""
2010-06-08 23:33:56 +04:00
group_dn = " CN= %s , %s , %s " % ( groupname , ( groupou or " CN=Users " ) , self . domain_dn ( ) )
2010-06-07 20:10:28 +04:00
2010-06-08 23:33:56 +04:00
# The new user record. Note the reliance on the SAMLDB module which
# fills in the default informations
2010-06-20 03:28:39 +04:00
ldbmessage = { " dn " : group_dn ,
2010-06-08 23:33:56 +04:00
" sAMAccountName " : groupname ,
" objectClass " : " group " }
2010-06-07 20:10:28 +04:00
2010-06-20 03:28:39 +04:00
if grouptype is not None :
2011-08-05 05:17:06 +04:00
ldbmessage [ " groupType " ] = normalise_int32 ( grouptype )
2010-06-07 20:10:28 +04:00
2010-06-08 23:33:56 +04:00
if description is not None :
ldbmessage [ " description " ] = description
2010-06-07 20:10:28 +04:00
2010-06-08 23:33:56 +04:00
if mailaddress is not None :
ldbmessage [ " mail " ] = mailaddress
2010-06-07 20:10:28 +04:00
2010-06-08 23:33:56 +04:00
if notes is not None :
ldbmessage [ " info " ] = notes
2010-06-07 20:10:28 +04:00
2014-10-18 02:34:35 +04:00
if gidnumber is not None :
ldbmessage [ " gidNumber " ] = normalise_int32 ( gidnumber )
if nisdomain is not None :
2015-06-11 22:20:55 +03:00
ldbmessage [ " msSFU30Name " ] = groupname
2014-10-18 02:34:35 +04:00
ldbmessage [ " msSFU30NisDomain " ] = nisdomain
2010-11-24 18:17:15 +03:00
if sd is not None :
ldbmessage [ " nTSecurityDescriptor " ] = ndr_pack ( sd )
2010-06-20 13:59:49 +04:00
self . add ( ldbmessage )
2010-06-07 20:10:28 +04:00
2010-06-20 04:32:23 +04:00
def deletegroup ( self , groupname ) :
2010-06-07 20:10:28 +04:00
""" Deletes a group
: param groupname : Name of the target group
"""
2011-07-28 11:14:28 +04:00
groupfilter = " (&(sAMAccountName= %s )(objectCategory= %s , %s )) " % ( ldb . binary_encode ( groupname ) , " CN=Group,CN=Schema,CN=Configuration " , self . domain_dn ( ) )
2010-06-07 20:10:28 +04:00
self . transaction_start ( )
try :
targetgroup = self . search ( base = self . domain_dn ( ) , scope = ldb . SCOPE_SUBTREE ,
expression = groupfilter , attrs = [ ] )
if len ( targetgroup ) == 0 :
2010-06-20 04:32:23 +04:00
raise Exception ( ' Unable to find group " %s " ' % groupname )
2010-06-07 20:10:28 +04:00
assert ( len ( targetgroup ) == 1 )
2010-09-29 02:35:51 +04:00
self . delete ( targetgroup [ 0 ] . dn )
2012-02-25 18:56:25 +04:00
except :
2010-06-07 20:10:28 +04:00
self . transaction_cancel ( )
raise
else :
self . transaction_commit ( )
2012-06-19 14:43:08 +04:00
def add_remove_group_members ( self , groupname , members ,
2010-06-07 20:10:28 +04:00
add_members_operation = True ) :
""" Adds or removes group members
: param groupname : Name of the target group
2012-06-19 14:43:08 +04:00
: param members : list of group members
2010-11-28 16:09:30 +03:00
: param add_members_operation : Defines if its an add or remove
operation
2010-06-07 20:10:28 +04:00
"""
2011-07-28 11:14:28 +04:00
groupfilter = " (&(sAMAccountName= %s )(objectCategory= %s , %s )) " % (
ldb . binary_encode ( groupname ) , " CN=Group,CN=Schema,CN=Configuration " , self . domain_dn ( ) )
2010-06-07 20:10:28 +04:00
self . transaction_start ( )
try :
targetgroup = self . search ( base = self . domain_dn ( ) , scope = ldb . SCOPE_SUBTREE ,
expression = groupfilter , attrs = [ ' member ' ] )
if len ( targetgroup ) == 0 :
2010-06-20 04:32:23 +04:00
raise Exception ( ' Unable to find group " %s " ' % groupname )
2010-06-07 20:10:28 +04:00
assert ( len ( targetgroup ) == 1 )
modified = False
addtargettogroup = """
dn : % s
changetype : modify
""" % (str(targetgroup[0].dn))
2012-06-19 14:43:08 +04:00
for member in members :
2017-06-07 17:57:53 +03:00
filter = ( ' (&(sAMAccountName= %s )(|(objectclass=user) '
' (objectclass=group))) ' % ldb . binary_encode ( member ) )
2018-02-26 19:04:00 +03:00
foreign_msg = None
try :
membersid = security . dom_sid ( member )
except TypeError as e :
membersid = None
if membersid is not None :
filter = ' (objectSid= %s ) ' % str ( membersid )
dn_str = " <SID= %s > " % str ( membersid )
foreign_msg = ldb . Message ( )
foreign_msg . dn = ldb . Dn ( self , dn_str )
2017-06-07 17:57:53 +03:00
targetmember = self . search ( base = self . domain_dn ( ) ,
scope = ldb . SCOPE_SUBTREE ,
expression = " %s " % filter ,
attrs = [ ] )
2010-06-07 20:10:28 +04:00
2018-02-26 19:04:00 +03:00
if len ( targetmember ) == 0 and foreign_msg is not None :
targetmember = [ foreign_msg ]
2010-06-07 20:10:28 +04:00
if len ( targetmember ) != 1 :
2014-10-12 18:32:08 +04:00
raise Exception ( ' Unable to find " %s " . Operation cancelled. ' % member )
2018-02-26 19:04:00 +03:00
targetmember_dn = targetmember [ 0 ] . dn . extended_str ( 1 )
2010-06-07 20:10:28 +04:00
2018-02-26 19:04:00 +03:00
if add_members_operation is True and ( targetgroup [ 0 ] . get ( ' member ' ) is None or str ( targetmember_dn ) not in targetgroup [ 0 ] [ ' member ' ] ) :
2010-09-29 02:35:51 +04:00
modified = True
addtargettogroup + = """ add: member
2010-06-07 20:10:28 +04:00
member : % s
2018-02-26 19:04:00 +03:00
""" % (str(targetmember_dn))
2010-06-07 20:10:28 +04:00
2018-02-26 19:04:00 +03:00
elif add_members_operation is False and ( targetgroup [ 0 ] . get ( ' member ' ) is not None and targetmember_dn in targetgroup [ 0 ] [ ' member ' ] ) :
2010-09-29 02:35:51 +04:00
modified = True
addtargettogroup + = """ delete: member
2010-06-07 20:10:28 +04:00
member : % s
2018-02-26 19:04:00 +03:00
""" % (str(targetmember_dn))
2010-06-07 20:10:28 +04:00
if modified is True :
2010-09-29 02:35:51 +04:00
self . modify_ldif ( addtargettogroup )
2010-06-07 20:10:28 +04:00
2012-02-25 18:56:25 +04:00
except :
2010-06-07 20:10:28 +04:00
self . transaction_cancel ( )
raise
else :
self . transaction_commit ( )
2010-05-09 12:54:19 +04:00
def newuser ( self , username , password ,
2010-11-28 05:34:47 +03:00
force_password_change_at_next_login_req = False ,
useusernameascn = False , userou = None , surname = None , givenname = None ,
initials = None , profilepath = None , scriptpath = None , homedrive = None ,
homedirectory = None , jobtitle = None , department = None , company = None ,
description = None , mailaddress = None , internetaddress = None ,
telephonenumber = None , physicaldeliveryoffice = None , sd = None ,
2012-09-30 06:31:59 +04:00
setpassword = True , uidnumber = None , gidnumber = None , gecos = None ,
2016-06-02 15:17:17 +03:00
loginshell = None , uid = None , nisdomain = None , unixhome = None ,
smartcard_required = False ) :
2010-06-07 20:10:28 +04:00
""" Adds a new user with additional parameters
2009-09-18 22:16:05 +04:00
2009-09-21 01:49:05 +04:00
: param username : Name of the new user
2007-12-30 03:14:15 +03:00
: param password : Password for the new user
2009-09-21 01:49:05 +04:00
: param force_password_change_at_next_login_req : Force password change
2010-11-28 05:34:47 +03:00
: param useusernameascn : Use username as cn rather that firstname +
initials + lastname
2010-06-07 20:10:28 +04:00
: param userou : Object container ( without domainDN postfix ) for new user
: param surname : Surname of the new user
: param givenname : First name of the new user
: param initials : Initials of the new user
: param profilepath : Profile path of the new user
: param scriptpath : Logon script path of the new user
: param homedrive : Home drive of the new user
: param homedirectory : Home directory of the new user
: param jobtitle : Job title of the new user
: param department : Department of the new user
: param company : Company of the new user
: param description : of the new user
: param mailaddress : Email address of the new user
: param internetaddress : Home page of the new user
: param telephonenumber : Phone number of the new user
: param physicaldeliveryoffice : Office location of the new user
2010-11-23 18:48:53 +03:00
: param sd : security descriptor of the object
: param setpassword : optionally disable password reset
2012-09-30 06:31:59 +04:00
: param uidnumber : RFC2307 Unix numeric UID of the new user
: param gidnumber : RFC2307 Unix primary GID of the new user
: param gecos : RFC2307 Unix GECOS field of the new user
: param loginshell : RFC2307 Unix login shell of the new user
: param uid : RFC2307 Unix username of the new user
2015-01-31 21:44:26 +03:00
: param nisdomain : RFC2307 Unix NIS domain of the new user
: param unixhome : RFC2307 Unix home directory of the new user
2016-06-02 15:17:17 +03:00
: param smartcard_required : set the UF_SMARTCARD_REQUIRED bit of the new user
2010-06-20 03:28:39 +04:00
"""
2010-06-07 20:10:28 +04:00
2010-09-29 02:35:51 +04:00
displayname = " "
2010-06-07 20:10:28 +04:00
if givenname is not None :
displayname + = givenname
if initials is not None :
displayname + = ' %s . ' % initials
if surname is not None :
displayname + = ' %s ' % surname
2010-06-20 03:28:39 +04:00
cn = username
2010-06-07 20:10:28 +04:00
if useusernameascn is None and displayname is not " " :
cn = displayname
2010-06-08 23:33:56 +04:00
user_dn = " CN= %s , %s , %s " % ( cn , ( userou or " CN=Users " ) , self . domain_dn ( ) )
2009-02-11 19:54:58 +03:00
2010-10-19 12:56:07 +04:00
dnsdomain = ldb . Dn ( self , self . domain_dn ( ) ) . canonical_str ( ) . replace ( " / " , " " )
user_principal_name = " %s @ %s " % ( username , dnsdomain )
2010-06-08 23:33:56 +04:00
# The new user record. Note the reliance on the SAMLDB module which
# fills in the default informations
2010-06-20 03:28:39 +04:00
ldbmessage = { " dn " : user_dn ,
2010-09-29 02:35:51 +04:00
" sAMAccountName " : username ,
2010-10-16 22:51:09 +04:00
" userPrincipalName " : user_principal_name ,
2010-09-29 02:35:51 +04:00
" objectClass " : " user " }
2010-06-07 20:10:28 +04:00
2016-06-02 15:17:17 +03:00
if smartcard_required :
ldbmessage [ " userAccountControl " ] = str ( dsdb . UF_NORMAL_ACCOUNT | dsdb . UF_SMARTCARD_REQUIRED )
setpassword = False
2010-06-20 03:28:39 +04:00
if surname is not None :
2010-06-08 23:33:56 +04:00
ldbmessage [ " sn " ] = surname
2010-06-07 20:10:28 +04:00
2010-06-20 03:28:39 +04:00
if givenname is not None :
2010-06-08 23:33:56 +04:00
ldbmessage [ " givenName " ] = givenname
2010-06-07 20:10:28 +04:00
2010-06-20 03:28:39 +04:00
if displayname is not " " :
2010-06-08 23:33:56 +04:00
ldbmessage [ " displayName " ] = displayname
ldbmessage [ " name " ] = displayname
2010-06-07 20:10:28 +04:00
2010-06-20 03:28:39 +04:00
if initials is not None :
2010-06-08 23:33:56 +04:00
ldbmessage [ " initials " ] = ' %s . ' % initials
2010-06-07 20:10:28 +04:00
2010-06-20 03:28:39 +04:00
if profilepath is not None :
2010-06-08 23:33:56 +04:00
ldbmessage [ " profilePath " ] = profilepath
2010-06-07 20:10:28 +04:00
2010-06-08 23:33:56 +04:00
if scriptpath is not None :
ldbmessage [ " scriptPath " ] = scriptpath
2010-06-07 20:10:28 +04:00
2010-06-08 23:33:56 +04:00
if homedrive is not None :
ldbmessage [ " homeDrive " ] = homedrive
2010-06-07 20:10:28 +04:00
2010-06-08 23:33:56 +04:00
if homedirectory is not None :
ldbmessage [ " homeDirectory " ] = homedirectory
2010-06-07 20:10:28 +04:00
2010-06-08 23:33:56 +04:00
if jobtitle is not None :
ldbmessage [ " title " ] = jobtitle
2010-06-07 20:10:28 +04:00
2010-06-08 23:33:56 +04:00
if department is not None :
ldbmessage [ " department " ] = department
2010-06-07 20:10:28 +04:00
2010-06-08 23:33:56 +04:00
if company is not None :
ldbmessage [ " company " ] = company
2010-06-07 20:10:28 +04:00
2010-06-08 23:33:56 +04:00
if description is not None :
ldbmessage [ " description " ] = description
2010-06-07 20:10:28 +04:00
2010-06-08 23:33:56 +04:00
if mailaddress is not None :
ldbmessage [ " mail " ] = mailaddress
2010-06-07 20:10:28 +04:00
2010-06-08 23:33:56 +04:00
if internetaddress is not None :
ldbmessage [ " wWWHomePage " ] = internetaddress
2010-06-07 20:10:28 +04:00
2010-06-08 23:33:56 +04:00
if telephonenumber is not None :
ldbmessage [ " telephoneNumber " ] = telephonenumber
2010-06-07 20:10:28 +04:00
2010-06-08 23:33:56 +04:00
if physicaldeliveryoffice is not None :
ldbmessage [ " physicalDeliveryOfficeName " ] = physicaldeliveryoffice
2010-06-07 20:10:28 +04:00
2010-11-23 18:48:53 +03:00
if sd is not None :
ldbmessage [ " nTSecurityDescriptor " ] = ndr_pack ( sd )
2012-09-30 06:31:59 +04:00
ldbmessage2 = None
2015-01-31 21:44:26 +03:00
if any ( map ( lambda b : b is not None , ( uid , uidnumber , gidnumber , gecos ,
loginshell , nisdomain , unixhome ) ) ) :
2012-09-30 06:31:59 +04:00
ldbmessage2 = ldb . Message ( )
ldbmessage2 . dn = ldb . Dn ( self , user_dn )
if uid is not None :
ldbmessage2 [ " uid " ] = ldb . MessageElement ( str ( uid ) , ldb . FLAG_MOD_REPLACE , ' uid ' )
if uidnumber is not None :
ldbmessage2 [ " uidNumber " ] = ldb . MessageElement ( str ( uidnumber ) , ldb . FLAG_MOD_REPLACE , ' uidNumber ' )
if gidnumber is not None :
ldbmessage2 [ " gidNumber " ] = ldb . MessageElement ( str ( gidnumber ) , ldb . FLAG_MOD_REPLACE , ' gidNumber ' )
if gecos is not None :
ldbmessage2 [ " gecos " ] = ldb . MessageElement ( str ( gecos ) , ldb . FLAG_MOD_REPLACE , ' gecos ' )
if loginshell is not None :
ldbmessage2 [ " loginShell " ] = ldb . MessageElement ( str ( loginshell ) , ldb . FLAG_MOD_REPLACE , ' loginShell ' )
2015-01-31 21:44:26 +03:00
if unixhome is not None :
ldbmessage2 [ " unixHomeDirectory " ] = ldb . MessageElement (
str ( unixhome ) , ldb . FLAG_MOD_REPLACE , ' unixHomeDirectory ' )
if nisdomain is not None :
ldbmessage2 [ " msSFU30NisDomain " ] = ldb . MessageElement (
str ( nisdomain ) , ldb . FLAG_MOD_REPLACE , ' msSFU30NisDomain ' )
ldbmessage2 [ " msSFU30Name " ] = ldb . MessageElement (
str ( username ) , ldb . FLAG_MOD_REPLACE , ' msSFU30Name ' )
ldbmessage2 [ " unixUserPassword " ] = ldb . MessageElement (
' ABCD!efgh12345$67890 ' , ldb . FLAG_MOD_REPLACE ,
' unixUserPassword ' )
2012-09-30 06:31:59 +04:00
2010-06-08 23:33:56 +04:00
self . transaction_start ( )
try :
2010-06-07 20:10:28 +04:00
self . add ( ldbmessage )
2012-09-30 06:31:59 +04:00
if ldbmessage2 :
self . modify ( ldbmessage2 )
2009-02-11 19:54:58 +03:00
2009-09-19 23:57:41 +04:00
# Sets the password for it
2010-11-23 18:48:53 +03:00
if setpassword :
2018-02-02 00:35:25 +03:00
self . setpassword ( ( " (distinguishedName= %s ) " %
ldb . binary_encode ( user_dn ) ) ,
password ,
2010-11-23 18:48:53 +03:00
force_password_change_at_next_login_req )
2012-02-25 18:56:25 +04:00
except :
2009-02-11 19:54:58 +03:00
self . transaction_cancel ( )
raise
2010-04-08 23:01:17 +04:00
else :
self . transaction_commit ( )
2008-03-28 04:08:54 +03:00
2017-12-07 23:38:28 +03:00
def newcomputer ( self , computername , computerou = None , description = None ,
prepare_oldjoin = False ) :
""" 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
"""
cn = re . sub ( r " \ $$ " , " " , computername )
if cn . count ( ' $ ' ) :
raise Exception ( ' Illegal computername " %s " ' % computername )
samaccountname = " %s $ " % cn
computercontainer_dn = " CN=Users, %s " % self . domain_dn ( )
if computerou :
computercontainer_dn = self . normalize_dn_in_domain ( computerou )
computer_dn = " CN= %s , %s " % ( cn , computercontainer_dn )
dnsdomain = ldb . Dn ( self ,
self . domain_dn ( ) ) . canonical_str ( ) . replace ( " / " , " " )
ldbmessage = { " dn " : computer_dn ,
" sAMAccountName " : samaccountname ,
" objectClass " : " computer " ,
}
if description is not None :
ldbmessage [ " description " ] = description
accountcontrol = str ( dsdb . UF_WORKSTATION_TRUST_ACCOUNT |
dsdb . UF_ACCOUNTDISABLE )
if prepare_oldjoin :
accountcontrol = str ( dsdb . UF_WORKSTATION_TRUST_ACCOUNT )
ldbmessage [ " userAccountControl " ] = accountcontrol
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 ( )
2011-08-15 06:06:59 +04:00
def deleteuser ( self , username ) :
""" Deletes a user
: param username : Name of the target user
"""
filter = " (&(sAMAccountName= %s )(objectCategory= %s , %s )) " % ( ldb . binary_encode ( username ) , " CN=Person,CN=Schema,CN=Configuration " , self . domain_dn ( ) )
self . transaction_start ( )
try :
target = self . search ( base = self . domain_dn ( ) , scope = ldb . SCOPE_SUBTREE ,
expression = filter , attrs = [ ] )
if len ( target ) == 0 :
raise Exception ( ' Unable to find user " %s " ' % username )
assert ( len ( target ) == 1 )
self . delete ( target [ 0 ] . dn )
2012-02-25 18:56:25 +04:00
except :
2011-08-15 06:06:59 +04:00
self . transaction_cancel ( )
raise
else :
self . transaction_commit ( )
2010-09-29 02:55:22 +04:00
def setpassword ( self , search_filter , password ,
2010-11-28 05:34:47 +03:00
force_change_at_next_login = False , username = None ) :
2009-09-18 22:16:05 +04:00
""" Sets the password for a user
2010-11-28 05:34:47 +03:00
: param search_filter : LDAP filter to find the user ( eg
samccountname = name )
2008-03-28 04:08:54 +03:00
: param password : Password for the user
2010-04-04 05:30:03 +04:00
: param force_change_at_next_login : Force password change
2008-03-28 04:08:54 +03:00
"""
self . transaction_start ( )
2009-02-11 19:54:58 +03:00
try :
2009-08-15 17:20:09 +04:00
res = self . search ( base = self . domain_dn ( ) , scope = ldb . SCOPE_SUBTREE ,
2010-09-29 02:55:22 +04:00
expression = search_filter , attrs = [ ] )
2010-04-15 11:15:25 +04:00
if len ( res ) == 0 :
2010-09-29 02:55:22 +04:00
raise Exception ( ' Unable to find user " %s " ' % ( username or search_filter ) )
2010-11-29 08:57:25 +03:00
if len ( res ) > 1 :
raise Exception ( ' Matched %u multiple users with filter " %s " ' % ( len ( res ) , search_filter ) )
2009-02-11 19:54:58 +03:00
user_dn = res [ 0 ] . dn
2018-01-30 20:52:11 +03:00
pw = text_type ( b ' " ' + password . encode ( ' utf-8 ' ) + b ' " ' , ' utf-8 ' ) . encode ( ' utf-16-le ' )
2009-09-10 02:46:51 +04:00
setpw = """
dn : % s
changetype : modify
2010-07-08 11:36:30 +04:00
replace : unicodePwd
unicodePwd : : % s
2018-01-30 20:09:00 +03:00
""" % (user_dn, base64.b64encode(pw).decode( ' utf-8 ' ))
2009-02-11 19:54:58 +03:00
2009-09-10 02:46:51 +04:00
self . modify_ldif ( setpw )
2009-02-11 19:54:58 +03:00
2010-04-04 05:30:03 +04:00
if force_change_at_next_login :
2009-09-21 01:49:05 +04:00
self . force_password_change_at_next_login (
2011-10-25 22:10:30 +04:00
" (distinguishedName= " + str ( user_dn ) + " ) " )
2009-06-17 03:14:17 +04:00
2009-02-11 19:54:58 +03:00
# modify the userAccountControl to remove the disabled bit
2010-09-29 02:55:22 +04:00
self . enable_account ( search_filter )
2012-02-25 18:56:25 +04:00
except :
2009-02-11 19:54:58 +03:00
self . transaction_cancel ( )
raise
2010-04-08 23:01:17 +04:00
else :
self . transaction_commit ( )
2007-12-17 10:20:20 +03:00
2010-09-29 02:55:22 +04:00
def setexpiry ( self , search_filter , expiry_seconds , no_expiry_req = False ) :
2009-09-18 22:16:05 +04:00
""" Sets the account expiry for a user
2010-11-28 05:34:47 +03:00
: param search_filter : LDAP filter to find the user ( eg
samaccountname = name )
2008-08-30 01:32:44 +04:00
: param expiry_seconds : expiry time from now in seconds
2009-09-21 01:49:05 +04:00
: param no_expiry_req : if set , then don ' t expire password
2008-08-30 01:32:44 +04:00
"""
2009-02-11 19:54:58 +03:00
self . transaction_start ( )
try :
res = self . search ( base = self . domain_dn ( ) , scope = ldb . SCOPE_SUBTREE ,
2010-09-29 02:55:22 +04:00
expression = search_filter ,
2009-09-21 15:53:47 +04:00
attrs = [ " userAccountControl " , " accountExpires " ] )
2011-06-01 08:46:04 +04:00
if len ( res ) == 0 :
raise Exception ( ' Unable to find user " %s " ' % search_filter )
2009-09-21 01:49:05 +04:00
assert ( len ( res ) == 1 )
2009-09-18 22:16:05 +04:00
user_dn = res [ 0 ] . dn
2009-02-11 19:54:58 +03:00
userAccountControl = int ( res [ 0 ] [ " userAccountControl " ] [ 0 ] )
accountExpires = int ( res [ 0 ] [ " accountExpires " ] [ 0 ] )
2009-09-21 01:49:05 +04:00
if no_expiry_req :
2009-02-11 19:54:58 +03:00
userAccountControl = userAccountControl | 0x10000
accountExpires = 0
else :
userAccountControl = userAccountControl & ~ 0x10000
2010-04-04 02:30:34 +04:00
accountExpires = samba . unix2nttime ( expiry_seconds + int ( time . time ( ) ) )
2009-02-11 19:54:58 +03:00
2009-09-18 22:16:05 +04:00
setexp = """
2009-03-12 05:13:14 +03:00
dn : % s
changetype : modify
replace : userAccountControl
userAccountControl : % u
replace : accountExpires
accountExpires : % u
2009-09-18 22:16:05 +04:00
""" % (user_dn, userAccountControl, accountExpires)
self . modify_ldif ( setexp )
2012-02-25 18:56:25 +04:00
except :
2009-02-11 19:54:58 +03:00
self . transaction_cancel ( )
raise
2010-04-08 23:01:17 +04:00
else :
self . transaction_commit ( )
2010-04-04 05:30:03 +04:00
def set_domain_sid ( self , sid ) :
""" Change the domain SID used by this LDB.
: param sid : The new domain sid to use .
"""
2010-06-20 17:22:49 +04:00
dsdb . _samdb_set_domain_sid ( self , sid )
2010-04-04 05:30:03 +04:00
def get_domain_sid ( self ) :
2010-11-28 05:34:47 +03:00
""" Read the domain SID used by this LDB. """
2010-08-20 01:26:53 +04:00
return dsdb . _samdb_get_domain_sid ( self )
2010-04-04 05:30:03 +04:00
2010-11-28 16:09:30 +03:00
domain_sid = property ( get_domain_sid , set_domain_sid ,
" SID for the domain " )
2010-04-04 05:30:03 +04:00
def set_invocation_id ( self , invocation_id ) :
""" Set the invocation id for this SamDB handle.
: param invocation_id : GUID of the invocation id .
"""
2010-06-20 17:22:49 +04:00
dsdb . _dsdb_set_ntds_invocation_id ( self , invocation_id )
2010-04-04 05:30:03 +04:00
2010-11-28 16:09:30 +03:00
def get_invocation_id ( self ) :
""" Get the invocation_id id """
return dsdb . _samdb_ntds_invocation_id ( self )
invocation_id = property ( get_invocation_id , set_invocation_id ,
" Invocation ID GUID " )
2010-06-20 03:28:39 +04:00
def get_oid_from_attid ( self , attid ) :
2010-06-20 17:22:49 +04:00
return dsdb . _dsdb_get_oid_from_attid ( self , attid )
2010-06-20 03:28:39 +04:00
2010-11-28 05:34:47 +03:00
def get_attid_from_lDAPDisplayName ( self , ldap_display_name ,
is_schema_nc = False ) :
2011-06-22 08:41:50 +04:00
''' return the attribute ID for a LDAP attribute as an integer as found in DRSUAPI '''
2010-11-28 05:34:47 +03:00
return dsdb . _dsdb_get_attid_from_lDAPDisplayName ( self ,
ldap_display_name , is_schema_nc )
2010-08-24 16:08:27 +04:00
2011-06-22 08:41:50 +04:00
def get_syntax_oid_from_lDAPDisplayName ( self , ldap_display_name ) :
''' return the syntax OID for a LDAP attribute as a string '''
return dsdb . _dsdb_get_syntax_oid_from_lDAPDisplayName ( self , ldap_display_name )
2011-07-07 00:29:58 +04:00
def get_systemFlags_from_lDAPDisplayName ( self , ldap_display_name ) :
''' return the systemFlags for a LDAP attribute as a integer '''
return dsdb . _dsdb_get_systemFlags_from_lDAPDisplayName ( self , ldap_display_name )
def get_linkId_from_lDAPDisplayName ( self , ldap_display_name ) :
''' return the linkID for a LDAP attribute as a integer '''
return dsdb . _dsdb_get_linkId_from_lDAPDisplayName ( self , ldap_display_name )
2011-07-11 08:27:21 +04:00
def get_lDAPDisplayName_by_attid ( self , attid ) :
''' return the lDAPDisplayName from an integer DRS attribute ID '''
return dsdb . _dsdb_get_lDAPDisplayName_by_attid ( self , attid )
2011-07-11 10:55:11 +04:00
def get_backlink_from_lDAPDisplayName ( self , ldap_display_name ) :
''' return the attribute name of the corresponding backlink from the name
of a forward link attribute . If there is no backlink return None '''
return dsdb . _dsdb_get_backlink_from_lDAPDisplayName ( self , ldap_display_name )
2010-04-20 05:48:51 +04:00
def set_ntds_settings_dn ( self , ntds_settings_dn ) :
2010-11-28 05:34:47 +03:00
""" Set the NTDS Settings DN, as would be returned on the dsServiceName
rootDSE attribute .
2010-04-20 05:48:51 +04:00
This allows the DN to be set before the database fully exists
: param ntds_settings_dn : The new DN to use
"""
2010-06-20 17:22:49 +04:00
dsdb . _samdb_set_ntds_settings_dn ( self , ntds_settings_dn )
2010-04-20 05:48:51 +04:00
2010-04-04 05:30:03 +04:00
def get_ntds_GUID ( self ) :
2010-11-28 05:34:47 +03:00
""" Get the NTDS objectGUID """
2010-06-20 17:22:49 +04:00
return dsdb . _samdb_ntds_objectGUID ( self )
2010-04-04 05:30:03 +04:00
def server_site_name ( self ) :
2010-11-28 05:34:47 +03:00
""" Get the server site name """
2010-06-20 17:22:49 +04:00
return dsdb . _samdb_server_site_name ( self )
2010-04-09 00:07:42 +04:00
2011-08-22 11:40:45 +04:00
def host_dns_name ( self ) :
""" return the DNS name of this host """
res = self . search ( base = ' ' , scope = ldb . SCOPE_BASE , attrs = [ ' dNSHostName ' ] )
return res [ 0 ] [ ' dNSHostName ' ] [ 0 ]
def domain_dns_name ( self ) :
""" return the DNS name of the domain root """
domain_dn = self . get_default_basedn ( )
return domain_dn . canonical_str ( ) . split ( ' / ' ) [ 0 ]
def forest_dns_name ( self ) :
""" return the DNS name of the forest root """
forest_dn = self . get_root_basedn ( )
return forest_dn . canonical_str ( ) . split ( ' / ' ) [ 0 ]
2010-04-09 00:07:42 +04:00
def load_partition_usn ( self , base_dn ) :
2010-06-20 17:22:49 +04:00
return dsdb . _dsdb_load_partition_usn ( self , base_dn )
2010-06-20 04:32:23 +04:00
2012-08-10 02:44:04 +04:00
def set_schema ( self , schema , write_indices_and_attributes = True ) :
self . set_schema_from_ldb ( schema . ldb , write_indices_and_attributes = write_indices_and_attributes )
2010-06-20 04:32:23 +04:00
2012-08-10 02:44:04 +04:00
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 )
2010-06-20 04:32:23 +04:00
2010-11-05 06:06:10 +03:00
def dsdb_DsReplicaAttribute ( self , ldb , ldap_display_name , ldif_elements ) :
2011-06-17 05:29:44 +04:00
''' convert a list of attribute values to a DRSUAPI DsReplicaAttribute '''
2010-11-05 06:06:10 +03:00
return dsdb . _dsdb_DsReplicaAttribute ( ldb , ldap_display_name , ldif_elements )
2011-06-17 05:29:44 +04:00
def dsdb_normalise_attributes ( self , ldb , ldap_display_name , ldif_elements ) :
''' normalise a list of attribute values '''
return dsdb . _dsdb_normalise_attributes ( ldb , ldap_display_name , ldif_elements )
2010-06-22 20:03:15 +04:00
def get_attribute_from_attid ( self , attid ) :
""" Get from an attid the associated attribute
2010-11-28 05:34:47 +03:00
: param attid : The attribute id for searched attribute
: return : The name of the attribute associated with this id
2010-06-22 20:03:15 +04:00
"""
if len ( self . hash_oid_name . keys ( ) ) == 0 :
self . _populate_oid_attid ( )
2018-01-30 20:52:11 +03:00
if self . get_oid_from_attid ( attid ) in self . hash_oid_name :
2010-06-22 20:03:15 +04:00
return self . hash_oid_name [ self . get_oid_from_attid ( attid ) ]
else :
return None
def _populate_oid_attid ( self ) :
2010-11-28 05:34:47 +03:00
""" Populate the hash hash_oid_name.
2010-06-22 20:03:15 +04:00
2010-11-28 05:34:47 +03:00
This hash contains the oid of the attribute as a key and
its display name as a value
2010-06-22 20:03:15 +04:00
"""
self . hash_oid_name = { }
res = self . search ( expression = " objectClass=attributeSchema " ,
controls = [ " search_options:1:2 " ] ,
attrs = [ " attributeID " ,
" lDAPDisplayName " ] )
if len ( res ) > 0 :
for e in res :
strDisplay = str ( e . get ( " lDAPDisplayName " ) )
self . hash_oid_name [ str ( e . get ( " attributeID " ) ) ] = strDisplay
def get_attribute_replmetadata_version ( self , dn , att ) :
2010-11-28 05:34:47 +03:00
""" Get the version field trom the replPropertyMetaData for
the given field
2010-06-22 20:03:15 +04:00
2010-11-28 05:34:47 +03:00
: param dn : The on which we want to get the version
: param att : The name of the attribute
: return : The value of the version field in the replPropertyMetaData
for the given attribute . None if the attribute is not replicated
2010-06-22 20:03:15 +04:00
"""
2011-10-25 22:10:30 +04:00
res = self . search ( expression = " distinguishedName= %s " % dn ,
2010-06-22 20:03:15 +04:00
scope = ldb . SCOPE_SUBTREE ,
controls = [ " search_options:1:2 " ] ,
attrs = [ " replPropertyMetaData " ] )
if len ( res ) == 0 :
return None
repl = ndr_unpack ( drsblobs . replPropertyMetaDataBlob ,
2018-01-30 20:52:11 +03:00
res [ 0 ] [ " replPropertyMetaData " ] [ 0 ] )
2010-06-22 20:03:15 +04:00
ctr = repl . ctr
if len ( self . hash_oid_name . keys ( ) ) == 0 :
self . _populate_oid_attid ( )
for o in ctr . array :
# Search for Description
att_oid = self . get_oid_from_attid ( o . attid )
2018-01-30 20:52:11 +03:00
if att_oid in self . hash_oid_name and \
2010-06-22 20:03:15 +04:00
att . lower ( ) == self . hash_oid_name [ att_oid ] . lower ( ) :
return o . version
return None
2010-11-28 05:34:47 +03:00
def set_attribute_replmetadata_version ( self , dn , att , value ,
addifnotexist = False ) :
2011-10-25 22:10:30 +04:00
res = self . search ( expression = " distinguishedName= %s " % dn ,
2010-06-22 20:03:15 +04:00
scope = ldb . SCOPE_SUBTREE ,
controls = [ " search_options:1:2 " ] ,
attrs = [ " replPropertyMetaData " ] )
if len ( res ) == 0 :
return None
repl = ndr_unpack ( drsblobs . replPropertyMetaDataBlob ,
2018-01-30 20:52:11 +03:00
res [ 0 ] [ " replPropertyMetaData " ] [ 0 ] )
2010-06-22 20:03:15 +04:00
ctr = repl . ctr
now = samba . unix2nttime ( int ( time . time ( ) ) )
found = False
if len ( self . hash_oid_name . keys ( ) ) == 0 :
self . _populate_oid_attid ( )
for o in ctr . array :
# Search for Description
att_oid = self . get_oid_from_attid ( o . attid )
2018-01-30 20:52:11 +03:00
if att_oid in self . hash_oid_name and \
2010-06-22 20:03:15 +04:00
att . lower ( ) == self . hash_oid_name [ att_oid ] . lower ( ) :
found = True
seq = self . sequence_number ( ldb . SEQ_NEXT )
o . version = value
o . originating_change_time = now
o . originating_invocation_id = misc . GUID ( self . get_invocation_id ( ) )
o . originating_usn = seq
o . local_usn = seq
2010-08-10 18:19:40 +04:00
if not found and addifnotexist and len ( ctr . array ) > 0 :
o2 = drsblobs . replPropertyMetaData1 ( )
o2 . attid = 589914
att_oid = self . get_oid_from_attid ( o2 . attid )
seq = self . sequence_number ( ldb . SEQ_NEXT )
o2 . version = value
o2 . originating_change_time = now
o2 . originating_invocation_id = misc . GUID ( self . get_invocation_id ( ) )
o2 . originating_usn = seq
o2 . local_usn = seq
found = True
tab = ctr . array
tab . append ( o2 )
ctr . count = ctr . count + 1
ctr . array = tab
2010-06-22 20:03:15 +04:00
if found :
replBlob = ndr_pack ( repl )
msg = ldb . Message ( )
msg . dn = res [ 0 ] . dn
msg [ " replPropertyMetaData " ] = ldb . MessageElement ( replBlob ,
ldb . FLAG_MOD_REPLACE ,
" replPropertyMetaData " )
self . modify ( msg , [ " local_oid:1.3.6.1.4.1.7165.4.3.14:0 " ] )
2010-06-20 04:32:23 +04:00
def write_prefixes_from_schema ( self ) :
2010-06-20 17:22:49 +04:00
dsdb . _dsdb_write_prefixes_from_schema_to_ldb ( self )
2010-09-09 11:34:55 +04:00
def get_partitions_dn ( self ) :
return dsdb . _dsdb_get_partitions_dn ( self )
2010-11-22 19:34:18 +03:00
2012-07-06 12:12:58 +04:00
def get_nc_root ( self , dn ) :
return dsdb . _dsdb_get_nc_root ( self , dn )
2012-07-06 13:57:58 +04:00
def get_wellknown_dn ( self , nc_root , wkguid ) :
2015-05-25 19:17:55 +03:00
h_nc = self . hash_well_known . get ( str ( nc_root ) )
dn = None
if h_nc is not None :
dn = h_nc . get ( wkguid )
if dn is None :
dn = dsdb . _dsdb_get_wellknown_dn ( self , nc_root , wkguid )
if dn is None :
return dn
if h_nc is None :
self . hash_well_known [ str ( nc_root ) ] = { }
h_nc = self . hash_well_known [ str ( nc_root ) ]
h_nc [ wkguid ] = dn
return dn
2012-07-06 13:57:58 +04:00
2010-11-22 19:34:18 +03:00
def set_minPwdAge ( self , value ) :
m = ldb . Message ( )
m . dn = ldb . Dn ( self , self . domain_dn ( ) )
m [ " minPwdAge " ] = ldb . MessageElement ( value , ldb . FLAG_MOD_REPLACE , " minPwdAge " )
self . modify ( m )
def get_minPwdAge ( self ) :
res = self . search ( self . domain_dn ( ) , scope = ldb . SCOPE_BASE , attrs = [ " minPwdAge " ] )
if len ( res ) == 0 :
return None
elif not " minPwdAge " in res [ 0 ] :
return None
else :
return res [ 0 ] [ " minPwdAge " ] [ 0 ]
2010-11-23 12:20:12 +03:00
2014-01-31 04:27:05 +04:00
def set_maxPwdAge ( self , value ) :
m = ldb . Message ( )
m . dn = ldb . Dn ( self , self . domain_dn ( ) )
m [ " maxPwdAge " ] = ldb . MessageElement ( value , ldb . FLAG_MOD_REPLACE , " maxPwdAge " )
self . modify ( m )
def get_maxPwdAge ( self ) :
res = self . search ( self . domain_dn ( ) , scope = ldb . SCOPE_BASE , attrs = [ " maxPwdAge " ] )
if len ( res ) == 0 :
return None
elif not " maxPwdAge " in res [ 0 ] :
return None
else :
return res [ 0 ] [ " maxPwdAge " ] [ 0 ]
2010-12-02 11:55:56 +03:00
def set_minPwdLength ( self , value ) :
m = ldb . Message ( )
m . dn = ldb . Dn ( self , self . domain_dn ( ) )
m [ " minPwdLength " ] = ldb . MessageElement ( value , ldb . FLAG_MOD_REPLACE , " minPwdLength " )
self . modify ( m )
def get_minPwdLength ( self ) :
res = self . search ( self . domain_dn ( ) , scope = ldb . SCOPE_BASE , attrs = [ " minPwdLength " ] )
if len ( res ) == 0 :
return None
elif not " minPwdLength " in res [ 0 ] :
return None
else :
return res [ 0 ] [ " minPwdLength " ] [ 0 ]
def set_pwdProperties ( self , value ) :
m = ldb . Message ( )
m . dn = ldb . Dn ( self , self . domain_dn ( ) )
m [ " pwdProperties " ] = ldb . MessageElement ( value , ldb . FLAG_MOD_REPLACE , " pwdProperties " )
self . modify ( m )
def get_pwdProperties ( self ) :
res = self . search ( self . domain_dn ( ) , scope = ldb . SCOPE_BASE , attrs = [ " pwdProperties " ] )
if len ( res ) == 0 :
return None
elif not " pwdProperties " in res [ 0 ] :
return None
else :
return res [ 0 ] [ " pwdProperties " ] [ 0 ]
2010-11-23 12:20:12 +03:00
def set_dsheuristics ( self , dsheuristics ) :
m = ldb . Message ( )
m . dn = ldb . Dn ( self , " CN=Directory Service,CN=Windows NT,CN=Services, %s "
% self . get_config_basedn ( ) . get_linearized ( ) )
if dsheuristics is not None :
2010-11-28 05:34:47 +03:00
m [ " dSHeuristics " ] = ldb . MessageElement ( dsheuristics ,
ldb . FLAG_MOD_REPLACE , " dSHeuristics " )
2010-11-23 12:20:12 +03:00
else :
2010-11-28 05:34:47 +03:00
m [ " dSHeuristics " ] = ldb . MessageElement ( [ ] , ldb . FLAG_MOD_DELETE ,
" dSHeuristics " )
2010-11-23 12:20:12 +03:00
self . modify ( m )
def get_dsheuristics ( self ) :
res = self . search ( " CN=Directory Service,CN=Windows NT,CN=Services, %s "
% self . get_config_basedn ( ) . get_linearized ( ) ,
scope = ldb . SCOPE_BASE , attrs = [ " dSHeuristics " ] )
if len ( res ) == 0 :
dsheuristics = None
elif " dSHeuristics " in res [ 0 ] :
dsheuristics = res [ 0 ] [ " dSHeuristics " ] [ 0 ]
else :
dsheuristics = None
return dsheuristics
2010-11-23 15:31:34 +03:00
def create_ou ( self , ou_dn , description = None , name = None , sd = None ) :
""" Creates an organizationalUnit object
: param ou_dn : dn of the new object
: param description : description attribute
: param name : name atttribute
: param sd : security descriptor of the object , can be
an SDDL string or security . descriptor type
"""
2010-11-25 15:25:28 +03:00
m = { " dn " : ou_dn ,
" objectClass " : " organizationalUnit " }
2010-11-23 15:31:34 +03:00
if description :
2010-11-25 20:57:51 +03:00
m [ " description " ] = description
2010-11-23 15:31:34 +03:00
if name :
2010-11-25 20:57:51 +03:00
m [ " name " ] = name
2010-11-23 15:31:34 +03:00
if sd :
2010-11-25 20:57:51 +03:00
m [ " nTSecurityDescriptor " ] = ndr_pack ( sd )
2010-11-23 15:31:34 +03:00
self . add ( m )
2011-11-28 10:19:50 +04:00
def sequence_number ( self , seq_type ) :
""" Returns the value of the sequence number according to the requested type
: param seq_type : type of sequence number
"""
self . transaction_start ( )
try :
seq = super ( SamDB , self ) . sequence_number ( seq_type )
2012-02-25 18:56:25 +04:00
except :
2012-07-03 05:27:21 +04:00
self . transaction_cancel ( )
raise
2011-11-28 10:19:50 +04:00
else :
self . transaction_commit ( )
return seq
2011-12-04 17:23:34 +04:00
def get_dsServiceName ( self ) :
''' get the NTDS DN from the rootDSE '''
res = self . search ( base = " " , scope = ldb . SCOPE_BASE , attrs = [ " dsServiceName " ] )
return res [ 0 ] [ " dsServiceName " ] [ 0 ]
def get_serverName ( self ) :
''' get the server DN from the rootDSE '''
res = self . search ( base = " " , scope = ldb . SCOPE_BASE , attrs = [ " serverName " ] )
return res [ 0 ] [ " serverName " ] [ 0 ]
2015-09-22 03:11:04 +03:00
2017-06-09 07:05:31 +03:00
def dns_lookup ( self , dns_name , dns_partition = None ) :
2015-09-22 03:11:04 +03:00
''' Do a DNS lookup in the database, returns the NDR database structures '''
2017-06-09 07:05:31 +03:00
if dns_partition is None :
return dsdb_dns . lookup ( self , dns_name )
else :
return dsdb_dns . lookup ( self , dns_name ,
dns_partition = dns_partition )
2015-09-22 03:11:04 +03:00
2015-09-22 06:32:57 +03:00
def dns_extract ( self , el ) :
''' Return the NDR database structures from a dnsRecord element '''
2017-04-11 03:43:22 +03:00
return dsdb_dns . extract ( self , el )
2015-09-22 06:32:57 +03:00
2015-09-22 03:11:04 +03:00
def dns_replace ( self , dns_name , new_records ) :
2015-10-14 06:56:41 +03:00
''' Do a DNS modification on the database, sets the NDR database
structures on a DNS name
'''
2015-09-22 03:11:04 +03:00
return dsdb_dns . replace ( self , dns_name , new_records )
2015-10-14 06:56:41 +03:00
def dns_replace_by_dn ( self , dn , new_records ) :
''' Do a DNS modification on the database, sets the NDR database
structures on a LDB DN
This routine is important because if the last record on the DN
is removed , this routine will put a tombstone in the record .
'''
return dsdb_dns . replace_by_dn ( self , dn , new_records )
2016-07-18 04:11:10 +03:00
def garbage_collect_tombstones ( self , dn , current_time ,
tombstone_lifetime = None ) :
''' garbage_collect_tombstones(lp, samdb, [dn], current_time, tombstone_lifetime)
- > ( num_objects_expunged , num_links_expunged ) '''
if tombstone_lifetime is None :
return dsdb . _dsdb_garbage_collect_tombstones ( self , dn ,
current_time )
else :
return dsdb . _dsdb_garbage_collect_tombstones ( self , dn ,
current_time ,
tombstone_lifetime )
2016-10-28 06:08:57 +03:00
def create_own_rid_set ( self ) :
''' create a RID set for this DSA '''
return dsdb . _dsdb_create_own_rid_set ( self )
def allocate_rid ( self ) :
''' return a new RID from the RID Pool on this DSA '''
return dsdb . _dsdb_allocate_rid ( self )
2018-01-24 19:06:50 +03:00
def normalize_dn_in_domain ( self , dn ) :
2018-02-08 06:46:29 +03:00
''' return a new DN expanded by adding the domain DN
If the dn is already a child of the domain DN , just
return it as - is .
2018-01-24 19:06:50 +03:00
: param dn : relative dn
2018-02-08 06:46:29 +03:00
'''
2018-01-24 19:06:50 +03:00
domain_dn = ldb . Dn ( self , self . domain_dn ( ) )
2018-02-08 06:27:17 +03:00
if isinstance ( dn , ldb . Dn ) :
dn = str ( dn )
2018-01-24 19:06:50 +03:00
full_dn = ldb . Dn ( self , dn )
if not full_dn . is_child_of ( domain_dn ) :
full_dn . add_base ( domain_dn )
return full_dn