from samba.credentials import Credentials, DONT_USE_KERBEROS
from samba.param import LoadParm
import samba.dcerpc.samr
from samba.dcerpc import security
from samba.dcerpc import lsa
import univention.admin.password
import binascii

from Crypto.Cipher import DES, AES, ARC4

admin_user = "Administrator"
admin_pass = "Univention.98"
domain = "w2k12"
server = "10.200.7.132"

user_name = "win1"
new_user_password = "univention"

def transformKey(InputKey):
    # Section 5.1.3
    OutputKey = []
    OutputKey.append( chr(ord(InputKey[0]) >> 0x01) )
    OutputKey.append( chr(((ord(InputKey[0])&0x01)<<6) | (ord(InputKey[1])>>2)) )
    OutputKey.append( chr(((ord(InputKey[1])&0x03)<<5) | (ord(InputKey[2])>>3)) )
    OutputKey.append( chr(((ord(InputKey[2])&0x07)<<4) | (ord(InputKey[3])>>4)) )
    OutputKey.append( chr(((ord(InputKey[3])&0x0F)<<3) | (ord(InputKey[4])>>5)) )
    OutputKey.append( chr(((ord(InputKey[4])&0x1F)<<2) | (ord(InputKey[5])>>6)) )
    OutputKey.append( chr(((ord(InputKey[5])&0x3F)<<1) | (ord(InputKey[6])>>7)) )
    OutputKey.append( chr(ord(InputKey[6]) & 0x7F) )
    for i in range(8):
        OutputKey[i] = chr((ord(OutputKey[i]) << 1) & 0xfe)
    return "".join(OutputKey)

def mySamEncryptNTLMHash(hash, key):
	# [MS-SAMR] Section 2.2.11.1.1
	Block1 = hash[:8]
	Block2 = hash[8:]
	Key1 = key[:7]
	Key1 = transformKey(Key1)
	Key2 = key[7:14]
	Key2 = transformKey(Key2)
	Crypt1 = DES.new(Key1, DES.MODE_ECB)
	Crypt2 = DES.new(Key2, DES.MODE_ECB)
	plain1 = Crypt1.encrypt(Block1)
	plain2 = Crypt2.encrypt(Block2)
	return plain1 + plain2

lp = LoadParm()
lp.load('/etc/samba/smb.conf')

creds = Credentials()
creds.guess(lp)
creds.set_kerberos_state(DONT_USE_KERBEROS)
creds.set_username(admin_user)
creds.set_password(admin_pass)

binding_options = "\pipe\samr"
binding= "ncacn_np:%s[%s]" % (server, binding_options)

samr = samba.dcerpc.samr.samr(binding, lp, creds)
handle = samr.Connect2(None, security.SEC_FLAG_MAXIMUM_ALLOWED)
# print "Static Session Key: %s" % (samr.session_key,)

sam_domain = lsa.String()
sam_domain.string = domain
sid = samr.LookupDomain(handle, sam_domain)
dom_handle = samr.OpenDomain(handle, security.SEC_FLAG_MAXIMUM_ALLOWED, sid)

samaccountname = lsa.String()
samaccountname.string = user_name
(rids, types) = samr.LookupNames(dom_handle, [samaccountname,])

rid=rids.ids[0]
user_handle = samr.OpenUser(dom_handle, security.SEC_FLAG_MAXIMUM_ALLOWED, rid)

new_password = new_user_password
(hex_nt_hash, hex_lm_hash) = univention.admin.password.ntlm(new_password)
userinfo18 = samba.dcerpc.samr.UserInfo18()
bin_hash = binascii.a2b_hex(hex_nt_hash)
enc_hash = mySamEncryptNTLMHash(bin_hash, samr.session_key)

samr_Password = samba.dcerpc.samr.Password()
samr_Password.hash = map(ord, enc_hash)

userinfo18.nt_pwd = samr_Password
userinfo18.nt_pwd_active = 1
userinfo18.password_expired = 0
info = samr.SetUserInfo(user_handle, 18, userinfo18)
