add credential handling, add probe function, add better acquired cred function

git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@22163 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Love Hörnquist Åstrand
2007-12-04 21:25:06 +00:00
parent 280b58bb08
commit 8ca9a4469c
7 changed files with 162 additions and 67 deletions

View File

@@ -43,7 +43,6 @@ OM_uint32
_gss_ntlm_allocate_ctx(OM_uint32 *minor_status, ntlm_ctx *ctx) _gss_ntlm_allocate_ctx(OM_uint32 *minor_status, ntlm_ctx *ctx)
{ {
OM_uint32 maj_stat; OM_uint32 maj_stat;
/* krb5_error_code ret; */
*ctx = calloc(1, sizeof(**ctx)); *ctx = calloc(1, sizeof(**ctx));
@@ -123,11 +122,20 @@ _gss_ntlm_accept_sec_context
} }
if ((type1.flags & NTLM_NEG_UNICODE) == 0) { if ((type1.flags & NTLM_NEG_UNICODE) == 0) {
heim_ntlm_free_type1(&type1);
_gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL);
*minor_status = EINVAL; *minor_status = EINVAL;
return GSS_S_FAILURE; 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) if (type1.flags & NTLM_NEG_SIGN)
ctx->gssflags |= GSS_C_CONF_FLAG; ctx->gssflags |= GSS_C_CONF_FLAG;
if (type1.flags & NTLM_NEG_SIGN) if (type1.flags & NTLM_NEG_SIGN)

View File

