diff --git a/lib/gssapi/ntlm/accept_sec_context.c b/lib/gssapi/ntlm/accept_sec_context.c index 40c4ee207..881f7f1b0 100644 --- a/lib/gssapi/ntlm/accept_sec_context.c +++ b/lib/gssapi/ntlm/accept_sec_context.c @@ -43,7 +43,6 @@ OM_uint32 _gss_ntlm_allocate_ctx(OM_uint32 *minor_status, ntlm_ctx *ctx) { OM_uint32 maj_stat; - /* krb5_error_code ret; */ *ctx = calloc(1, sizeof(**ctx)); @@ -123,11 +122,20 @@ _gss_ntlm_accept_sec_context } if ((type1.flags & NTLM_NEG_UNICODE) == 0) { + heim_ntlm_free_type1(&type1); _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); *minor_status = EINVAL; return GSS_S_FAILURE; } + major_status = (*ctx->server->nsi_probe)(minor_status, ctx->ictx, NULL); + if (major_status) { + heim_ntlm_free_type1(&type1); + _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); + return major_status; + } + + if (type1.flags & NTLM_NEG_SIGN) ctx->gssflags |= GSS_C_CONF_FLAG; if (type1.flags & NTLM_NEG_SIGN) diff --git a/lib/gssapi/ntlm/acquire_cred.c b/lib/gssapi/ntlm/acquire_cred.c index 097b78944..8db2b6ac6 100644 --- a/lib/gssapi/ntlm/acquire_cred.c +++ b/lib/gssapi/ntlm/acquire_cred.c @@ -46,6 +46,7 @@ OM_uint32 _gss_ntlm_acquire_cred OM_uint32 * time_rec ) { + ntlm_name name = (ntlm_name) desired_name; OM_uint32 maj_stat; ntlm_ctx ctx; @@ -57,14 +58,30 @@ OM_uint32 _gss_ntlm_acquire_cred if (time_rec) *time_rec = GSS_C_INDEFINITE; - maj_stat = _gss_ntlm_allocate_ctx(min_stat, &ctx); - if (maj_stat != GSS_S_COMPLETE) - return maj_stat; + if (desired_name == NULL) + return GSS_S_NO_CRED; - { - gss_ctx_id_t context = (gss_ctx_id_t)ctx; - _gss_ntlm_delete_sec_context(min_stat, &context, NULL); - *min_stat = 0; + if (cred_usage == GSS_C_BOTH || cred_usage == GSS_C_ACCEPT) { + + maj_stat = _gss_ntlm_allocate_ctx(min_stat, &ctx); + if (maj_stat != GSS_S_COMPLETE) + return maj_stat; + + maj_stat = (*ctx->server->nsi_probe)(min_stat, ctx->ictx, + name->domain); + + if (maj_stat) + return maj_stat; + + { + gss_ctx_id_t context = (gss_ctx_id_t)ctx; + _gss_ntlm_delete_sec_context(min_stat, &context, NULL); + *min_stat = 0; + } + } + + if (cred_usage == GSS_C_BOTH || cred_usage == GSS_C_INITIATE) { + /* check if cred exists XXX */ } return (GSS_S_COMPLETE); diff --git a/lib/gssapi/ntlm/delete_sec_context.c b/lib/gssapi/ntlm/delete_sec_context.c index 7b8b3c5d3..562359493 100644 --- a/lib/gssapi/ntlm/delete_sec_context.c +++ b/lib/gssapi/ntlm/delete_sec_context.c @@ -43,17 +43,14 @@ OM_uint32 _gss_ntlm_delete_sec_context { if (context_handle) { ntlm_ctx ctx = (ntlm_ctx)*context_handle; + gss_cred_id_t cred = (gss_cred_id_t)ctx->client; + *context_handle = GSS_C_NO_CONTEXT; if (ctx->server) (*ctx->server->nsi_destroy)(minor_status, ctx->ictx); - 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); - } + _gss_ntlm_release_cred(NULL, &cred); memset(ctx, 0, sizeof(*ctx)); free(ctx); diff --git a/lib/gssapi/ntlm/digest.c b/lib/gssapi/ntlm/digest.c index d5aeca774..81fc26854 100644 --- a/lib/gssapi/ntlm/digest.c +++ b/lib/gssapi/ntlm/digest.c @@ -45,6 +45,7 @@ struct ntlmkrb5 { krb5_realm kerberos_realm; krb5_ccache id; krb5_data opaque; + int destroy; OM_uint32 flags; struct ntlm_buf key; krb5_data sessionkey; @@ -58,11 +59,11 @@ static OM_uint32 kdc_destroy(OM_uint32 *, void *); */ static krb5_error_code -get_ccache(krb5_context context, krb5_ccache *id) +get_ccache(krb5_context context, int *destroy, krb5_ccache *id) { krb5_principal principal = NULL; krb5_error_code ret; - krb5_keytab kt; + krb5_keytab kt = NULL; *id = NULL; @@ -85,7 +86,7 @@ get_ccache(krb5_context context, krb5_ccache *id) ret = krb5_cc_cache_match(context, principal, NULL, id); if (ret == 0) - goto out; + return 0; /* did not find in default credcache, lets try default keytab */ ret = krb5_kt_default(context, &kt); @@ -93,27 +94,55 @@ get_ccache(krb5_context context, krb5_ccache *id) goto out; /* XXX check in keytab */ -#if 0 { - krb5_creds cred = NULL; + krb5_get_init_creds_opt *opt; + krb5_creds cred; + memset(&cred, 0, sizeof(cred)); + + ret = krb5_cc_new_unique(context, "MEMORY", NULL, id); + if (ret) + goto out; + *destroy = 1; + ret = krb5_get_init_creds_opt_alloc(context, &opt); + if (ret) + goto out; ret = krb5_get_init_creds_keytab (context, &cred, principal, kt, + 0, NULL, - NULL, - NULL); + opt); + krb5_get_init_creds_opt_free(context, opt); if (ret) goto out; - ret = krb5_cc_initialize (context, ccache, cred.client); - ret = krb5_cc_store_cred (context, ccache, &cred); + ret = krb5_cc_initialize (context, *id, cred.client); + if (ret) { + krb5_free_cred_contents (context, &cred); + goto out; + } + ret = krb5_cc_store_cred (context, *id, &cred); krb5_free_cred_contents (context, &cred); + if (ret) + goto out; } -#endif + krb5_kt_close(context, kt); + return 0; + out: + if (*destroy) + krb5_cc_destroy(context, *id); + else + krb5_cc_close(context, *id); + + *id = NULL; + + if (kt) + krb5_kt_close(context, kt); + if (principal) krb5_free_principal(context, principal); return ret; @@ -143,7 +172,7 @@ kdc_alloc(OM_uint32 *minor, void **ctx) return GSS_S_FAILURE; } - ret = get_ccache(c->context, &c->id); + ret = get_ccache(c->context, &c->destroy, &c->id); if (ret) { kdc_destroy(&junk, c); *minor = ret; @@ -162,6 +191,23 @@ kdc_alloc(OM_uint32 *minor, void **ctx) return GSS_S_COMPLETE; } +static int +kdc_probe(OM_uint32 *minor, void *ctx, const char *realm) +{ + struct ntlmkrb5 *c = ctx; + krb5_error_code ret; + unsigned flags; + + ret = krb5_digest_probe(c->context, realm, c->id, &flags); + if (ret) + return ret; + + if ((flags & (1|2|4)) == 0) + return EINVAL; + + return 0; +} + /* * */ @@ -174,8 +220,12 @@ kdc_destroy(OM_uint32 *minor, void *ctx) krb5_data_free(&c->sessionkey); if (c->ntlm) krb5_ntlm_free(c->context, c->ntlm); - if (c->id) - krb5_cc_close(c->context, c->id); + if (c->id) { + if (c->destroy) + krb5_cc_destroy(c->context, c->id); + else + krb5_cc_close(c->context, c->id); + } if (c->context) krb5_free_context(c->context); memset(c, 0, sizeof(*c)); @@ -378,6 +428,7 @@ kdc_free_buffer(struct ntlm_buf *sessionkey) struct ntlm_server_interface ntlmsspi_kdc_digest = { kdc_alloc, kdc_destroy, + kdc_probe, 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 be3a3e5fd..5879ff00e 100644 --- a/lib/gssapi/ntlm/init_sec_context.c +++ b/lib/gssapi/ntlm/init_sec_context.c @@ -166,15 +166,27 @@ out: } int -_gss_ntlm_get_user_info(const char *domain, - char **username, - struct ntlm_buf *key) +_gss_ntlm_get_user_cred(const char *domain, + ntlm_cred *rcred) { + ntlm_cred cred; int ret; - - ret = get_user_file(domain, username, key); + + cred = calloc(1, sizeof(*cred)); + if (cred == NULL) + return ENOMEM; + + ret = get_user_file(domain, &cred->username, &cred->key); if (ret) - ret = get_user_ccache(domain, username, key); + ret = get_user_ccache(domain, &cred->username, &cred->key); + if (ret) { + free(cred); + return ret; + } + + cred->domain = strdup(domain); + *rcred = cred; + return ret; } @@ -220,9 +232,7 @@ _gss_ntlm_init_sec_context } *context_handle = (gss_ctx_id_t)ctx; - ret = _gss_ntlm_get_user_info(name->domain, - &ctx->client.username, - &ctx->client.key); + ret = _gss_ntlm_get_user_cred(name->domain, &ctx->client); if (ret) { _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); *minor_status = ret; @@ -285,7 +295,7 @@ _gss_ntlm_init_sec_context memset(&type3, 0, sizeof(type3)); - type3.username = ctx->client.username; + type3.username = ctx->client->username; type3.flags = type2.flags; type3.targetname = type2.targetname; type3.ws = rk_UNCONST("workstation"); @@ -309,12 +319,12 @@ _gss_ntlm_init_sec_context ret = heim_ntlm_calculate_ntlm2_sess(nonce, type2.challange, - ctx->client.key.data, + ctx->client->key.data, &type3.lm, &type3.ntlm); } else { - ret = heim_ntlm_calculate_ntlm1(ctx->client.key.data, - ctx->client.key.length, + ret = heim_ntlm_calculate_ntlm1(ctx->client->key.data, + ctx->client->key.length, type2.challange, &type3.ntlm); @@ -325,8 +335,8 @@ _gss_ntlm_init_sec_context return GSS_S_FAILURE; } - ret = heim_ntlm_build_ntlm1_master(ctx->client.key.data, - ctx->client.key.length, + ret = heim_ntlm_build_ntlm1_master(ctx->client->key.data, + ctx->client->key.length, &sessionkey, &type3.sessionkey); if (ret) { @@ -375,9 +385,9 @@ _gss_ntlm_init_sec_context return GSS_S_FAILURE; } - ret = heim_ntlm_calculate_ntlm2(ctx->client.key.data, - ctx->client.key.length, - ctx->client.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 f903f5765..7f6ba838b 100644 --- a/lib/gssapi/ntlm/ntlm.h +++ b/lib/gssapi/ntlm/ntlm.h @@ -63,20 +63,16 @@ typedef OM_uint32 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 int +(*ntlm_interface_probe)(OM_uint32 *, void *, const char *); typedef OM_uint32 -(*ntlm_interface_type3)(OM_uint32 *minor_status, - void *ctx, - const struct ntlm_type3 *type3, - struct ntlm_buf *sessionkey); +(*ntlm_interface_type2)(OM_uint32 *, void *, uint32_t, const char *, + const char *, uint32_t *, struct ntlm_buf *); + +typedef OM_uint32 +(*ntlm_interface_type3)(OM_uint32 *, void *, const struct ntlm_type3 *, + struct ntlm_buf *); typedef void (*ntlm_interface_free_buffer)(struct ntlm_buf *); @@ -84,6 +80,7 @@ typedef void struct ntlm_server_interface { ntlm_interface_init nsi_init; ntlm_interface_destroy nsi_destroy; + ntlm_interface_probe nsi_probe; ntlm_interface_type2 nsi_type2; ntlm_interface_type3 nsi_type3; ntlm_interface_free_buffer nsi_free_buffer; @@ -99,13 +96,16 @@ struct ntlmv2_key { extern struct ntlm_server_interface ntlmsspi_kdc_digest; +typedef struct ntlm_cred { + char *username; + char *domain; + struct ntlm_buf key; +} *ntlm_cred; + typedef struct { struct ntlm_server_interface *server; void *ictx; - struct { - char *username; - struct ntlm_buf key; - } client; + ntlm_cred client; OM_uint32 gssflags; uint32_t flags; uint32_t status; @@ -127,10 +127,6 @@ typedef struct { } u; } *ntlm_ctx; -typedef struct { - int foo; -} *ntlm_cred; - typedef struct { char domain[1]; } *ntlm_name; diff --git a/lib/gssapi/ntlm/release_cred.c b/lib/gssapi/ntlm/release_cred.c index 6effc4f9b..d95544386 100644 --- a/lib/gssapi/ntlm/release_cred.c +++ b/lib/gssapi/ntlm/release_cred.c @@ -40,10 +40,26 @@ OM_uint32 _gss_ntlm_release_cred gss_cred_id_t * cred_handle ) { + ntlm_cred cred; + if (minor_status) *minor_status = 0; - if (cred_handle) - *cred_handle = GSS_C_NO_CREDENTIAL; + + if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) + return GSS_S_COMPLETE; + + cred = (ntlm_cred)*cred_handle; + *cred_handle = GSS_C_NO_CREDENTIAL; + + if (cred->username) + free(cred->username); + if (cred->domain) + free(cred->domain); + if (cred->key.data) { + memset(cred->key.data, 0, cred->key.length); + free(cred->key.data); + } + return GSS_S_COMPLETE; }