diff options
Diffstat (limited to 'source4/auth/credentials')
-rw-r--r-- | source4/auth/credentials/credentials.c | 1 | ||||
-rw-r--r-- | source4/auth/credentials/credentials.h | 2 | ||||
-rw-r--r-- | source4/auth/credentials/credentials_krb5.c | 113 |
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) { |