summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin@redhat.com>2009-11-24 12:04:58 -0500
committerSimo Sorce <ssorce@redhat.com>2009-11-24 12:07:27 -0500
commita094dfa91c88c1bd594b9fc29c8ba3639d3b3e90 (patch)
tree959ef9c97149c3eb81ee0460c4adbfc42fbf0ec8
parent5d2bbf53256c212ad26505bae6827f6739c73f22 (diff)
downloadfreeipa-a094dfa91c88c1bd594b9fc29c8ba3639d3b3e90.tar.gz
freeipa-a094dfa91c88c1bd594b9fc29c8ba3639d3b3e90.tar.xz
freeipa-a094dfa91c88c1bd594b9fc29c8ba3639d3b3e90.zip
Add code to handle stash files using keytab format
In krb5 1.7 and later, the stash file (/var/kerberos/krb5kdc/.k5.$REALM on Fedora) is created in the regular keytab format instead of the older less-portable one. Based from comments and code in kt_file.c, here's a change to try to recognize that case (the file starts with a magic number) and read the master key from Python. The KDC will still read either format, so I left the bits that set things up on replicas alone (advice appreciated). The patch works as expected on my 64-bit box, both on RHEL5 (krb5 1.6.1 with a traditional stash file) and on Raw Hide (krb5 1.7 with a keytab).
-rw-r--r--ipaserver/install/krbinstance.py62
1 files changed, 59 insertions, 3 deletions
diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py
index 407be8a39..a33ab233c 100644
--- a/ipaserver/install/krbinstance.py
+++ b/ipaserver/install/krbinstance.py
@@ -318,12 +318,68 @@ class KrbInstance(service.Service):
self._ldap_mod("pwd-extop-conf.ldif", self.sub_dict)
def __add_master_key(self):
+ #check for a keytab file by checking if the header magic is for a keytab
+ def __is_keytab(header):
+ if header == 0x0502 or header == 0x0501 or header == 0x0205 or header == 0x0105:
+ return 1
+ else:
+ return 0
+ #check whether a keytab file is v1 or v2
+ def __keytab_version(header):
+ if header == 0x0502 or header == 0x0205:
+ return 2
+ elif header == 0x0501 or header == 0x0105:
+ return 1
+ else:
+ return 0
#get the Master Key from the stash file
try:
stash = open("/var/kerberos/krb5kdc/.k5."+self.realm, "r")
keytype = struct.unpack('h', stash.read(2))[0]
- keylen = struct.unpack('i', stash.read(4))[0]
- keydata = stash.read(keylen)
+ if __is_keytab(keytype):
+ #in v2, all numbers are stored in network order
+ if __keytab_version(keytype) > 1:
+ __endian = '!'
+ else:
+ __endian = ''
+ #walk the first entry (there should only be one)
+ keyentrylen = struct.unpack(__endian + 'i', stash.read(4))[0]
+ #number of components in the principal name
+ keyprinccomps = struct.unpack(__endian + 'h', stash.read(2))[0]
+ #version 1 counted the realm as a component, version 2 doesn't
+ if __keytab_version(keytype) == 1:
+ keyprinccomps = keyprinccomps - 1
+ keyprinc = []
+ #read the components. the realm goes first, so we should
+ #end up with (realm, "K", "M")
+ for i in range(keyprinccomps + 1):
+ keyprinccompsize = struct.unpack(__endian + 'h', stash.read(2))[0]
+ keyprinc = keyprinc + [stash.read(keyprinccompsize)]
+ #version 2 added the principal name type, otherwise we just
+ #assume it's a regular old principal name
+ if __keytab_version(keytype) > 1:
+ keyprinctype = struct.unpack(__endian + 'i', stash.read(4))[0]
+ else:
+ keyprinctype = 1
+ #date the key was added to this keytab
+ keydate = struct.unpack(__endian + 'i', stash.read(4))[0]
+ #kvno
+ keyversion = struct.unpack('B', stash.read(1))[0]
+ #read the real enctype
+ keytype = struct.unpack(__endian + 'h', stash.read(2))[0]
+ keylen = struct.unpack(__endian + 'h', stash.read(2))[0]
+ keydata = stash.read(keylen)
+ #check that we parsed the whole file, so no surprises
+ keyoffset = stash.tell()
+ stash.seek(0,2)
+ if stash.tell() != keyoffset:
+ logging.critical("Unexpected unprocessed data in Stash file (processed %ld bytes, %ld left)." % (keyoffset, stash.tell() - keyoffset))
+ else:
+ keyversion = 1
+ keyprinctype = 1
+ keyprinc = [self.realm,"K","M"]
+ keylen = struct.unpack('i', stash.read(4))[0]
+ keydata = stash.read(keylen)
except os.error:
logging.critical("Failed to retrieve Master Key from Stash file: %s")
#encode it in the asn.1 attribute
@@ -331,7 +387,7 @@ class KrbInstance(service.Service):
MasterKey.setComponentByPosition(0, univ.Integer(keytype))
MasterKey.setComponentByPosition(1, univ.OctetString(keydata))
krbMKey = univ.Sequence()
- krbMKey.setComponentByPosition(0, univ.Integer(0)) #we have no kvno
+ krbMKey.setComponentByPosition(0, univ.Integer(keyversion))
krbMKey.setComponentByPosition(1, MasterKey)
asn1key = pyasn1.codec.ber.encoder.encode(krbMKey)