summaryrefslogtreecommitdiff
path: root/source4/auth/gensec
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/auth/gensec
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/auth/gensec')
-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
4 files changed, 98 insertions, 14 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;