#!/usr/bin/python3
#
# Univention Heimdal
#  kerberos_now
#
# SPDX-FileCopyrightText: 2004-2025 Univention GmbH
# SPDX-License-Identifier: AGPL-3.0-only

import ldap

import univention.config_registry
import univention.debug as ud
import univention.uldap


ud.init('/dev/null', ud.FLUSH, ud.FUNCTION)

configRegistry = univention.config_registry.ConfigRegistry()
configRegistry.load()

lo = univention.uldap.getAdminConnection()
realm = configRegistry['kerberos/realm']


def nt_password_to_arcfour_hmac_md5(nt_password):
    # all arcfour-hmac-md5 keys begin this way
    key = b'0\x1d\xa1\x1b0\x19\xa0\x03\x02\x01\x17\xa1\x12\x04\x10'

    for i in range(16):
        o = nt_password[2 * i:2 * i + 2]
        key += chr(int(o, 16)).encode('ISO8859-1')
    return key


ldap_attr = ['objectClass', 'sambaNTPassword', 'sambaAcctFlags', 'uid', 'krb5KDCFlags', 'krb5Key']
for dn, attrs in lo.search(filter='(&(objectClass=sambaSamAccount)(sambaNTPassword=*)(uid=*)(!(objectClass=univentionWindows)))', attr=ldap_attr):
    if attrs['sambaNTPassword'][0] != b"NO PASSWORDXXXXXXXXXXXXXXXXXXXXX":

        if attrs['uid'][0] == b'root':
            print('Skipping user root ')
            continue

        # check if the user was disabled
        sambaAcctFlags = attrs.get('sambaAcctFlags', [b''])[0]
        disabled = b'D' in sambaAcctFlags

        ocs = []
        ml = []
        if b'krb5Principal' not in attrs['objectClass']:
            ocs.append('krb5Principal')
            principal = b'%s@%s' % (attrs['uid'][0], realm.encode('UTF-8'))
            ml.append(('krb5PrincipalName', None, principal))

        if b'krb5KDCEntry' not in attrs['objectClass']:
            ocs.append('krb5KDCEntry')
            ml.extend([
                ('krb5MaxLife', None, b'86400'),
                ('krb5MaxRenew', None, b'604800'),
                ('krb5KeyVersionNumber', None, b'1'),
            ])

        old_flag = attrs.get('krb5KDCFlags', [])
        old_keys = attrs.get('krb5Key', [])

        ml.extend([
            ('krb5Key', old_keys, nt_password_to_arcfour_hmac_md5(attrs['sambaNTPassword'][0])),
            ('krb5KDCFlags', old_flag, b'256' if disabled else b'126'),
        ])

        if ocs:
            print('Adding Kerberos key for %r...' % (dn,), end=' ')
            ml.insert(0, ('objectClass', None, [x.encode('UTF-8') for x in ocs]))

        try:
            lo.modify(dn, ml)
        except ldap.ALREADY_EXISTS:
            print('already exists')
        else:
            print('done')

    else:
        print('Can not add Kerberos key for %s...' % repr(dn), end=' ')
        print('no password set')
