kadmin or keytab extraction

Gémes Géza geza at kzsdabas.hu
Sun Nov 27 14:15:49 MST 2011


2011-11-24 02:16 keltezéssel, Andrew Bartlett írta:
> On Thu, 2011-11-24 at 09:23 +1100, Andrew Bartlett wrote:
>> On Wed, 2011-11-23 at 22:32 +0100, Gémes Géza wrote:
>>> 2011-11-23 22:15 keltezéssel, Andrew Bartlett írta:
>>>> On Wed, 2011-11-23 at 20:34 +0100, Gémes Géza wrote:
>>>>> 2011-11-22 22:45 keltezéssel, Andrew Bartlett írta:
>>>>>> On Tue, 2011-11-22 at 21:14 +0100, Gémes Géza wrote:
>>>>>>
>>>>>>> 2. Problems from the point of view of a *nix sysadmin:
>>>>>>>     a. The KDC is quite hard to manage (no per principal keytab export
>>>>>>> utility (I've wrote one, but it doesn't take spns into account)) (Today
>>>>>>> I'll start to try implementing (at least parts of) kadmin into Samba4)
>>>>>> I've been taking a bit of a break from full time Samba development over
>>>>>> the past little while, but I'm happy to help you get the keytab
>>>>>> management code you need.
>>>>>>
>>>>>> Andrew Bartlett
>>>>>>
>>>>> Hi,
>>>>>
>>>>> My code practically replicates the code behind samba-tool domain
>>>>> exportkeytab, with a new structure (which mimics libnet_export_keytab
>>>>> adding just a principal) and passing that principal to a slightly
>>>>> modified auth/kerberos/keytab_copy.c based kt_ext function which
>>>>> iterates over the source keytab (Samba4:HDB in this case) and if the
>>>>> principal it seas is the same as the parameter given it copies it to the
>>>>> output keytab.
>>>>> Everything works quite well (I still feel the code quite hackish) except
>>>>> that I can't compare against spns (just now I've found the typedef of
>>>>> krb5_keytab_entry and try to get use of it).
>>>>>
>>>>> Thank you for your offer to help!
>>>> You really shouldn't try and handle it by iteration (because I do not
>>>> expose them for iteration), but you can try and call krb5_kt_get_entry
>>>> on the specific principal if you want.  
>>>>
>>>> I'm not sure that going via the keytab -> hdb -> hdb_samba4 -> sambdb
>>>> layers is the best approach.  There is code in the source3/ 'net samdump
>>>> keytab' that can write out a keytab from the raw database entries.  If
>>>> that code was made common, you could search for the entry in ldb, and
>>>> then just feed it the blobs to produce the keytab. 
>>>>
>>>> Andrew Bartlett
>>>>
>>> Calling krb5_kt_get_entry directly would be lot more efficient, I just
>>> couldn't figure out how to get all the vno and keyblock.keytype
>>> attributes of a given principal without iterating over the keytab.
>> The kvno is the msDs-keyversionnumber, and you can just iterate over the
>> known-to-be-stored key types (we only handle a few, see the
>> password_hash module). 
> In particular, you need:
>
> KRB5_ENCTYPE_DES_CBC_CRC
> KRB5_ENCTYPE_DES_CBC_MD5,
> KRB5_ENCTYPE_ARCFOUR_HMAC_MD5,
> KRB5_ENCTYPE_AES128_CTS_HMAC_SHA1_96,
> KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96,
>
> Andrew Bartlett
>
Hi,

Unfortunately after a few days spent it still segfaults at
krb5_kt_get_entry.
The code is a shameless copy of the libnet_export_keytab, with some
modifications (I've created a struct libnet_ext_keytab with the in part
having a keytab, a principal a kvno and an enctype), the fprintf's are
to know where it does fail:

