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:
@@ -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)
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user