summaryrefslogtreecommitdiff
path: root/source4/auth/credentials
diff options
context:
space:
mode:
Diffstat (limited to 'source4/auth/credentials')
-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
3 files changed, 113 insertions, 3 deletions
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)
{