summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2005-06-22 02:12:26 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:18:41 -0500
commit8a68f96f8cea2c53c8babf2ec826dfc6ef1cc199 (patch)
treeae8dc487623d695ce74f7d7f639f23823908031b /source4
parentcc98a92bb0396845ec1dcb75ac412df9db9652d9 (diff)
downloadsamba-8a68f96f8cea2c53c8babf2ec826dfc6ef1cc199.tar.gz
samba-8a68f96f8cea2c53c8babf2ec826dfc6ef1cc199.tar.bz2
samba-8a68f96f8cea2c53c8babf2ec826dfc6ef1cc199.zip
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 c19d5706f4fa760415b727b970bc99e7f1abd064)
Diffstat (limited to 'source4')
-rw-r--r--source4/auth/gensec/gensec.h5
-rw-r--r--source4/auth/gensec/gensec_gssapi.c59
-rw-r--r--source4/auth/gensec/gensec_krb5.c25
-rw-r--r--source4/auth/gensec/spnego.c23
-rw-r--r--source4/auth/kerberos/clikrb5.c11
-rw-r--r--source4/auth/kerberos/gssapi_parse.c21
-rw-r--r--source4/auth/kerberos/kerberos.h10
-rw-r--r--source4/auth/kerberos/kerberos_util.c163
-rw-r--r--source4/auth/kerberos/kerberos_verify.c115
-rw-r--r--source4/auth/ntlmssp/ntlmssp.c11
-rw-r--r--source4/lib/basic.mk1
-rw-r--r--source4/lib/server_mutex.c58
-rw-r--r--source4/passdb/secrets.c51
13 files changed, 322 insertions, 231 deletions
diff --git a/source4/auth/gensec/gensec.h b/source4/auth/gensec/gensec.h
index 2951e13dd9..20f0b1c642 100644
--- a/source4/auth/gensec/gensec.h
+++ b/source4/auth/gensec/gensec.h
@@ -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,
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c
index c6a16cdf33..1542441e27 100644
--- a/source4/auth/gensec/gensec_gssapi.c
+++ b/source4/auth/gensec/gensec_gssapi.c
@@ -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,
diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c
index d633794e1c..348a75b535 100644
--- a/source4/auth/gensec/gensec_krb5.c
+++ b/source4/auth/gensec/gensec_krb5.c
@@ -400,6 +400,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
*
* @param gensec_krb5_state KRB5 State
@@ -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,
diff --git a/source4/auth/gensec/spnego.c b/source4/auth/gensec/spnego.c
index f5d1dd2238..e3d335b71b 100644
--- a/source4/auth/gensec/spnego.c
+++ b/source4/auth/gensec/spnego.c
@@ -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;
diff --git a/source4/auth/kerberos/clikrb5.c b/source4/auth/kerberos/clikrb5.c
index ed075f9633..0fede8b2cd 100644
--- a/source4/auth/kerberos/clikrb5.c
+++ b/source4/auth/kerberos/clikrb5.c
@@ -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)
diff --git a/source4/auth/kerberos/gssapi_parse.c b/source4/auth/kerberos/gssapi_parse.c
index 2c2c4e17e5..048eb8204e 100644
--- a/source4/auth/kerberos/gssapi_parse.c
+++ b/source4/auth/kerberos/gssapi_parse.c
@@ -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;
+}
+
+
diff --git a/source4/auth/kerberos/kerberos.h b/source4/auth/kerberos/kerberos.h
index a3aff73c87..0f8fd28155 100644
--- a/source4/auth/kerberos/kerberos.h
+++ b/source4/auth/kerberos/kerberos.h
@@ -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 */
diff --git a/source4/auth/kerberos/kerberos_util.c b/source4/auth/kerberos/kerberos_util.c
index 7945094be9..9f93ffe7b0 100644
--- a/source4/auth/kerberos/kerberos_util.c
+++ b/source4/auth/kerberos/kerberos_util.c
@@ -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;
+}
diff --git a/source4/auth/kerberos/kerberos_verify.c b/source4/auth/kerberos/kerberos_verify.c
index f85819aa36..f269012ae3 100644
--- a/source4/auth/kerberos/kerberos_verify.c
+++ b/source4/auth/kerberos/kerberos_verify.c
@@ -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;
diff --git a/source4/auth/ntlmssp/ntlmssp.c b/source4/auth/ntlmssp/ntlmssp.c
index 26e9d66e6f..1fd7ac6756 100644
--- a/source4/auth/ntlmssp/ntlmssp.c
+++ b/source4/auth/ntlmssp/ntlmssp.c
@@ -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,
diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk
index 6a463b8ec6..58cbca0198 100644
--- a/source4/lib/basic.mk
+++ b/source4/lib/basic.mk
@@ -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 \
diff --git a/source4/lib/server_mutex.c b/source4/lib/server_mutex.c
deleted file mode 100644
index 878e5497d8..0000000000
--- a/source4/lib/server_mutex.c
+++ /dev/null
@@ -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);
- }
-}
diff --git a/source4/passdb/secrets.c b/source4/passdb/secrets.c
index 81e92b4da0..44f9fe9311 100644
--- a/source4/passdb/secrets.c
+++ b/source4/passdb/secrets.c
@@ -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
*/