# This program extracts a type 23 key from an MIT dump and installs the
# password in a Samba 4 LDB database.  The dump file name should be
# given on the command line.
# A copy of the key (in keytab format) used to encrypt the MIT dump must be 
# in /usr/local/private/x-key.  This key must have the same enctype as
# the one used to encrypt.
# We assume that Samba 4 is intalled in /usr/local/samba and that Heimdal
# is in /usr/heimdal.

""" Copyright (C) 2011 Steven Gaarder and Cornell University.

    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.

    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.

    For a copy of the GNU General Public License,  see 
    <http://www.gnu.org/licenses/>."""

import sys
import subprocess
import re
import base64
import StringIO

myrealm = "REALM.WHATSAMATTAU.EDU"
mybase = "dc=realm,dc=whatsamattau,dc=edu"
infile = sys.argv[1]

# Use hprop and hpropd to get a Heimdal-format key

pout = subprocess.Popen(["/usr/heimdal/libexec/hprop --database=" + infile + " --source=mit-dump --decrypt --master-key=/usr/local/private/x-key --stdout|/usr/heimdal/libexec/hpropd -n --print"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

outlist = pout.stdout.readlines()

pat = re.compile("(\w+)@" + myrealm + ".*\d+:\d*:23:(\w+):")

mat = pat.search(outlist[0])

username =  mat.group(1)
b64key = base64.b64encode( mat.group(2).decode("hex"))

# check to see that the user is in the system


ldbfilename = "/usr/local/samba/private/sam.ldb.d/" + mybase.upper() + ".ldb"

pout = subprocess.Popen(["/usr/local/samba/bin/ldbsearch", "-H", ldbfilename, "-b", "CN=Users," + mybase, "CN=" + username, "cn" ], shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

outlist = pout.stdout.readlines()

respat = re.compile("returned\s(\d+)\srecords")

found = 0
for line in outlist:
    resmat = respat.search(line)
    if resmat != None:
        found =  resmat.group(1)

if int(found) <= 0:
    print "User not found in database"
    sys.exit(1)

# run it

pinn = subprocess.Popen(["/usr/local/samba/bin/ldbmodify", "-H", ldbfilename, "-b", "CN=Users," + mybase,  "-i", "--nosync", "--controls=relax:0" ], shell=False, stdin=subprocess.PIPE)

ldifstr="dn: CN=" + username + ",CN=Users," + mybase +"\n" + "changetype: modify\n" + "replace: unicodePwd\n" + "unicodePwd:: " + b64key +"\n"

pinn.communicate(input=ldifstr)




