From 372ca26b2052e267711a45c8bf341f55505f3f8f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 20 Oct 2005 03:47:55 +0000 Subject: r11200: Reposition the creation of the kerberos keytab for GSSAPI and Krb5 authentication. This pulls the creating of the keytab back to the credentials code, and removes the special case of 'use keberos keytab = yes' for now. This allows (and requires) the callers to specify the credentials for the server credentails to GENSEC. This allows kpasswdd (soon to be added) to use a different set of kerberos credentials. The 'use kerberos keytab' code will be moved into the credentials layer, as the layers below now expect a keytab. We also now allow for the old secret to be stored into the credentials, allowing service password changes. Andrew Bartlett (This used to be commit 205f77c579ac8680c85f713a76de5767189c627b) --- source4/auth/credentials/credentials.c | 27 ++++++++++++ source4/auth/credentials/credentials.h | 5 +++ source4/auth/credentials/credentials_files.c | 57 ++++++++++++++++++++++++-- source4/auth/credentials/credentials_krb5.c | 61 ++++++++++++++++++++++++++-- 4 files changed, 142 insertions(+), 8 deletions(-) (limited to 'source4/auth/credentials') diff --git a/source4/auth/credentials/credentials.c b/source4/auth/credentials/credentials.c index f24c4e2231..9be877dd2c 100644 --- a/source4/auth/credentials/credentials.c +++ b/source4/auth/credentials/credentials.c @@ -46,7 +46,12 @@ 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->keytab_obtained = CRED_UNINITIALISED; cred->principal_obtained = CRED_UNINITIALISED; + + cred->old_password = NULL; + cred->smb_krb5_context = NULL; + return cred; } @@ -209,6 +214,28 @@ BOOL cli_credentials_set_password_callback(struct cli_credentials *cred, return False; } +/** + * Obtain the 'old' password for this credentials context (used for join accounts). + * @param cred credentials context + * @retval If set, the cleartext password, otherwise NULL + */ +const char *cli_credentials_get_old_password(struct cli_credentials *cred) +{ + if (cred->machine_account_pending) { + cli_credentials_set_machine_account(cred); + } + + return cred->old_password; +} + +BOOL cli_credentials_set_old_password(struct cli_credentials *cred, + const char *val, + enum credentials_obtained obtained) +{ + cred->old_password = talloc_strdup(cred, val); + return True; +} + /** * Obtain the password for this credentials context. * @param cred credentials context diff --git a/source4/auth/credentials/credentials.h b/source4/auth/credentials/credentials.h index 324b518462..aa2a0d0ac2 100644 --- a/source4/auth/credentials/credentials.h +++ b/source4/auth/credentials/credentials.h @@ -48,10 +48,12 @@ struct cli_credentials { enum credentials_obtained realm_obtained; enum credentials_obtained ccache_obtained; enum credentials_obtained principal_obtained; + enum credentials_obtained keytab_obtained; const char *workstation; const char *username; const char *password; + const char *old_password; const char *domain; const char *realm; const char *principal; @@ -59,6 +61,7 @@ struct cli_credentials { struct samr_Password *nt_hash; struct ccache_container *ccache; + struct keytab_container *keytab; const char *(*workstation_cb) (struct cli_credentials *); const char *(*password_cb) (struct cli_credentials *); @@ -74,6 +77,8 @@ struct cli_credentials { enum netr_SchannelType secure_channel_type; int kvno; + struct smb_krb5_context *smb_krb5_context; + /* We are flagged to get machine account details from the * secrets.ldb when we are asked for a username or password */ diff --git a/source4/auth/credentials/credentials_files.c b/source4/auth/credentials/credentials_files.c index 353ff61720..aa0a7f3213 100644 --- a/source4/auth/credentials/credentials_files.c +++ b/source4/auth/credentials/credentials_files.c @@ -164,7 +164,9 @@ BOOL cli_credentials_parse_file(struct cli_credentials *cred, const char *file, * @param cred Credentials structure to fill in * @retval NTSTATUS error detailing any failure */ -NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) +static NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred, + const char *base, + const char *filter) { TALLOC_CTX *mem_ctx; @@ -184,6 +186,7 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) const char *machine_account; const char *password; + const char *old_password; const char *domain; const char *realm; enum netr_SchannelType sct; @@ -201,10 +204,9 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) /* search for the secret record */ ldb_ret = gendb_search(ldb, - mem_ctx, ldb_dn_explode(mem_ctx, SECRETS_PRIMARY_DOMAIN_DN), + mem_ctx, ldb_dn_explode(mem_ctx, base), &msgs, attrs, - SECRETS_PRIMARY_DOMAIN_FILTER, - cli_credentials_get_domain(cred)); + "%s", filter); if (ldb_ret == 0) { DEBUG(1, ("Could not find join record to domain: %s\n", cli_credentials_get_domain(cred))); @@ -218,6 +220,7 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) } password = ldb_msg_find_string(msgs[0], "secret", NULL); + old_password = ldb_msg_find_string(msgs[0], "priorSecret", NULL); machine_account = ldb_msg_find_string(msgs[0], "samAccountName", NULL); @@ -277,6 +280,52 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) return NT_STATUS_OK; } +/** + * Fill in credentials for the machine trust account, from the secrets database. + * + * @param cred Credentials structure to fill in + * @retval NTSTATUS error detailing any failure + */ +NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) +{ + char *filter = talloc_asprintf(cred, SECRETS_PRIMARY_DOMAIN_FILTER, + cli_credentials_get_domain(cred)); + return cli_credentials_set_secrets(cred, SECRETS_PRIMARY_DOMAIN_DN, + filter); +} + +/** + * Fill in credentials for the machine trust account, from the secrets database. + * + * @param cred Credentials structure to fill in + * @retval NTSTATUS error detailing any failure + */ +NTSTATUS cli_credentials_set_krbtgt(struct cli_credentials *cred) +{ + char *filter = talloc_asprintf(cred, SECRETS_KRBTGT_SEARCH, + cli_credentials_get_realm(cred), + cli_credentials_get_domain(cred)); + return cli_credentials_set_secrets(cred, SECRETS_PRINCIPALS_DN, + filter); +} + +/** + * Fill in credentials for the machine trust account, from the secrets database. + * + * @param cred Credentials structure to fill in + * @retval NTSTATUS error detailing any failure + */ +NTSTATUS cli_credentials_set_stored_principal(struct cli_credentials *cred, + const char *serviceprincipal) +{ + char *filter = talloc_asprintf(cred, SECRETS_PRINCIPAL_SEARCH, + cli_credentials_get_realm(cred), + cli_credentials_get_domain(cred), + serviceprincipal); + return cli_credentials_set_secrets(cred, SECRETS_PRINCIPALS_DN, + filter); +} + /** * Ask that when required, the credentials system will be filled with * machine trust account, from the secrets database. diff --git a/source4/auth/credentials/credentials_krb5.c b/source4/auth/credentials/credentials_krb5.c index fb3239494e..b20d9ee750 100644 --- a/source4/auth/credentials/credentials_krb5.c +++ b/source4/auth/credentials/credentials_krb5.c @@ -26,6 +26,22 @@ #include "system/kerberos.h" #include "auth/kerberos/kerberos.h" +int cli_credentials_get_krb5_context(struct cli_credentials *cred, + struct smb_krb5_context **smb_krb5_context) +{ + int ret; + if (cred->smb_krb5_context) { + *smb_krb5_context = cred->smb_krb5_context; + return 0; + } + + ret = smb_krb5_init_context(cred, &cred->smb_krb5_context); + if (ret) { + return ret; + } + *smb_krb5_context = cred->smb_krb5_context; + return 0; +} int cli_credentials_set_from_ccache(struct cli_credentials *cred, enum credentials_obtained obtained) @@ -95,11 +111,13 @@ int cli_credentials_set_ccache(struct cli_credentials *cred, return ENOMEM; } - ret = smb_krb5_init_context(ccc, &ccc->smb_krb5_context); + ret = cli_credentials_get_krb5_context(cred, &ccc->smb_krb5_context); if (ret) { talloc_free(ccc); return ret; } + talloc_reference(ccc, ccc->smb_krb5_context); + if (name) { ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, name, &ccc->ccache); if (ret) { @@ -162,7 +180,7 @@ int cli_credentials_new_ccache(struct cli_credentials *cred) } ccache_name = talloc_asprintf(ccc, "MEMORY:%s", - rand_string); + rand_string); talloc_free(rand_string); if (!ccache_name) { @@ -170,12 +188,12 @@ int cli_credentials_new_ccache(struct cli_credentials *cred) return ENOMEM; } - ret = smb_krb5_init_context(ccc, &ccc->smb_krb5_context); + ret = cli_credentials_get_krb5_context(cred, &ccc->smb_krb5_context); if (ret) { - talloc_free(ccache_name); talloc_free(ccc); return ret; } + talloc_reference(ccc, ccc->smb_krb5_context); ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, ccache_name, &ccc->ccache); if (ret) { @@ -227,6 +245,41 @@ int cli_credentials_get_ccache(struct cli_credentials *cred, return ret; } +int cli_credentials_get_keytab(struct cli_credentials *cred, + struct keytab_container **_ktc) +{ + krb5_error_code ret; + struct keytab_container *ktc; + struct smb_krb5_context *smb_krb5_context; + + if (cred->keytab_obtained >= (MAX(cred->principal_obtained, + cred->username_obtained))) { + *_ktc = cred->keytab; + return 0; + } + + if (cli_credentials_is_anonymous(cred)) { + return EINVAL; + } + + ret = cli_credentials_get_krb5_context(cred, &smb_krb5_context); + if (ret) { + return ret; + } + + ret = create_memory_keytab(cred, cred, smb_krb5_context, &ktc); + if (ret) { + return ret; + } + + cred->keytab_obtained = (MAX(cred->principal_obtained, + cred->username_obtained)); + + cred->keytab = ktc; + *_ktc = cred->keytab; + return ret; +} + /** * Set Kerberos KVNO */ -- cgit