From 877b0883e82db65db545509973d50480f3200aab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Love=20H=C3=B6rnquist=20=C3=85strand?= Date: Tue, 8 May 2007 00:17:59 +0000 Subject: [PATCH] split out backend ntlm server processing git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@20579 ec53bebd-3082-4978-b11e-865c3cabbd6b --- lib/gssapi/ntlm/accept_sec_context.c | 353 +++++--------------------- lib/gssapi/ntlm/acquire_cred.c | 4 + lib/gssapi/ntlm/delete_sec_context.c | 20 +- lib/gssapi/ntlm/digest.c | 362 +++++++++++++++++++++++++++ lib/gssapi/ntlm/init_sec_context.c | 19 +- lib/gssapi/ntlm/ntlm.h | 56 ++++- 6 files changed, 497 insertions(+), 317 deletions(-) create mode 100644 lib/gssapi/ntlm/digest.c diff --git a/lib/gssapi/ntlm/accept_sec_context.c b/lib/gssapi/ntlm/accept_sec_context.c index b4fd79129..86cc5fadf 100644 --- a/lib/gssapi/ntlm/accept_sec_context.c +++ b/lib/gssapi/ntlm/accept_sec_context.c @@ -39,284 +39,20 @@ RCSID("$Id$"); * */ -static OM_uint32 -handle_type2(OM_uint32 *minor_status, - ntlm_ctx ctx, - uint32_t flags, - const char *hostname, - const char *domain, - gss_buffer_t output_token) -{ - krb5_error_code ret; - struct ntlm_type2 type2; - krb5_data challange; - struct ntlm_buf data; - krb5_data ti; - - memset(&type2, 0, sizeof(type2)); - - /* - * Request data for type 2 packet from the KDC. - */ - ret = krb5_ntlm_init_request(ctx->context, - ctx->ntlm, - NULL, - ctx->id, - flags, - hostname, - domain); - if (ret) { - *minor_status = ret; - return GSS_S_FAILURE; - } - - /* - * - */ - - ret = krb5_ntlm_init_get_opaque(ctx->context, ctx->ntlm, &ctx->opaque); - if (ret) { - *minor_status = ret; - return GSS_S_FAILURE; - } - - /* - * - */ - - ret = krb5_ntlm_init_get_flags(ctx->context, ctx->ntlm, &type2.flags); - if (ret) { - *minor_status = ret; - return GSS_S_FAILURE; - } - ctx->flags = type2.flags; - - ret = krb5_ntlm_init_get_challange(ctx->context, ctx->ntlm, &challange); - if (ret) { - *minor_status = ret; - return GSS_S_FAILURE; - } - - if (challange.length != sizeof(type2.challange)) { - *minor_status = EINVAL; - return GSS_S_FAILURE; - } - memcpy(type2.challange, challange.data, sizeof(type2.challange)); - krb5_data_free(&challange); - - ret = krb5_ntlm_init_get_targetname(ctx->context, ctx->ntlm, - &type2.targetname); - if (ret) { - *minor_status = ret; - return GSS_S_FAILURE; - } - - ret = krb5_ntlm_init_get_targetinfo(ctx->context, ctx->ntlm, &ti); - if (ret) { - free(type2.targetname); - *minor_status = ret; - return GSS_S_FAILURE; - } - - type2.targetinfo.data = ti.data; - type2.targetinfo.length = ti.length; - - ret = heim_ntlm_encode_type2(&type2, &data); - free(type2.targetname); - krb5_data_free(&ti); - if (ret) { - *minor_status = ret; - return GSS_S_FAILURE; - } - - output_token->value = data.data; - output_token->length = data.length; - - return GSS_S_COMPLETE; -} - -static OM_uint32 -handle_type3(OM_uint32 *minor_status, - ntlm_ctx ctx, - struct ntlm_type3 *type3) -{ - krb5_error_code ret; - - if (type3->username == NULL || type3->targetname == NULL || - type3->ntlm.length == 0) - { - ret = EINVAL; - goto out; - } - - ret = krb5_ntlm_req_set_flags(ctx->context, ctx->ntlm, type3->flags); - if (ret) goto out; - ret = krb5_ntlm_req_set_username(ctx->context, ctx->ntlm, type3->username); - if (ret) goto out; - ret = krb5_ntlm_req_set_targetname(ctx->context, ctx->ntlm, - type3->targetname); - if (ret) goto out; - ret = krb5_ntlm_req_set_lm(ctx->context, ctx->ntlm, - type3->lm.data, type3->lm.length); - if (ret) goto out; - ret = krb5_ntlm_req_set_ntlm(ctx->context, ctx->ntlm, - type3->ntlm.data, type3->ntlm.length); - if (ret) goto out; - ret = krb5_ntlm_req_set_opaque(ctx->context, ctx->ntlm, &ctx->opaque); - if (ret) goto out; - if (type3->sessionkey.length) { - ret = krb5_ntlm_req_set_session(ctx->context, ctx->ntlm, - type3->sessionkey.data, - type3->sessionkey.length); - if (ret) goto out; - } - - /* - * Verify with the KDC the type3 packet is ok - */ - ret = krb5_ntlm_request(ctx->context, - ctx->ntlm, - NULL, - ctx->id); - if (ret) - goto out; - - if (krb5_ntlm_rep_get_status(ctx->context, ctx->ntlm) != TRUE) { - ret = EINVAL; - goto out; - } - - ret = krb5_ntlm_rep_get_sessionkey(ctx->context, - ctx->ntlm, - &ctx->sessionkey); - if (ret == 0) { - if (ctx->sessionkey.length != 16) { - ret = EINVAL; - goto out; - } - - ctx->status |= STATUS_SESSIONKEY; - - if (ctx->flags & NTLM_NEG_NTLM2_SESSION) { - _gss_ntlm_set_key(&ctx->u.v2.send, 1, (ctx->flags & NTLM_NEG_KEYEX), - ctx->sessionkey.data, - ctx->sessionkey.length); - _gss_ntlm_set_key(&ctx->u.v2.recv, 0, (ctx->flags & NTLM_NEG_KEYEX), - ctx->sessionkey.data, - ctx->sessionkey.length); - } else { - RC4_set_key(&ctx->u.v1.crypto_send.key, - ctx->sessionkey.length, - ctx->sessionkey.data); - RC4_set_key(&ctx->u.v1.crypto_recv.key, - ctx->sessionkey.length, - ctx->sessionkey.data); - } - } - - return GSS_S_COMPLETE; -out: - *minor_status = ret; - return GSS_S_FAILURE; -} - -/* - * Get credential cache that the ntlm code can use to talk to the KDC - * using the digest API. - */ - -static krb5_error_code -get_ccache(krb5_context context, krb5_ccache *id) -{ - krb5_principal principal = NULL; - krb5_error_code ret; - krb5_keytab kt; - - *id = NULL; - - if (!issuid()) { - const char *cache; - - cache = getenv("NTLM_ACCEPTOR_CCACHE"); - if (cache) { - ret = krb5_cc_resolve(context, cache, id); - if (ret) - goto out; - return 0; - } - } - - ret = krb5_sname_to_principal(context, NULL, "host", - KRB5_NT_SRV_HST, &principal); - if (ret) - goto out; - - ret = krb5_cc_cache_match(context, principal, NULL, id); - if (ret == 0) - goto out; - - /* did not find in default credcache, lets try default keytab */ - ret = krb5_kt_default(context, &kt); - if (ret) - goto out; - - /* XXX check in keytab */ -#if 0 - { - krb5_creds cred = NULL; - - ret = krb5_get_init_creds_keytab (context, - &cred, - principal, - kt, - NULL, - NULL, - NULL); - if (ret) - goto out; - ret = krb5_cc_initialize (context, ccache, cred.client); - ret = krb5_cc_store_cred (context, ccache, &cred); - krb5_free_cred_contents (context, &cred); - } -#endif - krb5_kt_close(context, kt); - -out: - if (principal) - krb5_free_principal(context, principal); - return ret; -} - OM_uint32 _gss_ntlm_allocate_ctx(OM_uint32 *minor_status, ntlm_ctx *ctx) { - krb5_error_code ret; + OM_uint32 maj_stat; + /* krb5_error_code ret; */ *ctx = calloc(1, sizeof(**ctx)); - ret = krb5_init_context(&(*ctx)->context); - if (ret) { - gss_ctx_id_t context = (gss_ctx_id_t)*ctx; - _gss_ntlm_delete_sec_context(minor_status, &context, NULL); - *minor_status = ret; - return GSS_S_FAILURE; - } + (*ctx)->server = &ntlmsspi_kdc_digest; - ret = get_ccache((*ctx)->context, &(*ctx)->id); - if (ret) { - gss_ctx_id_t context = (gss_ctx_id_t)*ctx; - _gss_ntlm_delete_sec_context(minor_status, &context, NULL); - *minor_status = ret; - return GSS_S_FAILURE; - } + maj_stat = (*(*ctx)->server->nsi_init)(minor_status, &(*ctx)->ictx); + if (maj_stat != GSS_S_COMPLETE) + return maj_stat; - ret = krb5_ntlm_alloc((*ctx)->context, &(*ctx)->ntlm); - if (ret) { - gss_ctx_id_t context = (gss_ctx_id_t)*ctx; - _gss_ntlm_delete_sec_context(minor_status, &context, NULL); - *minor_status = ret; - return GSS_S_FAILURE; - } return GSS_S_COMPLETE; } @@ -368,6 +104,8 @@ _gss_ntlm_accept_sec_context if (*context_handle == GSS_C_NO_CONTEXT) { struct ntlm_type1 type1; OM_uint32 major_status; + OM_uint32 retflags; + struct ntlm_buf out; major_status = _gss_ntlm_allocate_ctx(minor_status, &ctx); if (major_status) @@ -391,27 +129,41 @@ _gss_ntlm_accept_sec_context } if (type1.flags & NTLM_NEG_SIGN) - ctx->flags |= GSS_C_CONF_FLAG; + ctx->gssflags |= GSS_C_CONF_FLAG; if (type1.flags & NTLM_NEG_SIGN) - ctx->flags |= GSS_C_INTEG_FLAG; + ctx->gssflags |= GSS_C_INTEG_FLAG; - major_status = handle_type2(minor_status, - ctx, - type1.flags, - type1.hostname, - type1.domain, - output_token); + major_status = (*ctx->server->nsi_type2)(minor_status, + ctx->ictx, + type1.flags, + type1.hostname, + type1.domain, + &retflags, + &out); heim_ntlm_free_type1(&type1); if (major_status != GSS_S_COMPLETE) { - _gss_ntlm_delete_sec_context(minor_status, - context_handle, NULL); + OM_uint32 junk; + _gss_ntlm_delete_sec_context(&junk, context_handle, NULL); return major_status; } + output_token->value = malloc(out.length); + if (output_token->value == NULL) { + OM_uint32 junk; + _gss_ntlm_delete_sec_context(&junk, context_handle, NULL); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy(output_token->value, out.data, out.length); + output_token->length = out.length; + + ctx->flags = retflags; + return GSS_S_CONTINUE_NEEDED; } else { OM_uint32 maj_stat; struct ntlm_type3 type3; + struct ntlm_buf session; ctx = (ntlm_ctx)*context_handle; @@ -420,20 +172,42 @@ _gss_ntlm_accept_sec_context ret = heim_ntlm_decode_type3(&data, 1, &type3); if (ret) { - _gss_ntlm_delete_sec_context(minor_status, - context_handle, NULL); + _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); *minor_status = ret; return GSS_S_FAILURE; } - maj_stat = handle_type3(minor_status, ctx, &type3); - if (maj_stat != GSS_S_COMPLETE) { - OM_uint32 junk; - _gss_ntlm_delete_sec_context(&junk, context_handle, NULL); - return maj_stat; + maj_stat = (*ctx->server->nsi_type3)(minor_status, + ctx->ictx, + &type3, + &session); + heim_ntlm_free_type3(&type3); + + ret = krb5_data_copy(&ctx->sessionkey, + session.data, session.length); + if (ret) { + _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); + *minor_status = ret; + return GSS_S_FAILURE; } - heim_ntlm_free_type3(&type3); + ctx->status |= STATUS_SESSIONKEY; + + if (ctx->flags & NTLM_NEG_NTLM2_SESSION) { + _gss_ntlm_set_key(&ctx->u.v2.send, 1, (ctx->flags & NTLM_NEG_KEYEX), + ctx->sessionkey.data, + ctx->sessionkey.length); + _gss_ntlm_set_key(&ctx->u.v2.recv, 0, (ctx->flags & NTLM_NEG_KEYEX), + ctx->sessionkey.data, + ctx->sessionkey.length); + } else { + RC4_set_key(&ctx->u.v1.crypto_send.key, + ctx->sessionkey.length, + ctx->sessionkey.data); + RC4_set_key(&ctx->u.v1.crypto_recv.key, + ctx->sessionkey.length, + ctx->sessionkey.data); + } if (mech_type) *mech_type = GSS_NTLM_MECHANISM; @@ -442,6 +216,9 @@ _gss_ntlm_accept_sec_context ctx->status |= STATUS_OPEN; + if (ret_flags) + *ret_flags = ctx->gssflags; + return GSS_S_COMPLETE; } } diff --git a/lib/gssapi/ntlm/acquire_cred.c b/lib/gssapi/ntlm/acquire_cred.c index a6c8447a5..e85c5a546 100644 --- a/lib/gssapi/ntlm/acquire_cred.c +++ b/lib/gssapi/ntlm/acquire_cred.c @@ -46,10 +46,12 @@ OM_uint32 _gss_ntlm_acquire_cred OM_uint32 * time_rec ) { +#if 0 OM_uint32 major_status; krb5_error_code ret; ntlm_ctx ctx; ntlm_name name = (ntlm_name)desired_name; +#endif *minor_status = 0; if (output_cred_handle) @@ -59,6 +61,7 @@ OM_uint32 _gss_ntlm_acquire_cred if (time_rec) *time_rec = GSS_C_INDEFINITE; +#if 0 /* XXX */ major_status = _gss_ntlm_allocate_ctx(minor_status, &ctx); if (major_status != GSS_S_COMPLETE) return GSS_S_FAILURE; @@ -80,6 +83,7 @@ OM_uint32 _gss_ntlm_acquire_cred _gss_ntlm_delete_sec_context(minor_status, &context, NULL); *minor_status = 0; } +#endif return (GSS_S_COMPLETE); } diff --git a/lib/gssapi/ntlm/delete_sec_context.c b/lib/gssapi/ntlm/delete_sec_context.c index 97f802ac0..7b8b3c5d3 100644 --- a/lib/gssapi/ntlm/delete_sec_context.c +++ b/lib/gssapi/ntlm/delete_sec_context.c @@ -45,20 +45,16 @@ OM_uint32 _gss_ntlm_delete_sec_context ntlm_ctx ctx = (ntlm_ctx)*context_handle; *context_handle = GSS_C_NO_CONTEXT; - if (ctx->id) - krb5_cc_close(ctx->context, ctx->id); + if (ctx->server) + (*ctx->server->nsi_destroy)(minor_status, ctx->ictx); - if (ctx->context) { - krb5_ntlm_free(ctx->context, ctx->ntlm); - krb5_free_context(ctx->context); + if (ctx->client.username) + free(ctx->client.username); + if (ctx->client.key.data) { + memset(ctx->client.key.data, 0, ctx->client.key.length); + free(ctx->client.key.data); } - if (ctx->username) - free(ctx->username); - if (ctx->key.data) { - memset(ctx->key.data, 0, ctx->key.length); - free(ctx->key.data); - } - krb5_data_free(&ctx->opaque); + memset(ctx, 0, sizeof(*ctx)); free(ctx); } diff --git a/lib/gssapi/ntlm/digest.c b/lib/gssapi/ntlm/digest.c new file mode 100644 index 000000000..9a5794fa1 --- /dev/null +++ b/lib/gssapi/ntlm/digest.c @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm/ntlm.h" + +RCSID("$Id$"); + +/* + * + */ + +struct ntlmkrb5 { + krb5_context context; + krb5_ntlm ntlm; + krb5_realm kerberos_realm; + krb5_ccache id; + krb5_data opaque; + OM_uint32 flags; + struct ntlm_buf key; + krb5_data sessionkey; +}; + +/* + * Get credential cache that the ntlm code can use to talk to the KDC + * using the digest API. + */ + +static krb5_error_code +get_ccache(krb5_context context, krb5_ccache *id) +{ + krb5_principal principal = NULL; + krb5_error_code ret; + krb5_keytab kt; + + *id = NULL; + + if (!issuid()) { + const char *cache; + + cache = getenv("NTLM_ACCEPTOR_CCACHE"); + if (cache) { + ret = krb5_cc_resolve(context, cache, id); + if (ret) + goto out; + return 0; + } + } + + ret = krb5_sname_to_principal(context, NULL, "host", + KRB5_NT_SRV_HST, &principal); + if (ret) + goto out; + + ret = krb5_cc_cache_match(context, principal, NULL, id); + if (ret == 0) + goto out; + + /* did not find in default credcache, lets try default keytab */ + ret = krb5_kt_default(context, &kt); + if (ret) + goto out; + + /* XXX check in keytab */ +#if 0 + { + krb5_creds cred = NULL; + + ret = krb5_get_init_creds_keytab (context, + &cred, + principal, + kt, + NULL, + NULL, + NULL); + if (ret) + goto out; + ret = krb5_cc_initialize (context, ccache, cred.client); + ret = krb5_cc_store_cred (context, ccache, &cred); + krb5_free_cred_contents (context, &cred); + } +#endif + krb5_kt_close(context, kt); + +out: + if (principal) + krb5_free_principal(context, principal); + return ret; +} + +/* + * + */ + +static OM_uint32 +kdc_alloc(OM_uint32 *minor, void **ctx) +{ + krb5_error_code ret; + struct ntlmkrb5 *c; + + c = calloc(1, sizeof(*c)); + + ret = krb5_init_context(&c->context); + if (ret) { + /* free */ + *minor = ret; + return GSS_S_FAILURE; + } + + ret = get_ccache(c->context, &c->id); + if (ret) { + /* free */ + *minor = ret; + return GSS_S_FAILURE; + } + + ret = krb5_ntlm_alloc(c->context, &c->ntlm); + if (ret) { + /* free */ + *minor = ret; + return GSS_S_FAILURE; + } + + *ctx = c; + + return GSS_S_COMPLETE; +} + +/* + * + */ + +static OM_uint32 +kdc_destroy(OM_uint32 *minor, void *ctx) +{ + struct ntlmkrb5 *c = ctx; + krb5_data_free(&c->opaque); + krb5_data_free(&c->sessionkey); + return GSS_S_COMPLETE; +} + +/* + * + */ + +static OM_uint32 +kdc_type2(OM_uint32 *minor_status, + void *ctx, + uint32_t flags, + const char *hostname, + const char *domain, + uint32_t *ret_flags, + struct ntlm_buf *out) +{ + struct ntlmkrb5 *c = ctx; + krb5_error_code ret; + struct ntlm_type2 type2; + krb5_data challange; + struct ntlm_buf data; + krb5_data ti; + + memset(&type2, 0, sizeof(type2)); + + /* + * Request data for type 2 packet from the KDC. + */ + ret = krb5_ntlm_init_request(c->context, + c->ntlm, + NULL, + c->id, + flags, + hostname, + domain); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + /* + * + */ + + ret = krb5_ntlm_init_get_opaque(c->context, c->ntlm, &c->opaque); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + /* + * + */ + + ret = krb5_ntlm_init_get_flags(c->context, c->ntlm, &type2.flags); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + *ret_flags = type2.flags; + + ret = krb5_ntlm_init_get_challange(c->context, c->ntlm, &challange); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + if (challange.length != sizeof(type2.challange)) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + memcpy(type2.challange, challange.data, sizeof(type2.challange)); + krb5_data_free(&challange); + + ret = krb5_ntlm_init_get_targetname(c->context, c->ntlm, + &type2.targetname); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_ntlm_init_get_targetinfo(c->context, c->ntlm, &ti); + if (ret) { + free(type2.targetname); + *minor_status = ret; + return GSS_S_FAILURE; + } + + type2.targetinfo.data = ti.data; + type2.targetinfo.length = ti.length; + + ret = heim_ntlm_encode_type2(&type2, &data); + free(type2.targetname); + krb5_data_free(&ti); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + out->data = data.data; + out->length = data.length; + + return GSS_S_COMPLETE; +} + +/* + * + */ + +static OM_uint32 +kdc_type3(OM_uint32 *minor_status, + void *ctx, + const struct ntlm_type3 *type3, + struct ntlm_buf *sessionkey) +{ + struct ntlmkrb5 *c = ctx; + krb5_error_code ret; + + ret = krb5_ntlm_req_set_flags(c->context, c->ntlm, type3->flags); + if (ret) goto out; + ret = krb5_ntlm_req_set_username(c->context, c->ntlm, type3->username); + if (ret) goto out; + ret = krb5_ntlm_req_set_targetname(c->context, c->ntlm, + type3->targetname); + if (ret) goto out; + ret = krb5_ntlm_req_set_lm(c->context, c->ntlm, + type3->lm.data, type3->lm.length); + if (ret) goto out; + ret = krb5_ntlm_req_set_ntlm(c->context, c->ntlm, + type3->ntlm.data, type3->ntlm.length); + if (ret) goto out; + ret = krb5_ntlm_req_set_opaque(c->context, c->ntlm, &c->opaque); + if (ret) goto out; + if (type3->sessionkey.length) { + ret = krb5_ntlm_req_set_session(c->context, c->ntlm, + type3->sessionkey.data, + type3->sessionkey.length); + if (ret) goto out; + } + + /* + * Verify with the KDC the type3 packet is ok + */ + ret = krb5_ntlm_request(c->context, + c->ntlm, + NULL, + c->id); + if (ret) + goto out; + + if (krb5_ntlm_rep_get_status(c->context, c->ntlm) != TRUE) { + ret = EINVAL; + goto out; + } + + ret = krb5_ntlm_rep_get_sessionkey(c->context, + c->ntlm, + &c->sessionkey); + if (ret) + goto out; + + sessionkey->data = c->sessionkey.data; + sessionkey->length = c->sessionkey.length; + + return 0; + + out: + *minor_status = ret; + return GSS_S_FAILURE; +} + +/* + * + */ + +static void +kdc_free_buffer(struct ntlm_buf *sessionkey) +{ + if (sessionkey->data) + free(sessionkey->data); + sessionkey->data = NULL; + sessionkey->length = 0; +} + +/* + * + */ + +struct ntlm_server_interface ntlmsspi_kdc_digest = { + kdc_alloc, + kdc_destroy, + kdc_type2, + kdc_type3, + kdc_free_buffer +}; diff --git a/lib/gssapi/ntlm/init_sec_context.c b/lib/gssapi/ntlm/init_sec_context.c index 10f7efbc7..8465e9740 100644 --- a/lib/gssapi/ntlm/init_sec_context.c +++ b/lib/gssapi/ntlm/init_sec_context.c @@ -207,9 +207,11 @@ _gss_ntlm_init_sec_context } *context_handle = (gss_ctx_id_t)ctx; - ret = get_user_file(name->domain, &ctx->username, &ctx->key); + ret = get_user_file(name->domain, + &ctx->client.username, &ctx->client.key); if (ret) - ret = get_user_ccache(name->domain, &ctx->username, &ctx->key); + ret = get_user_ccache(name->domain, + &ctx->client.username, &ctx->client.key); if (ret) { _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); *minor_status = ret; @@ -272,7 +274,7 @@ _gss_ntlm_init_sec_context memset(&type3, 0, sizeof(type3)); - type3.username = ctx->username; + type3.username = ctx->client.username; type3.flags = type2.flags; type3.targetname = type2.targetname; type3.ws = rk_UNCONST("workstation"); @@ -317,11 +319,13 @@ _gss_ntlm_init_sec_context } - heim_ntlm_calculate_ntlm1(ctx->key.data, ctx->key.length, + heim_ntlm_calculate_ntlm1(ctx->client.key.data, + ctx->client.key.length, challange, &type3.ntlm); - ret = heim_ntlm_build_ntlm1_master(ctx->key.data, ctx->key.length, + ret = heim_ntlm_build_ntlm1_master(ctx->client.key.data, + ctx->client.key.length, &sessionkey, &type3.sessionkey); if (ret) { @@ -366,8 +370,9 @@ _gss_ntlm_init_sec_context return GSS_S_FAILURE; } - ret = heim_ntlm_calculate_ntlm2(ctx->key.data, ctx->key.length, - ctx->username, + ret = heim_ntlm_calculate_ntlm2(ctx->client.key.data, + ctx->client.key.length, + ctx->client.username, name->domain, type2.challange, &type2.targetinfo, diff --git a/lib/gssapi/ntlm/ntlm.h b/lib/gssapi/ntlm/ntlm.h index 0b96808e4..f903f5765 100644 --- a/lib/gssapi/ntlm/ntlm.h +++ b/lib/gssapi/ntlm/ntlm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Kungliga Tekniska Högskolan + * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -57,6 +57,39 @@ #include "crypto-headers.h" +typedef OM_uint32 +(*ntlm_interface_init)(OM_uint32 *, void **); + +typedef OM_uint32 +(*ntlm_interface_destroy)(OM_uint32 *, void *); + +typedef OM_uint32 +(*ntlm_interface_type2)(OM_uint32 *minor_status, + void *ctx, + uint32_t flags, + const char *hostname, + const char *domain, + uint32_t *ret_flags, + struct ntlm_buf *type2); + +typedef OM_uint32 +(*ntlm_interface_type3)(OM_uint32 *minor_status, + void *ctx, + const struct ntlm_type3 *type3, + struct ntlm_buf *sessionkey); + +typedef void +(*ntlm_interface_free_buffer)(struct ntlm_buf *); + +struct ntlm_server_interface { + ntlm_interface_init nsi_init; + ntlm_interface_destroy nsi_destroy; + ntlm_interface_type2 nsi_type2; + ntlm_interface_type3 nsi_type3; + ntlm_interface_free_buffer nsi_free_buffer; +}; + + struct ntlmv2_key { uint32_t seq; RC4_KEY sealkey; @@ -64,19 +97,21 @@ struct ntlmv2_key { unsigned char signkey[16]; }; +extern struct ntlm_server_interface ntlmsspi_kdc_digest; + typedef struct { - krb5_context context; - krb5_ntlm ntlm; - krb5_realm kerberos_realm; - krb5_ccache id; - krb5_data opaque; - OM_uint32 flags; - OM_uint32 status; + struct ntlm_server_interface *server; + void *ictx; + struct { + char *username; + struct ntlm_buf key; + } client; + OM_uint32 gssflags; + uint32_t flags; + uint32_t status; #define STATUS_OPEN 1 #define STATUS_CLIENT 2 #define STATUS_SESSIONKEY 4 - char *username; - struct ntlm_buf key; krb5_data sessionkey; union { @@ -102,4 +137,5 @@ typedef struct { #include + #endif /* NTLM_NTLM_H */