summaryrefslogtreecommitdiff
path: root/source4/auth
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2005-11-02 00:31:22 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:45:38 -0500
commit3b2a6997b43dcfe37adf67c84e564a4fbff5b108 (patch)
treeb346357dacf58cc803e5fa5919199a1791eb20ea /source4/auth
parentf8ebd5a53ce115b9d9dc6e87e0dbe4cdd6f9b79d (diff)
downloadsamba-3b2a6997b43dcfe37adf67c84e564a4fbff5b108.tar.gz
samba-3b2a6997b43dcfe37adf67c84e564a4fbff5b108.tar.bz2
samba-3b2a6997b43dcfe37adf67c84e564a4fbff5b108.zip
r11452: Update Heimdal to current lorikeet, including removing the ccache side
of the gsskrb5_acquire_cred hack. Add support for delegated credentials into the auth and credentials subsystem, and specifically into gensec_gssapi. Add the CIFS NTVFS handler as a consumer of delegated credentials, when no user/domain/password is specified. Andrew Bartlett (This used to be commit 55b89899adb692d90e63873ccdf80b9f94a6b448)
Diffstat (limited to 'source4/auth')
-rw-r--r--source4/auth/auth.h1
-rw-r--r--source4/auth/auth_util.c2
-rw-r--r--source4/auth/credentials/credentials.c1
-rw-r--r--source4/auth/credentials/credentials.h2
-rw-r--r--source4/auth/credentials/credentials_krb5.c113
-rw-r--r--source4/auth/gensec/gensec_gssapi.c101
-rw-r--r--source4/auth/kerberos/kerberos.h10
7 files changed, 178 insertions, 52 deletions
diff --git a/source4/auth/auth.h b/source4/auth/auth.h
index 9f2e0b6a07..58f72aa8af 100644
--- a/source4/auth/auth.h
+++ b/source4/auth/auth.h
@@ -118,6 +118,7 @@ struct auth_session_info {
struct security_token *security_token;
struct auth_serversupplied_info *server_info;
DATA_BLOB session_key;
+ struct cli_credentials *credentials;
};
struct auth_method_context;
diff --git a/source4/auth/auth_util.c b/source4/auth/auth_util.c
index 753f680fb1..df4e510c2f 100644
--- a/source4/auth/auth_util.c
+++ b/source4/auth/auth_util.c
@@ -526,6 +526,8 @@ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx,
&session_info->security_token);
NT_STATUS_NOT_OK_RETURN(nt_status);
+ session_info->credentials = NULL;
+
*_session_info = session_info;
return NT_STATUS_OK;
}
diff --git a/source4/auth/credentials/credentials.c b/source4/auth/credentials/credentials.c
index 5d2c5c553e..86a3df0077 100644
--- a/source4/auth/credentials/credentials.c
+++ b/source4/auth/credentials/credentials.c
@@ -46,6 +46,7 @@ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx)
cred->domain_obtained = CRED_UNINITIALISED;
cred->realm_obtained = CRED_UNINITIALISED;
cred->ccache_obtained = CRED_UNINITIALISED;
+ cred->gss_creds_obtained = CRED_UNINITIALISED;
cred->keytab_obtained = CRED_UNINITIALISED;
cred->principal_obtained = CRED_UNINITIALISED;
diff --git a/source4/auth/credentials/credentials.h b/source4/auth/credentials/credentials.h
index b85337bd18..3e84db52a5 100644
--- a/source4/auth/credentials/credentials.h
+++ b/source4/auth/credentials/credentials.h
@@ -47,6 +47,7 @@ struct cli_credentials {
enum credentials_obtained domain_obtained;
enum credentials_obtained realm_obtained;
enum credentials_obtained ccache_obtained;
+ enum credentials_obtained gss_creds_obtained;
enum credentials_obtained principal_obtained;
enum credentials_obtained keytab_obtained;
@@ -62,6 +63,7 @@ struct cli_credentials {
struct samr_Password *nt_hash;
struct ccache_container *ccache;
+ struct gssapi_creds_container *gssapi_creds;
struct keytab_container *keytab;
const char *(*workstation_cb) (struct cli_credentials *);
diff --git a/source4/auth/credentials/credentials_krb5.c b/source4/auth/credentials/credentials_krb5.c
index abb8418748..a3761e8359 100644
--- a/source4/auth/credentials/credentials_krb5.c
+++ b/source4/auth/credentials/credentials_krb5.c
@@ -85,7 +85,7 @@ int cli_credentials_set_from_ccache(struct cli_credentials *cred,
return 0;
}
-
+/* Free a memory ccache */
static int free_mccache(void *ptr) {
struct ccache_container *ccc = ptr;
krb5_cc_destroy(ccc->smb_krb5_context->krb5_context, ccc->ccache);
@@ -93,6 +93,7 @@ static int free_mccache(void *ptr) {
return 0;
}
+/* Free a disk-based ccache */
static int free_dccache(void *ptr) {
struct ccache_container *ccc = ptr;
krb5_cc_close(ccc->smb_krb5_context->krb5_context, ccc->ccache);
@@ -163,7 +164,7 @@ int cli_credentials_set_ccache(struct cli_credentials *cred,
}
-int cli_credentials_new_ccache(struct cli_credentials *cred)
+int cli_credentials_new_ccache(struct cli_credentials *cred, struct ccache_container **_ccc)
{
krb5_error_code ret;
char *rand_string;
@@ -211,6 +212,10 @@ int cli_credentials_new_ccache(struct cli_credentials *cred)
talloc_steal(cred, ccc);
talloc_free(ccache_name);
+ if (_ccc) {
+ *_ccc = ccc;
+ }
+
return ret;
}
@@ -228,7 +233,7 @@ int cli_credentials_get_ccache(struct cli_credentials *cred,
return EINVAL;
}
- ret = cli_credentials_new_ccache(cred);
+ ret = cli_credentials_new_ccache(cred, NULL);
if (ret) {
return ret;
}
@@ -245,6 +250,108 @@ int cli_credentials_get_ccache(struct cli_credentials *cred,
return ret;
}
+static int free_gssapi_creds(void *ptr) {
+ OM_uint32 min_stat, maj_stat;
+ struct gssapi_creds_container *gcc = ptr;
+ maj_stat = gss_release_cred(&min_stat,
+ &gcc->creds);
+ return 0;
+}
+
+int cli_credentials_get_client_gss_creds(struct cli_credentials *cred,
+ struct gssapi_creds_container **_gcc)
+{
+ int ret = 0;
+ OM_uint32 maj_stat, min_stat;
+ struct gssapi_creds_container *gcc;
+ struct ccache_container *ccache;
+ if (cred->gss_creds_obtained >= (MAX(cred->ccache_obtained,
+ MAX(cred->principal_obtained,
+ cred->username_obtained)))) {
+ *_gcc = cred->gssapi_creds;
+ return 0;
+ }
+ ret = cli_credentials_get_ccache(cred,
+ &ccache);
+ if (ret) {
+ DEBUG(1, ("Failed to get CCACHE for GSSAPI client: %s\n", error_message(ret)));
+ return ret;
+ }
+
+ gcc = talloc(cred, struct gssapi_creds_container);
+ if (!gcc) {
+ return ENOMEM;
+ }
+
+ maj_stat = gss_krb5_import_ccache(&min_stat, ccache->ccache,
+ &gcc->creds);
+ if (maj_stat) {
+ if (min_stat) {
+ ret = min_stat;
+ } else {
+ ret = EINVAL;
+ }
+ }
+ if (ret == 0) {
+ cred->gss_creds_obtained = cred->ccache_obtained;
+ talloc_set_destructor(gcc, free_gssapi_creds);
+ cred->gssapi_creds = gcc;
+ *_gcc = gcc;
+ }
+ return ret;
+}
+
+/**
+ Set a gssapi cred_id_t into the credentails system.
+
+ This grabs the credentials both 'intact' and getting the krb5
+ ccache out of it. This routine can be generalised in future for
+ the case where we deal with GSSAPI mechs other than krb5.
+
+ On sucess, the caller must not free gssapi_cred, as it now belongs
+ to the credentials system.
+*/
+
+ int cli_credentials_set_client_gss_creds(struct cli_credentials *cred,
+ gss_cred_id_t gssapi_cred,
+ enum credentials_obtained obtained)
+{
+ int ret;
+ OM_uint32 maj_stat, min_stat;
+ struct ccache_container *ccc;
+ struct gssapi_creds_container *gcc = talloc(cred, struct gssapi_creds_container);
+ if (!gcc) {
+ return ENOMEM;
+ }
+
+ ret = cli_credentials_new_ccache(cred, &ccc);
+ if (ret != 0) {
+ return ret;
+ }
+
+ maj_stat = gss_krb5_copy_ccache(&min_stat,
+ gssapi_cred, ccc->ccache);
+ if (maj_stat) {
+ if (min_stat) {
+ ret = min_stat;
+ } else {
+ ret = EINVAL;
+ }
+ }
+
+ if (ret == 0) {
+ ret = cli_credentials_set_from_ccache(cred, obtained);
+ }
+ if (ret == 0) {
+ gcc->creds = gssapi_cred;
+ talloc_set_destructor(gcc, free_gssapi_creds);
+
+ cred->gss_creds_obtained = obtained;
+ cred->gssapi_creds = gcc;
+ }
+ return ret;
+}
+
int cli_credentials_get_keytab(struct cli_credentials *cred,
struct keytab_container **_ktc)
{
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c
index d59d19c636..4608b62db5 100644
--- a/source4/auth/gensec/gensec_gssapi.c
+++ b/source4/auth/gensec/gensec_gssapi.c
@@ -44,8 +44,10 @@ struct gensec_gssapi_state {
krb5_ccache ccache;
const char *ccache_name;
struct keytab_container *keytab;
+ struct gssapi_creds_container *client_cred;
gss_cred_id_t cred;
+ gss_cred_id_t delegated_cred_handle;
};
static char *gssapi_error_string(TALLOC_CTX *mem_ctx,
@@ -83,6 +85,10 @@ static int gensec_gssapi_destory(void *ptr)
maj_stat = gss_release_cred(&min_stat,
&gensec_gssapi_state->cred);
}
+ if (gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
+ maj_stat = gss_release_cred(&min_stat,
+ &gensec_gssapi_state->delegated_cred_handle);
+ }
if (gensec_gssapi_state->gssapi_context != GSS_C_NO_CONTEXT) {
maj_stat = gss_delete_sec_context (&min_stat,
@@ -118,13 +124,14 @@ static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security)
/* TODO: Fill in channel bindings */
gensec_gssapi_state->input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS;
- gensec_gssapi_state->want_flags = GSS_C_MUTUAL_FLAG;
+ gensec_gssapi_state->want_flags = GSS_C_MUTUAL_FLAG | GSS_C_DELEG_FLAG;
gensec_gssapi_state->got_flags = 0;
gensec_gssapi_state->session_key = data_blob(NULL, 0);
gensec_gssapi_state->pac = data_blob(NULL, 0);
gensec_gssapi_state->cred = GSS_C_NO_CREDENTIAL;
+ gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL;
talloc_set_destructor(gensec_gssapi_state, gensec_gssapi_destory);
@@ -205,7 +212,7 @@ static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_securi
}
maj_stat = gsskrb5_acquire_cred(&min_stat,
- gensec_gssapi_state->keytab->keytab, NULL,
+ gensec_gssapi_state->keytab->keytab,
gensec_gssapi_state->server_name,
GSS_C_INDEFINITE,
GSS_C_NULL_OID_SET,
@@ -227,7 +234,6 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi
{
struct gensec_gssapi_state *gensec_gssapi_state;
struct cli_credentials *creds = gensec_get_credentials(gensec_security);
- struct ccache_container *ccache;
krb5_error_code ret;
NTSTATUS nt_status;
gss_buffer_desc name_token;
@@ -235,6 +241,7 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi
OM_uint32 maj_stat, min_stat;
const char *hostname = gensec_get_target_hostname(gensec_security);
const char *principal;
+ struct gssapi_creds_container *gcc;
if (!hostname) {
DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n"));
@@ -256,29 +263,6 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi
gensec_gssapi_state = gensec_security->private_data;
- ret = cli_credentials_get_ccache(creds,
- &ccache);
- if (ret) {
- DEBUG(1, ("Failed to get CCACHE for gensec_gssapi: %s\n", error_message(ret)));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- principal = cli_credentials_get_principal(creds,
- gensec_gssapi_state);
- name_token.value = discard_const_p(uint8_t, principal);
- name_token.length = strlen(principal);
-
- maj_stat = gss_import_name (&min_stat,
- &name_token,
- GSS_C_NT_USER_NAME,
- &gensec_gssapi_state->client_name);
- if (maj_stat) {
- DEBUG(2, ("GSS Import name of %s failed: %s\n",
- (char *)name_token.value,
- gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat)));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
principal = gensec_get_target_principal(gensec_security);
if (principal && lp_client_use_spnego_principal()) {
name_token.value = discard_const_p(uint8_t, principal);
@@ -307,28 +291,20 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi
return NT_STATUS_INVALID_PARAMETER;
}
- maj_stat = gsskrb5_acquire_cred(&min_stat,
- NULL, ccache->ccache,
- gensec_gssapi_state->client_name,
- GSS_C_INDEFINITE,
- GSS_C_NULL_OID_SET,
- GSS_C_INITIATE,
- &gensec_gssapi_state->cred,
- NULL,
- NULL);
- if (maj_stat) {
- switch (min_stat) {
- case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN:
- DEBUG(3, ("Server [%s] is not registered with our KDC: %s\n",
- hostname, gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat)));
- return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
- default:
- DEBUG(1, ("Aquiring initiator credentails failed: %s\n",
- gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat)));
- return NT_STATUS_UNSUCCESSFUL;
- }
+ ret = cli_credentials_get_client_gss_creds(creds, &gcc);
+ switch (ret) {
+ case 0:
+ break;
+ case KRB5_KDC_UNREACH:
+ DEBUG(3, ("Cannot reach a KDC we require\n"));
+ return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
+ default:
+ DEBUG(1, ("Aquiring initiator credentails failed\n"));
+ return NT_STATUS_UNSUCCESSFUL;
}
+ gensec_gssapi_state->client_cred = gcc;
+
return NT_STATUS_OK;
}
@@ -369,7 +345,7 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security,
const DATA_BLOB in, DATA_BLOB *out)
{
struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
OM_uint32 maj_stat, min_stat;
OM_uint32 min_stat2;
gss_buffer_desc input_token, output_token;
@@ -381,7 +357,7 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security,
case GENSEC_CLIENT:
{
maj_stat = gss_init_sec_context(&min_stat,
- gensec_gssapi_state->cred,
+ gensec_gssapi_state->client_cred->creds,
&gensec_gssapi_state->gssapi_context,
gensec_gssapi_state->server_name,
discard_const_p(gss_OID_desc, gensec_gssapi_state->gss_oid),
@@ -407,7 +383,7 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security,
&output_token,
&gensec_gssapi_state->got_flags,
NULL,
- NULL);
+ &gensec_gssapi_state->delegated_cred_handle);
gensec_gssapi_state->gss_oid = gss_oid_p;
break;
}
@@ -420,6 +396,12 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security,
*out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
gss_release_buffer(&min_stat2, &output_token);
+ if (gensec_gssapi_state->got_flags & GSS_C_DELEG_FLAG) {
+ DEBUG(5, ("gensec_gssapi: credentials were delegated\n"));
+ } else {
+ DEBUG(5, ("gensec_gssapi: NO credentials were delegated\n"));
+ }
+
return NT_STATUS_OK;
} else if (maj_stat == GSS_S_CONTINUE_NEEDED) {
*out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
@@ -941,6 +923,27 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi
nt_status = gensec_gssapi_session_key(gensec_security, &session_info->session_key);
NT_STATUS_NOT_OK_RETURN(nt_status);
+ if (!(gensec_gssapi_state->got_flags & GSS_C_DELEG_FLAG)) {
+ DEBUG(10, ("gensec_gssapi: NO delegated credentials supplied by client"));
+ } else {
+ krb5_error_code ret;
+ DEBUG(10, ("gensec_gssapi: delegated credentials supplied by client\n"));
+ session_info->credentials = cli_credentials_init(session_info);
+ if (!session_info->credentials) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ cli_credentials_set_conf(session_info->credentials);
+
+ ret = cli_credentials_set_client_gss_creds(session_info->credentials,
+ gensec_gssapi_state->delegated_cred_handle,
+ CRED_SPECIFIED);
+ if (ret) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ /* It has been taken from this place... */
+ gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL;
+ }
*_session_info = session_info;
return NT_STATUS_OK;
diff --git a/source4/auth/kerberos/kerberos.h b/source4/auth/kerberos/kerberos.h
index 070293df68..9813290650 100644
--- a/source4/auth/kerberos/kerberos.h
+++ b/source4/auth/kerberos/kerberos.h
@@ -29,6 +29,11 @@ struct ccache_container {
};
+struct gssapi_creds_container {
+ gss_cred_id_t creds;
+};
+
+
struct keytab_container {
struct smb_krb5_context *smb_krb5_context;
krb5_keytab keytab;
@@ -155,5 +160,10 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
krb5_principal client_principal,
time_t tgs_authtime,
DATA_BLOB *pac);
+
+ int cli_credentials_set_client_gss_creds(struct cli_credentials *cred,
+ gss_cred_id_t gssapi_cred,
+ enum credentials_obtained obtained);
+
#endif /* HAVE_KRB5 */