NTSTATUS libnet_ext_keytab(struct libnet_context *ctx, TALLOC_CTX
*mem_ctx, struct libnet_ext_keytab *r)
{
    krb5_error_code ret;
    struct smb_krb5_context *smb_krb5_context;
    const char *from_keytab;

    /* Register hdb-samba4 hooks for use as a keytab */

    struct samba_kdc_base_context *base_ctx = talloc_zero(mem_ctx,
struct samba_kdc_base_context);
    if (!base_ctx) {
        return NT_STATUS_NO_MEMORY;
    }

    base_ctx->ev_ctx = ctx->event_ctx;
    base_ctx->lp_ctx = ctx->lp_ctx;

    from_keytab = talloc_asprintf(base_ctx, "HDB:samba4&%p", base_ctx);
    if (!from_keytab) {
        return NT_STATUS_NO_MEMORY;
    }

    ret = smb_krb5_init_context(ctx, ctx->event_ctx, ctx->lp_ctx,
&smb_krb5_context);
    if (ret) {
        return NT_STATUS_NO_MEMORY;
    }

    ret = krb5_plugin_register(smb_krb5_context->krb5_context,
                   PLUGIN_TYPE_DATA, "hdb",
                   &hdb_samba4);
    if(ret) {
        return NT_STATUS_NO_MEMORY;
    }

    ret = krb5_kt_register(smb_krb5_context->krb5_context, &hdb_kt_ops);
    if(ret) {
        return NT_STATUS_NO_MEMORY;
    }

        krb5_keytab keytab = (krb5_keytab) r->in.keytab_name;
       krb5_keytab_entry entry;

    fprintf(stderr, "principal: %s\nkvno: %d\nenctype: %s\n",
r->in.principal, r->in.kvno, r->in.enctype);

    krb5_principal entry_principal;
    ret = krb5_parse_name(smb_krb5_context->krb5_context,
r->in.principal, &entry_principal);
    if (ret) {
        r->out.error_string =
smb_get_krb5_error_message(smb_krb5_context->krb5_context,
                                 ret, mem_ctx);
        return NT_STATUS_UNSUCCESSFUL;
    }
    krb5_kvno entry_vno = (krb5_kvno) r->in.kvno;

    krb5_enctype entry_enctype;
    ret = krb5_string_to_enctype(smb_krb5_context->krb5_context,
r->in.enctype, &entry_enctype);
    if (ret) {
        r->out.error_string =
smb_get_krb5_error_message(smb_krb5_context->krb5_context,
                                 ret, mem_ctx);
        return NT_STATUS_UNSUCCESSFUL;
    }
    krb5_keyblock entry_keyblock;
    entry_keyblock.keytype = entry_enctype;

    fprintf(stderr, "keytab: %s\nprincipal: %s\nvno:
%d\nkeyblock.keytype: %d\n", keytab, entry_principal, entry_vno,
entry_keyblock.keytype);
    fprintf(stderr, "Now call krb5_kt_get_entry!\n");
   
    ret = krb5_kt_get_entry(smb_krb5_context->krb5_context,
                from_keytab,
                entry_principal,
                entry_vno,
                entry_keyblock.keytype,
                &entry);
   
    fprintf(stderr, "krb5_kt_get_entry FINISHED!\n");

    if(ret == KRB5_KT_NOTFOUND) {
        r->out.error_string =
smb_get_krb5_error_message(smb_krb5_context->krb5_context,
                                 ret, mem_ctx);
        return NT_STATUS_UNSUCCESSFUL;
    }

    fprintf(stderr, "Now call krb5_kt_add_entry!\n");
 
    ret = krb5_kt_add_entry (smb_krb5_context->krb5_context,
                keytab,
                &entry);
    if(ret) {
        r->out.error_string =
smb_get_krb5_error_message(smb_krb5_context->krb5_context,
                                 ret, mem_ctx);
        return NT_STATUS_UNSUCCESSFUL;
    }
    return NT_STATUS_OK;
}

I'm pretty sure that I'm doing a stupid error, but just can't figure it
out what :-(

Thanks for any idea!

Cheers

Geza


More information about the samba-technical mailing list