From d515c6cd5c4884d781f6a84290f16925a3e34af6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 6 Feb 2011 15:50:04 +0100 Subject: [PATCH] s3: Fix auth_netlogond to cope with netlogon_creds_CredentialState Autobuild-User: Volker Lendecke Autobuild-Date: Sun Feb 6 17:30:48 CET 2011 on sn-devel-104 --- source3/auth/auth_netlogond.c | 89 +++++++++++++++++++++++++++-------- source3/include/secrets.h | 2 - source3/passdb/secrets.c | 25 ---------- 3 files changed, 69 insertions(+), 47 deletions(-) diff --git a/source3/auth/auth_netlogond.c b/source3/auth/auth_netlogond.c index cff36a535d1..854060b75d4 100644 --- a/source3/auth/auth_netlogond.c +++ b/source3/auth/auth_netlogond.c @@ -20,6 +20,7 @@ #include "includes.h" #include "../libcli/auth/libcli_auth.h" #include "../librpc/gen_ndr/ndr_netlogon.h" +#include "librpc/gen_ndr/ndr_schannel.h" #include "rpc_client/cli_netlogon.h" #include "secrets.h" #include "tldap.h" @@ -28,10 +29,65 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH +static bool secrets_store_local_schannel_creds( + const struct netlogon_creds_CredentialState *creds) +{ + DATA_BLOB blob; + enum ndr_err_code ndr_err; + bool ret; + + ndr_err = ndr_push_struct_blob( + &blob, talloc_tos(), creds, + (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(10, ("ndr_push_netlogon_creds_CredentialState failed: " + "%s\n", ndr_errstr(ndr_err))); + return false; + } + ret = secrets_store(SECRETS_LOCAL_SCHANNEL_KEY, + blob.data, blob.length); + data_blob_free(&blob); + return ret; +} + +static struct netlogon_creds_CredentialState * +secrets_fetch_local_schannel_creds(TALLOC_CTX *mem_ctx) +{ + struct netlogon_creds_CredentialState *creds; + enum ndr_err_code ndr_err; + DATA_BLOB blob; + + blob.data = (uint8_t *)secrets_fetch(SECRETS_LOCAL_SCHANNEL_KEY, + &blob.length); + if (blob.data == NULL) { + DEBUG(10, ("secrets_fetch failed\n")); + return NULL; + } + + creds = talloc(mem_ctx, struct netlogon_creds_CredentialState); + if (creds == NULL) { + DEBUG(10, ("talloc failed\n")); + SAFE_FREE(blob.data); + return NULL; + } + ndr_err = ndr_pull_struct_blob( + &blob, creds, creds, + (ndr_pull_flags_fn_t)ndr_pull_netlogon_creds_CredentialState); + SAFE_FREE(blob.data); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(10, ("ndr_pull_netlogon_creds_CredentialState failed: " + "%s\n", ndr_errstr(ndr_err))); + TALLOC_FREE(creds); + return NULL; + } + + return creds; +} + static NTSTATUS netlogond_validate(TALLOC_CTX *mem_ctx, const struct auth_context *auth_context, const char *ncalrpc_sockname, - uint8_t schannel_key[16], + struct netlogon_creds_CredentialState *creds, const struct auth_usersupplied_info *user_info, struct netr_SamInfo3 **pinfo3, NTSTATUS *schannel_bind_result) @@ -51,17 +107,7 @@ static NTSTATUS netlogond_validate(TALLOC_CTX *mem_ctx, return status; } - /* - * We have to fake a struct dcinfo, so that - * rpccli_netlogon_sam_network_logon_ex can decrypt the session keys. - */ - - p->dc = netlogon_creds_client_init_session_key(p, schannel_key); - if (p->dc == NULL) { - DEBUG(0, ("talloc failed\n")); - TALLOC_FREE(p); - return NT_STATUS_NO_MEMORY; - } + p->dc = creds; status = rpccli_schannel_bind_data(p, lp_workgroup(), DCERPC_AUTH_LEVEL_PRIVACY, @@ -242,7 +288,7 @@ static NTSTATUS check_netlogond_security(const struct auth_context *auth_context struct pipe_auth_data *auth = NULL; uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; uint8_t machine_password[16]; - uint8_t schannel_key[16]; + struct netlogon_creds_CredentialState *creds; NTSTATUS schannel_bind_result, status; struct named_mutex *mutex = NULL; const char *ncalrpcsock; @@ -262,12 +308,13 @@ static NTSTATUS check_netlogond_security(const struct auth_context *auth_context goto done; } - if (!secrets_fetch_local_schannel_key(schannel_key)) { + creds = secrets_fetch_local_schannel_creds(talloc_tos()); + if (creds == NULL) { goto new_key; } status = netlogond_validate(talloc_tos(), auth_context, ncalrpcsock, - schannel_key, user_info, &info3, + creds, user_info, &info3, &schannel_bind_result); DEBUG(10, ("netlogond_validate returned %s\n", nt_errstr(status))); @@ -322,6 +369,9 @@ static NTSTATUS check_netlogond_security(const struct auth_context *auth_context goto done; } + DEBUG(10, ("machinepw ")); + dump_data(10, machine_password, 16); + status = rpccli_netlogon_setup_creds( p, global_myname(), lp_workgroup(), global_myname(), global_myname(), machine_password, SEC_CHAN_BDC, &neg_flags); @@ -332,10 +382,7 @@ static NTSTATUS check_netlogond_security(const struct auth_context *auth_context goto done; } - memcpy(schannel_key, p->dc->session_key, 16); - secrets_store_local_schannel_key(schannel_key); - - TALLOC_FREE(p); + secrets_store_local_schannel_creds(p->dc); /* * Retry the authentication with the mutex held. This way nobody else @@ -343,9 +390,11 @@ static NTSTATUS check_netlogond_security(const struct auth_context *auth_context */ status = netlogond_validate(talloc_tos(), auth_context, ncalrpcsock, - schannel_key, user_info, &info3, + creds, user_info, &info3, &schannel_bind_result); + TALLOC_FREE(p); + DEBUG(10, ("netlogond_validate returned %s\n", nt_errstr(status))); if (!NT_STATUS_IS_OK(status)) { diff --git a/source3/include/secrets.h b/source3/include/secrets.h index 095ab6ee78b..71206551266 100644 --- a/source3/include/secrets.h +++ b/source3/include/secrets.h @@ -123,7 +123,5 @@ void secrets_fetch_ipc_userpass(char **username, char **domain, char **password) bool secrets_store_generic(const char *owner, const char *key, const char *secret); char *secrets_fetch_generic(const char *owner, const char *key); bool secrets_delete_generic(const char *owner, const char *key); -bool secrets_store_local_schannel_key(uint8_t schannel_key[16]); -bool secrets_fetch_local_schannel_key(uint8_t schannel_key[16]); #endif /* _SECRETS_H */ diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c index 6571e6ef6ba..45f8e152be8 100644 --- a/source3/passdb/secrets.c +++ b/source3/passdb/secrets.c @@ -169,31 +169,6 @@ bool secrets_delete(const char *key) return NT_STATUS_IS_OK(status); } -bool secrets_store_local_schannel_key(uint8_t schannel_key[16]) -{ - return secrets_store(SECRETS_LOCAL_SCHANNEL_KEY, schannel_key, 16); -} - -bool secrets_fetch_local_schannel_key(uint8_t schannel_key[16]) -{ - size_t size = 0; - uint8_t *key; - - key = (uint8_t *)secrets_fetch(SECRETS_LOCAL_SCHANNEL_KEY, &size); - if (key == NULL) { - return false; - } - - if (size != 16) { - SAFE_FREE(key); - return false; - } - - memcpy(schannel_key, key, 16); - SAFE_FREE(key); - return true; -} - /** * Form a key for fetching a trusted domain password *