1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

credentials: Create a smb_gss_krb5_copy_ccache() function

This sets the default principal on the copied ccache if it hasn't been
set yet.

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
This commit is contained in:
Andreas Schneider 2016-12-22 13:50:05 +01:00 committed by Stefan Metzmacher
parent 72fe43f218
commit f981e2c980

View File

@ -63,6 +63,130 @@ static int free_dccache(struct ccache_container *ccc)
return 0; return 0;
} }
static uint32_t smb_gss_krb5_copy_ccache(uint32_t *min_stat,
gss_cred_id_t cred,
struct ccache_container *ccc)
{
#ifndef SAMBA4_USES_HEIMDAL /* MIT 1.10 */
krb5_context context = ccc->smb_krb5_context->krb5_context;
krb5_ccache dummy_ccache = NULL;
krb5_creds creds = {0};
krb5_cc_cursor cursor = NULL;
krb5_principal princ = NULL;
krb5_error_code code;
char *dummy_name;
uint32_t maj_stat = GSS_S_FAILURE;
dummy_name = talloc_asprintf(ccc,
"MEMORY:gss_krb5_copy_ccache-%p",
&ccc->ccache);
if (dummy_name == NULL) {
*min_stat = ENOMEM;
return GSS_S_FAILURE;
}
/*
* Create a dummy ccache, so we can iterate over the credentials
* and find the default principal for the ccache we want to
* copy. The new ccache needs to be initialized with this
* principal.
*/
code = krb5_cc_resolve(context, dummy_name, &dummy_ccache);
TALLOC_FREE(dummy_name);
if (code != 0) {
*min_stat = code;
return GSS_S_FAILURE;
}
/*
* We do not need set a default principal on the temporary dummy
* ccache, as we do consume it at all in this function.
*/
maj_stat = gss_krb5_copy_ccache(min_stat, cred, dummy_ccache);
if (maj_stat != 0) {
krb5_cc_close(context, dummy_ccache);
return maj_stat;
}
code = krb5_cc_start_seq_get(context, dummy_ccache, &cursor);
if (code != 0) {
krb5_cc_close(context, dummy_ccache);
*min_stat = EINVAL;
return GSS_S_FAILURE;
}
code = krb5_cc_next_cred(context,
dummy_ccache,
&cursor,
&creds);
if (code != 0) {
krb5_cc_close(context, dummy_ccache);
*min_stat = EINVAL;
return GSS_S_FAILURE;
}
do {
if (creds.ticket_flags & TKT_FLG_PRE_AUTH) {
krb5_data *tgs;
tgs = krb5_princ_component(context,
creds.server,
0);
if (tgs != NULL && tgs->length >= 1) {
int cmp;
cmp = memcmp(tgs->data,
KRB5_TGS_NAME,
tgs->length);
if (cmp == 0 && creds.client != NULL) {
princ = creds.client;
code = KRB5_CC_END;
break;
}
}
}
krb5_free_cred_contents(context, &creds);
code = krb5_cc_next_cred(context,
dummy_ccache,
&cursor,
&creds);
} while (code == 0);
if (code == KRB5_CC_END) {
krb5_cc_end_seq_get(context, dummy_ccache, &cursor);
code = 0;
}
krb5_cc_close(context, dummy_ccache);
if (code != 0 || princ == NULL) {
krb5_free_cred_contents(context, &creds);
*min_stat = EINVAL;
return GSS_S_FAILURE;
}
/*
* Set the default principal for the cache we copy
* into. This is needed to be able that other calls
* can read it with e.g. gss_acquire_cred() or
* krb5_cc_get_principal().
*/
code = krb5_cc_initialize(context, ccc->ccache, princ);
if (code != 0) {
krb5_free_cred_contents(context, &creds);
*min_stat = EINVAL;
return GSS_S_FAILURE;
}
krb5_free_cred_contents(context, &creds);
#endif /* SAMBA4_USES_HEIMDAL */
return gss_krb5_copy_ccache(min_stat,
cred,
ccc->ccache);
}
_PUBLIC_ int cli_credentials_get_krb5_context(struct cli_credentials *cred, _PUBLIC_ int cli_credentials_get_krb5_context(struct cli_credentials *cred,
struct loadparm_context *lp_ctx, struct loadparm_context *lp_ctx,
struct smb_krb5_context **smb_krb5_context) struct smb_krb5_context **smb_krb5_context)
@ -712,8 +836,8 @@ _PUBLIC_ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred,
{ {
int ret; int ret;
OM_uint32 maj_stat, min_stat; OM_uint32 maj_stat, min_stat;
struct ccache_container *ccc; struct ccache_container *ccc = NULL;
struct gssapi_creds_container *gcc; struct gssapi_creds_container *gcc = NULL;
if (cred->client_gss_creds_obtained > obtained) { if (cred->client_gss_creds_obtained > obtained) {
return 0; return 0;
} }
@ -729,8 +853,9 @@ _PUBLIC_ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred,
return ret; return ret;
} }
maj_stat = gss_krb5_copy_ccache(&min_stat, maj_stat = smb_gss_krb5_copy_ccache(&min_stat,
gssapi_cred, ccc->ccache); gssapi_cred,
ccc);
if (maj_stat) { if (maj_stat) {
if (min_stat) { if (min_stat) {
ret = min_stat; ret = min_stat;