@@ -46,6 +46,7 @@ OM_uint32 _gss_ntlm_acquire_cred
OM_uint32 * time_rec OM_uint32 * time_rec
) )
{ {
ntlm_name name = (ntlm_name) desired_name;
OM_uint32 maj_stat; OM_uint32 maj_stat;
ntlm_ctx ctx; ntlm_ctx ctx;
@@ -57,14 +58,30 @@ OM_uint32 _gss_ntlm_acquire_cred
if (time_rec) if (time_rec)
*time_rec = GSS_C_INDEFINITE; *time_rec = GSS_C_INDEFINITE;
maj_stat = _gss_ntlm_allocate_ctx(min_stat, &ctx); if (desired_name == NULL)
if (maj_stat != GSS_S_COMPLETE) return GSS_S_NO_CRED;
return maj_stat;
{ if (cred_usage == GSS_C_BOTH || cred_usage == GSS_C_ACCEPT) {
gss_ctx_id_t context = (gss_ctx_id_t)ctx;
_gss_ntlm_delete_sec_context(min_stat, &context, NULL); maj_stat = _gss_ntlm_allocate_ctx(min_stat, &ctx);
*min_stat = 0; 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); return (GSS_S_COMPLETE);

View File

@@ -43,17 +43,14 @@ OM_uint32 _gss_ntlm_delete_sec_context
{ {
if (context_handle) { if (context_handle) {
ntlm_ctx ctx = (ntlm_ctx)*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; *context_handle = GSS_C_NO_CONTEXT;
if (ctx->server) if (ctx->server)
(*ctx->server->nsi_destroy)(minor_status, ctx->ictx); (*ctx->server->nsi_destroy)(minor_status, ctx->ictx);
if (ctx->client.username) _gss_ntlm_release_cred(NULL, &cred);
free(ctx->client.username);
if (ctx->client.key.data) {
memset(ctx->client.key.data, 0, ctx->client.key.length);
free(ctx->client.key.data);
}
memset(ctx, 0, sizeof(*ctx)); memset(ctx, 0, sizeof(*ctx));
free(ctx); free(ctx);

View File

@@ -45,6 +45,7 @@ struct ntlmkrb5 {
krb5_realm kerberos_realm; krb5_realm kerberos_realm;
krb5_ccache id; krb5_ccache id;
krb5_data opaque; krb5_data opaque;
int destroy;
OM_uint32 flags; OM_uint32 flags;
struct ntlm_buf key; struct ntlm_buf key;
krb5_data sessionkey; krb5_data sessionkey;
@@ -58,11 +59,11 @@ static OM_uint32 kdc_destroy(OM_uint32 *, void *);
*/ */
static krb5_error_code 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_principal principal = NULL;
krb5_error_code ret; krb5_error_code ret;
krb5_keytab kt; krb5_keytab kt = NULL;
*id = NULL; *id = NULL;
@@ -85,7 +86,7 @@ get_ccache(krb5_context context, krb5_ccache *id)
ret = krb5_cc_cache_match(context, principal, NULL, id); ret = krb5_cc_cache_match(context, principal, NULL, id);
if (ret == 0) if (ret == 0)
goto out; return 0;
/* did not find in default credcache, lets try default keytab */ /* did not find in default credcache, lets try default keytab */
ret = krb5_kt_default(context, &kt); ret = krb5_kt_default(context, &kt);
@@ -93,27 +94,55 @@ get_ccache(krb5_context context, krb5_ccache *id)
goto out; goto out;
/* XXX check in keytab */ /* 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, ret = krb5_get_init_creds_keytab (context,
&cred, &cred,
principal, principal,
kt, kt,
0,
NULL, NULL,
NULL, opt);
NULL); krb5_get_init_creds_opt_free(context, opt);
if (ret) if (ret)
goto out; goto out;
ret = krb5_cc_initialize (context, ccache, cred.client); ret = krb5_cc_initialize (context, *id, cred.client);
ret = krb5_cc_store_cred (context, ccache, &cred); if (ret) {
krb5_free_cred_contents (context, &cred);
goto out;
}
ret = krb5_cc_store_cred (context, *id, &cred);
krb5_free_cred_contents (context, &cred); krb5_free_cred_contents (context, &cred);
if (ret)
goto out;
} }
#endif
krb5_kt_close(context, kt); krb5_kt_close(context, kt);
return 0;
out: 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) if (principal)
krb5_free_principal(context, principal); krb5_free_principal(context, principal);
return ret; return ret;
@@ -143,7 +172,7 @@ kdc_alloc(OM_uint32 *minor, void **ctx)
return GSS_S_FAILURE; return GSS_S_FAILURE;
} }
ret = get_ccache(c->context, &c->id); ret = get_ccache(c->context, &c->destroy, &c->id);
if (ret) { if (ret) {
kdc_destroy(&junk, c); kdc_destroy(&junk, c);
*minor = ret; *minor = ret;
@@ -162,6 +191,23 @@ kdc_alloc(OM_uint32 *minor, void **ctx)
return GSS_S_COMPLETE; 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); krb5_data_free(&c->sessionkey);
if (c->ntlm) if (c->ntlm)
krb5_ntlm_free(c->context, c->ntlm); krb5_ntlm_free(c->context, c->ntlm);
if (c->id) if (c->id) {
krb5_cc_close(c->context, c->id); if (c->destroy)
krb5_cc_destroy(c->context, c->id);
else
krb5_cc_close(c->context, c->id);
}
if (c->context) if (c->context)
krb5_free_context(c->context); krb5_free_context(c->context);
memset(c, 0, sizeof(*c)); memset(c, 0, sizeof(*c));
@@ -378,6 +428,7 @@ kdc_free_buffer(struct ntlm_buf *sessionkey)
struct ntlm_server_interface ntlmsspi_kdc_digest = { struct ntlm_server_interface ntlmsspi_kdc_digest = {
kdc_alloc, kdc_alloc,
kdc_destroy, kdc_destroy,
kdc_probe,
kdc_type2, kdc_type2,
kdc_type3, kdc_type3,
kdc_free_buffer kdc_free_buffer

View File

@@ -166,15 +166,27 @@ out:
} }
int int
_gss_ntlm_get_user_info(const char *domain, _gss_ntlm_get_user_cred(const char *domain,
char **username, ntlm_cred *rcred)
struct ntlm_buf *key)
{ {
ntlm_cred cred;
int ret; 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) 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; return ret;
} }
@@ -220,9 +232,7 @@ _gss_ntlm_init_sec_context
} }
*context_handle = (gss_ctx_id_t)ctx; *context_handle = (gss_ctx_id_t)ctx;
ret = _gss_ntlm_get_user_info(name->domain, ret = _gss_ntlm_get_user_cred(name->domain, &ctx->client);
&ctx->client.username,
&ctx->client.key);
if (ret) { 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; *minor_status = ret;
@@ -285,7 +295,7 @@ _gss_ntlm_init_sec_context
memset(&type3, 0, sizeof(type3)); memset(&type3, 0, sizeof(type3));
type3.username = ctx->client.username; type3.username = ctx->client->username;
type3.flags = type2.flags; type3.flags = type2.flags;
type3.targetname = type2.targetname; type3.targetname = type2.targetname;
type3.ws = rk_UNCONST("workstation"); type3.ws = rk_UNCONST("workstation");
@@ -309,12 +319,12 @@ _gss_ntlm_init_sec_context
ret = heim_ntlm_calculate_ntlm2_sess(nonce, ret = heim_ntlm_calculate_ntlm2_sess(nonce,
type2.challange, type2.challange,
ctx->client.key.data, ctx->client->key.data,
&type3.lm, &type3.lm,
&type3.ntlm); &type3.ntlm);
} else { } else {
ret = heim_ntlm_calculate_ntlm1(ctx->client.key.data, ret = heim_ntlm_calculate_ntlm1(ctx->client->key.data,
ctx->client.key.length, ctx->client->key.length,
type2.challange, type2.challange,
&type3.ntlm); &type3.ntlm);
@@ -325,8 +335,8 @@ _gss_ntlm_init_sec_context
return GSS_S_FAILURE; return GSS_S_FAILURE;
} }
ret = heim_ntlm_build_ntlm1_master(ctx->client.key.data, ret = heim_ntlm_build_ntlm1_master(ctx->client->key.data,
ctx->client.key.length, ctx->client->key.length,
&sessionkey, &sessionkey,
&type3.sessionkey); &type3.sessionkey);
if (ret) { if (ret) {
@@ -375,9 +385,9 @@ _gss_ntlm_init_sec_context
return GSS_S_FAILURE; return GSS_S_FAILURE;
} }
ret = heim_ntlm_calculate_ntlm2(ctx->client.key.data, ret = heim_ntlm_calculate_ntlm2(ctx->client->key.data,
ctx->client.key.length, ctx->client->key.length,
ctx->client.username, ctx->client->username,
name->domain, name->domain,
type2.challange, type2.challange,
&type2.targetinfo, &type2.targetinfo,

View File

@@ -63,20 +63,16 @@ typedef OM_uint32
typedef OM_uint32 typedef OM_uint32
(*ntlm_interface_destroy)(OM_uint32 *, void *); (*ntlm_interface_destroy)(OM_uint32 *, void *);
typedef OM_uint32 typedef int
(*ntlm_interface_type2)(OM_uint32 *minor_status, (*ntlm_interface_probe)(OM_uint32 *, void *, const char *);
void *ctx,
uint32_t flags,
const char *hostname,
const char *domain,
uint32_t *ret_flags,
struct ntlm_buf *type2);
typedef OM_uint32 typedef OM_uint32
(*ntlm_interface_type3)(OM_uint32 *minor_status, (*ntlm_interface_type2)(OM_uint32 *, void *, uint32_t, const char *,
void *ctx, const char *, uint32_t *, struct ntlm_buf *);
const struct ntlm_type3 *type3,
struct ntlm_buf *sessionkey); typedef OM_uint32
(*ntlm_interface_type3)(OM_uint32 *, void *, const struct ntlm_type3 *,
struct ntlm_buf *);
typedef void typedef void
(*ntlm_interface_free_buffer)(struct ntlm_buf *); (*ntlm_interface_free_buffer)(struct ntlm_buf *);
@@ -84,6 +80,7 @@ typedef void
struct ntlm_server_interface { struct ntlm_server_interface {
ntlm_interface_init nsi_init; ntlm_interface_init nsi_init;
ntlm_interface_destroy nsi_destroy; ntlm_interface_destroy nsi_destroy;
ntlm_interface_probe nsi_probe;
ntlm_interface_type2 nsi_type2; ntlm_interface_type2 nsi_type2;
ntlm_interface_type3 nsi_type3; ntlm_interface_type3 nsi_type3;
ntlm_interface_free_buffer nsi_free_buffer; ntlm_interface_free_buffer nsi_free_buffer;
@@ -99,13 +96,16 @@ struct ntlmv2_key {
extern struct ntlm_server_interface ntlmsspi_kdc_digest; extern struct ntlm_server_interface ntlmsspi_kdc_digest;
typedef struct ntlm_cred {
char *username;
char *domain;
struct ntlm_buf key;
} *ntlm_cred;
typedef struct { typedef struct {
struct ntlm_server_interface *server; struct ntlm_server_interface *server;
void *ictx; void *ictx;
struct { ntlm_cred client;
char *username;
struct ntlm_buf key;
} client;
OM_uint32 gssflags; OM_uint32 gssflags;
uint32_t flags; uint32_t flags;
uint32_t status; uint32_t status;
@@ -127,10 +127,6 @@ typedef struct {
} u; } u;
} *ntlm_ctx; } *ntlm_ctx;
typedef struct {
int foo;
} *ntlm_cred;
typedef struct { typedef struct {
char domain[1]; char domain[1];
} *ntlm_name; } *ntlm_name;

View File

@@ -40,10 +40,26 @@ OM_uint32 _gss_ntlm_release_cred
gss_cred_id_t * cred_handle gss_cred_id_t * cred_handle
) )
{ {
ntlm_cred cred;
if (minor_status) if (minor_status)
*minor_status = 0; *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; return GSS_S_COMPLETE;
} }