diff options
author | Andrew Bartlett <abartlet@samba.org> | 2012-08-27 21:37:19 +1000 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2012-08-28 07:57:29 +1000 |
commit | f873d422b153c55754c0d1e83670cda7c3a7f7e3 (patch) | |
tree | 8bb53dadfbe1e19c4686aa0c285176829971e205 | |
parent | 1a8fd711d7e4f97a6749b5d6c4806b11c38f20f4 (diff) | |
download | samba-f873d422b153c55754c0d1e83670cda7c3a7f7e3.tar.gz samba-f873d422b153c55754c0d1e83670cda7c3a7f7e3.tar.xz samba-f873d422b153c55754c0d1e83670cda7c3a7f7e3.zip |
auth/credentials: Rework credentials handling to try and find the most recent machine pw
As winbindd will update secrets.tdb but not secrets.ldb, we need to detect this and use secrets.tdb
Andrew Bartlett
-rw-r--r-- | auth/credentials/credentials_secrets.c | 104 |
1 files changed, 71 insertions, 33 deletions
diff --git a/auth/credentials/credentials_secrets.c b/auth/credentials/credentials_secrets.c index dc31f9d8ca..3304200607 100644 --- a/auth/credentials/credentials_secrets.c +++ b/auth/credentials/credentials_secrets.c @@ -204,6 +204,15 @@ _PUBLIC_ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cr char *error_string; const char *domain; const char *realm; + bool secrets_tdb_password_more_recent; + time_t secrets_tdb_lct = 0; + char *secrets_tdb_password = NULL; + char *keystr; + char *keystr_upper = NULL; + char *secrets_tdb = lpcfg_private_path(cred, lp_ctx, "secrets.tdb"); + struct db_context *db_ctx = dbwrap_local_open(cred, lp_ctx, secrets_tdb, 0, + TDB_DEFAULT, O_RDWR, 0600, + DBWRAP_LOCK_ORDER_1); /* Bleh, nasty recursion issues: We are setting a machine * account here, so we don't want the 'pending' flag around * any more */ @@ -213,49 +222,78 @@ _PUBLIC_ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cr * cli_credentials_set_secrets is to run as anonymous, so the domain is wiped */ domain = cli_credentials_get_domain(cred); realm = cli_credentials_get_realm(cred); + + if (db_ctx) { + TDB_DATA dbuf; + keystr = talloc_asprintf(cred, "%s/%s", + SECRETS_MACHINE_LAST_CHANGE_TIME, + domain); + keystr_upper = strupper_talloc(cred, keystr); + TALLOC_FREE(keystr); + status = dbwrap_fetch(db_ctx, cred, string_tdb_data(keystr_upper), + &dbuf); + TALLOC_FREE(keystr_upper); + if (NT_STATUS_IS_OK(status) && dbuf.dsize == 4) { + secrets_tdb_lct = IVAL(dbuf.dptr,0); + } + TALLOC_FREE(dbuf.dptr); + + keystr = talloc_asprintf(cred, "%s/%s", + SECRETS_MACHINE_PASSWORD, + domain); + keystr_upper = strupper_talloc(cred, keystr); + TALLOC_FREE(keystr); + status = dbwrap_fetch(db_ctx, cred, string_tdb_data(keystr_upper), + &dbuf); + if (NT_STATUS_IS_OK(status)) { + secrets_tdb_password = (char *)dbuf.dptr; + } + } + filter = talloc_asprintf(cred, SECRETS_PRIMARY_DOMAIN_FILTER, domain); status = cli_credentials_set_secrets(cred, lp_ctx, NULL, SECRETS_PRIMARY_DOMAIN_DN, filter, &error_string); - if (NT_STATUS_EQUAL(NT_STATUS_CANT_ACCESS_DOMAIN_INFO, status) + if (secrets_tdb_password == NULL) { + secrets_tdb_password_more_recent = false; + } else if (NT_STATUS_EQUAL(NT_STATUS_CANT_ACCESS_DOMAIN_INFO, status) || NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, status)) { - TDB_DATA dbuf; - char *secrets_tdb = lpcfg_private_path(cred, lp_ctx, "secrets.tdb"); - struct db_context *db_ctx = dbwrap_local_open(cred, lp_ctx, secrets_tdb, 0, - TDB_DEFAULT, O_RDWR, 0600, - DBWRAP_LOCK_ORDER_1); + secrets_tdb_password_more_recent = true; + } else if (secrets_tdb_lct > cli_credentials_get_password_last_changed_time(cred)) { + secrets_tdb_password_more_recent = true; + } else if (secrets_tdb_lct == cli_credentials_get_password_last_changed_time(cred)) { + secrets_tdb_password_more_recent = strcmp(secrets_tdb_password, cli_credentials_get_password(cred)) != 0; + } else { + secrets_tdb_password_more_recent = false; + } + + if (secrets_tdb_password_more_recent) { + char *machine_account = talloc_asprintf(cred, "%s$", lpcfg_netbios_name(lp_ctx)); + cli_credentials_set_password(cred, secrets_tdb_password, CRED_SPECIFIED); + cli_credentials_set_domain(cred, domain, CRED_SPECIFIED); + cli_credentials_set_realm(cred, realm, CRED_SPECIFIED); + cli_credentials_set_workstation(cred, lpcfg_netbios_name(lp_ctx), CRED_SPECIFIED); + cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED); + TALLOC_FREE(machine_account); + } else if (NT_STATUS_EQUAL(NT_STATUS_CANT_ACCESS_DOMAIN_INFO, status) + || NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, status)) { if (db_ctx) { - char *keystr; - char *keystr_upper; - keystr = talloc_asprintf(cred, "%s/%s", - SECRETS_MACHINE_PASSWORD, - domain); - keystr_upper = strupper_talloc(cred, keystr); - TALLOC_FREE(keystr); - status = dbwrap_fetch(db_ctx, cred, string_tdb_data(keystr_upper), - &dbuf); - - if (NT_STATUS_IS_OK(status)) { - char *machine_account = talloc_asprintf(cred, "%s$", lpcfg_netbios_name(lp_ctx)); - cli_credentials_set_password(cred, (const char *)dbuf.dptr, CRED_SPECIFIED); - cli_credentials_set_domain(cred, domain, CRED_SPECIFIED); - cli_credentials_set_realm(cred, domain, CRED_SPECIFIED); - cli_credentials_set_workstation(cred, lpcfg_netbios_name(lp_ctx), CRED_SPECIFIED); - cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED); - TALLOC_FREE(machine_account); - TALLOC_FREE(dbuf.dptr); - } else { - error_string = talloc_asprintf(cred, - "Failed to fetch machine account password from " - "secrets.ldb: %s and failed to fetch %s from %s", - error_string, keystr_upper, secrets_tdb); - } - TALLOC_FREE(keystr_upper); - TALLOC_FREE(secrets_tdb); + error_string = talloc_asprintf(cred, + "Failed to fetch machine account password from " + "secrets.ldb: %s and failed to fetch %s from %s", + error_string, keystr_upper, secrets_tdb); + } else { + error_string = talloc_asprintf(cred, + "Failed to fetch machine account password from " + "secrets.ldb: %s and failed to open %s", + error_string, secrets_tdb); } } + TALLOC_FREE(secrets_tdb_password); + TALLOC_FREE(secrets_tdb); + TALLOC_FREE(db_ctx); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Could not find machine account in secrets database: %s: %s\n", error_string, nt_errstr(status))); |