diff options
Diffstat (limited to 'source4/auth/credentials')
-rw-r--r-- | source4/auth/credentials/credentials.c | 27 | ||||
-rw-r--r-- | source4/auth/credentials/credentials.h | 5 | ||||
-rw-r--r-- | source4/auth/credentials/credentials_files.c | 57 | ||||
-rw-r--r-- | source4/auth/credentials/credentials_krb5.c | 61 |
4 files changed, 142 insertions, 8 deletions
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; } @@ -210,6 +215,28 @@ BOOL cli_credentials_set_password_callback(struct cli_credentials *cred, } /** + * 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 * @retval If set, the cleartext password, otherwise NULL 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); @@ -278,6 +281,52 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) } /** + * 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 */ |