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