1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

r7827: Add in-memory keytab to Samba4, using the new MEMORY_WILDCARD keytab

support in Heimdal.

This removes the 'ext_keytab' step from my Samba4/WinXP client howto.

In doing this work, I realised that the replay cache in Heimdal is
currently a no-op, so I have removed the calls to it, and therefore
the mutex calls from passdb/secrets.c.

This patch also includes a replacement 'magic' mechanism detection,
that does not issue extra error messages from deep inside the GSSAPI
code.

Andrew Bartlett
(This used to be commit c19d5706f4)
This commit is contained in:
Andrew Bartlett 2005-06-22 02:12:26 +00:00 committed by Gerald (Jerry) Carter
parent cc98a92bb0
commit 8a68f96f8c
13 changed files with 322 additions and 231 deletions

View File

@ -57,6 +57,11 @@ struct gensec_security_ops {
const char **oid; /* NULL if not offered by SPNEGO */
NTSTATUS (*client_start)(struct gensec_security *gensec_security);
NTSTATUS (*server_start)(struct gensec_security *gensec_security);
/**
Determine if a packet has the right 'magic' for this mechanism
*/
NTSTATUS (*magic)(struct gensec_security *gensec_security,
const DATA_BLOB *first_packet);
NTSTATUS (*update)(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx,
const DATA_BLOB in, DATA_BLOB *out);
NTSTATUS (*seal_packet)(struct gensec_security *gensec_security, TALLOC_CTX *sig_mem_ctx,

View File

@ -46,6 +46,7 @@ struct gensec_gssapi_state {
struct smb_krb5_context *smb_krb5_context;
krb5_ccache ccache;
const char *ccache_name;
krb5_keytab keytab;
gss_cred_id_t cred;
};
@ -170,6 +171,7 @@ static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_securi
{
NTSTATUS nt_status;
struct gensec_gssapi_state *gensec_gssapi_state;
struct cli_credentials *machine_account;
nt_status = gensec_gssapi_start(gensec_security);
if (!NT_STATUS_IS_OK(nt_status)) {
@ -178,7 +180,30 @@ static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_securi
gensec_gssapi_state = gensec_security->private_data;
machine_account = cli_credentials_init(gensec_gssapi_state);
cli_credentials_set_conf(machine_account);
nt_status = cli_credentials_set_machine_account(machine_account);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(3, ("Could not obtain machine account credentials from the local database\n"));
talloc_free(machine_account);
return nt_status;
} else {
nt_status = create_memory_keytab(gensec_gssapi_state,
machine_account,
gensec_gssapi_state->smb_krb5_context,
&gensec_gssapi_state->keytab);
talloc_free(machine_account);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(3, ("Could not create memory keytab!\n"));
talloc_free(machine_account);
return nt_status;
}
}
gsskrb5_register_acceptor_keytab(gensec_gssapi_state->keytab);
return NT_STATUS_OK;
}
static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_security)
@ -236,7 +261,6 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi
return nt_status;
}
#ifdef HAVE_GSS_KRB5_CCACHE_NAME /* FIXME, we need an alternate function */
maj_stat = gss_krb5_ccache_name(&min_stat,
gensec_gssapi_state->ccache_name,
NULL);
@ -246,7 +270,6 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi
gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat)));
return NT_STATUS_UNSUCCESSFUL;
}
#endif
maj_stat = gss_acquire_cred(&min_stat,
gensec_gssapi_state->client_name,
@ -266,6 +289,25 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi
}
/**
* Check if the packet is one for this mechansim
*
* @param gensec_security GENSEC state
* @param in The request, as a DATA_BLOB
* @return Error, INVALID_PARAMETER if it's not a packet for us
* or NT_STATUS_OK if the packet is ok.
*/
static NTSTATUS gensec_gssapi_magic(struct gensec_security *gensec_security,
const DATA_BLOB *in)
{
if (gensec_gssapi_check_oid(in, GENSEC_OID_KERBEROS5)) {
return NT_STATUS_OK;
} else {
return NT_STATUS_INVALID_PARAMETER;
}
}
/**
* Next state function for the GSSAPI GENSEC mechanism
@ -294,8 +336,18 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security,
switch (gensec_security->gensec_role) {
case GENSEC_CLIENT:
{
maj_stat = gss_krb5_ccache_name(&min_stat,
gensec_gssapi_state->ccache_name,
NULL);
if (maj_stat) {
DEBUG(1, ("GSS krb5 ccache set %s failed: %s\n",
gensec_gssapi_state->ccache_name,
gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat)));
return NT_STATUS_UNSUCCESSFUL;
}
maj_stat = gss_init_sec_context(&min_stat,
GSS_C_NO_CREDENTIAL,
gensec_gssapi_state->cred,
&gensec_gssapi_state->gssapi_context,
gensec_gssapi_state->server_name,
discard_const_p(gss_OID_desc, gensec_gssapi_state->gss_oid),
@ -756,6 +808,7 @@ static const struct gensec_security_ops gensec_gssapi_krb5_security_ops = {
.oid = gensec_krb5_oids,
.client_start = gensec_gssapi_client_start,
.server_start = gensec_gssapi_server_start,
.magic = gensec_gssapi_magic,
.update = gensec_gssapi_update,
.session_key = gensec_gssapi_session_key,
.session_info = gensec_gssapi_session_info,

View File

@ -399,6 +399,26 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security
}
/**
* Check if the packet is one for this mechansim
*
* @param gensec_security GENSEC state
* @param in The request, as a DATA_BLOB
* @return Error, INVALID_PARAMETER if it's not a packet for us
* or NT_STATUS_OK if the packet is ok.
*/
static NTSTATUS gensec_krb5_magic(struct gensec_security *gensec_security,
const DATA_BLOB *in)
{
if (gensec_gssapi_check_oid(in, GENSEC_OID_KERBEROS5)) {
return NT_STATUS_OK;
} else {
return NT_STATUS_INVALID_PARAMETER;
}
}
/**
* Next state function for the Krb5 GENSEC mechanism
*
@ -494,7 +514,7 @@ static NTSTATUS gensec_krb5_update(struct gensec_security *gensec_security,
/* Parse the GSSAPI wrapping, if it's there... (win2k3 allows it to be omited) */
if (!gensec_gssapi_parse_krb5_wrap(out_mem_ctx, &in, &unwrapped_in, tok_id)) {
nt_status = ads_verify_ticket(out_mem_ctx,
gensec_krb5_state->smb_krb5_context->krb5_context,
gensec_krb5_state->smb_krb5_context,
gensec_krb5_state->auth_context,
lp_realm(),
gensec_get_target_service(gensec_security), &in,
@ -503,7 +523,7 @@ static NTSTATUS gensec_krb5_update(struct gensec_security *gensec_security,
} else {
/* TODO: check the tok_id */
nt_status = ads_verify_ticket(out_mem_ctx,
gensec_krb5_state->smb_krb5_context->krb5_context,
gensec_krb5_state->smb_krb5_context,
gensec_krb5_state->auth_context,
lp_realm(),
gensec_get_target_service(gensec_security),
@ -669,6 +689,7 @@ static const struct gensec_security_ops gensec_krb5_security_ops = {
.oid = gensec_krb5_oids,
.client_start = gensec_krb5_client_start,
.server_start = gensec_krb5_server_start,
.magic = gensec_krb5_magic,
.update = gensec_krb5_update,
.session_key = gensec_krb5_session_key,
.session_info = gensec_krb5_session_info,

View File

@ -269,9 +269,21 @@ static NTSTATUS gensec_spnego_server_try_fallback(struct gensec_security *gensec
continue;
}
if (!all_ops[i]->magic) {
continue;
}
nt_status = all_ops[i]->magic(gensec_security, &in);
if (!NT_STATUS_IS_OK(nt_status)) {
continue;
}
spnego_state->state_position = SPNEGO_FALLBACK;
nt_status = gensec_subcontext_start(spnego_state,
gensec_security,
&spnego_state->sub_sec_security);
if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
}
@ -279,18 +291,11 @@ static NTSTATUS gensec_spnego_server_try_fallback(struct gensec_security *gensec
nt_status = gensec_start_mech_by_ops(spnego_state->sub_sec_security,
all_ops[i]);
if (!NT_STATUS_IS_OK(nt_status)) {
talloc_free(spnego_state->sub_sec_security);
spnego_state->sub_sec_security = NULL;
continue;
return nt_status;
}
nt_status = gensec_update(spnego_state->sub_sec_security,
out_mem_ctx, in, out);
if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
spnego_state->state_position = SPNEGO_FALLBACK;
return nt_status;
}
talloc_free(spnego_state->sub_sec_security);
spnego_state->sub_sec_security = NULL;
return nt_status;
}
DEBUG(1, ("Failed to parse SPNEGO request\n"));
return NT_STATUS_INVALID_PARAMETER;

View File

@ -440,17 +440,6 @@ cleanup_princ:
return retval;
}
#if defined(HAVE_KRB5_PRINCIPAL_GET_COMP_STRING) && !defined(HAVE_KRB5_PRINC_COMPONENT)
const krb5_data *krb5_princ_component(krb5_context context, krb5_principal principal, int i )
{
static krb5_data kdata;
kdata.data = discard_const(krb5_principal_get_comp_string(context, principal, i));
kdata.length = strlen(kdata.data);
return &kdata;
}
#endif
krb5_error_code smb_krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *kt_entry)
{
#if defined(HAVE_KRB5_KT_FREE_ENTRY)

View File

@ -93,3 +93,24 @@ BOOL gensec_gssapi_parse_krb5_wrap(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, D
}
/*
check a GSS-API wrapper packet givin an expected OID
*/
BOOL gensec_gssapi_check_oid(const DATA_BLOB *blob, const char *oid)
{
BOOL ret;
struct asn1_data data;
int data_remaining;
asn1_load(&data, *blob);
asn1_start_tag(&data, ASN1_APPLICATION(0));
asn1_check_OID(&data, GENSEC_OID_KERBEROS5);
ret = !data.has_error;
asn1_free(&data);
return ret;
}

View File

@ -91,7 +91,7 @@ DATA_BLOB get_auth_data_from_tkt(TALLOC_CTX *mem_ctx,
krb5_ticket *tkt);
NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
krb5_context context,
struct smb_krb5_context *smb_krb5_context,
krb5_auth_context auth_context,
const char *realm, const char *service,
const DATA_BLOB *ticket,
@ -116,5 +116,13 @@ NTSTATUS kinit_to_ccache(TALLOC_CTX *parent_ctx,
const char **ccache_name);
krb5_error_code smb_krb5_init_context(TALLOC_CTX *parent_ctx,
struct smb_krb5_context **smb_krb5_context);
krb5_error_code salt_principal_from_credentials(TALLOC_CTX *parent_ctx,
struct cli_credentials *machine_account,
struct smb_krb5_context *smb_krb5_context,
krb5_principal *salt_princ);
NTSTATUS create_memory_keytab(TALLOC_CTX *parent_ctx,
struct cli_credentials *machine_account,
struct smb_krb5_context *smb_krb5_context,
krb5_keytab *keytab);
#endif /* HAVE_KRB5 */

View File

@ -28,10 +28,77 @@
#include "auth/kerberos/kerberos.h"
#include "auth/auth.h"
struct principal_container {
struct smb_krb5_context *smb_krb5_context;
krb5_principal principal;
};
struct ccache_container {
struct smb_krb5_context *smb_krb5_context;
krb5_ccache ccache;
} ccache_container;
};
struct keytab_container {
struct smb_krb5_context *smb_krb5_context;
krb5_keytab keytab;
};
static int free_principal(void *ptr) {
struct principal_container *pc = ptr;
/* current heimdal - 0.6.3, which we need anyway, fixes segfaults here */
krb5_free_principal(pc->smb_krb5_context->krb5_context, pc->principal);
return 0;
}
krb5_error_code salt_principal_from_credentials(TALLOC_CTX *parent_ctx,
struct cli_credentials *machine_account,
struct smb_krb5_context *smb_krb5_context,
krb5_principal *salt_princ)
{
krb5_error_code ret;
char *machine_username;
char *salt_body;
char *lower_realm;
struct principal_container *mem_ctx = talloc(parent_ctx, struct principal_container);
if (!mem_ctx) {
return ENOMEM;
}
machine_username = talloc_strdup(mem_ctx, cli_credentials_get_username(machine_account));
if (!machine_username) {
talloc_free(mem_ctx);
return ENOMEM;
}
if (machine_username[strlen(machine_username)-1] == '$') {
machine_username[strlen(machine_username)-1] = '\0';
}
lower_realm = strlower_talloc(mem_ctx, cli_credentials_get_realm(machine_account));
if (!lower_realm) {
talloc_free(mem_ctx);
return ENOMEM;
}
salt_body = talloc_asprintf(mem_ctx, "%s.%s", machine_username,
lower_realm);
if (!salt_body) {
talloc_free(mem_ctx);
return ENOMEM;
}
ret = krb5_make_principal(smb_krb5_context->krb5_context, salt_princ,
cli_credentials_get_realm(machine_account),
"host", salt_body, NULL);
if (ret != 0) {
mem_ctx->smb_krb5_context = talloc_reference(mem_ctx, smb_krb5_context);
mem_ctx->principal = *salt_princ;
talloc_set_destructor(mem_ctx, free_principal);
}
return ret;
}
static int free_ccache(void *ptr) {
struct ccache_container *ccc = ptr;
@ -71,7 +138,7 @@ static int free_ccache(void *ptr) {
ret = krb5_cc_resolve(smb_krb5_context->krb5_context, ccache_string, ccache);
if (ret) {
DEBUG(1,("failed to generate a new krb5 keytab (%s): %s\n",
DEBUG(1,("failed to generate a new krb5 ccache (%s): %s\n",
ccache_string,
error_message(ret)));
talloc_free(mem_ctx);
@ -114,3 +181,95 @@ static int free_ccache(void *ptr) {
return NT_STATUS_OK;
}
static int free_keytab(void *ptr) {
struct keytab_container *ktc = ptr;
krb5_kt_close(ktc->smb_krb5_context->krb5_context, ktc->keytab);
return 0;
}
NTSTATUS create_memory_keytab(TALLOC_CTX *parent_ctx,
struct cli_credentials *machine_account,
struct smb_krb5_context *smb_krb5_context,
krb5_keytab *keytab)
{
krb5_error_code ret;
const char *password_s;
krb5_data password;
int i;
struct keytab_container *mem_ctx = talloc(parent_ctx, struct keytab_container);
krb5_enctype *enctypes;
krb5_principal salt_princ;
if (!mem_ctx) {
return NT_STATUS_NO_MEMORY;
}
password_s = talloc_strdup(mem_ctx, cli_credentials_get_password(machine_account));
if (!password_s) {
DEBUG(1, ("create_memory_keytab: Could not obtain password for our local machine account!\n"));
talloc_free(mem_ctx);
return NT_STATUS_NO_MEMORY;
}
password.data = password_s;
password.length = strlen(password_s);
/* this string should be unique */
ret = krb5_kt_resolve(smb_krb5_context->krb5_context, "MEMORY_WILDCARD:", keytab);
if (ret) {
DEBUG(1,("failed to generate a new krb5 keytab: %s\n",
error_message(ret)));
talloc_free(mem_ctx);
return NT_STATUS_INTERNAL_ERROR;
}
mem_ctx->smb_krb5_context = talloc_reference(mem_ctx, smb_krb5_context);
mem_ctx->keytab = *keytab;
talloc_set_destructor(mem_ctx, free_keytab);
ret = salt_principal_from_credentials(mem_ctx, machine_account,
smb_krb5_context,
&salt_princ);
if (ret) {
DEBUG(1,("create_memory_keytab: maksing salt principal failed (%s)\n",
error_message(ret)));
return NT_STATUS_INTERNAL_ERROR;
}
ret = get_kerberos_allowed_etypes(smb_krb5_context->krb5_context,
&enctypes);
if (ret) {
DEBUG(1,("create_memory_keytab: getting encrption types failed (%s)\n",
error_message(ret)));
return NT_STATUS_INTERNAL_ERROR;
}
for (i=0; enctypes[i]; i++) {
krb5_keytab_entry entry;
ret = create_kerberos_key_from_string(smb_krb5_context->krb5_context,
salt_princ, &password, &entry.keyblock, enctypes[i]);
if (ret) {
return NT_STATUS_INTERNAL_ERROR;
}
entry.principal = salt_princ;
entry.vno = 0 /* replace with real kvno */;
ret = krb5_kt_add_entry(smb_krb5_context->krb5_context, *keytab, &entry);
if (ret) {
DEBUG(1, ("Failed to add entry for %s to keytab: %s",
cli_credentials_get_principal(machine_account, mem_ctx),
smb_get_krb5_error_message(smb_krb5_context->krb5_context,
ret, mem_ctx)));
return NT_STATUS_INTERNAL_ERROR;
}
krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
}
free_kerberos_etypes(smb_krb5_context->krb5_context, enctypes);
return NT_STATUS_OK;
}

View File

@ -34,9 +34,6 @@
#ifdef HAVE_KRB5
#if !defined(HAVE_KRB5_PRINC_COMPONENT)
const krb5_data *krb5_princ_component(krb5_context, krb5_principal, int );
#endif
static DATA_BLOB unwrap_pac(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data)
{
DATA_BLOB out;
@ -308,7 +305,7 @@ static krb5_error_code ads_secrets_verify_ticket(TALLOC_CTX *mem_ctx,
***********************************************************************************/
NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
krb5_context context,
struct smb_krb5_context *smb_krb5_context,
krb5_auth_context auth_context,
const char *realm, const char *service,
const DATA_BLOB *ticket,
@ -319,15 +316,10 @@ static krb5_error_code ads_secrets_verify_ticket(TALLOC_CTX *mem_ctx,
NTSTATUS sret = NT_STATUS_LOGON_FAILURE;
krb5_data packet;
krb5_ticket *tkt = NULL;
krb5_rcache rcache = NULL;
krb5_principal salt_princ;
int ret;
BOOL got_replay_mutex = False;
char *malloc_principal;
char *machine_username;
krb5_principal salt_princ = NULL;
char *salt_princ_string;
NTSTATUS creds_nt_status;
struct cli_credentials *machine_account;
@ -342,100 +334,45 @@ static krb5_error_code ads_secrets_verify_ticket(TALLOC_CTX *mem_ctx,
if (!NT_STATUS_IS_OK(creds_nt_status)) {
DEBUG(3, ("Could not obtain machine account credentials from the local database\n"));
/* This just becomes a locking key, if we don't have creds, we must be using the keytab */
salt_princ_string = talloc_asprintf(mem_ctx, "host/%s@%s", lp_netbios_name(), lp_realm());
if (!salt_princ_string) {
ret = ENOMEM;
} else {
ret = krb5_parse_name(context, salt_princ_string, &salt_princ);
}
talloc_free(machine_account);
machine_account = NULL;
} else {
machine_username = talloc_strdup(mem_ctx, cli_credentials_get_username(machine_account));
if (!machine_username) {
ret = ENOMEM;
} else {
char *salt_body;
char *lower_realm = strlower_talloc(mem_ctx, cli_credentials_get_realm(machine_account));;
if (machine_username[strlen(machine_username)-1] == '$') {
machine_username[strlen(machine_username)-1] = '\0';
}
if (!lower_realm) {
ret = ENOMEM;
} else {
salt_body = talloc_asprintf(mem_ctx, "%s.%s", machine_username,
lower_realm);
if (!salt_body) {
ret = ENOMEM;
} else {
salt_princ_string = talloc_asprintf(mem_ctx, "host/%s@%s", salt_body, cli_credentials_get_realm(machine_account));
if (!salt_princ_string) {
ret = ENOMEM;
} else {
ret = krb5_parse_name(context, salt_princ_string, &salt_princ);
}
}
}
ret = salt_principal_from_credentials(mem_ctx, machine_account,
smb_krb5_context,
&salt_princ);
if (ret) {
DEBUG(1,("ads_verify_ticket: maksing salt principal failed (%s)\n",
error_message(ret)));
return NT_STATUS_INTERNAL_ERROR;
}
}
if (ret) {
DEBUG(1,("ads_verify_ticket: maksing salt principal failed (%s)\n",
error_message(ret)));
return NT_STATUS_INTERNAL_ERROR;
}
/* This whole process is far more complex than I would
like. We have to go through all this to allow us to store
the secret internally, instead of using /etc/krb5.keytab */
/* Lock a mutex surrounding the replay as there is no locking in the MIT krb5
* code surrounding the replay cache... */
if (!grab_server_mutex("replay cache mutex")) {
DEBUG(1,("ads_verify_ticket: unable to protect replay cache with mutex.\n"));
goto out;
}
got_replay_mutex = True;
/*
* JRA. We must set the rcache here. This will prevent replay attacks.
* TODO: Actually hook in the replay cache in Heimdal, then
* re-add calls to setup a replay cache here, in our private
* directory. This will eventually prevent replay attacks
*/
ret = krb5_get_server_rcache(context, krb5_princ_component(context, salt_princ, 0), &rcache);
if (ret) {
DEBUG(1,("ads_verify_ticket: krb5_get_server_rcache failed (%s)\n", error_message(ret)));
goto out;
}
ret = krb5_auth_con_setrcache(context, auth_context, rcache);
if (ret) {
DEBUG(1,("ads_verify_ticket: krb5_auth_con_setrcache failed (%s)\n", error_message(ret)));
goto out;
}
ret = ads_keytab_verify_ticket(mem_ctx, context, auth_context,
ret = ads_keytab_verify_ticket(mem_ctx, smb_krb5_context->krb5_context, auth_context,
service, ticket, &packet, &tkt, keyblock);
if (ret) {
ret = ads_secrets_verify_ticket(mem_ctx, machine_account, context, auth_context,
if (ret && machine_account) {
ret = ads_secrets_verify_ticket(mem_ctx, machine_account, smb_krb5_context->krb5_context, auth_context,
salt_princ, ticket,
&packet, &tkt, keyblock);
}
release_server_mutex();
got_replay_mutex = False;
if (ret) {
goto out;
}
ret = krb5_mk_rep(context, auth_context, &packet);
ret = krb5_mk_rep(smb_krb5_context->krb5_context, auth_context, &packet);
if (ret) {
DEBUG(3,("ads_verify_ticket: Failed to generate mutual authentication reply (%s)\n",
smb_get_krb5_error_message(context, ret, mem_ctx)));
smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
goto out;
}
@ -459,10 +396,10 @@ static krb5_error_code ads_secrets_verify_ticket(TALLOC_CTX *mem_ctx,
}
#endif
if ((ret = krb5_unparse_name(context, get_principal_from_tkt(tkt),
if ((ret = krb5_unparse_name(smb_krb5_context->krb5_context, get_principal_from_tkt(tkt),
&malloc_principal))) {
DEBUG(3,("ads_verify_ticket: krb5_unparse_name failed (%s)\n",
smb_get_krb5_error_message(context, ret, mem_ctx)));
smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
sret = NT_STATUS_LOGON_FAILURE;
goto out;
}
@ -479,10 +416,6 @@ static krb5_error_code ads_secrets_verify_ticket(TALLOC_CTX *mem_ctx,
out:
if (got_replay_mutex) {
release_server_mutex();
}
if (!NT_STATUS_IS_OK(sret)) {
data_blob_free(auth_data);
}
@ -492,11 +425,7 @@ static krb5_error_code ads_secrets_verify_ticket(TALLOC_CTX *mem_ctx,
}
if (tkt != NULL) {
krb5_free_ticket(context, tkt);
}
if (salt_princ != NULL) {
krb5_free_principal(context, salt_princ);
krb5_free_ticket(smb_krb5_context->krb5_context, tkt);
}
return sret;

View File

@ -89,6 +89,16 @@ void debug_ntlmssp_flags(uint32_t neg_flags)
DEBUGADD(4, (" NTLMSSP_NEGOTIATE_KEY_EXCH\n"));
}
static NTSTATUS gensec_ntlmssp_magic(struct gensec_security *gensec_security,
const DATA_BLOB *first_packet)
{
if (first_packet->length > 8 && memcmp("NTLMSSP\0", first_packet->data, 8) == 0) {
return NT_STATUS_OK;
} else {
return NT_STATUS_INVALID_PARAMETER;
}
}
/**
* Next state function for the wrapped NTLMSSP state machine
*
@ -337,6 +347,7 @@ static const struct gensec_security_ops gensec_ntlmssp_security_ops = {
.oid = gensec_ntlmssp_oids,
.client_start = gensec_ntlmssp_client_start,
.server_start = gensec_ntlmssp_server_start,
.magic = gensec_ntlmssp_magic,
.update = gensec_ntlmssp_update,
.sig_size = gensec_ntlmssp_sig_size,
.sign_packet = gensec_ntlmssp_sign_packet,

View File

@ -73,7 +73,6 @@ ADD_OBJ_FILES = \
lib/ms_fnmatch.o \
lib/select.o \
lib/mutex.o \
lib/server_mutex.o \
lib/idtree.o \
lib/unix_privs.o \
lib/db_wrap.o \

View File

@ -1,58 +0,0 @@
/*
Unix SMB/CIFS implementation.
Authenticate against a remote domain
Copyright (C) Andrew Tridgell 1992-2002
Copyright (C) Andrew Bartlett 2002
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
/* For reasons known only to MS, many of their NT/Win2k versions
need serialised access only. Two connections at the same time
may (in certain situations) cause connections to be reset,
or access to be denied.
This locking allows smbd's mutlithread architecture to look
like the single-connection that NT makes. */
static char *mutex_server_name;
/* FIXME. ref_count should be allocated per name... JRA. */
size_t ref_count;
BOOL grab_server_mutex(const char *name)
{
mutex_server_name = strdup(name);
if (!mutex_server_name) {
DEBUG(0,("grab_server_mutex: malloc failed for %s\n", name));
return False;
}
if (!secrets_named_mutex(mutex_server_name, 10, &ref_count)) {
DEBUG(10,("grab_server_mutex: failed for %s\n", name));
SAFE_FREE(mutex_server_name);
return False;
}
return True;
}
void release_server_mutex(void)
{
if (mutex_server_name) {
secrets_named_mutex_release(mutex_server_name, &ref_count);
SAFE_FREE(mutex_server_name);
}
}

View File

@ -123,57 +123,6 @@ char *secrets_fetch_machine_password(const char *domain)
}
/*******************************************************************************
Lock the secrets tdb based on a string - this is used as a primitive form of mutex
between smbd instances.
*******************************************************************************/
BOOL secrets_named_mutex(const char *name, uint_t timeout, size_t *p_ref_count)
{
size_t ref_count = *p_ref_count;
int ret = 0;
secrets_init();
if (!tdb)
return False;
if (ref_count == 0) {
ret = tdb_lock_bystring(tdb->tdb, name);
if (ret == 0)
DEBUG(10,("secrets_named_mutex: got mutex for %s\n", name ));
}
if (ret == 0) {
*p_ref_count = ++ref_count;
DEBUG(10,("secrets_named_mutex: ref_count for mutex %s = %u\n", name, (uint_t)ref_count ));
}
return (ret == 0);
}
/*******************************************************************************
Unlock a named mutex.
*******************************************************************************/
void secrets_named_mutex_release(const char *name, size_t *p_ref_count)
{
size_t ref_count = *p_ref_count;
SMB_ASSERT(ref_count != 0);
secrets_init();
if (!tdb)
return;
if (ref_count == 1) {
tdb_unlock_bystring(tdb->tdb, name);
DEBUG(10,("secrets_named_mutex: released mutex for %s\n", name ));
}
*p_ref_count = --ref_count;
DEBUG(10,("secrets_named_mutex_release: ref_count for mutex %s = %u\n", name, (uint_t)ref_count ));
}
/*
connect to the schannel ldb
*/