diff options
113 files changed, 1936 insertions, 4185 deletions
diff --git a/libcli/auth/config.mk b/libcli/auth/config.mk new file mode 100644 index 0000000000..103402099d --- /dev/null +++ b/libcli/auth/config.mk @@ -0,0 +1,31 @@ +[SUBSYSTEM::ntlm_check] +PRIVATE_DEPENDENCIES = LIBSAMBA-UTIL + +ntlm_check_OBJ_FILES = $(addprefix $(libclicommonsrcdir)/auth/, ntlm_check.o) + +[SUBSYSTEM::MSRPC_PARSE] + +MSRPC_PARSE_OBJ_FILES = $(addprefix $(libclicommonsrcdir)/auth/, msrpc_parse.o) + +$(eval $(call proto_header_template,$(libclicommonsrcdir)/auth/msrpc_parse.h,$(MSRPC_PARSE_OBJ_FILES:.o=.c))) + +[SUBSYSTEM::LIBCLI_AUTH] +PUBLIC_DEPENDENCIES = \ + MSRPC_PARSE \ + LIBSAMBA-HOSTCONFIG + +LIBCLI_AUTH_OBJ_FILES = $(addprefix $(libclicommonsrcdir)/auth/, \ + credentials.o \ + session.o \ + smbencrypt.o \ + smbdes.o) + +PUBLIC_HEADERS += ../libcli/auth/credentials.h +$(eval $(call proto_header_template,$(libclicommonsrcdir)/auth/proto.h,$(LIBCLI_AUTH_OBJ_FILES:.o=.c))) + +[SUBSYSTEM::COMMON_SCHANNELDB] +PRIVATE_DEPENDENCIES = LDB_WRAP + +COMMON_SCHANNELDB_OBJ_FILES = $(addprefix $(libclicommonsrcdir)/auth/, schannel_state.o) +$(eval $(call proto_header_template,$(libclicommonsrcdir)/auth/schannel_state_proto.h,$(COMMON_SCHANNELDB_OBJ_FILES:.o=.c))) + diff --git a/source4/libcli/auth/credentials.c b/libcli/auth/credentials.c index 3c77b0836d..dc84ffb474 100644 --- a/source4/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -22,7 +22,6 @@ #include "includes.h" #include "system/time.h" -#include "auth/auth.h" #include "../lib/crypto/crypto.h" #include "libcli/auth/libcli_auth.h" @@ -31,10 +30,10 @@ this call is made after the netr_ServerReqChallenge call */ -static void creds_init_64bit(struct creds_CredentialState *creds, - const struct netr_Credential *client_challenge, - const struct netr_Credential *server_challenge, - const struct samr_Password *machine_password) +static void netlogon_creds_init_64bit(struct netlogon_creds_CredentialState *creds, + const struct netr_Credential *client_challenge, + const struct netr_Credential *server_challenge, + const struct samr_Password *machine_password) { uint32_t sum[2]; uint8_t sum2[8]; @@ -60,10 +59,10 @@ static void creds_init_64bit(struct creds_CredentialState *creds, this call is made after the netr_ServerReqChallenge call */ -static void creds_init_128bit(struct creds_CredentialState *creds, - const struct netr_Credential *client_challenge, - const struct netr_Credential *server_challenge, - const struct samr_Password *machine_password) +static void netlogon_creds_init_128bit(struct netlogon_creds_CredentialState *creds, + const struct netr_Credential *client_challenge, + const struct netr_Credential *server_challenge, + const struct samr_Password *machine_password) { unsigned char zero[4], tmp[16]; HMACMD5Context ctx; @@ -96,7 +95,7 @@ static void creds_init_128bit(struct creds_CredentialState *creds, step the credentials to the next element in the chain, updating the current client and server credentials and the seed */ -static void creds_step(struct creds_CredentialState *creds) +static void netlogon_creds_step(struct netlogon_creds_CredentialState *creds) { struct netr_Credential time_cred; @@ -131,7 +130,7 @@ static void creds_step(struct creds_CredentialState *creds) /* DES encrypt a 8 byte LMSessionKey buffer using the Netlogon session key */ -void creds_des_encrypt_LMKey(struct creds_CredentialState *creds, struct netr_LMSessionKey *key) +void netlogon_creds_des_encrypt_LMKey(struct netlogon_creds_CredentialState *creds, struct netr_LMSessionKey *key) { struct netr_LMSessionKey tmp; des_crypt56(tmp.key, key->key, creds->session_key, 1); @@ -141,7 +140,7 @@ void creds_des_encrypt_LMKey(struct creds_CredentialState *creds, struct netr_LM /* DES decrypt a 8 byte LMSessionKey buffer using the Netlogon session key */ -void creds_des_decrypt_LMKey(struct creds_CredentialState *creds, struct netr_LMSessionKey *key) +void netlogon_creds_des_decrypt_LMKey(struct netlogon_creds_CredentialState *creds, struct netr_LMSessionKey *key) { struct netr_LMSessionKey tmp; des_crypt56(tmp.key, key->key, creds->session_key, 0); @@ -151,7 +150,7 @@ void creds_des_decrypt_LMKey(struct creds_CredentialState *creds, struct netr_LM /* DES encrypt a 16 byte password buffer using the session key */ -void creds_des_encrypt(struct creds_CredentialState *creds, struct samr_Password *pass) +void netlogon_creds_des_encrypt(struct netlogon_creds_CredentialState *creds, struct samr_Password *pass) { struct samr_Password tmp; des_crypt112_16(tmp.hash, pass->hash, creds->session_key, 1); @@ -161,7 +160,7 @@ void creds_des_encrypt(struct creds_CredentialState *creds, struct samr_Password /* DES decrypt a 16 byte password buffer using the session key */ -void creds_des_decrypt(struct creds_CredentialState *creds, struct samr_Password *pass) +void netlogon_creds_des_decrypt(struct netlogon_creds_CredentialState *creds, struct samr_Password *pass) { struct samr_Password tmp; des_crypt112_16(tmp.hash, pass->hash, creds->session_key, 0); @@ -171,7 +170,7 @@ void creds_des_decrypt(struct creds_CredentialState *creds, struct samr_Password /* ARCFOUR encrypt/decrypt a password buffer using the session key */ -void creds_arcfour_crypt(struct creds_CredentialState *creds, uint8_t *data, size_t len) +void netlogon_creds_arcfour_crypt(struct netlogon_creds_CredentialState *creds, uint8_t *data, size_t len) { DATA_BLOB session_key = data_blob(creds->session_key, 16); @@ -189,30 +188,69 @@ next comes the client specific functions initialise the credentials chain and return the first client credentials */ -void creds_client_init(struct creds_CredentialState *creds, - const struct netr_Credential *client_challenge, - const struct netr_Credential *server_challenge, - const struct samr_Password *machine_password, - struct netr_Credential *initial_credential, - uint32_t negotiate_flags) + +struct netlogon_creds_CredentialState *netlogon_creds_client_init(TALLOC_CTX *mem_ctx, + const char *client_account, + const char *client_computer_name, + const struct netr_Credential *client_challenge, + const struct netr_Credential *server_challenge, + const struct samr_Password *machine_password, + struct netr_Credential *initial_credential, + uint32_t negotiate_flags) { + struct netlogon_creds_CredentialState *creds = talloc(mem_ctx, struct netlogon_creds_CredentialState); + + if (!creds) { + return NULL; + } + creds->sequence = time(NULL); creds->negotiate_flags = negotiate_flags; + creds->computer_name = talloc_strdup(creds, client_computer_name); + if (!creds->computer_name) { + talloc_free(creds); + return NULL; + } + creds->account_name = talloc_strdup(creds, client_account); + if (!creds->account_name) { + talloc_free(creds); + return NULL; + } + dump_data_pw("Client chall", client_challenge->data, sizeof(client_challenge->data)); dump_data_pw("Server chall", server_challenge->data, sizeof(server_challenge->data)); dump_data_pw("Machine Pass", machine_password->hash, sizeof(machine_password->hash)); if (negotiate_flags & NETLOGON_NEG_128BIT) { - creds_init_128bit(creds, client_challenge, server_challenge, machine_password); + netlogon_creds_init_128bit(creds, client_challenge, server_challenge, machine_password); } else { - creds_init_64bit(creds, client_challenge, server_challenge, machine_password); + netlogon_creds_init_64bit(creds, client_challenge, server_challenge, machine_password); } dump_data_pw("Session key", creds->session_key, 16); dump_data_pw("Credential ", creds->client.data, 8); *initial_credential = creds->client; + return creds; +} + +/* + initialise the credentials structure with only a session key. The caller better know what they are doing! + */ + +struct netlogon_creds_CredentialState *netlogon_creds_client_init_session_key(TALLOC_CTX *mem_ctx, + const uint8_t session_key[16]) +{ + struct netlogon_creds_CredentialState *creds = talloc(mem_ctx, struct netlogon_creds_CredentialState); + + if (!creds) { + return NULL; + } + + memcpy(creds->session_key, session_key, 16); + + return creds; } /* @@ -222,11 +260,11 @@ void creds_client_init(struct creds_CredentialState *creds, produce the next authenticator in the sequence ready to send to the server */ -void creds_client_authenticator(struct creds_CredentialState *creds, +void netlogon_creds_client_authenticator(struct netlogon_creds_CredentialState *creds, struct netr_Authenticator *next) { creds->sequence += 2; - creds_step(creds); + netlogon_creds_step(creds); next->cred = creds->client; next->timestamp = creds->sequence; @@ -235,7 +273,7 @@ void creds_client_authenticator(struct creds_CredentialState *creds, /* check that a credentials reply from a server is correct */ -bool creds_client_check(struct creds_CredentialState *creds, +bool netlogon_creds_client_check(struct netlogon_creds_CredentialState *creds, const struct netr_Credential *received_credentials) { if (!received_credentials || @@ -253,33 +291,10 @@ next comes the server specific functions ******************************************************************/ /* - initialise the credentials chain and return the first server - credentials -*/ -void creds_server_init(struct creds_CredentialState *creds, - const struct netr_Credential *client_challenge, - const struct netr_Credential *server_challenge, - const struct samr_Password *machine_password, - struct netr_Credential *initial_credential, - uint32_t negotiate_flags) -{ - if (negotiate_flags & NETLOGON_NEG_128BIT) { - creds_init_128bit(creds, client_challenge, server_challenge, - machine_password); - } else { - creds_init_64bit(creds, client_challenge, server_challenge, - machine_password); - } - - *initial_credential = creds->server; - creds->negotiate_flags = negotiate_flags; -} - -/* check that a credentials reply from a server is correct */ -bool creds_server_check(const struct creds_CredentialState *creds, - const struct netr_Credential *received_credentials) +static bool netlogon_creds_server_check_internal(const struct netlogon_creds_CredentialState *creds, + const struct netr_Credential *received_credentials) { if (memcmp(received_credentials->data, creds->client.data, 8) != 0) { DEBUG(2,("credentials check failed\n")); @@ -290,7 +305,62 @@ bool creds_server_check(const struct creds_CredentialState *creds, return true; } -NTSTATUS creds_server_step_check(struct creds_CredentialState *creds, +/* + initialise the credentials chain and return the first server + credentials +*/ +struct netlogon_creds_CredentialState *netlogon_creds_server_init(TALLOC_CTX *mem_ctx, + const char *client_account, + const char *client_computer_name, + uint16_t secure_channel_type, + const struct netr_Credential *client_challenge, + const struct netr_Credential *server_challenge, + const struct samr_Password *machine_password, + struct netr_Credential *credentials_in, + struct netr_Credential *credentials_out, + uint32_t negotiate_flags) +{ + + struct netlogon_creds_CredentialState *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState); + + if (!creds) { + return NULL; + } + + creds->negotiate_flags = negotiate_flags; + + creds->computer_name = talloc_strdup(creds, client_computer_name); + if (!creds->computer_name) { + talloc_free(creds); + return NULL; + } + creds->account_name = talloc_strdup(creds, client_account); + if (!creds->account_name) { + talloc_free(creds); + return NULL; + } + + if (negotiate_flags & NETLOGON_NEG_128BIT) { + netlogon_creds_init_128bit(creds, client_challenge, server_challenge, + machine_password); + } else { + netlogon_creds_init_64bit(creds, client_challenge, server_challenge, + machine_password); + } + + /* And before we leak information about the machine account + * password, check that they got the first go right */ + if (!netlogon_creds_server_check_internal(creds, credentials_in)) { + talloc_free(creds); + return NULL; + } + + *credentials_out = creds->server; + + return creds; +} + +NTSTATUS netlogon_creds_server_step_check(struct netlogon_creds_CredentialState *creds, struct netr_Authenticator *received_authenticator, struct netr_Authenticator *return_authenticator) { @@ -305,8 +375,8 @@ NTSTATUS creds_server_step_check(struct creds_CredentialState *creds, /* TODO: this may allow the a replay attack on a non-signed connection. Should we check that this is increasing? */ creds->sequence = received_authenticator->timestamp; - creds_step(creds); - if (creds_server_check(creds, &received_authenticator->cred)) { + netlogon_creds_step(creds); + if (netlogon_creds_server_check_internal(creds, &received_authenticator->cred)) { return_authenticator->cred = creds->server; return_authenticator->timestamp = creds->sequence; return NT_STATUS_OK; @@ -316,7 +386,7 @@ NTSTATUS creds_server_step_check(struct creds_CredentialState *creds, } } -void creds_decrypt_samlogon(struct creds_CredentialState *creds, +void netlogon_creds_decrypt_samlogon(struct netlogon_creds_CredentialState *creds, uint16_t validation_level, union netr_Validation *validation) { @@ -354,22 +424,23 @@ void creds_decrypt_samlogon(struct creds_CredentialState *creds, } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { if (memcmp(base->key.key, zeros, sizeof(base->key.key)) != 0) { - creds_arcfour_crypt(creds, + netlogon_creds_arcfour_crypt(creds, base->key.key, sizeof(base->key.key)); } if (memcmp(base->LMSessKey.key, zeros, sizeof(base->LMSessKey.key)) != 0) { - creds_arcfour_crypt(creds, + netlogon_creds_arcfour_crypt(creds, base->LMSessKey.key, sizeof(base->LMSessKey.key)); } } else { if (memcmp(base->LMSessKey.key, zeros, sizeof(base->LMSessKey.key)) != 0) { - creds_des_decrypt_LMKey(creds, + netlogon_creds_des_decrypt_LMKey(creds, &base->LMSessKey); } } } + diff --git a/source4/libcli/auth/credentials.h b/libcli/auth/credentials.h index 4e11cb090f..b84b902fa0 100644 --- a/source4/libcli/auth/credentials.h +++ b/libcli/auth/credentials.h @@ -21,7 +21,7 @@ #include "librpc/gen_ndr/netlogon.h" -struct creds_CredentialState { +struct netlogon_creds_CredentialState { uint32_t negotiate_flags; uint8_t session_key[16]; uint32_t sequence; @@ -29,18 +29,56 @@ struct creds_CredentialState { struct netr_Credential client; struct netr_Credential server; uint16_t secure_channel_type; - const char *domain; const char *computer_name; const char *account_name; struct dom_sid *sid; }; -/* for the timebeing, use the same neg flags as Samba3. */ /* The 7 here seems to be required to get Win2k not to downgrade us to NT4. Actually, anything other than 1ff would seem to do... */ -#define NETLOGON_NEG_AUTH2_FLAGS 0x000701ff +#define NETLOGON_NEG_AUTH2_FLAGS 0x000701ff +/* + (NETLOGON_NEG_ACCOUNT_LOCKOUT | + NETLOGON_NEG_PERSISTENT_SAMREPL | + NETLOGON_NEG_ARCFOUR | + NETLOGON_NEG_PROMOTION_COUNT | + NETLOGON_NEG_CHANGELOG_BDC | + NETLOGON_NEG_FULL_SYNC_REPL | + NETLOGON_NEG_MULTIPLE_SIDS | + NETLOGON_NEG_REDO | + NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL | + NETLOGON_NEG_DNS_DOMAIN_TRUSTS | + NETLOGON_NEG_PASSWORD_SET2 | + NETLOGON_NEG_GETDOMAININFO) +*/ +#define NETLOGON_NEG_DOMAIN_TRUST_ACCOUNT 0x2010b000 /* these are the flags that ADS clients use */ +/* + (NETLOGON_NEG_ACCOUNT_LOCKOUT | + NETLOGON_NEG_PERSISTENT_SAMREPL | + NETLOGON_NEG_ARCFOUR | + NETLOGON_NEG_PROMOTION_COUNT | + NETLOGON_NEG_CHANGELOG_BDC | + NETLOGON_NEG_FULL_SYNC_REPL | + NETLOGON_NEG_MULTIPLE_SIDS | + NETLOGON_NEG_REDO | + NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL | + NETLOGON_NEG_SEND_PASSWORD_INFO_PDC | + NETLOGON_NEG_GENERIC_PASSTHROUGH | + NETLOGON_NEG_CONCURRENT_RPC | + NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL | + NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL | + NETLOGON_NEG_128BIT | + NETLOGON_NEG_TRANSITIVE_TRUSTS | + NETLOGON_NEG_DNS_DOMAIN_TRUSTS | + NETLOGON_NEG_PASSWORD_SET2 | + NETLOGON_NEG_GETDOMAININFO | + NETLOGON_NEG_CROSS_FOREST_TRUSTS | + NETLOGON_NEG_AUTHENTICATED_RPC_LSASS | + NETLOGON_NEG_SCHANNEL) +*/ + #define NETLOGON_NEG_AUTH2_ADS_FLAGS (0x200fbffb | NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT | NETLOGON_NEG_SCHANNEL) diff --git a/source4/libcli/auth/libcli_auth.h b/libcli/auth/libcli_auth.h index ec1c1e7d98..be43007d85 100644 --- a/source4/libcli/auth/libcli_auth.h +++ b/libcli/auth/libcli_auth.h @@ -18,7 +18,15 @@ #define __LIBCLI_AUTH_H__ #include "librpc/gen_ndr/netlogon.h" +#include "librpc/gen_ndr/wkssvc.h" #include "libcli/auth/credentials.h" +#include "libcli/auth/ntlm_check.h" #include "libcli/auth/proto.h" +#include "libcli/auth/msrpc_parse.h" + +#define NTLMSSP_NAME_TYPE_SERVER 0x01 +#define NTLMSSP_NAME_TYPE_DOMAIN 0x02 +#define NTLMSSP_NAME_TYPE_SERVER_DNS 0x03 +#define NTLMSSP_NAME_TYPE_DOMAIN_DNS 0x04 #endif /* __LIBCLI_AUTH_H__ */ diff --git a/source4/auth/ntlmssp/ntlmssp_parse.c b/libcli/auth/msrpc_parse.c index 969845d6c5..2f78f5f190 100644 --- a/source4/auth/ntlmssp/ntlmssp_parse.c +++ b/libcli/auth/msrpc_parse.c @@ -20,7 +20,7 @@ */ #include "includes.h" -#include "auth/ntlmssp/msrpc_parse.h" +#include "libcli/auth/msrpc_parse.h" /* this is a tiny msrpc packet generator. I am only using this to @@ -209,7 +209,7 @@ bool msrpc_parse(TALLOC_CTX *mem_ctx, { int i; va_list ap; - const char **ps, *s; + char **ps, *s; DATA_BLOB *b; size_t head_ofs = 0; uint16_t len1, len2; @@ -228,9 +228,9 @@ bool msrpc_parse(TALLOC_CTX *mem_ctx, len2 = SVAL(blob->data, head_ofs); head_ofs += 2; ptr = IVAL(blob->data, head_ofs); head_ofs += 4; - ps = (const char **)va_arg(ap, char **); + ps = va_arg(ap, char **); if (len1 == 0 && len2 == 0) { - *ps = ""; + *ps = discard_const(""); } else { /* make sure its in the right format - be strict */ if ((len1 != len2) || (ptr + len1 < ptr) || (ptr + len1 < len1) || (ptr + len1 > blob->length)) { @@ -249,15 +249,15 @@ bool msrpc_parse(TALLOC_CTX *mem_ctx, } if (0 < len1) { - pull_string(p, blob->data + ptr, p_len, - len1, STR_UNICODE|STR_NOALIGN); - (*ps) = talloc_strdup(mem_ctx, p); - if (!(*ps)) { + size_t pull_len; + if (!convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, + blob->data + ptr, len1, + ps, &pull_len, false)) { ret = false; goto cleanup; } } else { - (*ps) = ""; + (*ps) = discard_const(""); } } break; @@ -267,10 +267,10 @@ bool msrpc_parse(TALLOC_CTX *mem_ctx, len2 = SVAL(blob->data, head_ofs); head_ofs += 2; ptr = IVAL(blob->data, head_ofs); head_ofs += 4; - ps = (const char **)va_arg(ap, char **); + ps = (char **)va_arg(ap, char **); /* make sure its in the right format - be strict */ if (len1 == 0 && len2 == 0) { - *ps = ""; + *ps = discard_const(""); } else { if ((len1 != len2) || (ptr + len1 < ptr) || (ptr + len1 < len1) || (ptr + len1 > blob->length)) { ret = false; @@ -284,15 +284,16 @@ bool msrpc_parse(TALLOC_CTX *mem_ctx, } if (0 < len1) { - pull_string(p, blob->data + ptr, p_len, - len1, STR_ASCII|STR_NOALIGN); - (*ps) = talloc_strdup(mem_ctx, p); - if (!(*ps)) { + size_t pull_len; + + if (!convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, + blob->data + ptr, len1, + ps, &pull_len, false)) { ret = false; goto cleanup; } } else { - (*ps) = ""; + (*ps) = discard_const(""); } } break; @@ -344,19 +345,18 @@ bool msrpc_parse(TALLOC_CTX *mem_ctx, s = va_arg(ap, char *); if (blob->data + head_ofs < (uint8_t *)head_ofs || - blob->data + head_ofs < blob->data) { + blob->data + head_ofs < blob->data || + (head_ofs + (strlen(s) + 1)) > blob->length) { ret = false; goto cleanup; } - head_ofs += pull_string(p, - blob->data+head_ofs, p_len, - blob->length - head_ofs, - STR_ASCII|STR_TERMINATE); - if (strcmp(s, p) != 0) { + if (memcmp(blob->data + head_ofs, s, strlen(s)+1) != 0) { ret = false; goto cleanup; } + head_ofs += (strlen(s) + 1); + break; } } diff --git a/source4/auth/ntlm/ntlm_check.c b/libcli/auth/ntlm_check.c index 0805b1b043..2cfe8e1ef8 100644 --- a/source4/auth/ntlm/ntlm_check.c +++ b/libcli/auth/ntlm_check.c @@ -23,7 +23,6 @@ #include "../lib/crypto/crypto.h" #include "librpc/gen_ndr/netlogon.h" #include "libcli/auth/libcli_auth.h" -#include "auth/ntlm/ntlm_check.h" /**************************************************************************** Core of smb password checking routine. @@ -357,9 +356,8 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, client_domain, false, user_sess_key)) { - *lm_sess_key = *user_sess_key; if (user_sess_key->length) { - lm_sess_key->length = 8; + *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length)); } return NT_STATUS_OK; } @@ -372,9 +370,8 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, client_domain, true, user_sess_key)) { - *lm_sess_key = *user_sess_key; if (user_sess_key->length) { - lm_sess_key->length = 8; + *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length)); } return NT_STATUS_OK; } @@ -387,9 +384,8 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, "", false, user_sess_key)) { - *lm_sess_key = *user_sess_key; if (user_sess_key->length) { - lm_sess_key->length = 8; + *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length)); } return NT_STATUS_OK; } else { @@ -409,7 +405,7 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, so use it only if we otherwise allow LM authentication */ if (lanman_auth && stored_lanman) { - *lm_sess_key = data_blob_talloc(mem_ctx, stored_lanman->hash, 8); + *lm_sess_key = data_blob_talloc(mem_ctx, stored_lanman->hash, MIN(8, user_sess_key->length)); } return NT_STATUS_OK; } else { @@ -498,9 +494,8 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, /* Otherwise, use the LMv2 session key */ *user_sess_key = tmp_sess_key; } - *lm_sess_key = *user_sess_key; if (user_sess_key->length) { - lm_sess_key->length = 8; + *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length)); } return NT_STATUS_OK; } @@ -529,9 +524,8 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, /* Otherwise, use the LMv2 session key */ *user_sess_key = tmp_sess_key; } - *lm_sess_key = *user_sess_key; if (user_sess_key->length) { - lm_sess_key->length = 8; + *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length)); } return NT_STATUS_OK; } @@ -560,9 +554,8 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, /* Otherwise, use the LMv2 session key */ *user_sess_key = tmp_sess_key; } - *lm_sess_key = *user_sess_key; if (user_sess_key->length) { - lm_sess_key->length = 8; + *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length)); } return NT_STATUS_OK; } diff --git a/source4/auth/ntlm/ntlm_check.h b/libcli/auth/ntlm_check.h index df11f7d7a2..df11f7d7a2 100644 --- a/source4/auth/ntlm/ntlm_check.h +++ b/libcli/auth/ntlm_check.h diff --git a/libcli/auth/schannel_state.c b/libcli/auth/schannel_state.c new file mode 100644 index 0000000000..e01330010b --- /dev/null +++ b/libcli/auth/schannel_state.c @@ -0,0 +1,321 @@ +/* + Unix SMB/CIFS implementation. + + module to store/fetch session keys for the schannel server + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2009 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "lib/ldb/include/ldb.h" +#include "librpc/gen_ndr/ndr_security.h" +#include "ldb_wrap.h" +#include "../lib/util/util_ldb.h" +#include "libcli/auth/libcli_auth.h" +#include "auth/auth.h" +#include "param/param.h" +#include "auth/gensec/schannel_state.h" + +static struct ldb_val *schannel_dom_sid_ldb_val(TALLOC_CTX *mem_ctx, + struct dom_sid *sid) +{ + enum ndr_err_code ndr_err; + struct ldb_val *v; + + v = talloc(mem_ctx, struct ldb_val); + if (!v) return NULL; + + ndr_err = ndr_push_struct_blob(v, mem_ctx, NULL, sid, + (ndr_push_flags_fn_t)ndr_push_dom_sid); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + talloc_free(v); + return NULL; + } + + return v; +} + +static struct dom_sid *schannel_ldb_val_dom_sid(TALLOC_CTX *mem_ctx, + const struct ldb_val *v) +{ + enum ndr_err_code ndr_err; + struct dom_sid *sid; + + sid = talloc(mem_ctx, struct dom_sid); + if (!sid) return NULL; + + ndr_err = ndr_pull_struct_blob(v, sid, NULL, sid, + (ndr_pull_flags_fn_t)ndr_pull_dom_sid); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + talloc_free(sid); + return NULL; + } + return sid; +} + + +/* + remember an established session key for a netr server authentication + use a simple ldb structure +*/ +NTSTATUS schannel_store_session_key(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct netlogon_creds_CredentialState *creds) +{ + struct ldb_message *msg; + struct ldb_val val, seed, client_state, server_state; + struct ldb_val *sid_val; + char *f; + char *sct; + int ret; + + f = talloc_asprintf(mem_ctx, "%u", (unsigned int)creds->negotiate_flags); + + if (f == NULL) { + return NT_STATUS_NO_MEMORY; + } + + sct = talloc_asprintf(mem_ctx, "%u", (unsigned int)creds->secure_channel_type); + + if (sct == NULL) { + return NT_STATUS_NO_MEMORY; + } + + msg = ldb_msg_new(ldb); + if (msg == NULL) { + return NT_STATUS_NO_MEMORY; + } + + msg->dn = ldb_dn_new_fmt(msg, ldb, "computerName=%s", creds->computer_name); + if ( ! msg->dn) { + return NT_STATUS_NO_MEMORY; + } + + sid_val = schannel_dom_sid_ldb_val(msg, creds->sid); + if (sid_val == NULL) { + return NT_STATUS_NO_MEMORY; + } + + val.data = creds->session_key; + val.length = sizeof(creds->session_key); + + seed.data = creds->seed.data; + seed.length = sizeof(creds->seed.data); + + client_state.data = creds->client.data; + client_state.length = sizeof(creds->client.data); + server_state.data = creds->server.data; + server_state.length = sizeof(creds->server.data); + + ldb_msg_add_string(msg, "objectClass", "schannelState"); + ldb_msg_add_value(msg, "sessionKey", &val, NULL); + ldb_msg_add_value(msg, "seed", &seed, NULL); + ldb_msg_add_value(msg, "clientState", &client_state, NULL); + ldb_msg_add_value(msg, "serverState", &server_state, NULL); + ldb_msg_add_string(msg, "negotiateFlags", f); + ldb_msg_add_string(msg, "secureChannelType", sct); + ldb_msg_add_string(msg, "accountName", creds->account_name); + ldb_msg_add_string(msg, "computerName", creds->computer_name); + ldb_msg_add_value(msg, "objectSid", sid_val, NULL); + + ret = ldb_add(ldb, msg); + if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) { + int i; + /* from samdb_replace() */ + /* mark all the message elements as LDB_FLAG_MOD_REPLACE */ + for (i=0;i<msg->num_elements;i++) { + msg->elements[i].flags = LDB_FLAG_MOD_REPLACE; + } + + ret = ldb_modify(ldb, msg); + } + + /* We don't need a transaction here, as we either add or + * modify records, never delete them, so it must exist */ + + if (ret != LDB_SUCCESS) { + DEBUG(0,("Unable to add %s to session key db - %s\n", + ldb_dn_get_linearized(msg->dn), ldb_errstring(ldb))); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + return NT_STATUS_OK; +} + +/* + read back a credentials back for a computer +*/ +NTSTATUS schannel_fetch_session_key(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const char *computer_name, + struct netlogon_creds_CredentialState **creds) +{ + struct ldb_result *res; + int ret; + const struct ldb_val *val; + + *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState); + if (!*creds) { + return NT_STATUS_NO_MEMORY; + } + + ret = ldb_search(ldb, mem_ctx, &res, + NULL, LDB_SCOPE_SUBTREE, NULL, + "(computerName=%s)", computer_name); + if (ret != LDB_SUCCESS) { + DEBUG(3,("schannel: Failed to find a record for client %s: %s\n", computer_name, ldb_errstring(ldb))); + return NT_STATUS_INVALID_HANDLE; + } + if (res->count != 1) { + DEBUG(3,("schannel: Failed to find a record for client: %s (found %d records)\n", computer_name, res->count)); + talloc_free(res); + return NT_STATUS_INVALID_HANDLE; + } + + val = ldb_msg_find_ldb_val(res->msgs[0], "sessionKey"); + if (val == NULL || val->length != 16) { + DEBUG(1,("schannel: record in schannel DB must contain a sessionKey of length 16, when searching for client: %s\n", computer_name)); + talloc_free(res); + return NT_STATUS_INTERNAL_ERROR; + } + + memcpy((*creds)->session_key, val->data, 16); + + val = ldb_msg_find_ldb_val(res->msgs[0], "seed"); + if (val == NULL || val->length != 8) { + DEBUG(1,("schannel: record in schannel DB must contain a vaid seed of length 8, when searching for client: %s\n", computer_name)); + talloc_free(res); + return NT_STATUS_INTERNAL_ERROR; + } + + memcpy((*creds)->seed.data, val->data, 8); + + val = ldb_msg_find_ldb_val(res->msgs[0], "clientState"); + if (val == NULL || val->length != 8) { + DEBUG(1,("schannel: record in schannel DB must contain a vaid clientState of length 8, when searching for client: %s\n", computer_name)); + talloc_free(res); + return NT_STATUS_INTERNAL_ERROR; + } + memcpy((*creds)->client.data, val->data, 8); + + val = ldb_msg_find_ldb_val(res->msgs[0], "serverState"); + if (val == NULL || val->length != 8) { + DEBUG(1,("schannel: record in schannel DB must contain a vaid serverState of length 8, when searching for client: %s\n", computer_name)); + talloc_free(res); + return NT_STATUS_INTERNAL_ERROR; + } + memcpy((*creds)->server.data, val->data, 8); + + (*creds)->negotiate_flags = ldb_msg_find_attr_as_int(res->msgs[0], "negotiateFlags", 0); + + (*creds)->secure_channel_type = ldb_msg_find_attr_as_int(res->msgs[0], "secureChannelType", 0); + + (*creds)->account_name = talloc_strdup(*creds, ldb_msg_find_attr_as_string(res->msgs[0], "accountName", NULL)); + if ((*creds)->account_name == NULL) { + talloc_free(res); + return NT_STATUS_NO_MEMORY; + } + + (*creds)->computer_name = talloc_strdup(*creds, ldb_msg_find_attr_as_string(res->msgs[0], "computerName", NULL)); + if ((*creds)->computer_name == NULL) { + talloc_free(res); + return NT_STATUS_NO_MEMORY; + } + + val = ldb_msg_find_ldb_val(res->msgs[0], "objectSid"); + if (val) { + (*creds)->sid = schannel_ldb_val_dom_sid(*creds, val); + if ((*creds)->sid == NULL) { + talloc_free(res); + return NT_STATUS_INTERNAL_ERROR; + } + } else { + (*creds)->sid = NULL; + } + + talloc_free(res); + return NT_STATUS_OK; +} + +/* + Validate an incoming authenticator against the credentials for the remote machine. + + The credentials are (re)read and from the schannel database, and + written back after the caclulations are performed. + + The creds_out parameter (if not NULL) returns the credentials, if + the caller needs some of that information. + +*/ +NTSTATUS schannel_creds_server_step_check(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const char *computer_name, + bool schannel_required_for_call, + bool schannel_in_use, + struct netr_Authenticator *received_authenticator, + struct netr_Authenticator *return_authenticator, + struct netlogon_creds_CredentialState **creds_out) +{ + struct netlogon_creds_CredentialState *creds; + NTSTATUS nt_status; + int ret; + + ret = ldb_transaction_start(ldb); + if (ret != 0) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + /* Because this is a shared structure (even across + * disconnects) we must update the database every time we + * update the structure */ + + nt_status = schannel_fetch_session_key(ldb, ldb, computer_name, + &creds); + + /* If we are flaged that schannel is required for a call, and + * it is not in use, then make this an error */ + + /* It would be good to make this mandetory once schannel is + * negoiated, bu this is not what windows does */ + if (schannel_required_for_call && !schannel_in_use) { + DEBUG(0,("schannel_creds_server_step_check: client %s not using schannel for netlogon, despite negotiating it\n", + creds->computer_name )); + ldb_transaction_cancel(ldb); + return NT_STATUS_ACCESS_DENIED; + } + + if (NT_STATUS_IS_OK(nt_status)) { + nt_status = netlogon_creds_server_step_check(creds, + received_authenticator, + return_authenticator); + } + + if (NT_STATUS_IS_OK(nt_status)) { + nt_status = schannel_store_session_key(ldb, mem_ctx, creds); + } + + if (NT_STATUS_IS_OK(nt_status)) { + ldb_transaction_commit(ldb); + if (creds_out) { + *creds_out = creds; + talloc_steal(mem_ctx, creds); + } + } else { + ldb_transaction_cancel(ldb); + } + return nt_status; +} diff --git a/libcli/auth/schannel_state.h b/libcli/auth/schannel_state.h new file mode 100644 index 0000000000..048baa90d2 --- /dev/null +++ b/libcli/auth/schannel_state.h @@ -0,0 +1,24 @@ +/* + Unix SMB/CIFS implementation. + + module to store/fetch session keys for the schannel server + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +struct ldb_context; +#include "libcli/auth/schannel_state_proto.h" diff --git a/source4/libcli/auth/session.c b/libcli/auth/session.c index 10c728662d..10c728662d 100644 --- a/source4/libcli/auth/session.c +++ b/libcli/auth/session.c diff --git a/source4/libcli/auth/smbdes.c b/libcli/auth/smbdes.c index 32e65e779d..32e65e779d 100644 --- a/source4/libcli/auth/smbdes.c +++ b/libcli/auth/smbdes.c diff --git a/source4/libcli/auth/smbencrypt.c b/libcli/auth/smbencrypt.c index c6118c6568..7659446b75 100644 --- a/source4/libcli/auth/smbencrypt.c +++ b/libcli/auth/smbencrypt.c @@ -23,35 +23,42 @@ #include "includes.h" #include "system/time.h" -#include "auth/ntlmssp/ntlmssp.h" -#include "auth/ntlmssp/msrpc_parse.h" +#include "../libcli/auth/msrpc_parse.h" #include "../lib/crypto/crypto.h" -#include "libcli/auth/libcli_auth.h" +#include "../libcli/auth/libcli_auth.h" -/* - This implements the X/Open SMB password encryption - It takes a password ('unix' string), a 8 byte "crypt key" - and puts 24 bytes of encrypted password into p24 - - Returns false if password must have been truncated to create LM hash -*/ -bool SMBencrypt(const char *passwd, const uint8_t *c8, uint8_t p24[24]) +void SMBencrypt_hash(const uint8_t lm_hash[16], const uint8_t *c8, uint8_t p24[24]) { - bool ret; uint8_t p21[21]; memset(p21,'\0',21); - ret = E_deshash(passwd, p21); + memcpy(p21, lm_hash, 16); SMBOWFencrypt(p21, c8, p24); #ifdef DEBUG_PASSWORD - DEBUG(100,("SMBencrypt: lm#, challenge, response\n")); + DEBUG(100,("SMBencrypt_hash: lm#, challenge, response\n")); dump_data(100, p21, 16); dump_data(100, c8, 8); dump_data(100, p24, 24); #endif +} +/* + This implements the X/Open SMB password encryption + It takes a password ('unix' string), a 8 byte "crypt key" + and puts 24 bytes of encrypted password into p24 + + Returns False if password must have been truncated to create LM hash +*/ + +bool SMBencrypt(const char *passwd, const uint8_t *c8, uint8_t p24[24]) +{ + bool ret; + uint8_t lm_hash[16]; + + ret = E_deshash(passwd, lm_hash); + SMBencrypt_hash(lm_hash, c8, p24); return ret; } @@ -83,6 +90,26 @@ bool E_md4hash(const char *passwd, uint8_t p16[16]) } /** + * Creates the MD5 Hash of a combination of 16 byte salt and 16 byte NT hash. + * @param 16 byte salt. + * @param 16 byte NT hash. + * @param 16 byte return hashed with md5, caller allocated 16 byte buffer + */ + +void E_md5hash(const uint8_t salt[16], const uint8_t nthash[16], uint8_t hash_out[16]) +{ + struct MD5Context tctx; + uint8_t array[32]; + + memset(hash_out, '\0', 16); + memcpy(array, salt, 16); + memcpy(&array[16], nthash, 16); + MD5Init(&tctx); + MD5Update(&tctx, array, 32); + MD5Final(hash_out, &tctx); +} + +/** * Creates the DES forward-only Hash of the users password in DOS ASCII charset * @param passwd password in 'unix' charset. * @param p16 return password hashed with DES, caller allocated 16 byte buffer @@ -111,6 +138,36 @@ bool E_deshash(const char *passwd, uint8_t p16[16]) return ret; } +/** + * Creates the MD4 and DES (LM) Hash of the users password. + * MD4 is of the NT Unicode, DES is of the DOS UPPERCASE password. + * @param passwd password in 'unix' charset. + * @param nt_p16 return password hashed with md4, caller allocated 16 byte buffer + * @param p16 return password hashed with des, caller allocated 16 byte buffer + */ + +/* Does both the NT and LM owfs of a user's password */ +void nt_lm_owf_gen(const char *pwd, uint8_t nt_p16[16], uint8_t p16[16]) +{ + /* Calculate the MD4 hash (NT compatible) of the password */ + memset(nt_p16, '\0', 16); + E_md4hash(pwd, nt_p16); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("nt_lm_owf_gen: pwd, nt#\n")); + dump_data(120, (uint8_t *)pwd, strlen(pwd)); + dump_data(100, nt_p16, 16); +#endif + + E_deshash(pwd, (uint8_t *)p16); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("nt_lm_owf_gen: pwd, lm#\n")); + dump_data(120, (uint8_t *)pwd, strlen(pwd)); + dump_data(100, p16, 16); +#endif +} + /* Does both the NTLMv2 owfs of a user's password */ bool ntv2_owf_gen(const uint8_t owf[16], const char *user_in, const char *domain_in, @@ -154,14 +211,14 @@ bool ntv2_owf_gen(const uint8_t owf[16], ret = push_ucs2_talloc(mem_ctx, &user, user_in, &user_byte_len ); if (!ret) { - DEBUG(0, ("push_uss2_talloc() for user returned -1 (probably talloc() failure)\n")); + DEBUG(0, ("push_uss2_talloc() for user failed)\n")); talloc_free(mem_ctx); return false; } ret = push_ucs2_talloc(mem_ctx, &domain, domain_in, &domain_byte_len); if (!ret) { - DEBUG(0, ("push_ucs2_talloc() for domain returned -1 (probably talloc() failure)\n")); + DEBUG(0, ("push_ucs2_talloc() for domain failed\n")); talloc_free(mem_ctx); return false; } @@ -201,15 +258,14 @@ void SMBOWFencrypt(const uint8_t passwd[16], const uint8_t *c8, uint8_t p24[24]) E_P24(p21, c8, p24); } -/* Does the NT MD4 hash then des encryption. */ +/* Does the des encryption. */ -void SMBNTencrypt(const char *passwd, uint8_t *c8, uint8_t *p24) +void SMBNTencrypt_hash(const uint8_t nt_hash[16], uint8_t *c8, uint8_t *p24) { uint8_t p21[21]; memset(p21,'\0',21); - - E_md4hash(passwd, p21); + memcpy(p21, nt_hash, 16); SMBOWFencrypt(p21, c8, p24); #ifdef DEBUG_PASSWORD @@ -220,6 +276,16 @@ void SMBNTencrypt(const char *passwd, uint8_t *c8, uint8_t *p24) #endif } +/* Does the NT MD4 hash then des encryption. Plaintext version of the above. */ + +void SMBNTencrypt(const char *passwd, uint8_t *c8, uint8_t *p24) +{ + uint8_t nt_hash[16]; + E_md4hash(passwd, nt_hash); + SMBNTencrypt_hash(nt_hash, c8, p24); +} + + /* Does the md5 encryption from the Key Response for NTLMv2. */ void SMBOWFencrypt_ntv2(const uint8_t kr[16], const DATA_BLOB *srv_chal, @@ -494,14 +560,17 @@ bool encode_pw_buffer(uint8_t buffer[516], const char *password, int string_flag *new_pw_len is the length in bytes of the possibly mulitbyte returned password including termination. ************************************************************/ -bool decode_pw_buffer(uint8_t in_buffer[516], char *new_pwrd, - int new_pwrd_size, int string_flags) + +bool decode_pw_buffer(TALLOC_CTX *ctx, + uint8_t in_buffer[516], + char **pp_new_pwrd, + size_t *new_pw_len, + charset_t string_charset) { int byte_len=0; - ssize_t converted_pw_len; - /* the incoming buffer can be any alignment. */ - string_flags |= STR_NOALIGN; + *pp_new_pwrd = NULL; + *new_pw_len = 0; /* Warning !!! : This function is called from some rpc call. @@ -520,28 +589,52 @@ bool decode_pw_buffer(uint8_t in_buffer[516], char *new_pwrd, /* Password cannot be longer than the size of the password buffer */ if ( (byte_len < 0) || (byte_len > 512)) { + DEBUG(0, ("decode_pw_buffer: incorrect password length (%d).\n", byte_len)); + DEBUG(0, ("decode_pw_buffer: check that 'encrypt passwords = yes'\n")); return false; } - /* decode into the return buffer. Buffer length supplied */ - converted_pw_len = pull_string(new_pwrd, &in_buffer[512 - byte_len], new_pwrd_size, - byte_len, string_flags); - - if (converted_pw_len == -1) { + /* decode into the return buffer. */ + if (!convert_string_talloc(ctx, string_charset, CH_UNIX, + &in_buffer[512 - byte_len], + byte_len, + (void *)pp_new_pwrd, + new_pw_len, + false)) { + DEBUG(0, ("decode_pw_buffer: failed to convert incoming password\n")); return false; } #ifdef DEBUG_PASSWORD DEBUG(100,("decode_pw_buffer: new_pwrd: ")); - dump_data(100, (const uint8_t *)new_pwrd, converted_pw_len); - DEBUG(100,("multibyte len:%d\n", (int)converted_pw_len)); + dump_data(100, (uint8_t *)*pp_new_pwrd, *new_pw_len); + DEBUG(100,("multibyte len:%lu\n", (unsigned long int)*new_pw_len)); DEBUG(100,("original char len:%d\n", byte_len/2)); #endif - + return true; } /*********************************************************** + Decode an arc4 encrypted password change buffer. +************************************************************/ + +void encode_or_decode_arc4_passwd_buffer(unsigned char pw_buf[532], const DATA_BLOB *psession_key) +{ + struct MD5Context tctx; + unsigned char key_out[16]; + + /* Confounder is last 16 bytes. */ + + MD5Init(&tctx); + MD5Update(&tctx, &pw_buf[516], 16); + MD5Update(&tctx, psession_key->data, psession_key->length); + MD5Final(key_out, &tctx); + /* arc4 with key_out. */ + arcfour_crypt(pw_buf, key_out, 516); +} + +/*********************************************************** encode a password buffer with an already unicode password. The rest of the buffer is filled with random data to make it harder to attack. ************************************************************/ @@ -593,3 +686,97 @@ bool extract_pw_from_buffer(TALLOC_CTX *mem_ctx, return true; } + + +/* encode a wkssvc_PasswordBuffer: + * + * similar to samr_CryptPasswordEx. Different: 8byte confounder (instead of + * 16byte), confounder in front of the 516 byte buffer (instead of after that + * buffer), calling MD5Update() first with session_key and then with confounder + * (vice versa in samr) - Guenther */ + +void encode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx, + const char *pwd, + DATA_BLOB *session_key, + struct wkssvc_PasswordBuffer **pwd_buf) +{ + uint8_t buffer[516]; + struct MD5Context ctx; + struct wkssvc_PasswordBuffer *my_pwd_buf = NULL; + DATA_BLOB confounded_session_key; + int confounder_len = 8; + uint8_t confounder[8]; + + my_pwd_buf = talloc_zero(mem_ctx, struct wkssvc_PasswordBuffer); + if (!my_pwd_buf) { + return; + } + + confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16); + + encode_pw_buffer(buffer, pwd, STR_UNICODE); + + generate_random_buffer((uint8_t *)confounder, confounder_len); + + MD5Init(&ctx); + MD5Update(&ctx, session_key->data, session_key->length); + MD5Update(&ctx, confounder, confounder_len); + MD5Final(confounded_session_key.data, &ctx); + + arcfour_crypt_blob(buffer, 516, &confounded_session_key); + + memcpy(&my_pwd_buf->data[0], confounder, confounder_len); + memcpy(&my_pwd_buf->data[8], buffer, 516); + + data_blob_free(&confounded_session_key); + + *pwd_buf = my_pwd_buf; +} + +WERROR decode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx, + struct wkssvc_PasswordBuffer *pwd_buf, + DATA_BLOB *session_key, + char **pwd) +{ + uint8_t buffer[516]; + struct MD5Context ctx; + size_t pwd_len; + + DATA_BLOB confounded_session_key; + + int confounder_len = 8; + uint8_t confounder[8]; + + *pwd = NULL; + + if (!pwd_buf) { + return WERR_BAD_PASSWORD; + } + + if (session_key->length != 16) { + DEBUG(10,("invalid session key\n")); + return WERR_BAD_PASSWORD; + } + + confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16); + + memcpy(&confounder, &pwd_buf->data[0], confounder_len); + memcpy(&buffer, &pwd_buf->data[8], 516); + + MD5Init(&ctx); + MD5Update(&ctx, session_key->data, session_key->length); + MD5Update(&ctx, confounder, confounder_len); + MD5Final(confounded_session_key.data, &ctx); + + arcfour_crypt_blob(buffer, 516, &confounded_session_key); + + if (!decode_pw_buffer(mem_ctx, buffer, pwd, &pwd_len, CH_UTF16)) { + data_blob_free(&confounded_session_key); + return WERR_BAD_PASSWORD; + } + + data_blob_free(&confounded_session_key); + + return WERR_OK; +} + diff --git a/libcli/drsuapi/config.mk b/libcli/drsuapi/config.mk new file mode 100644 index 0000000000..cb002ca3dc --- /dev/null +++ b/libcli/drsuapi/config.mk @@ -0,0 +1,8 @@ +[SUBSYSTEM::LIBCLI_DRSUAPI] +PUBLIC_DEPENDENCIES = \ + LIBCLI_AUTH + +LIBCLI_DRSUAPI_OBJ_FILES = $(addprefix $(libclicommonsrcdir)/drsuapi/, \ + repl_decrypt.o) + +PUBLIC_HEADERS += ../libcli/drsuapi/drsuapi.h diff --git a/libcli/drsuapi/drsuapi.h b/libcli/drsuapi/drsuapi.h new file mode 100644 index 0000000000..b95350779a --- /dev/null +++ b/libcli/drsuapi/drsuapi.h @@ -0,0 +1,33 @@ +/* + Unix SMB/CIFS mplementation. + Helper functions for applying replicated objects + + Copyright (C) Stefan Metzmacher <metze@samba.org> 2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +WERROR drsuapi_decrypt_attribute_value(TALLOC_CTX *mem_ctx, + const DATA_BLOB *gensec_skey, + bool rid_crypt, + uint32_t rid, + DATA_BLOB *in, + DATA_BLOB *out); + +WERROR drsuapi_decrypt_attribute(TALLOC_CTX *mem_ctx, + const DATA_BLOB *gensec_skey, + uint32_t rid, + struct drsuapi_DsReplicaAttribute *attr); + diff --git a/libcli/drsuapi/repl_decrypt.c b/libcli/drsuapi/repl_decrypt.c new file mode 100644 index 0000000000..9d7c1b6acf --- /dev/null +++ b/libcli/drsuapi/repl_decrypt.c @@ -0,0 +1,188 @@ +/* + Unix SMB/CIFS mplementation. + Helper functions for applying replicated objects + + Copyright (C) Stefan Metzmacher <metze@samba.org> 2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "includes.h" +#include "../lib/util/dlinklist.h" +#include "librpc/gen_ndr/ndr_misc.h" +#include "librpc/gen_ndr/ndr_drsuapi.h" +#include "librpc/gen_ndr/ndr_drsblobs.h" +#include "../lib/crypto/crypto.h" +#include "../libcli/drsuapi/drsuapi.h" +#include "libcli/auth/libcli_auth.h" + +WERROR drsuapi_decrypt_attribute_value(TALLOC_CTX *mem_ctx, + const DATA_BLOB *gensec_skey, + bool rid_crypt, + uint32_t rid, + DATA_BLOB *in, + DATA_BLOB *out) +{ + DATA_BLOB confounder; + DATA_BLOB enc_buffer; + + struct MD5Context md5; + uint8_t _enc_key[16]; + DATA_BLOB enc_key; + + DATA_BLOB dec_buffer; + + uint32_t crc32_given; + uint32_t crc32_calc; + DATA_BLOB checked_buffer; + + DATA_BLOB plain_buffer; + + /* + * users with rid == 0 should not exist + */ + if (rid_crypt && rid == 0) { + return WERR_DS_DRA_INVALID_PARAMETER; + } + + /* + * the first 16 bytes at the beginning are the confounder + * followed by the 4 byte crc32 checksum + */ + if (in->length < 20) { + return WERR_DS_DRA_INVALID_PARAMETER; + } + confounder = data_blob_const(in->data, 16); + enc_buffer = data_blob_const(in->data + 16, in->length - 16); + + /* + * build the encryption key md5 over the session key followed + * by the confounder + * + * here the gensec session key is used and + * not the dcerpc ncacn_ip_tcp "SystemLibraryDTC" key! + */ + enc_key = data_blob_const(_enc_key, sizeof(_enc_key)); + MD5Init(&md5); + MD5Update(&md5, gensec_skey->data, gensec_skey->length); + MD5Update(&md5, confounder.data, confounder.length); + MD5Final(enc_key.data, &md5); + + /* + * copy the encrypted buffer part and + * decrypt it using the created encryption key using arcfour + */ + dec_buffer = data_blob_const(enc_buffer.data, enc_buffer.length); + arcfour_crypt_blob(dec_buffer.data, dec_buffer.length, &enc_key); + + /* + * the first 4 byte are the crc32 checksum + * of the remaining bytes + */ + crc32_given = IVAL(dec_buffer.data, 0); + crc32_calc = crc32_calc_buffer(dec_buffer.data + 4 , dec_buffer.length - 4); + if (crc32_given != crc32_calc) { + return WERR_SEC_E_DECRYPT_FAILURE; + } + checked_buffer = data_blob_const(dec_buffer.data + 4, dec_buffer.length - 4); + + plain_buffer = data_blob_talloc(mem_ctx, checked_buffer.data, checked_buffer.length); + W_ERROR_HAVE_NO_MEMORY(plain_buffer.data); + + /* + * The following rid_crypt obfuscation isn't session specific + * and not really needed here, because we allways know the rid of the + * user account. + * + * some attributes with this 'additional encryption' include + * dBCSPwd, unicodePwd, ntPwdHistory, lmPwdHistory + * + * But for the rest of samba it's easier when we remove this static + * obfuscation here + */ + if (rid_crypt) { + uint32_t i, num_hashes; + + if ((checked_buffer.length % 16) != 0) { + return WERR_DS_DRA_INVALID_PARAMETER; + } + + num_hashes = plain_buffer.length / 16; + for (i = 0; i < num_hashes; i++) { + uint32_t offset = i * 16; + sam_rid_crypt(rid, checked_buffer.data + offset, plain_buffer.data + offset, 0); + } + } + + *out = plain_buffer; + return WERR_OK; +} + +WERROR drsuapi_decrypt_attribute(TALLOC_CTX *mem_ctx, + const DATA_BLOB *gensec_skey, + uint32_t rid, + struct drsuapi_DsReplicaAttribute *attr) +{ + WERROR status; + DATA_BLOB *enc_data; + DATA_BLOB plain_data; + bool rid_crypt = false; + + if (attr->value_ctr.num_values == 0) { + return WERR_OK; + } + + switch (attr->attid) { + case DRSUAPI_ATTRIBUTE_dBCSPwd: + case DRSUAPI_ATTRIBUTE_unicodePwd: + case DRSUAPI_ATTRIBUTE_ntPwdHistory: + case DRSUAPI_ATTRIBUTE_lmPwdHistory: + rid_crypt = true; + break; + case DRSUAPI_ATTRIBUTE_supplementalCredentials: + case DRSUAPI_ATTRIBUTE_priorValue: + case DRSUAPI_ATTRIBUTE_currentValue: + case DRSUAPI_ATTRIBUTE_trustAuthOutgoing: + case DRSUAPI_ATTRIBUTE_trustAuthIncoming: + case DRSUAPI_ATTRIBUTE_initialAuthOutgoing: + case DRSUAPI_ATTRIBUTE_initialAuthIncoming: + break; + default: + return WERR_OK; + } + + if (attr->value_ctr.num_values > 1) { + return WERR_DS_DRA_INVALID_PARAMETER; + } + + if (!attr->value_ctr.values[0].blob) { + return WERR_DS_DRA_INVALID_PARAMETER; + } + + enc_data = attr->value_ctr.values[0].blob; + + status = drsuapi_decrypt_attribute_value(mem_ctx, + gensec_skey, + rid_crypt, + rid, + enc_data, + &plain_data); + W_ERROR_NOT_OK_RETURN(status); + + talloc_free(attr->value_ctr.values[0].blob->data); + *attr->value_ctr.values[0].blob = plain_data; + + return WERR_OK; +} diff --git a/libcli/samsync/config.mk b/libcli/samsync/config.mk new file mode 100644 index 0000000000..69f798342e --- /dev/null +++ b/libcli/samsync/config.mk @@ -0,0 +1,10 @@ +[SUBSYSTEM::LIBCLI_SAMSYNC] +PUBLIC_DEPENDENCIES = \ + LIBCLI_AUTH + +LIBCLI_SAMSYNC_OBJ_FILES = $(addprefix $(libclicommonsrcdir)/samsync/, \ + decrypt.o) + +PUBLIC_HEADERS += ../libcli/samsync/samsync.h + +$(eval $(call proto_header_template,$(libclicommonsrcdir)/samsync/samsync.h,$(LIBCLI_SAMSYNC_OBJ_FILES:.o=.c))) diff --git a/libcli/samsync/decrypt.c b/libcli/samsync/decrypt.c new file mode 100644 index 0000000000..b3fab712bc --- /dev/null +++ b/libcli/samsync/decrypt.c @@ -0,0 +1,174 @@ +/* + Unix SMB/CIFS implementation. + + Extract the user/system database from a remote SamSync server + + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005 + Copyright (C) Guenther Deschner <gd@samba.org> 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include "includes.h" +#include "../lib/crypto/crypto.h" +#include "../libcli/auth/libcli_auth.h" +#include "../libcli/samsync/samsync.h" +#include "librpc/gen_ndr/ndr_netlogon.h" + +/** + * Decrypt and extract the user's passwords. + * + * The writes decrypted (no longer 'RID encrypted' or arcfour encrypted) + * passwords back into the structure + */ + +static NTSTATUS fix_user(TALLOC_CTX *mem_ctx, + struct netlogon_creds_CredentialState *creds, + enum netr_SamDatabaseID database_id, + struct netr_DELTA_ENUM *delta) +{ + + uint32_t rid = delta->delta_id_union.rid; + struct netr_DELTA_USER *user = delta->delta_union.user; + struct samr_Password lm_hash; + struct samr_Password nt_hash; + unsigned char zero_buf[16]; + + memset(zero_buf, '\0', sizeof(zero_buf)); + + /* Note that win2000 may send us all zeros + * for the hashes if it doesn't + * think this channel is secure enough. */ + if (user->lm_password_present) { + if (memcmp(user->lmpassword.hash, zero_buf, 16) != 0) { + sam_rid_crypt(rid, user->lmpassword.hash, lm_hash.hash, 0); + } else { + memset(lm_hash.hash, '\0', sizeof(lm_hash.hash)); + } + user->lmpassword = lm_hash; + } + + if (user->nt_password_present) { + if (memcmp(user->ntpassword.hash, zero_buf, 16) != 0) { + sam_rid_crypt(rid, user->ntpassword.hash, nt_hash.hash, 0); + } else { + memset(nt_hash.hash, '\0', sizeof(nt_hash.hash)); + } + user->ntpassword = nt_hash; + } + + if (user->user_private_info.SensitiveData) { + DATA_BLOB data; + struct netr_USER_KEYS keys; + enum ndr_err_code ndr_err; + data.data = user->user_private_info.SensitiveData; + data.length = user->user_private_info.DataLength; + netlogon_creds_arcfour_crypt(creds, data.data, data.length); + user->user_private_info.SensitiveData = data.data; + user->user_private_info.DataLength = data.length; + + ndr_err = ndr_pull_struct_blob(&data, mem_ctx, NULL, &keys, + (ndr_pull_flags_fn_t)ndr_pull_netr_USER_KEYS); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + dump_data(10, data.data, data.length); + return ndr_map_error2ntstatus(ndr_err); + } + + /* Note that win2000 may send us all zeros + * for the hashes if it doesn't + * think this channel is secure enough. */ + if (keys.keys.keys2.lmpassword.length == 16) { + if (memcmp(keys.keys.keys2.lmpassword.pwd.hash, + zero_buf, 16) != 0) { + sam_rid_crypt(rid, + keys.keys.keys2.lmpassword.pwd.hash, + lm_hash.hash, 0); + } else { + memset(lm_hash.hash, '\0', sizeof(lm_hash.hash)); + } + user->lmpassword = lm_hash; + user->lm_password_present = true; + } + if (keys.keys.keys2.ntpassword.length == 16) { + if (memcmp(keys.keys.keys2.ntpassword.pwd.hash, + zero_buf, 16) != 0) { + sam_rid_crypt(rid, + keys.keys.keys2.ntpassword.pwd.hash, + nt_hash.hash, 0); + } else { + memset(nt_hash.hash, '\0', sizeof(nt_hash.hash)); + } + user->ntpassword = nt_hash; + user->nt_password_present = true; + } + /* TODO: rid decrypt history fields */ + } + return NT_STATUS_OK; +} + +/** + * Decrypt and extract the secrets + * + * The writes decrypted secrets back into the structure + */ +static NTSTATUS fix_secret(TALLOC_CTX *mem_ctx, + struct netlogon_creds_CredentialState *creds, + enum netr_SamDatabaseID database, + struct netr_DELTA_ENUM *delta) +{ + struct netr_DELTA_SECRET *secret = delta->delta_union.secret; + netlogon_creds_arcfour_crypt(creds, secret->current_cipher.cipher_data, + secret->current_cipher.maxlen); + + netlogon_creds_arcfour_crypt(creds, secret->old_cipher.cipher_data, + secret->old_cipher.maxlen); + + return NT_STATUS_OK; +} + +/** + * Fix up the delta, dealing with encryption issues so that the final + * callback need only do the printing or application logic + */ + +NTSTATUS samsync_fix_delta(TALLOC_CTX *mem_ctx, + struct netlogon_creds_CredentialState *creds, + enum netr_SamDatabaseID database_id, + struct netr_DELTA_ENUM *delta) +{ + NTSTATUS status = NT_STATUS_OK; + + switch (delta->delta_type) { + case NETR_DELTA_USER: + + status = fix_user(mem_ctx, + creds, + database_id, + delta); + break; + case NETR_DELTA_SECRET: + + status = fix_secret(mem_ctx, + creds, + database_id, + delta); + break; + default: + break; + } + + return status; +} + diff --git a/nsswitch/wbinfo.c b/nsswitch/wbinfo.c index 4d935f5239..1d7ad004ac 100644 --- a/nsswitch/wbinfo.c +++ b/nsswitch/wbinfo.c @@ -23,6 +23,7 @@ #include "includes.h" #include "winbind_client.h" #include "libwbclient/wbclient.h" +#include "../libcli/auth/libcli_auth.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND @@ -1323,11 +1324,11 @@ static bool wbinfo_auth_crap(char *username) server_chal = data_blob(params.password.response.challenge, 8); /* Pretend this is a login to 'us', for blob purposes */ - names_blob = NTLMv2_generate_names_blob(global_myname(), lp_workgroup()); + names_blob = NTLMv2_generate_names_blob(NULL, global_myname(), lp_workgroup()); - if (!SMBNTLMv2encrypt(name_user, name_domain, pass, &server_chal, + if (!SMBNTLMv2encrypt(NULL, name_user, name_domain, pass, &server_chal, &names_blob, - &lm, &nt, NULL)) { + &lm, &nt, NULL, NULL)) { data_blob_free(&names_blob); data_blob_free(&server_chal); SAFE_FREE(pass); diff --git a/source3/Makefile.in b/source3/Makefile.in index bd09be988d..b47c6e91b2 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -445,15 +445,16 @@ DOSERR_OBJ = ../libcli/util/doserr.o ERRORMAP_OBJ = libsmb/errormap.o DCE_RPC_ERR_OBJ = ../librpc/rpc/dcerpc_error.o -LIBSMB_ERR_OBJ0 = $(NTERR_OBJ) $(DOSERR_OBJ) $(ERRORMAP_OBJ) $(DCE_RPC_ERR_OBJ) \ - libsmb/smbdes.o libsmb/smbencrypt.o libsmb/ntlmssp_parse.o +LIBSMB_ERR_OBJ0 = $(NTERR_OBJ) $(DOSERR_OBJ) $(ERRORMAP_OBJ) $(DCE_RPC_ERR_OBJ) -LIBSMB_ERR_OBJ = $(LIBSMB_ERR_OBJ0) \ +LIBSMB_ERR_OBJ1 = ../libcli/auth/smbdes.o ../libcli/auth/smbencrypt.o ../libcli/auth/msrpc_parse.o ../libcli/auth/session.o + +LIBSMB_ERR_OBJ = $(LIBSMB_ERR_OBJ0) $(LIBSMB_ERR_OBJ1) \ $(RPC_PARSE_OBJ1) \ $(SECRETS_OBJ) LIBSMB_OBJ0 = \ - libsmb/ntlm_check.o \ + ../libcli/auth/ntlm_check.o \ libsmb/ntlmssp.o \ libsmb/ntlmssp_sign.o @@ -481,7 +482,7 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \ libsmb/clireadwrite.o libsmb/clilist.o libsmb/cliprint.o \ libsmb/clitrans.o libsmb/clisecdesc.o libsmb/clidgram.o \ libsmb/clistr.o libsmb/cliquota.o libsmb/clifsinfo.o libsmb/clidfs.o \ - libsmb/credentials.o \ + libsmb/credentials.o ../libcli/auth/credentials.o \ libsmb/clioplock.o libsmb/clirap2.o \ libsmb/smb_seal.o libsmb/async_smb.o \ $(LIBSAMBA_OBJ) \ @@ -929,7 +930,9 @@ LIBNET_OBJ = libnet/libnet_join.o \ libnet/libnet_samsync_keytab.o \ libnet/libnet_dssync.o \ libnet/libnet_dssync_keytab.o \ - librpc/gen_ndr/ndr_libnet_join.o + librpc/gen_ndr/ndr_libnet_join.o \ + ../libcli/samsync/decrypt.o \ + ../libcli/drsuapi/repl_decrypt.o NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_help.o \ utils/net_rap.o utils/net_rpc.o utils/net_rpc_samsync.o \ @@ -1145,7 +1148,7 @@ LDB_LDAP_OBJ=@LDBLDAP@ LDB_OBJ = ${LDB_COMMON_OBJ} ${LDB_TDB_OBJ} ${LDB_LDAP_OBJ} ${LDB_MODULES_OBJ} LDB_CMDLINE_OBJ = $(PARAM_OBJ) \ - $(POPT_LIB_OBJ) $(LIB_OBJ) $(LIB_DUMMY_OBJ) $(LIBSMB_ERR_OBJ0) \ + $(POPT_LIB_OBJ) $(LIB_OBJ) $(LIB_DUMMY_OBJ) $(LIBSMB_ERR_OBJ0) $(LIBSMB_ERR_OBJ1) \ $(RPC_PARSE_OBJ1) $(SECRETS_OBJ) \ $(LDB_OBJ) lib/ldb/tools/cmdline.o diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index f11dbe60ee..6aca443fe7 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -19,6 +19,7 @@ */ #include "includes.h" +#include "../libcli/auth/libcli_auth.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH diff --git a/source3/auth/auth_netlogond.c b/source3/auth/auth_netlogond.c index c39dd8c752..3947873aaa 100644 --- a/source3/auth/auth_netlogond.c +++ b/source3/auth/auth_netlogond.c @@ -18,6 +18,7 @@ */ #include "includes.h" +#include "../libcli/auth/libcli_auth.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH @@ -68,15 +69,13 @@ static NTSTATUS netlogond_validate(TALLOC_CTX *mem_ctx, * rpccli_netlogon_sam_network_logon_ex can decrypt the session keys. */ - p->dc = talloc(p, struct dcinfo); + 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; } - memcpy(p->dc->sess_key, schannel_key, 16); - status = rpccli_netlogon_sam_network_logon_ex( p, p, user_info->logon_parameters,/* flags such as 'allow @@ -256,7 +255,7 @@ static NTSTATUS check_netlogond_security(const struct auth_context *auth_context goto done; } - memcpy(schannel_key, p->dc->sess_key, 16); + memcpy(schannel_key, p->dc->session_key, 16); secrets_store_local_schannel_key(schannel_key); TALLOC_FREE(p); diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c index f5d61e9a9b..a2634feb6c 100644 --- a/source3/auth/auth_sam.c +++ b/source3/auth/auth_sam.c @@ -21,6 +21,7 @@ */ #include "includes.h" +#include "../libcli/auth/libcli_auth.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH @@ -39,7 +40,12 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, { uint32 acct_ctrl; const uint8 *lm_pw, *nt_pw; + struct samr_Password lm_hash, nt_hash, client_lm_hash, client_nt_hash; const char *username = pdb_get_username(sampass); + bool got_lm = false, got_nt = false; + + *user_sess_key = data_blob(NULL, 0); + *lm_sess_key = data_blob(NULL, 0); acct_ctrl = pdb_get_acct_ctrl(sampass); if (acct_ctrl & ACB_PWNOTREQ) { @@ -54,14 +60,45 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, lm_pw = pdb_get_lanman_passwd(sampass); nt_pw = pdb_get_nt_passwd(sampass); - - return ntlm_password_check(mem_ctx, &auth_context->challenge, - &user_info->lm_resp, &user_info->nt_resp, - &user_info->lm_interactive_pwd, &user_info->nt_interactive_pwd, - username, - user_info->smb_name, - user_info->client_domain, - lm_pw, nt_pw, user_sess_key, lm_sess_key); + if (lm_pw) { + memcpy(lm_hash.hash, lm_pw, sizeof(lm_hash.hash)); + } + if (nt_pw) { + memcpy(nt_hash.hash, nt_pw, sizeof(nt_hash.hash)); + } + if (user_info->lm_interactive_pwd.data && sizeof(client_lm_hash.hash) == user_info->lm_interactive_pwd.length) { + memcpy(client_lm_hash.hash, user_info->lm_interactive_pwd.data, sizeof(lm_hash.hash)); + got_lm = true; + } + if (user_info->nt_interactive_pwd.data && sizeof(client_nt_hash.hash) == user_info->nt_interactive_pwd.length) { + memcpy(client_nt_hash.hash, user_info->nt_interactive_pwd.data, sizeof(nt_hash.hash)); + got_nt = true; + } + if (got_lm || got_nt) { + *user_sess_key = data_blob(mem_ctx, 16); + if (!user_sess_key->data) { + return NT_STATUS_NO_MEMORY; + } + SMBsesskeygen_ntv1(nt_pw, user_sess_key->data); + return hash_password_check(mem_ctx, lp_lanman_auth(), + got_lm ? &client_lm_hash : NULL, + got_nt ? &client_nt_hash : NULL, + username, + lm_pw ? &lm_hash: NULL, + nt_pw ? &nt_hash : NULL); + } else { + return ntlm_password_check(mem_ctx, lp_lanman_auth(), + lp_ntlm_auth(), + user_info->logon_parameters, + &auth_context->challenge, + &user_info->lm_resp, &user_info->nt_resp, + username, + user_info->smb_name, + user_info->client_domain, + lm_pw ? &lm_hash: NULL, + nt_pw ? &nt_hash : NULL, + user_sess_key, lm_sess_key); + } } /**************************************************************************** diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index cf6588ad82..c55fb70ef2 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -22,6 +22,7 @@ */ #include "includes.h" +#include "../libcli/auth/libcli_auth.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH @@ -330,10 +331,10 @@ bool make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, #endif if (lm_interactive_pwd) - SamOEMhash(lm_pwd, key, sizeof(lm_pwd)); + arcfour_crypt(lm_pwd, key, sizeof(lm_pwd)); if (nt_interactive_pwd) - SamOEMhash(nt_pwd, key, sizeof(nt_pwd)); + arcfour_crypt(nt_pwd, key, sizeof(nt_pwd)); #ifdef DEBUG_PASSWORD DEBUG(100,("decrypt of lm owf password:")); diff --git a/source3/include/client.h b/source3/include/client.h index c314c9c6a9..6d84f482c2 100644 --- a/source3/include/client.h +++ b/source3/include/client.h @@ -132,8 +132,8 @@ struct rpc_pipe_client { struct cli_pipe_auth_data *auth; - /* The following is only non-null on a netlogon pipe. */ - struct dcinfo *dc; + /* The following is only non-null on a netlogon client pipe. */ + struct netlogon_creds_CredentialState *dc; /* Used by internal rpc_pipe_client */ pipes_struct *pipes_struct; diff --git a/source3/include/ntlmssp.h b/source3/include/ntlmssp.h index f3414fe928..67cdd5a551 100644 --- a/source3/include/ntlmssp.h +++ b/source3/include/ntlmssp.h @@ -68,11 +68,6 @@ enum NTLM_MESSAGE_TYPE #define NTLMSSP_FEATURE_SIGN 0x00000002 #define NTLMSSP_FEATURE_SEAL 0x00000004 -#define NTLMSSP_NAME_TYPE_SERVER 0x01 -#define NTLMSSP_NAME_TYPE_DOMAIN 0x02 -#define NTLMSSP_NAME_TYPE_SERVER_DNS 0x03 -#define NTLMSSP_NAME_TYPE_DOMAIN_DNS 0x04 - #define NTLMSSP_SIG_SIZE 16 typedef struct ntlmssp_state diff --git a/source3/include/proto.h b/source3/include/proto.h index fa60e6de09..c40d9c680c 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1782,6 +1782,23 @@ bool create_local_private_krb5_conf_for_domain(const char *realm, const char *sitename, struct sockaddr_storage *pss); + +/* The following definitions come from libsmb/credentials.c */ + +char *credstr(const unsigned char *cred); +void creds_server_init(uint32 neg_flags, + struct dcinfo *dc, + struct netr_Credential *clnt_chal, + struct netr_Credential *srv_chal, + const unsigned char mach_pw[16], + struct netr_Credential *init_chal_out); +bool netlogon_creds_server_check(const struct dcinfo *dc, + const struct netr_Credential *rcv_cli_chal_in); +bool netlogon_creds_server_step(struct dcinfo *dc, + const struct netr_Authenticator *received_cred, + struct netr_Authenticator *cred_out); +void cred_hash3(unsigned char *out, const unsigned char *in, const unsigned char *key, int forw); + /* The following definitions come from libads/kerberos_keytab.c */ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc); @@ -2933,31 +2950,6 @@ void delete_negative_conn_cache(const char *domain, const char *server); void flush_negative_conn_cache( void ); void flush_negative_conn_cache_for_domain(const char *domain); -/* The following definitions come from libsmb/credentials.c */ - -char *credstr(const unsigned char *cred); -void creds_server_init(uint32 neg_flags, - struct dcinfo *dc, - struct netr_Credential *clnt_chal, - struct netr_Credential *srv_chal, - const unsigned char mach_pw[16], - struct netr_Credential *init_chal_out); -bool netlogon_creds_server_check(const struct dcinfo *dc, - const struct netr_Credential *rcv_cli_chal_in); -bool netlogon_creds_server_step(struct dcinfo *dc, - const struct netr_Authenticator *received_cred, - struct netr_Authenticator *cred_out); -void creds_client_init(uint32 neg_flags, - struct dcinfo *dc, - struct netr_Credential *clnt_chal, - struct netr_Credential *srv_chal, - const unsigned char mach_pw[16], - struct netr_Credential *init_chal_out); -bool netlogon_creds_client_check(const struct dcinfo *dc, - const struct netr_Credential *rcv_srv_chal_in); -void netlogon_creds_client_step(struct dcinfo *dc, - struct netr_Authenticator *next_cred_out); - /* The following definitions come from ../librpc/rpc/dcerpc_error.c */ const char *dcerpc_errstr(TALLOC_CTX *mem_ctx, uint32_t fault_code); @@ -3109,21 +3101,6 @@ const char *get_nt_error_c_code(NTSTATUS nt_code); NTSTATUS nt_status_string_to_code(const char *nt_status_str); NTSTATUS nt_status_squash(NTSTATUS nt_status); -/* The following definitions come from libsmb/ntlm_check.c */ - -NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, - const DATA_BLOB *challenge, - const DATA_BLOB *lm_response, - const DATA_BLOB *nt_response, - const DATA_BLOB *lm_interactive_pwd, - const DATA_BLOB *nt_interactive_pwd, - const char *username, - const char *client_username, - const char *client_domain, - const uint8 *lm_pw, const uint8 *nt_pw, - DATA_BLOB *user_sess_key, - DATA_BLOB *lm_sess_key); - /* The following definitions come from libsmb/ntlmssp.c */ void debug_ntlmssp_flags(uint32 neg_flags); @@ -3145,13 +3122,6 @@ DATA_BLOB ntlmssp_weaken_keys(NTLMSSP_STATE *ntlmssp_state, TALLOC_CTX *mem_ctx) NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state); NTSTATUS ntlmssp_client_start(NTLMSSP_STATE **ntlmssp_state); -/* The following definitions come from libsmb/ntlmssp_parse.c */ - -bool msrpc_gen(DATA_BLOB *blob, - const char *format, ...); -bool msrpc_parse(const DATA_BLOB *blob, - const char *format, ...); - /* The following definitions come from libsmb/ntlmssp_sign.c */ NTSTATUS ntlmssp_sign_packet(NTLMSSP_STATE *ntlmssp_state, @@ -3235,84 +3205,6 @@ void srv_set_signing(struct smbd_server_connection *conn, const DATA_BLOB user_session_key, const DATA_BLOB response); -/* The following definitions come from libsmb/smbdes.c */ - -void des_crypt56(unsigned char *out, const unsigned char *in, const unsigned char *key, int forw); -void E_P16(const unsigned char *p14,unsigned char *p16); -void E_P24(const unsigned char *p21, const unsigned char *c8, unsigned char *p24); -void D_P16(const unsigned char *p14, const unsigned char *in, unsigned char *out); -void E_old_pw_hash( unsigned char *p14, const unsigned char *in, unsigned char *out); -void des_crypt128(unsigned char out[8], const unsigned char in[8], const unsigned char key[16]); -void des_crypt64(unsigned char out[8], const unsigned char in[8], const unsigned char key[8]); -void des_crypt112(unsigned char out[8], const unsigned char in[8], const unsigned char key[14], int forw); -void cred_hash3(unsigned char *out, const unsigned char *in, const unsigned char *key, int forw); -void des_crypt112_16(unsigned char out[16], unsigned char in[16], const unsigned char key[14], int forw); -void SamOEMhash( unsigned char *data, const unsigned char key[16], size_t len); -void SamOEMhashBlob( unsigned char *data, size_t len, DATA_BLOB *key); -void sam_pwd_hash(unsigned int rid, const uchar *in, uchar *out, int forw); - -/* The following definitions come from libsmb/smbencrypt.c */ - -void SMBencrypt_hash(const uchar lm_hash[16], const uchar *c8, uchar p24[24]); -bool SMBencrypt(const char *passwd, const uchar *c8, uchar p24[24]); -void E_md4hash(const char *passwd, uchar p16[16]); -void E_md5hash(const uchar salt[16], const uchar nthash[16], uchar hash_out[16]); -bool E_deshash(const char *passwd, uchar p16[16]); -void nt_lm_owf_gen(const char *pwd, uchar nt_p16[16], uchar p16[16]); -bool ntv2_owf_gen(const uchar owf[16], - const char *user_in, const char *domain_in, - bool upper_case_domain, /* Transform the domain into UPPER case */ - uchar kr_buf[16]); -void SMBOWFencrypt(const uchar passwd[16], const uchar *c8, uchar p24[24]); -void NTLMSSPOWFencrypt(const uchar passwd[8], const uchar *ntlmchalresp, uchar p24[24]); -void SMBNTencrypt_hash(const uchar nt_hash[16], uchar *c8, uchar *p24); -void SMBNTencrypt(const char *passwd, uchar *c8, uchar *p24); -void SMBOWFencrypt_ntv2(const uchar kr[16], - const DATA_BLOB *srv_chal, - const DATA_BLOB *cli_chal, - uchar resp_buf[16]); -void SMBsesskeygen_ntv2(const uchar kr[16], - const uchar * nt_resp, uint8 sess_key[16]); -void SMBsesskeygen_ntv1(const uchar kr[16], - const uchar * nt_resp, uint8 sess_key[16]); -void SMBsesskeygen_lm_sess_key(const uchar lm_hash[16], - const uchar lm_resp[24], /* only uses 8 */ - uint8 sess_key[16]); -DATA_BLOB NTLMv2_generate_names_blob(const char *hostname, - const char *domain); -bool SMBNTLMv2encrypt_hash(const char *user, const char *domain, const uchar nt_hash[16], - const DATA_BLOB *server_chal, - const DATA_BLOB *names_blob, - DATA_BLOB *lm_response, DATA_BLOB *nt_response, - DATA_BLOB *user_session_key) ; -bool SMBNTLMv2encrypt(const char *user, const char *domain, const char *password, - const DATA_BLOB *server_chal, - const DATA_BLOB *names_blob, - DATA_BLOB *lm_response, DATA_BLOB *nt_response, - DATA_BLOB *user_session_key) ; -bool encode_pw_buffer(uint8 buffer[516], const char *password, int string_flags); -bool decode_pw_buffer(TALLOC_CTX *ctx, - uint8 in_buffer[516], - char **pp_new_pwrd, - uint32 *new_pw_len, - int string_flags); -void encode_or_decode_arc4_passwd_buffer(unsigned char pw_buf[532], const DATA_BLOB *psession_key); -void sess_crypt_blob(DATA_BLOB *out, const DATA_BLOB *in, const DATA_BLOB *session_key, int forward); -char *decrypt_trustdom_secret(uint8_t nt_hash[16], DATA_BLOB *data_in); -void encode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx, - const char *pwd, - DATA_BLOB *session_key, - struct wkssvc_PasswordBuffer **pwd_buf); -WERROR decode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx, - struct wkssvc_PasswordBuffer *pwd_buf, - DATA_BLOB *session_key, - char **pwd); -DATA_BLOB decrypt_drsuapi_blob(TALLOC_CTX *mem_ctx, - const DATA_BLOB *session_key, - bool rcrypt, - uint32_t rid, - const DATA_BLOB *buffer); - /* The following definitions come from libsmb/smberr.c */ const char *smb_dos_err_name(uint8 e_class, uint16 num); @@ -4744,11 +4636,11 @@ bool secrets_store_afs_keyfile(const char *cell, const struct afs_keyfile *keyfi bool secrets_fetch_afs_key(const char *cell, struct afs_key *result); void secrets_fetch_ipc_userpass(char **username, char **domain, char **password); bool secrets_store_schannel_session_info(TALLOC_CTX *mem_ctx, - const char *remote_machine, - const struct dcinfo *pdc); + const char *remote_machine, + const struct dcinfo *pdc); bool secrets_restore_schannel_session_info(TALLOC_CTX *mem_ctx, - const char *remote_machine, - struct dcinfo **ppdc); + const char *remote_machine, + struct dcinfo **ppdc); 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_store_local_schannel_key(uint8_t schannel_key[16]); @@ -5352,7 +5244,7 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, const struct ndr_syntax_id *interface, enum pipe_auth_level auth_level, const char *domain, - const struct dcinfo *pdc, + struct netlogon_creds_CredentialState **pdc, struct rpc_pipe_client **presult); NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli, const struct ndr_syntax_id *interface, diff --git a/source3/include/rpc_dce.h b/source3/include/rpc_dce.h index ca58040757..8780169c75 100644 --- a/source3/include/rpc_dce.h +++ b/source3/include/rpc_dce.h @@ -88,51 +88,6 @@ enum RPC_PKT_TYPE { #define RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN 0x20 #define RPC_AUTH_SCHANNEL_SIGN_ONLY_CHK_LEN 0x18 -/* The 7 here seems to be required to get Win2k not to downgrade us - to NT4. Actually, anything other than 1ff would seem to do... */ -#define NETLOGON_NEG_AUTH2_FLAGS 0x000701ff -/* - (NETLOGON_NEG_ACCOUNT_LOCKOUT | - NETLOGON_NEG_PERSISTENT_SAMREPL | - NETLOGON_NEG_ARCFOUR | - NETLOGON_NEG_PROMOTION_COUNT | - NETLOGON_NEG_CHANGELOG_BDC | - NETLOGON_NEG_FULL_SYNC_REPL | - NETLOGON_NEG_MULTIPLE_SIDS | - NETLOGON_NEG_REDO | - NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL | - NETLOGON_NEG_DNS_DOMAIN_TRUSTS | - NETLOGON_NEG_PASSWORD_SET2 | - NETLOGON_NEG_GETDOMAININFO) -*/ -#define NETLOGON_NEG_DOMAIN_TRUST_ACCOUNT 0x2010b000 - -/* these are the flags that ADS clients use */ -#define NETLOGON_NEG_AUTH2_ADS_FLAGS 0x600fffff -/* - (NETLOGON_NEG_ACCOUNT_LOCKOUT | - NETLOGON_NEG_PERSISTENT_SAMREPL | - NETLOGON_NEG_ARCFOUR | - NETLOGON_NEG_PROMOTION_COUNT | - NETLOGON_NEG_CHANGELOG_BDC | - NETLOGON_NEG_FULL_SYNC_REPL | - NETLOGON_NEG_MULTIPLE_SIDS | - NETLOGON_NEG_REDO | - NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL | - NETLOGON_NEG_SEND_PASSWORD_INFO_PDC | - NETLOGON_NEG_GENERIC_PASSTHROUGH | - NETLOGON_NEG_CONCURRENT_RPC | - NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL | - NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL | - NETLOGON_NEG_128BIT | - NETLOGON_NEG_TRANSITIVE_TRUSTS | - NETLOGON_NEG_DNS_DOMAIN_TRUSTS | - NETLOGON_NEG_PASSWORD_SET2 | - NETLOGON_NEG_GETDOMAININFO | - NETLOGON_NEG_CROSS_FOREST_TRUSTS | - NETLOGON_NEG_AUTHENTICATED_RPC_LSASS | - NETLOGON_NEG_SCHANNEL) -*/ enum schannel_direction { SENDER_IS_INITIATOR, diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index 567ee7b8d1..374079c8ae 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -1600,6 +1600,7 @@ size_t push_string_check_fn(const char *function, unsigned int line, return push_ascii(dest, src, dest_len, flags); } + /** Copy a string from a char* src to a unicode or ascii dos codepage destination choosing unicode or ascii based on the @@ -1641,6 +1642,43 @@ size_t push_string_base(const char *function, unsigned int line, return push_ascii(dest, src, dest_len, flags); } +/** + Copy a string from a char* src to a unicode or ascii + dos codepage destination choosing unicode or ascii based on the + flags supplied + Return the number of bytes occupied by the string in the destination. + flags can have: + STR_TERMINATE means include the null termination. + STR_UPPER means uppercase in the destination. + STR_ASCII use ascii even with unicode packet. + STR_NOALIGN means don't do alignment. + dest_len is the maximum length allowed in the destination. If dest_len + is -1 then no maxiumum is used. +**/ + +ssize_t push_string(void *dest, const char *src, size_t dest_len, int flags) +{ + size_t ret; +#ifdef DEVELOPER + /* We really need to zero fill here, not clobber + * region, as we want to ensure that valgrind thinks + * all of the outgoing buffer has been written to + * so a send() or write() won't trap an error. + * JRA. + */ + memset(dest, '\0', dest_len); +#endif + + if (!(flags & STR_ASCII) && \ + (flags & STR_UNICODE)) { + ret = push_ucs2(NULL, dest, src, dest_len, flags); + } + ret = push_ascii(dest, src, dest_len, flags); + if (ret == (size_t)-1) { + return -1; + } + return ret; +} /** Copy a string from a unicode or ascii source (depending on diff --git a/source3/lib/netapi/joindomain.c b/source3/lib/netapi/joindomain.c index 9eedc5de03..d4eba5ffee 100644 --- a/source3/lib/netapi/joindomain.c +++ b/source3/lib/netapi/joindomain.c @@ -24,6 +24,7 @@ #include "lib/netapi/netapi_private.h" #include "lib/netapi/libnetapi.h" #include "libnet/libnet.h" +#include "libcli/auth/libcli_auth.h" /**************************************************************** ****************************************************************/ diff --git a/source3/libnet/libnet_dssync.c b/source3/libnet/libnet_dssync.c index 746b09635d..59feac2495 100644 --- a/source3/libnet/libnet_dssync.c +++ b/source3/libnet/libnet_dssync.c @@ -22,6 +22,7 @@ #include "includes.h" #include "libnet/libnet.h" +#include "../libcli/drsuapi/drsuapi.h" /**************************************************************** ****************************************************************/ @@ -61,49 +62,6 @@ NTSTATUS libnet_dssync_init_context(TALLOC_CTX *mem_ctx, /**************************************************************** ****************************************************************/ -static DATA_BLOB *decrypt_attr_val(TALLOC_CTX *mem_ctx, - DATA_BLOB *session_key, - uint32_t rid, - enum drsuapi_DsAttributeId id, - DATA_BLOB *raw_data) -{ - bool rcrypt = false; - DATA_BLOB out_data; - - ZERO_STRUCT(out_data); - - switch (id) { - case DRSUAPI_ATTRIBUTE_dBCSPwd: - case DRSUAPI_ATTRIBUTE_unicodePwd: - case DRSUAPI_ATTRIBUTE_ntPwdHistory: - case DRSUAPI_ATTRIBUTE_lmPwdHistory: - rcrypt = true; - break; - case DRSUAPI_ATTRIBUTE_supplementalCredentials: - case DRSUAPI_ATTRIBUTE_priorValue: - case DRSUAPI_ATTRIBUTE_currentValue: - case DRSUAPI_ATTRIBUTE_trustAuthOutgoing: - case DRSUAPI_ATTRIBUTE_trustAuthIncoming: - case DRSUAPI_ATTRIBUTE_initialAuthOutgoing: - case DRSUAPI_ATTRIBUTE_initialAuthIncoming: - break; - default: - return raw_data; - } - - out_data = decrypt_drsuapi_blob(mem_ctx, session_key, rcrypt, - rid, raw_data); - - if (out_data.length) { - return (DATA_BLOB *)talloc_memdup(mem_ctx, &out_data, sizeof(DATA_BLOB)); - } - - return raw_data; -} - -/**************************************************************** -****************************************************************/ - static void parse_obj_identifier(struct drsuapi_DsReplicaObjectIdentifier *id, uint32_t *rid) { @@ -121,30 +79,6 @@ static void parse_obj_identifier(struct drsuapi_DsReplicaObjectIdentifier *id, /**************************************************************** ****************************************************************/ -static void parse_obj_attribute(TALLOC_CTX *mem_ctx, - DATA_BLOB *session_key, - uint32_t rid, - struct drsuapi_DsReplicaAttribute *attr) -{ - int i = 0; - - for (i=0; i<attr->value_ctr.num_values; i++) { - - DATA_BLOB *plain_data = NULL; - - plain_data = decrypt_attr_val(mem_ctx, - session_key, - rid, - attr->attid, - attr->value_ctr.values[i].blob); - - attr->value_ctr.values[i].blob = plain_data; - } -} - -/**************************************************************** -****************************************************************/ - static void libnet_dssync_decrypt_attributes(TALLOC_CTX *mem_ctx, DATA_BLOB *session_key, struct drsuapi_DsReplicaObjectListItemEx *cur) @@ -170,10 +104,10 @@ static void libnet_dssync_decrypt_attributes(TALLOC_CTX *mem_ctx, continue; } - parse_obj_attribute(mem_ctx, - session_key, - rid, - attr); + drsuapi_decrypt_attribute(mem_ctx, + session_key, + rid, + attr); } } } diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index 6b0604bb9f..894f5cba32 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -20,6 +20,7 @@ #include "includes.h" #include "libnet/libnet.h" +#include "libcli/auth/libcli_auth.h" /**************************************************************** ****************************************************************/ @@ -1071,7 +1072,7 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name, status = cli_rpc_pipe_open_schannel_with_key( cli, &ndr_table_netlogon.syntax_id, PIPE_AUTH_LEVEL_PRIVACY, - netbios_domain_name, netlogon_pipe->dc, &pipe_hnd); + netbios_domain_name, &netlogon_pipe->dc, &pipe_hnd); cli_shutdown(cli); diff --git a/source3/libnet/libnet_samsync.c b/source3/libnet/libnet_samsync.c index 0c00b8518a..df7e875ab6 100644 --- a/source3/libnet/libnet_samsync.c +++ b/source3/libnet/libnet_samsync.c @@ -23,154 +23,9 @@ #include "includes.h" #include "libnet/libnet.h" - -/** - * Decrypt and extract the user's passwords. - * - * The writes decrypted (no longer 'RID encrypted' or arcfour encrypted) - * passwords back into the structure - */ - -static NTSTATUS fix_user(TALLOC_CTX *mem_ctx, - DATA_BLOB *session_key, - enum netr_SamDatabaseID database_id, - struct netr_DELTA_ENUM *delta) -{ - - uint32_t rid = delta->delta_id_union.rid; - struct netr_DELTA_USER *user = delta->delta_union.user; - struct samr_Password lm_hash; - struct samr_Password nt_hash; - unsigned char zero_buf[16]; - - memset(zero_buf, '\0', sizeof(zero_buf)); - - /* Note that win2000 may send us all zeros - * for the hashes if it doesn't - * think this channel is secure enough. */ - if (user->lm_password_present) { - if (memcmp(user->lmpassword.hash, zero_buf, 16) != 0) { - sam_pwd_hash(rid, user->lmpassword.hash, lm_hash.hash, 0); - } else { - memset(lm_hash.hash, '\0', sizeof(lm_hash.hash)); - } - user->lmpassword = lm_hash; - } - - if (user->nt_password_present) { - if (memcmp(user->ntpassword.hash, zero_buf, 16) != 0) { - sam_pwd_hash(rid, user->ntpassword.hash, nt_hash.hash, 0); - } else { - memset(nt_hash.hash, '\0', sizeof(nt_hash.hash)); - } - user->ntpassword = nt_hash; - } - - if (user->user_private_info.SensitiveData) { - DATA_BLOB data; - struct netr_USER_KEYS keys; - enum ndr_err_code ndr_err; - data.data = user->user_private_info.SensitiveData; - data.length = user->user_private_info.DataLength; - SamOEMhashBlob(data.data, data.length, session_key); - user->user_private_info.SensitiveData = data.data; - user->user_private_info.DataLength = data.length; - - ndr_err = ndr_pull_struct_blob(&data, mem_ctx, NULL, &keys, - (ndr_pull_flags_fn_t)ndr_pull_netr_USER_KEYS); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - dump_data(10, data.data, data.length); - return ndr_map_error2ntstatus(ndr_err); - } - - /* Note that win2000 may send us all zeros - * for the hashes if it doesn't - * think this channel is secure enough. */ - if (keys.keys.keys2.lmpassword.length == 16) { - if (memcmp(keys.keys.keys2.lmpassword.pwd.hash, - zero_buf, 16) != 0) { - sam_pwd_hash(rid, - keys.keys.keys2.lmpassword.pwd.hash, - lm_hash.hash, 0); - } else { - memset(lm_hash.hash, '\0', sizeof(lm_hash.hash)); - } - user->lmpassword = lm_hash; - user->lm_password_present = true; - } - if (keys.keys.keys2.ntpassword.length == 16) { - if (memcmp(keys.keys.keys2.ntpassword.pwd.hash, - zero_buf, 16) != 0) { - sam_pwd_hash(rid, - keys.keys.keys2.ntpassword.pwd.hash, - nt_hash.hash, 0); - } else { - memset(nt_hash.hash, '\0', sizeof(nt_hash.hash)); - } - user->ntpassword = nt_hash; - user->nt_password_present = true; - } - /* TODO: rid decrypt history fields */ - } - return NT_STATUS_OK; -} - -/** - * Decrypt and extract the secrets - * - * The writes decrypted secrets back into the structure - */ -static NTSTATUS fix_secret(TALLOC_CTX *mem_ctx, - DATA_BLOB *session_key, - enum netr_SamDatabaseID database_id, - struct netr_DELTA_ENUM *delta) -{ - struct netr_DELTA_SECRET *secret = delta->delta_union.secret; - - SamOEMhashBlob(secret->current_cipher.cipher_data, - secret->current_cipher.maxlen, - session_key); - - SamOEMhashBlob(secret->old_cipher.cipher_data, - secret->old_cipher.maxlen, - session_key); - - return NT_STATUS_OK; -} - -/** - * Fix up the delta, dealing with encryption issues so that the final - * callback need only do the printing or application logic - */ - -static NTSTATUS samsync_fix_delta(TALLOC_CTX *mem_ctx, - DATA_BLOB *session_key, - enum netr_SamDatabaseID database_id, - struct netr_DELTA_ENUM *delta) -{ - NTSTATUS status = NT_STATUS_OK; - - switch (delta->delta_type) { - case NETR_DELTA_USER: - - status = fix_user(mem_ctx, - session_key, - database_id, - delta); - break; - case NETR_DELTA_SECRET: - - status = fix_secret(mem_ctx, - session_key, - database_id, - delta); - break; - default: - break; - } - - return status; -} +#include "../lib/crypto/crypto.h" +#include "../libcli/samsync/samsync.h" +#include "../libcli/auth/libcli_auth.h" /** * Fix up the delta, dealing with encryption issues so that the final @@ -178,7 +33,7 @@ static NTSTATUS samsync_fix_delta(TALLOC_CTX *mem_ctx, */ static NTSTATUS samsync_fix_delta_array(TALLOC_CTX *mem_ctx, - DATA_BLOB *session_key, + struct netlogon_creds_CredentialState *creds, enum netr_SamDatabaseID database_id, struct netr_DELTA_ENUM_ARRAY *r) { @@ -188,7 +43,7 @@ static NTSTATUS samsync_fix_delta_array(TALLOC_CTX *mem_ctx, for (i = 0; i < r->num_deltas; i++) { status = samsync_fix_delta(mem_ctx, - session_key, + creds, database_id, &r->delta_enum[i]); if (!NT_STATUS_IS_OK(status)) { @@ -345,14 +200,13 @@ static NTSTATUS libnet_samsync_delta(TALLOC_CTX *mem_ctx, struct netr_Authenticator return_authenticator; uint16_t restart_state = 0; uint32_t sync_context = 0; - DATA_BLOB session_key; ZERO_STRUCT(return_authenticator); do { struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; - netlogon_creds_client_step(ctx->cli->dc, &credential); + netlogon_creds_client_authenticator(ctx->cli->dc, &credential); if (ctx->single_object_replication && !ctx->force_full_replication) { @@ -403,10 +257,8 @@ static NTSTATUS libnet_samsync_delta(TALLOC_CTX *mem_ctx, break; } - session_key = data_blob_const(ctx->cli->dc->sess_key, 16); - samsync_fix_delta_array(mem_ctx, - &session_key, + ctx->cli->dc, database_id, delta_enum_array); diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 0ff9f253ef..ffe2960967 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -19,6 +19,7 @@ */ #include "includes.h" +#include "../libcli/auth/libcli_auth.h" static const struct { int prot; @@ -433,11 +434,11 @@ static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user, the server's domain at this point. The 'server name' is also dodgy... */ - names_blob = NTLMv2_generate_names_blob(cli->called.name, workgroup); + names_blob = NTLMv2_generate_names_blob(NULL, cli->called.name, workgroup); - if (!SMBNTLMv2encrypt(user, workgroup, pass, &server_chal, + if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass, &server_chal, &names_blob, - &lm_response, &nt_response, &session_key)) { + &lm_response, &nt_response, NULL, &session_key)) { data_blob_free(&names_blob); data_blob_free(&server_chal); return NT_STATUS_ACCESS_DENIED; @@ -474,7 +475,7 @@ static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user, E_deshash(pass, session_key.data); memset(&session_key.data[8], '\0', 8); #else - SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); + SMBsesskeygen_ntv1(nt_hash, session_key.data); #endif } cli_temp_set_signing(cli); diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c index 3f95e77aee..976e184e9c 100644 --- a/source3/libsmb/clirap.c +++ b/source3/libsmb/clirap.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "../libcli/auth/libcli_auth.h" /**************************************************************************** Call a remote api @@ -468,7 +469,7 @@ bool cli_oem_change_password(struct cli_state *cli, const char *user, const char DEBUG(100,("make_oem_passwd_hash\n")); dump_data(100, data, 516); #endif - SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, 516); + arcfour_crypt( (unsigned char *)data, (unsigned char *)old_pw_hash, 516); /* * Now place the old password hash in the data. diff --git a/source3/libsmb/credentials.c b/source3/libsmb/credentials.c index 9ba460f869..0d7bde0c09 100644 --- a/source3/libsmb/credentials.c +++ b/source3/libsmb/credentials.c @@ -19,6 +19,8 @@ */ #include "includes.h" +#include "../lib/crypto/crypto.h" +#include "libcli/auth/libcli_auth.h" /**************************************************************************** Represent a credential as a string. @@ -278,84 +280,12 @@ bool netlogon_creds_server_step(struct dcinfo *dc, return true; } -/**************************************************************************** - Create a client credential struct. -****************************************************************************/ - -void creds_client_init(uint32 neg_flags, - struct dcinfo *dc, - struct netr_Credential *clnt_chal, - struct netr_Credential *srv_chal, - const unsigned char mach_pw[16], - struct netr_Credential *init_chal_out) -{ - dc->sequence = time(NULL); - - DEBUG(10,("creds_client_init: neg_flags : %x\n", (unsigned int)neg_flags)); - DEBUG(10,("creds_client_init: client chal : %s\n", credstr(clnt_chal->data) )); - DEBUG(10,("creds_client_init: server chal : %s\n", credstr(srv_chal->data) )); - dump_data_pw("creds_client_init: machine pass", (const unsigned char *)mach_pw, 16); - - /* Generate the session key and the next client and server creds. */ - if (neg_flags & NETLOGON_NEG_128BIT) { - creds_init_128(dc, - clnt_chal, - srv_chal, - mach_pw); - } else { - creds_init_64(dc, - clnt_chal, - srv_chal, - mach_pw); - } - - dump_data_pw("creds_client_init: session key", dc->sess_key, 16); - - DEBUG(10,("creds_client_init: clnt : %s\n", credstr(dc->clnt_chal.data) )); - DEBUG(10,("creds_client_init: server : %s\n", credstr(dc->srv_chal.data) )); - DEBUG(10,("creds_client_init: seed : %s\n", credstr(dc->seed_chal.data) )); - - memcpy(init_chal_out->data, dc->clnt_chal.data, 8); -} - -/**************************************************************************** - Check a credential returned by the server. -****************************************************************************/ - -bool netlogon_creds_client_check(const struct dcinfo *dc, - const struct netr_Credential *rcv_srv_chal_in) -{ - if (memcmp(dc->srv_chal.data, rcv_srv_chal_in->data, - sizeof(dc->srv_chal.data))) { - - DEBUG(0,("netlogon_creds_client_check: credentials check failed.\n")); - DEBUGADD(5,("netlogon_creds_client_check: challenge : %s\n", - credstr(rcv_srv_chal_in->data))); - DEBUGADD(5,("calculated: %s\n", credstr(dc->srv_chal.data))); - return false; - } - - DEBUG(10,("netlogon_creds_client_check: credentials check OK.\n")); - - return true; -} - - -/**************************************************************************** - Step the client credentials to the next element in the chain, updating the - current client and server credentials and the seed - produce the next authenticator in the sequence ready to send to - the server -****************************************************************************/ - -void netlogon_creds_client_step(struct dcinfo *dc, - struct netr_Authenticator *next_cred_out) +void cred_hash3(unsigned char *out, const unsigned char *in, const unsigned char *key, int forw) { - dc->sequence += 2; - creds_step(dc); - creds_reseed(dc); + unsigned char key2[8]; - memcpy(&next_cred_out->cred.data, &dc->clnt_chal.data, - sizeof(next_cred_out->cred.data)); - next_cred_out->timestamp = dc->sequence; + memset(key2,'\0',8); + des_crypt56(out, in, key, forw); + key2[0] = key[7]; + des_crypt56(out + 8, in + 8, key2, forw); } diff --git a/source3/libsmb/ntlm_check.c b/source3/libsmb/ntlm_check.c deleted file mode 100644 index 9380a83ea0..0000000000 --- a/source3/libsmb/ntlm_check.c +++ /dev/null @@ -1,470 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Password and authentication handling - Copyright (C) Andrew Tridgell 1992-2000 - Copyright (C) Luke Kenneth Casson Leighton 1996-2000 - Copyright (C) Andrew Bartlett 2001-2003 - Copyright (C) Gerald Carter 2003 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_AUTH - -/**************************************************************************** - Core of smb password checking routine. -****************************************************************************/ - -static bool smb_pwd_check_ntlmv1(const DATA_BLOB *nt_response, - const uchar *part_passwd, - const DATA_BLOB *sec_blob, - DATA_BLOB *user_sess_key) -{ - /* Finish the encryption of part_passwd. */ - uchar p24[24]; - - if (part_passwd == NULL) { - DEBUG(10,("No password set - DISALLOWING access\n")); - /* No password set - always false ! */ - return false; - } - - if (sec_blob->length != 8) { - DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect challenge size (%lu)\n", - (unsigned long)sec_blob->length)); - return false; - } - - if (nt_response->length != 24) { - DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect password length (%lu)\n", - (unsigned long)nt_response->length)); - return false; - } - - SMBOWFencrypt(part_passwd, sec_blob->data, p24); - if (user_sess_key != NULL) { - *user_sess_key = data_blob(NULL, 16); - SMBsesskeygen_ntv1(part_passwd, NULL, user_sess_key->data); - } - - -#if DEBUG_PASSWORD - DEBUG(100,("Part password (P16) was |\n")); - dump_data(100, part_passwd, 16); - DEBUGADD(100,("Password from client was |\n")); - dump_data(100, nt_response->data, nt_response->length); - DEBUGADD(100,("Given challenge was |\n")); - dump_data(100, sec_blob->data, sec_blob->length); - DEBUGADD(100,("Value from encryption was |\n")); - dump_data(100, p24, 24); -#endif - return (memcmp(p24, nt_response->data, 24) == 0); -} - -/**************************************************************************** - Core of smb password checking routine. (NTLMv2, LMv2) - Note: The same code works with both NTLMv2 and LMv2. -****************************************************************************/ - -static bool smb_pwd_check_ntlmv2(TALLOC_CTX *mem_ctx, - const DATA_BLOB *ntv2_response, - const uint8_t *part_passwd, - const DATA_BLOB *sec_blob, - const char *user, const char *domain, - bool upper_case_domain, /* should the domain be transformed into upper case? */ - DATA_BLOB *user_sess_key) -{ - /* Finish the encryption of part_passwd. */ - uint8_t kr[16]; - uint8_t value_from_encryption[16]; - uint8_t client_response[16]; - DATA_BLOB client_key_data; - bool res; - - if (part_passwd == NULL) { - DEBUG(10,("No password set - DISALLOWING access\n")); - /* No password set - always false */ - return false; - } - - if (sec_blob->length != 8) { - DEBUG(0, ("smb_pwd_check_ntlmv2: incorrect challenge size (%lu)\n", - (unsigned long)sec_blob->length)); - return false; - } - - if (ntv2_response->length < 24) { - /* We MUST have more than 16 bytes, or the stuff below will go - crazy. No known implementation sends less than the 24 bytes - for LMv2, let alone NTLMv2. */ - DEBUG(0, ("smb_pwd_check_ntlmv2: incorrect password length (%lu)\n", - (unsigned long)ntv2_response->length)); - return false; - } - - client_key_data = data_blob_talloc(mem_ctx, ntv2_response->data+16, ntv2_response->length-16); - /* - todo: should we be checking this for anything? We can't for LMv2, - but for NTLMv2 it is meant to contain the current time etc. - */ - - memcpy(client_response, ntv2_response->data, sizeof(client_response)); - - if (!ntv2_owf_gen(part_passwd, user, domain, upper_case_domain, kr)) { - return false; - } - - SMBOWFencrypt_ntv2(kr, sec_blob, &client_key_data, value_from_encryption); - if (user_sess_key != NULL) { - *user_sess_key = data_blob(NULL, 16); - SMBsesskeygen_ntv2(kr, value_from_encryption, user_sess_key->data); - } - -#if DEBUG_PASSWORD - DEBUG(100,("Part password (P16) was |\n")); - dump_data(100, part_passwd, 16); - DEBUGADD(100,("Password from client was |\n")); - dump_data(100, ntv2_response->data, ntv2_response->length); - DEBUGADD(100,("Variable data from client was |\n")); - dump_data(100, client_key_data.data, client_key_data.length); - DEBUGADD(100,("Given challenge was |\n")); - dump_data(100, sec_blob->data, sec_blob->length); - DEBUGADD(100,("Value from encryption was |\n")); - dump_data(100, value_from_encryption, 16); -#endif - data_blob_clear_free(&client_key_data); - res = (memcmp(value_from_encryption, client_response, 16) == 0); - if ((!res) && (user_sess_key != NULL)) - data_blob_clear_free(user_sess_key); - return res; -} - -/** - * Check a challenge-response password against the value of the NT or - * LM password hash. - * - * @param mem_ctx talloc context - * @param challenge 8-byte challenge. If all zero, forces plaintext comparison - * @param nt_response 'unicode' NT response to the challenge, or unicode password - * @param lm_response ASCII or LANMAN response to the challenge, or password in DOS code page - * @param username internal Samba username, for log messages - * @param client_username username the client used - * @param client_domain domain name the client used (may be mapped) - * @param nt_pw MD4 unicode password from our passdb or similar - * @param lm_pw LANMAN ASCII password from our passdb or similar - * @param user_sess_key User session key - * @param lm_sess_key LM session key (first 8 bytes of the LM hash) - */ - -NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, - const DATA_BLOB *challenge, - const DATA_BLOB *lm_response, - const DATA_BLOB *nt_response, - const DATA_BLOB *lm_interactive_pwd, - const DATA_BLOB *nt_interactive_pwd, - const char *username, - const char *client_username, - const char *client_domain, - const uint8_t *lm_pw, const uint8_t *nt_pw, - DATA_BLOB *user_sess_key, - DATA_BLOB *lm_sess_key) -{ - unsigned char zeros[8]; - - ZERO_STRUCT(zeros); - - if (nt_pw == NULL) { - DEBUG(3,("ntlm_password_check: NO NT password stored for user %s.\n", - username)); - } - - if (nt_interactive_pwd && nt_interactive_pwd->length && nt_pw) { - if (nt_interactive_pwd->length != 16) { - DEBUG(3,("ntlm_password_check: Interactive logon: Invalid NT password length (%d) supplied for user %s\n", (int)nt_interactive_pwd->length, - username)); - return NT_STATUS_WRONG_PASSWORD; - } - - if (memcmp(nt_interactive_pwd->data, nt_pw, 16) == 0) { - if (user_sess_key) { - *user_sess_key = data_blob(NULL, 16); - SMBsesskeygen_ntv1(nt_pw, NULL, user_sess_key->data); - } - return NT_STATUS_OK; - } else { - DEBUG(3,("ntlm_password_check: Interactive logon: NT password check failed for user %s\n", - username)); - return NT_STATUS_WRONG_PASSWORD; - } - - } else if (lm_interactive_pwd && lm_interactive_pwd->length && lm_pw) { - if (lm_interactive_pwd->length != 16) { - DEBUG(3,("ntlm_password_check: Interactive logon: Invalid LANMAN password length (%d) supplied for user %s\n", (int)lm_interactive_pwd->length, - username)); - return NT_STATUS_WRONG_PASSWORD; - } - - if (!lp_lanman_auth()) { - DEBUG(3,("ntlm_password_check: Interactive logon: only LANMAN password supplied for user %s, and LM passwords are disabled!\n", - username)); - return NT_STATUS_WRONG_PASSWORD; - } - - if (memcmp(lm_interactive_pwd->data, lm_pw, 16) == 0) { - return NT_STATUS_OK; - } else { - DEBUG(3,("ntlm_password_check: Interactive logon: LANMAN password check failed for user %s\n", - username)); - return NT_STATUS_WRONG_PASSWORD; - } - } - - /* Check for cleartext netlogon. Used by Exchange 5.5. */ - if (challenge->length == sizeof(zeros) && - (memcmp(challenge->data, zeros, challenge->length) == 0 )) { - - DEBUG(4,("ntlm_password_check: checking plaintext passwords for user %s\n", - username)); - if (nt_pw && nt_response->length) { - unsigned char pwhash[16]; - mdfour(pwhash, nt_response->data, nt_response->length); - if (memcmp(pwhash, nt_pw, sizeof(pwhash)) == 0) { - return NT_STATUS_OK; - } else { - DEBUG(3,("ntlm_password_check: NT (Unicode) plaintext password check failed for user %s\n", - username)); - return NT_STATUS_WRONG_PASSWORD; - } - - } else if (!lp_lanman_auth()) { - DEBUG(3,("ntlm_password_check: (plaintext password check) LANMAN passwords NOT PERMITTED for user %s\n", - username)); - - } else if (lm_pw && lm_response->length) { - uchar dospwd[14]; - uchar p16[16]; - ZERO_STRUCT(dospwd); - - memcpy(dospwd, lm_response->data, MIN(lm_response->length, sizeof(dospwd))); - /* Only the fisrt 14 chars are considered, password need not be null terminated. */ - - /* we *might* need to upper-case the string here */ - E_P16((const unsigned char *)dospwd, p16); - - if (memcmp(p16, lm_pw, sizeof(p16)) == 0) { - return NT_STATUS_OK; - } else { - DEBUG(3,("ntlm_password_check: LANMAN (ASCII) plaintext password check failed for user %s\n", - username)); - return NT_STATUS_WRONG_PASSWORD; - } - } else { - DEBUG(3, ("Plaintext authentication for user %s attempted, but neither NT nor LM passwords available\n", username)); - return NT_STATUS_WRONG_PASSWORD; - } - } - - if (nt_response->length != 0 && nt_response->length < 24) { - DEBUG(2,("ntlm_password_check: invalid NT password length (%lu) for user %s\n", - (unsigned long)nt_response->length, username)); - } - - if (nt_response->length >= 24 && nt_pw) { - if (nt_response->length > 24) { - /* We have the NT MD4 hash challenge available - see if we can - use it - */ - DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with domain [%s]\n", client_domain)); - if (smb_pwd_check_ntlmv2(mem_ctx, - nt_response, - nt_pw, challenge, - client_username, - client_domain, - False, - user_sess_key)) { - return NT_STATUS_OK; - } - - DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with uppercased version of domain [%s]\n", client_domain)); - if (smb_pwd_check_ntlmv2(mem_ctx, - nt_response, - nt_pw, challenge, - client_username, - client_domain, - true, - user_sess_key)) { - return NT_STATUS_OK; - } - - DEBUG(4,("ntlm_password_check: Checking NTLMv2 password without a domain\n")); - if (smb_pwd_check_ntlmv2(mem_ctx, - nt_response, - nt_pw, challenge, - client_username, - "", - False, - user_sess_key)) { - return NT_STATUS_OK; - } else { - DEBUG(3,("ntlm_password_check: NTLMv2 password check failed\n")); - return NT_STATUS_WRONG_PASSWORD; - } - } - - if (lp_ntlm_auth()) { - /* We have the NT MD4 hash challenge available - see if we can - use it (ie. does it exist in the smbpasswd file). - */ - DEBUG(4,("ntlm_password_check: Checking NT MD4 password\n")); - if (smb_pwd_check_ntlmv1(nt_response, - nt_pw, challenge, - user_sess_key)) { - /* The LM session key for this response is not very secure, - so use it only if we otherwise allow LM authentication */ - - if (lp_lanman_auth() && lm_pw) { - uint8_t first_8_lm_hash[16]; - memcpy(first_8_lm_hash, lm_pw, 8); - memset(first_8_lm_hash + 8, '\0', 8); - if (lm_sess_key) { - *lm_sess_key = data_blob(first_8_lm_hash, 16); - } - } - return NT_STATUS_OK; - } else { - DEBUG(3,("ntlm_password_check: NT MD4 password check failed for user %s\n", - username)); - return NT_STATUS_WRONG_PASSWORD; - } - } else { - DEBUG(2,("ntlm_password_check: NTLMv1 passwords NOT PERMITTED for user %s\n", - username)); - /* no return, becouse we might pick up LMv2 in the LM field */ - } - } - - if (lm_response->length == 0) { - DEBUG(3,("ntlm_password_check: NEITHER LanMan nor NT password supplied for user %s\n", - username)); - return NT_STATUS_WRONG_PASSWORD; - } - - if (lm_response->length < 24) { - DEBUG(2,("ntlm_password_check: invalid LanMan password length (%lu) for user %s\n", - (unsigned long)nt_response->length, username)); - return NT_STATUS_WRONG_PASSWORD; - } - - if (!lp_lanman_auth()) { - DEBUG(3,("ntlm_password_check: Lanman passwords NOT PERMITTED for user %s\n", - username)); - } else if (!lm_pw) { - DEBUG(3,("ntlm_password_check: NO LanMan password set for user %s (and no NT password supplied)\n", - username)); - } else { - DEBUG(4,("ntlm_password_check: Checking LM password\n")); - if (smb_pwd_check_ntlmv1(lm_response, - lm_pw, challenge, - NULL)) { - uint8_t first_8_lm_hash[16]; - memcpy(first_8_lm_hash, lm_pw, 8); - memset(first_8_lm_hash + 8, '\0', 8); - if (user_sess_key) { - *user_sess_key = data_blob(first_8_lm_hash, 16); - } - - if (lm_sess_key) { - *lm_sess_key = data_blob(first_8_lm_hash, 16); - } - return NT_STATUS_OK; - } - } - - if (!nt_pw) { - DEBUG(4,("ntlm_password_check: LM password check failed for user, no NT password %s\n",username)); - return NT_STATUS_WRONG_PASSWORD; - } - - /* This is for 'LMv2' authentication. almost NTLMv2 but limited to 24 bytes. - - related to Win9X, legacy NAS pass-though authentication - */ - DEBUG(4,("ntlm_password_check: Checking LMv2 password with domain %s\n", client_domain)); - if (smb_pwd_check_ntlmv2(mem_ctx, - lm_response, - nt_pw, challenge, - client_username, - client_domain, - false, - NULL)) { - return NT_STATUS_OK; - } - - DEBUG(4,("ntlm_password_check: Checking LMv2 password with upper-cased version of domain %s\n", client_domain)); - if (smb_pwd_check_ntlmv2(mem_ctx, - lm_response, - nt_pw, challenge, - client_username, - client_domain, - true, - NULL)) { - return NT_STATUS_OK; - } - - DEBUG(4,("ntlm_password_check: Checking LMv2 password without a domain\n")); - if (smb_pwd_check_ntlmv2(mem_ctx, - lm_response, - nt_pw, challenge, - client_username, - "", - false, - NULL)) { - return NT_STATUS_OK; - } - - /* Apparently NT accepts NT responses in the LM field - - I think this is related to Win9X pass-though authentication - */ - DEBUG(4,("ntlm_password_check: Checking NT MD4 password in LM field\n")); - if (lp_ntlm_auth()) { - if (smb_pwd_check_ntlmv1(lm_response, - nt_pw, challenge, - NULL)) { - /* The session key for this response is still very odd. - It not very secure, so use it only if we otherwise - allow LM authentication */ - - if (lp_lanman_auth() && lm_pw) { - uint8_t first_8_lm_hash[16]; - memcpy(first_8_lm_hash, lm_pw, 8); - memset(first_8_lm_hash + 8, '\0', 8); - if (user_sess_key) { - *user_sess_key = data_blob(first_8_lm_hash, 16); - } - - if (lm_sess_key) { - *lm_sess_key = data_blob(first_8_lm_hash, 16); - } - } - return NT_STATUS_OK; - } - DEBUG(3,("ntlm_password_check: LM password, NT MD4 password in LM field and LMv2 failed for user %s\n",username)); - } else { - DEBUG(3,("ntlm_password_check: LM password and LMv2 failed for user %s, and NT MD4 password in LM field not permitted\n",username)); - } - return NT_STATUS_WRONG_PASSWORD; -} - diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 0764f97d85..c5d271cdba 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -22,6 +22,7 @@ */ #include "includes.h" +#include "../libcli/auth/libcli_auth.h" static NTSTATUS ntlmssp_client_initial(struct ntlmssp_state *ntlmssp_state, DATA_BLOB reply, DATA_BLOB *next_request); @@ -322,7 +323,7 @@ NTSTATUS ntlmssp_update(NTLMSSP_STATE *ntlmssp_state, break; } } else { - if (!msrpc_parse(&input, "Cd", + if (!msrpc_parse(ntlmssp_state, &input, "Cd", "NTLMSSP", &ntlmssp_command)) { DEBUG(1, ("Failed to parse NTLMSSP packet, could not extract NTLMSSP command\n")); @@ -524,10 +525,10 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, #endif if (request.length) { - if ((request.length < 16) || !msrpc_parse(&request, "Cdd", - "NTLMSSP", - &ntlmssp_command, - &neg_flags)) { + if ((request.length < 16) || !msrpc_parse(ntlmssp_state, &request, "Cdd", + "NTLMSSP", + &ntlmssp_command, + &neg_flags)) { DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP Negotiate of length %u\n", (unsigned int)request.length)); dump_data(2, request.data, request.length); @@ -581,7 +582,7 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, /* This creates the 'blob' of names that appears at the end of the packet */ if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) { - msrpc_gen(&struct_blob, "aaaaa", + msrpc_gen(ntlmssp_state, &struct_blob, "aaaaa", NTLMSSP_NAME_TYPE_DOMAIN, target_name, NTLMSSP_NAME_TYPE_SERVER, ntlmssp_state->get_global_myname(), NTLMSSP_NAME_TYPE_DOMAIN_DNS, dnsdomname, @@ -600,7 +601,7 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, gen_string = "CdAdbddB"; } - msrpc_gen(reply, gen_string, + msrpc_gen(ntlmssp_state, reply, gen_string, "NTLMSSP", NTLMSSP_CHALLENGE, target_name, @@ -643,9 +644,6 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, uchar session_nonce_hash[16]; const char *parse_string; - char *domain = NULL; - char *user = NULL; - char *workstation = NULL; /* parse the NTLMSSP packet */ *reply = data_blob_null; @@ -668,20 +666,16 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, ntlmssp_state->workstation = NULL; /* now the NTLMSSP encoded auth hashes */ - if (!msrpc_parse(&request, parse_string, + if (!msrpc_parse(ntlmssp_state, &request, parse_string, "NTLMSSP", &ntlmssp_command, &ntlmssp_state->lm_resp, &ntlmssp_state->nt_resp, - &domain, - &user, - &workstation, + &ntlmssp_state->domain, + &ntlmssp_state->user, + &ntlmssp_state->workstation, &encrypted_session_key, &auth_flags)) { - SAFE_FREE(domain); - SAFE_FREE(user); - SAFE_FREE(workstation); - data_blob_free(&encrypted_session_key); auth_flags = 0; /* Try again with a shorter string (Win9X truncates this packet) */ @@ -692,19 +686,16 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, } /* now the NTLMSSP encoded auth hashes */ - if (!msrpc_parse(&request, parse_string, + if (!msrpc_parse(ntlmssp_state, &request, parse_string, "NTLMSSP", &ntlmssp_command, &ntlmssp_state->lm_resp, &ntlmssp_state->nt_resp, - &domain, - &user, - &workstation)) { + &ntlmssp_state->domain, + &ntlmssp_state->user, + &ntlmssp_state->workstation)) { DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP (tried both formats):\n")); dump_data(2, request.data, request.length); - SAFE_FREE(domain); - SAFE_FREE(user); - SAFE_FREE(workstation); return NT_STATUS_INVALID_PARAMETER; } @@ -713,34 +704,6 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, if (auth_flags) ntlmssp_handle_neg_flags(ntlmssp_state, auth_flags, lp_lanman_auth()); - if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) { - SAFE_FREE(domain); - SAFE_FREE(user); - SAFE_FREE(workstation); - data_blob_free(&encrypted_session_key); - return nt_status; - } - - if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) { - SAFE_FREE(domain); - SAFE_FREE(user); - SAFE_FREE(workstation); - data_blob_free(&encrypted_session_key); - return nt_status; - } - - if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_workstation(ntlmssp_state, workstation))) { - SAFE_FREE(domain); - SAFE_FREE(user); - SAFE_FREE(workstation); - data_blob_free(&encrypted_session_key); - return nt_status; - } - - SAFE_FREE(domain); - SAFE_FREE(user); - SAFE_FREE(workstation); - DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%lu len2=%lu\n", ntlmssp_state->user, ntlmssp_state->domain, ntlmssp_state->workstation, (unsigned long)ntlmssp_state->lm_resp.length, (unsigned long)ntlmssp_state->nt_resp.length)); @@ -873,9 +836,9 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, ntlmssp_state->session_key = session_key; } else { dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length); - SamOEMhash(encrypted_session_key.data, - session_key.data, - encrypted_session_key.length); + arcfour_crypt_blob(encrypted_session_key.data, + encrypted_session_key.length, + &session_key); ntlmssp_state->session_key = data_blob_talloc( ntlmssp_state, encrypted_session_key.data, encrypted_session_key.length); @@ -970,7 +933,7 @@ static NTSTATUS ntlmssp_client_initial(struct ntlmssp_state *ntlmssp_state, } /* generate the ntlmssp negotiate packet */ - msrpc_gen(next_request, "CddAA", + msrpc_gen(ntlmssp_state, next_request, "CddAA", "NTLMSSP", NTLMSSP_NEGOTIATE, ntlmssp_state->neg_flags, @@ -1007,7 +970,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB encrypted_session_key = data_blob_null; NTSTATUS nt_status = NT_STATUS_OK; - if (!msrpc_parse(&reply, "CdBd", + if (!msrpc_parse(ntlmssp_state, &reply, "CdBd", "NTLMSSP", &ntlmssp_command, &server_domain_blob, @@ -1045,7 +1008,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, DEBUG(3, ("NTLMSSP: Set final flags:\n")); debug_ntlmssp_flags(ntlmssp_state->neg_flags); - if (!msrpc_parse(&reply, chal_parse_string, + if (!msrpc_parse(ntlmssp_state, &reply, chal_parse_string, "NTLMSSP", &ntlmssp_command, &server_domain, @@ -1058,10 +1021,8 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, return NT_STATUS_INVALID_PARAMETER; } - ntlmssp_state->server_domain = talloc_strdup(ntlmssp_state, - server_domain); + ntlmssp_state->server_domain = server_domain; - SAFE_FREE(server_domain); if (challenge_blob.length != 8) { data_blob_free(&struct_blob); return NT_STATUS_INVALID_PARAMETER; @@ -1079,7 +1040,6 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, /* not doing NLTM2 without a password */ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2; } else if (ntlmssp_state->use_ntlmv2) { - if (!struct_blob.length) { /* be lazy, match win2k - we can't do NTLMv2 without it */ DEBUG(1, ("Server did not provide 'target information', required for NTLMv2\n")); @@ -1089,11 +1049,13 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, /* TODO: if the remote server is standalone, then we should replace 'domain' with the server name as supplied above */ - if (!SMBNTLMv2encrypt_hash(ntlmssp_state->user, - ntlmssp_state->domain, - ntlmssp_state->nt_hash, &challenge_blob, - &struct_blob, - &lm_response, &nt_response, &session_key)) { + if (!SMBNTLMv2encrypt_hash(ntlmssp_state, + ntlmssp_state->user, + ntlmssp_state->domain, + ntlmssp_state->nt_hash, &challenge_blob, + &struct_blob, + &lm_response, &nt_response, NULL, + &session_key)) { data_blob_free(&challenge_blob); data_blob_free(&struct_blob); return NT_STATUS_NO_MEMORY; @@ -1122,12 +1084,12 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, nt_response = data_blob_talloc(ntlmssp_state, NULL, 24); SMBNTencrypt_hash(ntlmssp_state->nt_hash, - session_nonce_hash, - nt_response.data); + session_nonce_hash, + nt_response.data); session_key = data_blob_talloc(ntlmssp_state, NULL, 16); - SMBsesskeygen_ntv1(ntlmssp_state->nt_hash, NULL, user_session_key); + SMBsesskeygen_ntv1(ntlmssp_state->nt_hash, user_session_key); hmac_md5(user_session_key, session_nonce, sizeof(session_nonce), session_key.data); dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length); } else { @@ -1150,7 +1112,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, session_key.data); dump_data_pw("LM session key\n", session_key.data, session_key.length); } else { - SMBsesskeygen_ntv1(ntlmssp_state->nt_hash, NULL, session_key.data); + SMBsesskeygen_ntv1(ntlmssp_state->nt_hash, session_key.data); dump_data_pw("NT session key:\n", session_key.data, session_key.length); } } @@ -1166,7 +1128,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, /* Encrypt the new session key with the old one */ encrypted_session_key = data_blob(client_session_key, sizeof(client_session_key)); dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, encrypted_session_key.length); - SamOEMhash(encrypted_session_key.data, session_key.data, encrypted_session_key.length); + arcfour_crypt_blob(encrypted_session_key.data, encrypted_session_key.length, &session_key); dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length); /* Mark the new session key as the 'real' session key */ @@ -1177,7 +1139,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, } /* this generates the actual auth packet */ - if (!msrpc_gen(next_request, auth_gen_string, + if (!msrpc_gen(ntlmssp_state, next_request, auth_gen_string, "NTLMSSP", NTLMSSP_AUTH, lm_response.data, lm_response.length, diff --git a/source3/libsmb/ntlmssp_parse.c b/source3/libsmb/ntlmssp_parse.c deleted file mode 100644 index 98c50596be..0000000000 --- a/source3/libsmb/ntlmssp_parse.c +++ /dev/null @@ -1,384 +0,0 @@ -/* - Unix SMB/CIFS implementation. - simple kerberos5/SPNEGO routines - Copyright (C) Andrew Tridgell 2001 - Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002 - Copyright (C) Andrew Bartlett 2002-2003 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" - -/* - this is a tiny msrpc packet generator. I am only using this to - avoid tying this code to a particular varient of our rpc code. This - generator is not general enough for all our rpc needs, its just - enough for the spnego/ntlmssp code - - format specifiers are: - - U = unicode string (input is unix string) - a = address (input is char *unix_string) - (1 byte type, 1 byte length, unicode/ASCII string, all inline) - A = ASCII string (input is unix string) - B = data blob (pointer + length) - b = data blob in header (pointer + length) - D - d = word (4 bytes) - C = constant ascii string - */ -bool msrpc_gen(DATA_BLOB *blob, - const char *format, ...) -{ - int i, n; - va_list ap; - char *s; - uint8 *b; - int head_size=0, data_size=0; - int head_ofs, data_ofs; - - /* first scan the format to work out the header and body size */ - va_start(ap, format); - for (i=0; format[i]; i++) { - switch (format[i]) { - case 'U': - s = va_arg(ap, char *); - head_size += 8; - data_size += str_charnum(s) * 2; - break; - case 'A': - s = va_arg(ap, char *); - head_size += 8; - data_size += str_ascii_charnum(s); - break; - case 'a': - n = va_arg(ap, int); - s = va_arg(ap, char *); - data_size += (str_charnum(s) * 2) + 4; - break; - case 'B': - b = va_arg(ap, uint8 *); - head_size += 8; - data_size += va_arg(ap, int); - break; - case 'b': - b = va_arg(ap, uint8 *); - head_size += va_arg(ap, int); - break; - case 'd': - n = va_arg(ap, int); - head_size += 4; - break; - case 'C': - s = va_arg(ap, char *); - head_size += str_charnum(s) + 1; - break; - } - } - va_end(ap); - - /* allocate the space, then scan the format - * again to fill in the values */ - - *blob = data_blob(NULL, head_size + data_size); - - head_ofs = 0; - data_ofs = head_size; - - va_start(ap, format); - for (i=0; format[i]; i++) { - switch (format[i]) { - case 'U': - s = va_arg(ap, char *); - n = str_charnum(s); - SSVAL(blob->data, head_ofs, n*2); head_ofs += 2; - SSVAL(blob->data, head_ofs, n*2); head_ofs += 2; - SIVAL(blob->data, head_ofs, data_ofs); head_ofs += 4; - push_string_check(blob->data+data_ofs, - s, n*2, STR_UNICODE|STR_NOALIGN); - data_ofs += n*2; - break; - case 'A': - s = va_arg(ap, char *); - n = str_ascii_charnum(s); - SSVAL(blob->data, head_ofs, n); head_ofs += 2; - SSVAL(blob->data, head_ofs, n); head_ofs += 2; - SIVAL(blob->data, head_ofs, data_ofs); head_ofs += 4; - push_string_check(blob->data+data_ofs, - s, n, STR_ASCII|STR_NOALIGN); - data_ofs += n; - break; - case 'a': - n = va_arg(ap, int); - SSVAL(blob->data, data_ofs, n); data_ofs += 2; - s = va_arg(ap, char *); - n = str_charnum(s); - SSVAL(blob->data, data_ofs, n*2); data_ofs += 2; - if (0 < n) { - push_string_check(blob->data+data_ofs, s, n*2, - STR_UNICODE|STR_NOALIGN); - } - data_ofs += n*2; - break; - - case 'B': - b = va_arg(ap, uint8 *); - n = va_arg(ap, int); - SSVAL(blob->data, head_ofs, n); head_ofs += 2; - SSVAL(blob->data, head_ofs, n); head_ofs += 2; - SIVAL(blob->data, head_ofs, data_ofs); head_ofs += 4; - if (n && b) /* don't follow null pointers... */ - memcpy(blob->data+data_ofs, b, n); - data_ofs += n; - break; - case 'd': - n = va_arg(ap, int); - SIVAL(blob->data, head_ofs, n); head_ofs += 4; - break; - case 'b': - b = va_arg(ap, uint8 *); - n = va_arg(ap, int); - memcpy(blob->data + head_ofs, b, n); - head_ofs += n; - break; - case 'C': - s = va_arg(ap, char *); - n = str_charnum(s) + 1; - head_ofs += push_string_check(blob->data+head_ofs, s, n, - STR_ASCII|STR_TERMINATE); - break; - } - } - va_end(ap); - - return true; -} - - -/* a helpful macro to avoid running over the end of our blob */ -#define NEED_DATA(amount) \ -if ((head_ofs + amount) > blob->length) { \ - va_end(ap); \ - return False; \ -} - -/* - this is a tiny msrpc packet parser. This the the partner of msrpc_gen - - format specifiers are: - - U = unicode string (output is unix string) - A = ascii string - B = data blob - b = data blob in header - d = word (4 bytes) - C = constant ascii string - */ - -bool msrpc_parse(const DATA_BLOB *blob, - const char *format, ...) -{ - int i; - va_list ap; - char **ps, *s; - DATA_BLOB *b; - size_t head_ofs = 0; - uint16 len1, len2; - uint32 ptr; - uint32 *v; - - va_start(ap, format); - for (i=0; format[i]; i++) { - switch (format[i]) { - case 'U': - NEED_DATA(8); - len1 = SVAL(blob->data, head_ofs); head_ofs += 2; - len2 = SVAL(blob->data, head_ofs); head_ofs += 2; - ptr = IVAL(blob->data, head_ofs); head_ofs += 4; - - ps = va_arg(ap, char **); - if (len1 == 0 && len2 == 0) { - *ps = smb_xstrdup(""); - } else { - /* make sure its in the right format - * be strict */ - if ((len1 != len2) || (ptr + len1 < ptr) || - (ptr + len1 < len1) || - (ptr + len1 > blob->length)) { - va_end(ap); - return false; - } - if (len1 & 1) { - /* if odd length and unicode */ - va_end(ap); - return false; - } - if (blob->data + ptr < - (uint8 *)(unsigned long)ptr || - blob->data + ptr < blob->data) { - va_end(ap); - return false; - } - - if (0 < len1) { - char *p = NULL; - pull_string_talloc(talloc_tos(), - NULL, - 0, - &p, - blob->data + ptr, - len1, - STR_UNICODE|STR_NOALIGN); - if (p) { - (*ps) = smb_xstrdup(p); - TALLOC_FREE(p); - } else { - (*ps) = smb_xstrdup(""); - } - } else { - (*ps) = smb_xstrdup(""); - } - } - break; - case 'A': - NEED_DATA(8); - len1 = SVAL(blob->data, head_ofs); head_ofs += 2; - len2 = SVAL(blob->data, head_ofs); head_ofs += 2; - ptr = IVAL(blob->data, head_ofs); head_ofs += 4; - - ps = va_arg(ap, char **); - /* make sure its in the right format - be strict */ - if (len1 == 0 && len2 == 0) { - *ps = smb_xstrdup(""); - } else { - if ((len1 != len2) || (ptr + len1 < ptr) || - (ptr + len1 < len1) || - (ptr + len1 > blob->length)) { - va_end(ap); - return false; - } - - if (blob->data + ptr < - (uint8 *)(unsigned long)ptr || - blob->data + ptr < blob->data) { - va_end(ap); - return false; - } - - if (0 < len1) { - char *p = NULL; - pull_string_talloc(talloc_tos(), - NULL, - 0, - &p, - blob->data + ptr, - len1, - STR_ASCII|STR_NOALIGN); - if (p) { - (*ps) = smb_xstrdup(p); - TALLOC_FREE(p); - } else { - (*ps) = smb_xstrdup(""); - } - } else { - (*ps) = smb_xstrdup(""); - } - } - break; - case 'B': - NEED_DATA(8); - len1 = SVAL(blob->data, head_ofs); head_ofs += 2; - len2 = SVAL(blob->data, head_ofs); head_ofs += 2; - ptr = IVAL(blob->data, head_ofs); head_ofs += 4; - - b = (DATA_BLOB *)va_arg(ap, void *); - if (len1 == 0 && len2 == 0) { - *b = data_blob_null; - } else { - /* make sure its in the right format - * be strict */ - if ((len1 != len2) || (ptr + len1 < ptr) || - (ptr + len1 < len1) || - (ptr + len1 > blob->length)) { - va_end(ap); - return false; - } - - if (blob->data + ptr < - (uint8 *)(unsigned long)ptr || - blob->data + ptr < blob->data) { - va_end(ap); - return false; - } - - *b = data_blob(blob->data + ptr, len1); - } - break; - case 'b': - b = (DATA_BLOB *)va_arg(ap, void *); - len1 = va_arg(ap, unsigned); - /* make sure its in the right format - be strict */ - NEED_DATA(len1); - if (blob->data + head_ofs < (uint8 *)head_ofs || - blob->data + head_ofs < blob->data) { - va_end(ap); - return false; - } - - *b = data_blob(blob->data + head_ofs, len1); - head_ofs += len1; - break; - case 'd': - v = va_arg(ap, uint32 *); - NEED_DATA(4); - *v = IVAL(blob->data, head_ofs); head_ofs += 4; - break; - case 'C': - s = va_arg(ap, char *); - - if (blob->data + head_ofs < (uint8 *)head_ofs || - blob->data + head_ofs < blob->data) { - va_end(ap); - return false; - } - - { - char *p = NULL; - size_t ret = pull_string_talloc(talloc_tos(), - NULL, - 0, - &p, - blob->data+head_ofs, - blob->length - head_ofs, - STR_ASCII|STR_TERMINATE); - if (ret == (size_t)-1 || p == NULL) { - va_end(ap); - return false; - } - head_ofs += ret; - if (strcmp(s, p) != 0) { - TALLOC_FREE(p); - va_end(ap); - return false; - } - TALLOC_FREE(p); - } - break; - } - } - va_end(ap); - - return True; -} diff --git a/source3/libsmb/ntlmssp_sign.c b/source3/libsmb/ntlmssp_sign.c index d3d358d332..030161f76c 100644 --- a/source3/libsmb/ntlmssp_sign.c +++ b/source3/libsmb/ntlmssp_sign.c @@ -19,6 +19,7 @@ */ #include "includes.h" +#include "../libcli/auth/libcli_auth.h" #define CLI_SIGN "session key to client-to-server signing key magic constant" #define CLI_SEAL "session key to client-to-server sealing key magic constant" @@ -124,7 +125,7 @@ static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_STATE *ntlmssp_state, } else { uint32 crc; crc = crc32_calc_buffer(data, length); - if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmv1_seq_num)) { + if (!msrpc_gen(ntlmssp_state, sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmv1_seq_num)) { return NT_STATUS_NO_MEMORY; } @@ -271,7 +272,7 @@ NTSTATUS ntlmssp_seal_packet(NTLMSSP_STATE *ntlmssp_state, } else { uint32 crc; crc = crc32_calc_buffer(data, length); - if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmv1_seq_num)) { + if (!msrpc_gen(ntlmssp_state, sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmv1_seq_num)) { return NT_STATUS_NO_MEMORY; } diff --git a/source3/libsmb/smbdes.c b/source3/libsmb/smbdes.c deleted file mode 100644 index 8087d66799..0000000000 --- a/source3/libsmb/smbdes.c +++ /dev/null @@ -1,421 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - a partial implementation of DES designed for use in the - SMB authentication protocol - - Copyright (C) Andrew Tridgell 1998 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" - -/* NOTES: - - This code makes no attempt to be fast! In fact, it is a very - slow implementation - - This code is NOT a complete DES implementation. It implements only - the minimum necessary for SMB authentication, as used by all SMB - products (including every copy of Microsoft Windows95 ever sold) - - In particular, it can only do a unchained forward DES pass. This - means it is not possible to use this code for encryption/decryption - of data, instead it is only useful as a "hash" algorithm. - - There is no entry point into this code that allows normal DES operation. - - I believe this means that this code does not come under ITAR - regulations but this is NOT a legal opinion. If you are concerned - about the applicability of ITAR regulations to this code then you - should confirm it for yourself (and maybe let me know if you come - up with a different answer to the one above) -*/ - - -#define uchar unsigned char - -static const uchar perm1[56] = {57, 49, 41, 33, 25, 17, 9, - 1, 58, 50, 42, 34, 26, 18, - 10, 2, 59, 51, 43, 35, 27, - 19, 11, 3, 60, 52, 44, 36, - 63, 55, 47, 39, 31, 23, 15, - 7, 62, 54, 46, 38, 30, 22, - 14, 6, 61, 53, 45, 37, 29, - 21, 13, 5, 28, 20, 12, 4}; - -static const uchar perm2[48] = {14, 17, 11, 24, 1, 5, - 3, 28, 15, 6, 21, 10, - 23, 19, 12, 4, 26, 8, - 16, 7, 27, 20, 13, 2, - 41, 52, 31, 37, 47, 55, - 30, 40, 51, 45, 33, 48, - 44, 49, 39, 56, 34, 53, - 46, 42, 50, 36, 29, 32}; - -static const uchar perm3[64] = {58, 50, 42, 34, 26, 18, 10, 2, - 60, 52, 44, 36, 28, 20, 12, 4, - 62, 54, 46, 38, 30, 22, 14, 6, - 64, 56, 48, 40, 32, 24, 16, 8, - 57, 49, 41, 33, 25, 17, 9, 1, - 59, 51, 43, 35, 27, 19, 11, 3, - 61, 53, 45, 37, 29, 21, 13, 5, - 63, 55, 47, 39, 31, 23, 15, 7}; - -static const uchar perm4[48] = { 32, 1, 2, 3, 4, 5, - 4, 5, 6, 7, 8, 9, - 8, 9, 10, 11, 12, 13, - 12, 13, 14, 15, 16, 17, - 16, 17, 18, 19, 20, 21, - 20, 21, 22, 23, 24, 25, - 24, 25, 26, 27, 28, 29, - 28, 29, 30, 31, 32, 1}; - -static const uchar perm5[32] = { 16, 7, 20, 21, - 29, 12, 28, 17, - 1, 15, 23, 26, - 5, 18, 31, 10, - 2, 8, 24, 14, - 32, 27, 3, 9, - 19, 13, 30, 6, - 22, 11, 4, 25}; - - -static const uchar perm6[64] ={ 40, 8, 48, 16, 56, 24, 64, 32, - 39, 7, 47, 15, 55, 23, 63, 31, - 38, 6, 46, 14, 54, 22, 62, 30, - 37, 5, 45, 13, 53, 21, 61, 29, - 36, 4, 44, 12, 52, 20, 60, 28, - 35, 3, 43, 11, 51, 19, 59, 27, - 34, 2, 42, 10, 50, 18, 58, 26, - 33, 1, 41, 9, 49, 17, 57, 25}; - - -static const uchar sc[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1}; - -static const uchar sbox[8][4][16] = { - {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7}, - {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8}, - {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0}, - {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}}, - - {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10}, - {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5}, - {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15}, - {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}}, - - {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8}, - {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1}, - {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7}, - {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}}, - - {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15}, - {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9}, - {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4}, - {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}}, - - {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9}, - {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6}, - {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14}, - {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}}, - - {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11}, - {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8}, - {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6}, - {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}}, - - {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1}, - {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6}, - {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2}, - {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}}, - - {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7}, - {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2}, - {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8}, - {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}}; - -static void permute(char *out, const char *in, const uchar *p, int n) -{ - int i; - for (i=0;i<n;i++) - out[i] = in[p[i]-1]; -} - -static void lshift(char *d, int count, int n) -{ - char out[64]; - int i; - for (i=0;i<n;i++) - out[i] = d[(i+count)%n]; - for (i=0;i<n;i++) - d[i] = out[i]; -} - -static void concat(char *out, char *in1, char *in2, int l1, int l2) -{ - while (l1--) - *out++ = *in1++; - while (l2--) - *out++ = *in2++; -} - -static void x_or(char *out, char *in1, char *in2, int n) -{ - int i; - for (i=0;i<n;i++) - out[i] = in1[i] ^ in2[i]; -} - -static void dohash(char *out, char *in, char *key, int forw) -{ - int i, j, k; - char pk1[56]; - char c[28]; - char d[28]; - char cd[56]; - char ki[16][48]; - char pd1[64]; - char l[32], r[32]; - char rl[64]; - - permute(pk1, key, perm1, 56); - - for (i=0;i<28;i++) - c[i] = pk1[i]; - for (i=0;i<28;i++) - d[i] = pk1[i+28]; - - for (i=0;i<16;i++) { - lshift(c, sc[i], 28); - lshift(d, sc[i], 28); - - concat(cd, c, d, 28, 28); - permute(ki[i], cd, perm2, 48); - } - - permute(pd1, in, perm3, 64); - - for (j=0;j<32;j++) { - l[j] = pd1[j]; - r[j] = pd1[j+32]; - } - - for (i=0;i<16;i++) { - char er[48]; - char erk[48]; - char b[8][6]; - char cb[32]; - char pcb[32]; - char r2[32]; - - permute(er, r, perm4, 48); - - x_or(erk, er, ki[forw ? i : 15 - i], 48); - - for (j=0;j<8;j++) - for (k=0;k<6;k++) - b[j][k] = erk[j*6 + k]; - - for (j=0;j<8;j++) { - int m, n; - m = (b[j][0]<<1) | b[j][5]; - - n = (b[j][1]<<3) | (b[j][2]<<2) | (b[j][3]<<1) | b[j][4]; - - for (k=0;k<4;k++) - b[j][k] = (sbox[j][m][n] & (1<<(3-k)))?1:0; - } - - for (j=0;j<8;j++) - for (k=0;k<4;k++) - cb[j*4+k] = b[j][k]; - permute(pcb, cb, perm5, 32); - - x_or(r2, l, pcb, 32); - - for (j=0;j<32;j++) - l[j] = r[j]; - - for (j=0;j<32;j++) - r[j] = r2[j]; - } - - concat(rl, r, l, 32, 32); - - permute(out, rl, perm6, 64); -} - -/* Convert a 7 byte string to an 8 byte key. */ -static void str_to_key(const unsigned char str[7], unsigned char key[8]) -{ - int i; - - key[0] = str[0]>>1; - key[1] = ((str[0]&0x01)<<6) | (str[1]>>2); - key[2] = ((str[1]&0x03)<<5) | (str[2]>>3); - key[3] = ((str[2]&0x07)<<4) | (str[3]>>4); - key[4] = ((str[3]&0x0F)<<3) | (str[4]>>5); - key[5] = ((str[4]&0x1F)<<2) | (str[5]>>6); - key[6] = ((str[5]&0x3F)<<1) | (str[6]>>7); - key[7] = str[6]&0x7F; - for (i=0;i<8;i++) { - key[i] = (key[i]<<1); - } -} - - -void des_crypt56(unsigned char *out, const unsigned char *in, const unsigned char *key, int forw) -{ - int i; - char outb[64]; - char inb[64]; - char keyb[64]; - unsigned char key2[8]; - - str_to_key(key, key2); - - for (i=0;i<64;i++) { - inb[i] = (in[i/8] & (1<<(7-(i%8)))) ? 1 : 0; - keyb[i] = (key2[i/8] & (1<<(7-(i%8)))) ? 1 : 0; - outb[i] = 0; - } - - dohash(outb, inb, keyb, forw); - - for (i=0;i<8;i++) { - out[i] = 0; - } - - for (i=0;i<64;i++) { - if (outb[i]) - out[i/8] |= (1<<(7-(i%8))); - } -} - -void E_P16(const unsigned char *p14,unsigned char *p16) -{ - unsigned char sp8[8] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25}; - des_crypt56(p16, sp8, p14, 1); - des_crypt56(p16+8, sp8, p14+7, 1); -} - -void E_P24(const unsigned char *p21, const unsigned char *c8, unsigned char *p24) -{ - des_crypt56(p24, c8, p21, 1); - des_crypt56(p24+8, c8, p21+7, 1); - des_crypt56(p24+16, c8, p21+14, 1); -} - -void D_P16(const unsigned char *p14, const unsigned char *in, unsigned char *out) -{ - des_crypt56(out, in, p14, 0); - des_crypt56(out+8, in+8, p14+7, 0); -} - -void E_old_pw_hash( unsigned char *p14, const unsigned char *in, unsigned char *out) -{ - des_crypt56(out, in, p14, 1); - des_crypt56(out+8, in+8, p14+7, 1); -} - -/* forward des encryption with a 128 bit key */ -void des_crypt128(unsigned char out[8], const unsigned char in[8], const unsigned char key[16]) -{ - unsigned char buf[8]; - - des_crypt56(buf, in, key, 1); - des_crypt56(out, buf, key+9, 1); -} - -/* forward des encryption with a 64 bit key */ -void des_crypt64(unsigned char out[8], const unsigned char in[8], const unsigned char key[8]) -{ - unsigned char buf[8]; - unsigned char key2[8]; - - memset(key2,'\0',8); - des_crypt56(buf, in, key, 1); - key2[0] = key[7]; - des_crypt56(out, buf, key2, 1); -} - -/* des encryption with a 112 bit (14 byte) key */ -/* Note that if the forw is 1, and key is actually 8 bytes of key, followed by 6 bytes of zeros, - this is identical to des_crypt64(). JRA. */ - -void des_crypt112(unsigned char out[8], const unsigned char in[8], const unsigned char key[14], int forw) -{ - unsigned char buf[8]; - des_crypt56(buf, in, key, forw); - des_crypt56(out, buf, key+7, forw); -} - -void cred_hash3(unsigned char *out, const unsigned char *in, const unsigned char *key, int forw) -{ - unsigned char key2[8]; - - memset(key2,'\0',8); - des_crypt56(out, in, key, forw); - key2[0] = key[7]; - des_crypt56(out + 8, in + 8, key2, forw); -} - -/* des encryption of a 16 byte lump of data with a 112 bit key */ -/* Note that if the key is actually 8 bytes of key, followed by 6 bytes of zeros, - this is identical to cred_hash3(). JRA. */ - -void des_crypt112_16(unsigned char out[16], unsigned char in[16], const unsigned char key[14], int forw) -{ - des_crypt56(out, in, key, forw); - des_crypt56(out + 8, in + 8, key+7, forw); -} - -/***************************************************************** - arc4 crypt/decrypt with a 16 byte key. -*****************************************************************/ - -void SamOEMhash( unsigned char *data, const unsigned char key[16], size_t len) -{ - struct arcfour_state arc4_state; - const DATA_BLOB keyblob = data_blob_const(key, 16); - - arcfour_init(&arc4_state, &keyblob); - arcfour_crypt_sbox(&arc4_state, data, len); -} - -void SamOEMhashBlob( unsigned char *data, size_t len, DATA_BLOB *key) -{ - struct arcfour_state arc4_state; - - arcfour_init(&arc4_state, key); - arcfour_crypt_sbox(&arc4_state, data, len); -} - -/* Decode a sam password hash into a password. The password hash is the - same method used to store passwords in the NT registry. The DES key - used is based on the RID of the user. */ - -void sam_pwd_hash(unsigned int rid, const uchar *in, uchar *out, int forw) -{ - uchar s[14]; - - s[0] = s[4] = s[8] = s[12] = (uchar)(rid & 0xFF); - s[1] = s[5] = s[9] = s[13] = (uchar)((rid >> 8) & 0xFF); - s[2] = s[6] = s[10] = (uchar)((rid >> 16) & 0xFF); - s[3] = s[7] = s[11] = (uchar)((rid >> 24) & 0xFF); - - des_crypt56(out, in, s, forw); - des_crypt56(out+8, in+8, s+7, forw); -} diff --git a/source3/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c deleted file mode 100644 index 27702b9f42..0000000000 --- a/source3/libsmb/smbencrypt.c +++ /dev/null @@ -1,898 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SMB parameters and setup - Copyright (C) Andrew Tridgell 1992-1998 - Modified by Jeremy Allison 1995. - Copyright (C) Jeremy Allison 1995-2000. - Copyright (C) Luke Kennethc Casson Leighton 1996-2000. - Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" -#include "../lib/util/byteorder.h" - -void SMBencrypt_hash(const uchar lm_hash[16], const uchar *c8, uchar p24[24]) -{ - uchar p21[21]; - - memset(p21,'\0',21); - memcpy(p21, lm_hash, 16); - - SMBOWFencrypt(p21, c8, p24); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("SMBencrypt_hash: lm#, challenge, response\n")); - dump_data(100, p21, 16); - dump_data(100, c8, 8); - dump_data(100, p24, 24); -#endif -} - -/* - This implements the X/Open SMB password encryption - It takes a password ('unix' string), a 8 byte "crypt key" - and puts 24 bytes of encrypted password into p24 - - Returns False if password must have been truncated to create LM hash -*/ - -bool SMBencrypt(const char *passwd, const uchar *c8, uchar p24[24]) -{ - bool ret; - uchar lm_hash[16]; - - ret = E_deshash(passwd, lm_hash); - SMBencrypt_hash(lm_hash, c8, p24); - return ret; -} - -/** - * Creates the MD4 Hash of the users password in NT UNICODE. - * @param passwd password in 'unix' charset. - * @param p16 return password hashed with md4, caller allocated 16 byte buffer - */ - -void E_md4hash(const char *passwd, uchar p16[16]) -{ - int len; - smb_ucs2_t wpwd[129]; - - /* Password must be converted to NT unicode - null terminated. */ - push_ucs2(NULL, wpwd, (const char *)passwd, 256, STR_UNICODE|STR_NOALIGN|STR_TERMINATE); - /* Calculate length in bytes */ - len = strlen_w(wpwd) * sizeof(int16); - - mdfour(p16, (unsigned char *)wpwd, len); - ZERO_STRUCT(wpwd); -} - -/** - * Creates the MD5 Hash of a combination of 16 byte salt and 16 byte NT hash. - * @param 16 byte salt. - * @param 16 byte NT hash. - * @param 16 byte return hashed with md5, caller allocated 16 byte buffer - */ - -void E_md5hash(const uchar salt[16], const uchar nthash[16], uchar hash_out[16]) -{ - struct MD5Context tctx; - uchar array[32]; - - memset(hash_out, '\0', 16); - memcpy(array, salt, 16); - memcpy(&array[16], nthash, 16); - MD5Init(&tctx); - MD5Update(&tctx, array, 32); - MD5Final(hash_out, &tctx); -} - -/** - * Creates the DES forward-only Hash of the users password in DOS ASCII charset - * @param passwd password in 'unix' charset. - * @param p16 return password hashed with DES, caller allocated 16 byte buffer - * @return False if password was > 14 characters, and therefore may be incorrect, otherwise True - * @note p16 is filled in regardless - */ - -bool E_deshash(const char *passwd, uchar p16[16]) -{ - bool ret = True; - fstring dospwd; - ZERO_STRUCT(dospwd); - - /* Password must be converted to DOS charset - null terminated, uppercase. */ - push_ascii(dospwd, passwd, sizeof(dospwd), STR_UPPER|STR_TERMINATE); - - /* Only the fisrt 14 chars are considered, password need not be null terminated. */ - E_P16((const unsigned char *)dospwd, p16); - - if (strlen(dospwd) > 14) { - ret = False; - } - - ZERO_STRUCT(dospwd); - - return ret; -} - -/** - * Creates the MD4 and DES (LM) Hash of the users password. - * MD4 is of the NT Unicode, DES is of the DOS UPPERCASE password. - * @param passwd password in 'unix' charset. - * @param nt_p16 return password hashed with md4, caller allocated 16 byte buffer - * @param p16 return password hashed with des, caller allocated 16 byte buffer - */ - -/* Does both the NT and LM owfs of a user's password */ -void nt_lm_owf_gen(const char *pwd, uchar nt_p16[16], uchar p16[16]) -{ - /* Calculate the MD4 hash (NT compatible) of the password */ - memset(nt_p16, '\0', 16); - E_md4hash(pwd, nt_p16); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("nt_lm_owf_gen: pwd, nt#\n")); - dump_data(120, (uint8 *)pwd, strlen(pwd)); - dump_data(100, nt_p16, 16); -#endif - - E_deshash(pwd, (uchar *)p16); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("nt_lm_owf_gen: pwd, lm#\n")); - dump_data(120, (uint8 *)pwd, strlen(pwd)); - dump_data(100, p16, 16); -#endif -} - -/* Does both the NTLMv2 owfs of a user's password */ -bool ntv2_owf_gen(const uchar owf[16], - const char *user_in, const char *domain_in, - bool upper_case_domain, /* Transform the domain into UPPER case */ - uchar kr_buf[16]) -{ - smb_ucs2_t *user; - smb_ucs2_t *domain; - - size_t user_byte_len; - size_t domain_byte_len; - - HMACMD5Context ctx; - - if (!push_ucs2_talloc(NULL, &user, user_in, &user_byte_len)) { - DEBUG(0, ("push_uss2_talloc() for user failed: %s\n", - strerror(errno))); - return False; - } - - if (!push_ucs2_talloc(NULL, &domain, domain_in, &domain_byte_len)) { - DEBUG(0, ("push_uss2_talloc() for domain failed: %s\n", - strerror(errno))); - TALLOC_FREE(user); - return False; - } - - strupper_w(user); - - if (upper_case_domain) - strupper_w(domain); - - SMB_ASSERT(user_byte_len >= 2); - SMB_ASSERT(domain_byte_len >= 2); - - /* We don't want null termination */ - user_byte_len = user_byte_len - 2; - domain_byte_len = domain_byte_len - 2; - - hmac_md5_init_limK_to_64(owf, 16, &ctx); - hmac_md5_update((const unsigned char *)user, user_byte_len, &ctx); - hmac_md5_update((const unsigned char *)domain, domain_byte_len, &ctx); - hmac_md5_final(kr_buf, &ctx); - -#ifdef DEBUG_PASSWORD - DEBUG(100, ("ntv2_owf_gen: user, domain, owfkey, kr\n")); - dump_data(100, (uint8 *)user, user_byte_len); - dump_data(100, (uint8 *)domain, domain_byte_len); - dump_data(100, (uint8 *)owf, 16); - dump_data(100, (uint8 *)kr_buf, 16); -#endif - - TALLOC_FREE(user); - TALLOC_FREE(domain); - return True; -} - -/* Does the des encryption from the NT or LM MD4 hash. */ -void SMBOWFencrypt(const uchar passwd[16], const uchar *c8, uchar p24[24]) -{ - uchar p21[21]; - - ZERO_STRUCT(p21); - - memcpy(p21, passwd, 16); - E_P24(p21, c8, p24); -} - -/* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */ -void NTLMSSPOWFencrypt(const uchar passwd[8], const uchar *ntlmchalresp, uchar p24[24]) -{ - uchar p21[21]; - - memset(p21,'\0',21); - memcpy(p21, passwd, 8); - memset(p21 + 8, 0xbd, 8); - - E_P24(p21, ntlmchalresp, p24); -#ifdef DEBUG_PASSWORD - DEBUG(100,("NTLMSSPOWFencrypt: p21, c8, p24\n")); - dump_data(100, p21, 21); - dump_data(100, ntlmchalresp, 8); - dump_data(100, p24, 24); -#endif -} - - -/* Does the des encryption. */ - -void SMBNTencrypt_hash(const uchar nt_hash[16], uchar *c8, uchar *p24) -{ - uchar p21[21]; - - memset(p21,'\0',21); - memcpy(p21, nt_hash, 16); - SMBOWFencrypt(p21, c8, p24); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("SMBNTencrypt: nt#, challenge, response\n")); - dump_data(100, p21, 16); - dump_data(100, c8, 8); - dump_data(100, p24, 24); -#endif -} - -/* Does the NT MD4 hash then des encryption. Plaintext version of the above. */ - -void SMBNTencrypt(const char *passwd, uchar *c8, uchar *p24) -{ - uchar nt_hash[16]; - E_md4hash(passwd, nt_hash); - SMBNTencrypt_hash(nt_hash, c8, p24); -} - -/* Does the md5 encryption from the Key Response for NTLMv2. */ -void SMBOWFencrypt_ntv2(const uchar kr[16], - const DATA_BLOB *srv_chal, - const DATA_BLOB *cli_chal, - uchar resp_buf[16]) -{ - HMACMD5Context ctx; - - hmac_md5_init_limK_to_64(kr, 16, &ctx); - hmac_md5_update(srv_chal->data, srv_chal->length, &ctx); - hmac_md5_update(cli_chal->data, cli_chal->length, &ctx); - hmac_md5_final(resp_buf, &ctx); - -#ifdef DEBUG_PASSWORD - DEBUG(100, ("SMBOWFencrypt_ntv2: srv_chal, cli_chal, resp_buf\n")); - dump_data(100, srv_chal->data, srv_chal->length); - dump_data(100, cli_chal->data, cli_chal->length); - dump_data(100, resp_buf, 16); -#endif -} - -void SMBsesskeygen_ntv2(const uchar kr[16], - const uchar * nt_resp, uint8 sess_key[16]) -{ - /* a very nice, 128 bit, variable session key */ - - HMACMD5Context ctx; - - hmac_md5_init_limK_to_64(kr, 16, &ctx); - hmac_md5_update(nt_resp, 16, &ctx); - hmac_md5_final((unsigned char *)sess_key, &ctx); - -#ifdef DEBUG_PASSWORD - DEBUG(100, ("SMBsesskeygen_ntv2:\n")); - dump_data(100, sess_key, 16); -#endif -} - -void SMBsesskeygen_ntv1(const uchar kr[16], - const uchar * nt_resp, uint8 sess_key[16]) -{ - /* yes, this session key does not change - yes, this - is a problem - but it is 128 bits */ - - mdfour((unsigned char *)sess_key, kr, 16); - -#ifdef DEBUG_PASSWORD - DEBUG(100, ("SMBsesskeygen_ntv1:\n")); - dump_data(100, sess_key, 16); -#endif -} - -void SMBsesskeygen_lm_sess_key(const uchar lm_hash[16], - const uchar lm_resp[24], /* only uses 8 */ - uint8 sess_key[16]) -{ - uchar p24[24]; - uchar partial_lm_hash[16]; - - memcpy(partial_lm_hash, lm_hash, 8); - memset(partial_lm_hash + 8, 0xbd, 8); - - SMBOWFencrypt(partial_lm_hash, lm_resp, p24); - - memcpy(sess_key, p24, 16); - -#ifdef DEBUG_PASSWORD - DEBUG(100, ("SMBsesskeygen_lmv1_jerry:\n")); - dump_data(100, sess_key, 16); -#endif -} - -DATA_BLOB NTLMv2_generate_names_blob(const char *hostname, - const char *domain) -{ - DATA_BLOB names_blob = data_blob_null; - - msrpc_gen(&names_blob, "aaa", - NTLMSSP_NAME_TYPE_DOMAIN, domain, - NTLMSSP_NAME_TYPE_SERVER, hostname, - 0, ""); - return names_blob; -} - -static DATA_BLOB NTLMv2_generate_client_data(const DATA_BLOB *names_blob) -{ - uchar client_chal[8]; - DATA_BLOB response = data_blob_null; - char long_date[8]; - - generate_random_buffer(client_chal, sizeof(client_chal)); - - put_long_date(long_date, time(NULL)); - - /* See http://www.ubiqx.org/cifs/SMB.html#SMB.8.5 */ - - msrpc_gen(&response, "ddbbdb", - 0x00000101, /* Header */ - 0, /* 'Reserved' */ - long_date, 8, /* Timestamp */ - client_chal, 8, /* client challenge */ - 0, /* Unknown */ - names_blob->data, names_blob->length); /* End of name list */ - - return response; -} - -static DATA_BLOB NTLMv2_generate_response(const uchar ntlm_v2_hash[16], - const DATA_BLOB *server_chal, - const DATA_BLOB *names_blob) -{ - uchar ntlmv2_response[16]; - DATA_BLOB ntlmv2_client_data; - DATA_BLOB final_response; - - /* NTLMv2 */ - /* generate some data to pass into the response function - including - the hostname and domain name of the server */ - ntlmv2_client_data = NTLMv2_generate_client_data(names_blob); - - /* Given that data, and the challenge from the server, generate a response */ - SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, &ntlmv2_client_data, ntlmv2_response); - - final_response = data_blob(NULL, sizeof(ntlmv2_response) + ntlmv2_client_data.length); - - memcpy(final_response.data, ntlmv2_response, sizeof(ntlmv2_response)); - - memcpy(final_response.data+sizeof(ntlmv2_response), - ntlmv2_client_data.data, ntlmv2_client_data.length); - - data_blob_free(&ntlmv2_client_data); - - return final_response; -} - -static DATA_BLOB LMv2_generate_response(const uchar ntlm_v2_hash[16], - const DATA_BLOB *server_chal) -{ - uchar lmv2_response[16]; - DATA_BLOB lmv2_client_data = data_blob(NULL, 8); - DATA_BLOB final_response = data_blob(NULL, 24); - - /* LMv2 */ - /* client-supplied random data */ - generate_random_buffer(lmv2_client_data.data, lmv2_client_data.length); - - /* Given that data, and the challenge from the server, generate a response */ - SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, &lmv2_client_data, lmv2_response); - memcpy(final_response.data, lmv2_response, sizeof(lmv2_response)); - - /* after the first 16 bytes is the random data we generated above, - so the server can verify us with it */ - memcpy(final_response.data+sizeof(lmv2_response), - lmv2_client_data.data, lmv2_client_data.length); - - data_blob_free(&lmv2_client_data); - - return final_response; -} - -bool SMBNTLMv2encrypt_hash(const char *user, const char *domain, const uchar nt_hash[16], - const DATA_BLOB *server_chal, - const DATA_BLOB *names_blob, - DATA_BLOB *lm_response, DATA_BLOB *nt_response, - DATA_BLOB *user_session_key) -{ - uchar ntlm_v2_hash[16]; - - /* We don't use the NT# directly. Instead we use it mashed up with - the username and domain. - This prevents username swapping during the auth exchange - */ - if (!ntv2_owf_gen(nt_hash, user, domain, False, ntlm_v2_hash)) { - return False; - } - - if (nt_response) { - *nt_response = NTLMv2_generate_response(ntlm_v2_hash, server_chal, - names_blob); - if (user_session_key) { - *user_session_key = data_blob(NULL, 16); - - /* The NTLMv2 calculations also provide a session key, for signing etc later */ - /* use only the first 16 bytes of nt_response for session key */ - SMBsesskeygen_ntv2(ntlm_v2_hash, nt_response->data, user_session_key->data); - } - } - - /* LMv2 */ - - if (lm_response) { - *lm_response = LMv2_generate_response(ntlm_v2_hash, server_chal); - } - - return True; -} - -/* Plaintext version of the above. */ - -bool SMBNTLMv2encrypt(const char *user, const char *domain, const char *password, - const DATA_BLOB *server_chal, - const DATA_BLOB *names_blob, - DATA_BLOB *lm_response, DATA_BLOB *nt_response, - DATA_BLOB *user_session_key) -{ - uchar nt_hash[16]; - E_md4hash(password, nt_hash); - - return SMBNTLMv2encrypt_hash(user, domain, nt_hash, - server_chal, - names_blob, - lm_response, nt_response, - user_session_key); -} - -/*********************************************************** - encode a password buffer with a unicode password. The buffer - is filled with random data to make it harder to attack. -************************************************************/ -bool encode_pw_buffer(uint8 buffer[516], const char *password, int string_flags) -{ - uchar new_pw[512]; - size_t new_pw_len; - - /* the incoming buffer can be any alignment. */ - string_flags |= STR_NOALIGN; - - new_pw_len = push_string_check(new_pw, - password, - sizeof(new_pw), string_flags); - - memcpy(&buffer[512 - new_pw_len], new_pw, new_pw_len); - - generate_random_buffer(buffer, 512 - new_pw_len); - - /* - * The length of the new password is in the last 4 bytes of - * the data buffer. - */ - SIVAL(buffer, 512, new_pw_len); - ZERO_STRUCT(new_pw); - return True; -} - - -/*********************************************************** - decode a password buffer - *new_pw_len is the length in bytes of the possibly mulitbyte - returned password including termination. -************************************************************/ - -bool decode_pw_buffer(TALLOC_CTX *ctx, - uint8 in_buffer[516], - char **pp_new_pwrd, - uint32 *new_pw_len, - int string_flags) -{ - int byte_len=0; - - *pp_new_pwrd = NULL; - *new_pw_len = 0; - - /* the incoming buffer can be any alignment. */ - string_flags |= STR_NOALIGN; - - /* - Warning !!! : This function is called from some rpc call. - The password IN the buffer may be a UNICODE string. - The password IN new_pwrd is an ASCII string - If you reuse that code somewhere else check first. - */ - - /* The length of the new password is in the last 4 bytes of the data buffer. */ - - byte_len = IVAL(in_buffer, 512); - -#ifdef DEBUG_PASSWORD - dump_data(100, in_buffer, 516); -#endif - - /* Password cannot be longer than the size of the password buffer */ - if ( (byte_len < 0) || (byte_len > 512)) { - DEBUG(0, ("decode_pw_buffer: incorrect password length (%d).\n", byte_len)); - DEBUG(0, ("decode_pw_buffer: check that 'encrypt passwords = yes'\n")); - return false; - } - - /* decode into the return buffer. */ - *new_pw_len = pull_string_talloc(ctx, - NULL, - 0, - pp_new_pwrd, - &in_buffer[512 - byte_len], - byte_len, - string_flags); - - if (!*pp_new_pwrd || *new_pw_len == 0) { - DEBUG(0, ("decode_pw_buffer: pull_string_talloc failed\n")); - return false; - } - -#ifdef DEBUG_PASSWORD - DEBUG(100,("decode_pw_buffer: new_pwrd: ")); - dump_data(100, (uint8 *)*pp_new_pwrd, *new_pw_len); - DEBUG(100,("multibyte len:%d\n", *new_pw_len)); - DEBUG(100,("original char len:%d\n", byte_len/2)); -#endif - - return true; -} - -/*********************************************************** - Decode an arc4 encrypted password change buffer. -************************************************************/ - -void encode_or_decode_arc4_passwd_buffer(unsigned char pw_buf[532], const DATA_BLOB *psession_key) -{ - struct MD5Context tctx; - unsigned char key_out[16]; - - /* Confounder is last 16 bytes. */ - - MD5Init(&tctx); - MD5Update(&tctx, &pw_buf[516], 16); - MD5Update(&tctx, psession_key->data, psession_key->length); - MD5Final(key_out, &tctx); - /* arc4 with key_out. */ - SamOEMhash(pw_buf, key_out, 516); -} - -/*********************************************************** - Encrypt/Decrypt used for LSA secrets and trusted domain - passwords. -************************************************************/ - -void sess_crypt_blob(DATA_BLOB *out, const DATA_BLOB *in, const DATA_BLOB *session_key, int forward) -{ - int i, k; - - for (i=0,k=0; - i<in->length; - i += 8, k += 7) { - uint8 bin[8], bout[8], key[7]; - - memset(bin, 0, 8); - memcpy(bin, &in->data[i], MIN(8, in->length-i)); - - if (k + 7 > session_key->length) { - k = (session_key->length - k); - } - memcpy(key, &session_key->data[k], 7); - - des_crypt56(bout, bin, key, forward?1:0); - - memcpy(&out->data[i], bout, MIN(8, in->length-i)); - } -} - -/* Decrypts password-blob with session-key - * @param nt_hash NT hash for the session key - * @param data_in DATA_BLOB encrypted password - * - * Returns cleartext password in CH_UNIX - * Caller must free the returned string - */ - -char *decrypt_trustdom_secret(uint8_t nt_hash[16], DATA_BLOB *data_in) -{ - DATA_BLOB data_out, sess_key; - uint32_t length; - uint32_t version; - fstring cleartextpwd; - - if (!data_in || !nt_hash) - return NULL; - - /* hashed twice with md4 */ - mdfour(nt_hash, nt_hash, 16); - - /* 16-Byte session-key */ - sess_key = data_blob(nt_hash, 16); - if (sess_key.data == NULL) - return NULL; - - data_out = data_blob(NULL, data_in->length); - if (data_out.data == NULL) - return NULL; - - /* decrypt with des3 */ - sess_crypt_blob(&data_out, data_in, &sess_key, 0); - - /* 4 Byte length, 4 Byte version */ - length = IVAL(data_out.data, 0); - version = IVAL(data_out.data, 4); - - if (length > data_in->length - 8) { - DEBUG(0,("decrypt_trustdom_secret: invalid length (%d)\n", length)); - return NULL; - } - - if (version != 1) { - DEBUG(0,("decrypt_trustdom_secret: unknown version number (%d)\n", version)); - return NULL; - } - - rpcstr_pull(cleartextpwd, data_out.data + 8, sizeof(fstring), length, 0 ); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("decrypt_trustdom_secret: length is: %d, version is: %d, password is: %s\n", - length, version, cleartextpwd)); -#endif - - data_blob_free(&data_out); - data_blob_free(&sess_key); - - return SMB_STRDUP(cleartextpwd); - -} - -/* encode a wkssvc_PasswordBuffer: - * - * similar to samr_CryptPasswordEx. Different: 8byte confounder (instead of - * 16byte), confounder in front of the 516 byte buffer (instead of after that - * buffer), calling MD5Update() first with session_key and then with confounder - * (vice versa in samr) - Guenther */ - -void encode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx, - const char *pwd, - DATA_BLOB *session_key, - struct wkssvc_PasswordBuffer **pwd_buf) -{ - uint8_t buffer[516]; - struct MD5Context ctx; - struct wkssvc_PasswordBuffer *my_pwd_buf = NULL; - DATA_BLOB confounded_session_key; - int confounder_len = 8; - uint8_t confounder[8]; - - my_pwd_buf = talloc_zero(mem_ctx, struct wkssvc_PasswordBuffer); - if (!my_pwd_buf) { - return; - } - - confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16); - - encode_pw_buffer(buffer, pwd, STR_UNICODE); - - generate_random_buffer((uint8_t *)confounder, confounder_len); - - MD5Init(&ctx); - MD5Update(&ctx, session_key->data, session_key->length); - MD5Update(&ctx, confounder, confounder_len); - MD5Final(confounded_session_key.data, &ctx); - - SamOEMhashBlob(buffer, 516, &confounded_session_key); - - memcpy(&my_pwd_buf->data[0], confounder, confounder_len); - memcpy(&my_pwd_buf->data[8], buffer, 516); - - data_blob_free(&confounded_session_key); - - *pwd_buf = my_pwd_buf; -} - -WERROR decode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx, - struct wkssvc_PasswordBuffer *pwd_buf, - DATA_BLOB *session_key, - char **pwd) -{ - uint8_t buffer[516]; - struct MD5Context ctx; - uint32_t pwd_len; - - DATA_BLOB confounded_session_key; - - int confounder_len = 8; - uint8_t confounder[8]; - - *pwd = NULL; - - if (!pwd_buf) { - return WERR_BAD_PASSWORD; - } - - if (session_key->length != 16) { - DEBUG(10,("invalid session key\n")); - return WERR_BAD_PASSWORD; - } - - confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16); - - memcpy(&confounder, &pwd_buf->data[0], confounder_len); - memcpy(&buffer, &pwd_buf->data[8], 516); - - MD5Init(&ctx); - MD5Update(&ctx, session_key->data, session_key->length); - MD5Update(&ctx, confounder, confounder_len); - MD5Final(confounded_session_key.data, &ctx); - - SamOEMhashBlob(buffer, 516, &confounded_session_key); - - if (!decode_pw_buffer(mem_ctx, buffer, pwd, &pwd_len, STR_UNICODE)) { - data_blob_free(&confounded_session_key); - return WERR_BAD_PASSWORD; - } - - data_blob_free(&confounded_session_key); - - return WERR_OK; -} - -DATA_BLOB decrypt_drsuapi_blob(TALLOC_CTX *mem_ctx, - const DATA_BLOB *session_key, - bool rcrypt, - uint32_t rid, - const DATA_BLOB *buffer) -{ - DATA_BLOB confounder; - DATA_BLOB enc_buffer; - - struct MD5Context md5; - uint8_t _enc_key[16]; - DATA_BLOB enc_key; - - DATA_BLOB dec_buffer; - - uint32_t crc32_given; - uint32_t crc32_calc; - DATA_BLOB checked_buffer; - - DATA_BLOB plain_buffer; - - /* - * the combination "c[3] s[1] e[1] d[0]..." - * was successful!!!!!!!!!!!!!!!!!!!!!!!!!! - */ - - /* - * the first 16 bytes at the beginning are the confounder - * followed by the 4 byte crc32 checksum - */ - if (buffer->length < 20) { - return data_blob_const(NULL, 0); - } - confounder = data_blob_const(buffer->data, 16); - enc_buffer = data_blob_const(buffer->data + 16, buffer->length - 16); - - /* - * build the encryption key md5 over the session key followed - * by the confounder - * - * here the gensec session key is used and - * not the dcerpc ncacn_ip_tcp "SystemLibraryDTC" key! - */ - enc_key = data_blob_const(_enc_key, sizeof(_enc_key)); - MD5Init(&md5); - MD5Update(&md5, session_key->data, session_key->length); - MD5Update(&md5, confounder.data, confounder.length); - MD5Final(enc_key.data, &md5); - - /* - * copy the encrypted buffer part and - * decrypt it using the created encryption key using arcfour - */ - dec_buffer = data_blob_talloc(mem_ctx, enc_buffer.data, enc_buffer.length); - if (!dec_buffer.data) { - return data_blob_const(NULL, 0); - } - SamOEMhashBlob(dec_buffer.data, dec_buffer.length, &enc_key); - - /* - * the first 4 byte are the crc32 checksum - * of the remaining bytes - */ - crc32_given = IVAL(dec_buffer.data, 0); - crc32_calc = crc32_calc_buffer(dec_buffer.data + 4 , dec_buffer.length - 4); - if (crc32_given != crc32_calc) { - DEBUG(1,("CRC32: given[0x%08X] calc[0x%08X]\n", - crc32_given, crc32_calc)); - return data_blob_const(NULL, 0); - } - checked_buffer = data_blob_talloc(mem_ctx, dec_buffer.data + 4, dec_buffer.length - 4); - if (!checked_buffer.data) { - return data_blob_const(NULL, 0); - } - - /* - * some attributes seem to be in a usable form after this decryption - * (supplementalCredentials, priorValue, currentValue, trustAuthOutgoing, - * trustAuthIncoming, initialAuthOutgoing, initialAuthIncoming) - * At least supplementalCredentials contains plaintext - * like "Primary:Kerberos" (in unicode form) - * - * some attributes seem to have some additional encryption - * dBCSPwd, unicodePwd, ntPwdHistory, lmPwdHistory - * - * it's the sam_rid_crypt() function, as the value is constant, - * so it doesn't depend on sessionkeys. - */ - if (rcrypt) { - uint32_t i, num_hashes; - - if ((checked_buffer.length % 16) != 0) { - return data_blob_const(NULL, 0); - } - - plain_buffer = data_blob_talloc(mem_ctx, checked_buffer.data, checked_buffer.length); - if (!plain_buffer.data) { - return data_blob_const(NULL, 0); - } - - num_hashes = plain_buffer.length / 16; - for (i = 0; i < num_hashes; i++) { - uint32_t offset = i * 16; - sam_pwd_hash(rid, checked_buffer.data + offset, plain_buffer.data + offset, 0); - } - } else { - plain_buffer = checked_buffer; - } - - return plain_buffer; -} - - diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c index 5b6bc00c57..929816e92d 100644 --- a/source3/libsmb/trusts_util.c +++ b/source3/libsmb/trusts_util.c @@ -19,6 +19,7 @@ */ #include "includes.h" +#include "../libcli/auth/libcli_auth.h" /********************************************************* Change the domain password on the PDC. diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index fd715d201f..c36cda5ecd 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -23,6 +23,7 @@ */ #include "includes.h" +#include "../libcli/auth/libcli_auth.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_PASSDB diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c index c79caf2d36..f55b77f675 100644 --- a/source3/passdb/pdb_get_set.c +++ b/source3/passdb/pdb_get_set.c @@ -22,6 +22,7 @@ */ #include "includes.h" +#include "../libcli/auth/libcli_auth.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_PASSDB diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 35ce8bb41a..d548fe9ee9 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -44,6 +44,7 @@ */ #include "includes.h" +#include "../libcli/auth/libcli_auth.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_PASSDB diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c index 2b507d0c4d..2fab765d87 100644 --- a/source3/passdb/secrets.c +++ b/source3/passdb/secrets.c @@ -23,7 +23,7 @@ such as the local SID and machine trust password */ #include "includes.h" - +#include "../libcli/auth/libcli_auth.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_PASSDB diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index 5f115e537b..32485ead9f 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -21,6 +21,7 @@ */ #include "includes.h" +#include "../libcli/auth/libcli_auth.h" /**************************************************************************** Wrapper function that uses the auth and auth2 calls to set up a NETLOGON @@ -40,28 +41,19 @@ NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; struct netr_Credential clnt_chal_send; struct netr_Credential srv_chal_recv; - struct dcinfo *dc; + struct samr_Password password; bool retried = false; + fstring mach_acct; SMB_ASSERT(ndr_syntax_id_equal(&cli->abstract_syntax, &ndr_table_netlogon.syntax_id)); TALLOC_FREE(cli->dc); - cli->dc = talloc_zero(cli, struct dcinfo); - if (cli->dc == NULL) { - return NT_STATUS_NO_MEMORY; - } - dc = cli->dc; /* Store the machine account password we're going to use. */ - memcpy(dc->mach_pw, machine_pwd, 16); - - fstrcpy(dc->remote_machine, "\\\\"); - fstrcat(dc->remote_machine, server_name); - - fstrcpy(dc->domain, domain); + memcpy(password.hash, machine_pwd, 16); - fstr_sprintf( dc->mach_acct, "%s$", machine_account); + fstr_sprintf( mach_acct, "%s$", machine_account); again: /* Create the client challenge. */ @@ -69,7 +61,7 @@ NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, /* Get the server challenge. */ result = rpccli_netr_ServerReqChallenge(cli, talloc_tos(), - dc->remote_machine, + cli->srv_name_slash, clnt_name, &clnt_chal_send, &srv_chal_recv); @@ -78,22 +70,29 @@ NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, } /* Calculate the session key and client credentials */ - creds_client_init(*neg_flags_inout, - dc, - &clnt_chal_send, - &srv_chal_recv, - machine_pwd, - &clnt_chal_send); + + cli->dc = netlogon_creds_client_init(cli, + clnt_name, + machine_account, + &clnt_chal_send, + &srv_chal_recv, + &password, + &clnt_chal_send, + *neg_flags_inout); + + if (!cli->dc) { + return NT_STATUS_NO_MEMORY; + } /* * Send client auth-2 challenge and receive server repy. */ result = rpccli_netr_ServerAuthenticate2(cli, talloc_tos(), - dc->remote_machine, - dc->mach_acct, + cli->srv_name_slash, + cli->dc->account_name, sec_chan_type, - clnt_name, + cli->dc->computer_name, &clnt_chal_send, /* input. */ &srv_chal_recv, /* output. */ neg_flags_inout); @@ -102,7 +101,7 @@ NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, * with the returned neg_flags - gd */ if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) && !retried) { - retried = true; + TALLOC_FREE(cli->dc); goto again; } @@ -115,7 +114,7 @@ NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, * server received challenge. */ - if (!netlogon_creds_client_check(dc, &srv_chal_recv)) { + if (!netlogon_creds_client_check(cli->dc, &srv_chal_recv)) { /* * Server replied with bad credential. Fail. */ @@ -169,7 +168,7 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, /* Initialise input parameters */ - netlogon_creds_client_step(cli->dc, &clnt_creds); + netlogon_creds_client_authenticator(cli->dc, &clnt_creds); switch (logon_type) { case NetlogonInteractiveInformation: { @@ -179,43 +178,20 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, struct samr_Password lmpassword; struct samr_Password ntpassword; - unsigned char lm_owf_user_pwd[16], nt_owf_user_pwd[16]; - - unsigned char lm_owf[16]; - unsigned char nt_owf[16]; - unsigned char key[16]; - password_info = TALLOC_ZERO_P(mem_ctx, struct netr_PasswordInfo); if (!password_info) { return NT_STATUS_NO_MEMORY; } - nt_lm_owf_gen(password, nt_owf_user_pwd, lm_owf_user_pwd); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("lm cypher:")); - dump_data(100, lm_owf_user_pwd, 16); - - DEBUG(100,("nt cypher:")); - dump_data(100, nt_owf_user_pwd, 16); -#endif - memset(key, 0, 16); - memcpy(key, cli->dc->sess_key, 8); + nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash); - memcpy(lm_owf, lm_owf_user_pwd, 16); - SamOEMhash(lm_owf, key, 16); - memcpy(nt_owf, nt_owf_user_pwd, 16); - SamOEMhash(nt_owf, key, 16); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("encrypt of lm owf password:")); - dump_data(100, lm_owf, 16); - - DEBUG(100,("encrypt of nt owf password:")); - dump_data(100, nt_owf, 16); -#endif - memcpy(lmpassword.hash, lm_owf, 16); - memcpy(ntpassword.hash, nt_owf, 16); + if (cli->dc->negotiate_flags & NETLOGON_NEG_ARCFOUR) { + netlogon_creds_arcfour_crypt(cli->dc, lmpassword.hash, 16); + netlogon_creds_arcfour_crypt(cli->dc, ntpassword.hash, 16); + } else { + netlogon_creds_des_encrypt(cli->dc, &lmpassword); + netlogon_creds_des_encrypt(cli->dc, &ntpassword); + } init_netr_PasswordInfo(password_info, domain, @@ -280,7 +256,7 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, } result = rpccli_netr_LogonSamLogon(cli, mem_ctx, - cli->dc->remote_machine, + cli->srv_name_slash, global_myname(), &clnt_creds, &ret_creds, @@ -290,12 +266,10 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, &validation, &authoritative); - if (memcmp(zeros, &ret_creds.cred.data, sizeof(ret_creds.cred.data)) != 0) { - /* Check returned credentials if present. */ - if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) { - DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n")); - return NT_STATUS_ACCESS_DENIED; - } + /* Always check returned credentials */ + if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) { + DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n")); + return NT_STATUS_ACCESS_DENIED; } return result; @@ -352,7 +326,7 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, return NT_STATUS_NO_MEMORY; } - netlogon_creds_client_step(cli->dc, &clnt_creds); + netlogon_creds_client_authenticator(cli->dc, &clnt_creds); if (server[0] != '\\' && server[1] != '\\') { server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server); @@ -407,23 +381,13 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, return result; } - if (memcmp(zeros, validation.sam3->base.key.key, 16) != 0) { - SamOEMhash(validation.sam3->base.key.key, - cli->dc->sess_key, 16); - } - - if (memcmp(zeros, validation.sam3->base.LMSessKey.key, 8) != 0) { - SamOEMhash(validation.sam3->base.LMSessKey.key, - cli->dc->sess_key, 8); + /* Always check returned credentials. */ + if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) { + DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n")); + return NT_STATUS_ACCESS_DENIED; } - if (memcmp(zeros, ret_creds.cred.data, sizeof(ret_creds.cred.data)) != 0) { - /* Check returned credentials if present. */ - if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) { - DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n")); - return NT_STATUS_ACCESS_DENIED; - } - } + netlogon_creds_decrypt_samlogon(cli->dc, validation_level, &validation); *info3 = validation.sam3; @@ -524,15 +488,7 @@ NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli, return result; } - if (memcmp(zeros, validation.sam3->base.key.key, 16) != 0) { - SamOEMhash(validation.sam3->base.key.key, - cli->dc->sess_key, 16); - } - - if (memcmp(zeros, validation.sam3->base.LMSessKey.key, 8) != 0) { - SamOEMhash(validation.sam3->base.LMSessKey.key, - cli->dc->sess_key, 8); - } + netlogon_creds_decrypt_samlogon(cli->dc, validation_level, &validation); *info3 = validation.sam3; @@ -574,21 +530,21 @@ NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli, return result; } - netlogon_creds_client_step(cli->dc, &clnt_creds); + netlogon_creds_client_authenticator(cli->dc, &clnt_creds); if (neg_flags & NETLOGON_NEG_PASSWORD_SET2) { struct netr_CryptPassword new_password; init_netr_CryptPassword(new_trust_pwd_cleartext, - cli->dc->sess_key, + cli->dc->session_key, &new_password); result = rpccli_netr_ServerPasswordSet2(cli, mem_ctx, - cli->dc->remote_machine, - cli->dc->mach_acct, + cli->srv_name_slash, + cli->dc->account_name, sec_channel_type, - global_myname(), + cli->dc->computer_name, &clnt_creds, &srv_cred, &new_password); @@ -600,16 +556,14 @@ NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli, } else { struct samr_Password new_password; - - cred_hash3(new_password.hash, - new_trust_passwd_hash, - cli->dc->sess_key, 1); + memcpy(new_password.hash, new_trust_passwd_hash, sizeof(new_password.hash)); + netlogon_creds_des_encrypt(cli->dc, &new_password); result = rpccli_netr_ServerPasswordSet(cli, mem_ctx, - cli->dc->remote_machine, - cli->dc->mach_acct, + cli->srv_name_slash, + cli->dc->account_name, sec_channel_type, - global_myname(), + cli->dc->computer_name, &clnt_creds, &srv_cred, &new_password); diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index a8cc33f585..3d7db068d5 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -18,6 +18,7 @@ */ #include "includes.h" +#include "../libcli/auth/libcli_auth.h" #include "librpc/gen_ndr/cli_epmapper.h" #undef DBGC_CLASS @@ -3844,13 +3845,15 @@ NTSTATUS get_schannel_session_key(struct cli_state *cli, External interface. Open a named pipe to an SMB server and bind using schannel (bind type 68) using session_key. sign and seal. + + The *pdc will be stolen onto this new pipe ****************************************************************************/ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, const struct ndr_syntax_id *interface, enum pipe_auth_level auth_level, const char *domain, - const struct dcinfo *pdc, + struct netlogon_creds_CredentialState **pdc, struct rpc_pipe_client **presult) { struct rpc_pipe_client *result; @@ -3863,7 +3866,7 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, } status = rpccli_schannel_bind_data(result, domain, auth_level, - pdc->sess_key, &auth); + (*pdc)->session_key, &auth); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("rpccli_schannel_bind_data returned %s\n", nt_errstr(status))); @@ -3882,11 +3885,11 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, /* * The credentials on a new netlogon pipe are the ones we are passed - * in - copy them over. + * in - reference them in */ - result->dc = (struct dcinfo *)talloc_memdup(result, pdc, sizeof(*pdc)); + result->dc = talloc_move(result, pdc); if (result->dc == NULL) { - DEBUG(0, ("talloc failed\n")); + DEBUG(0, ("talloc reference failed\n")); TALLOC_FREE(result); return NT_STATUS_NO_MEMORY; } @@ -3963,7 +3966,7 @@ NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli, } status = cli_rpc_pipe_open_schannel_with_key( - cli, interface, auth_level, domain, netlogon_pipe->dc, + cli, interface, auth_level, domain, &netlogon_pipe->dc, &result); /* Now we've bound using the session key we can close the netlog pipe. */ @@ -4001,7 +4004,7 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, } status = cli_rpc_pipe_open_schannel_with_key( - cli, interface, auth_level, domain, netlogon_pipe->dc, + cli, interface, auth_level, domain, &netlogon_pipe->dc, &result); /* Now we've bound using the session key we can close the netlog pipe. */ diff --git a/source3/rpc_client/cli_samr.c b/source3/rpc_client/cli_samr.c index 86bc041374..5a0dff2965 100644 --- a/source3/rpc_client/cli_samr.c +++ b/source3/rpc_client/cli_samr.c @@ -22,6 +22,7 @@ */ #include "includes.h" +#include "../libcli/auth/libcli_auth.h" /* User change password */ @@ -115,7 +116,7 @@ NTSTATUS rpccli_samr_chgpasswd_user2(struct rpc_pipe_client *cli, encode_pw_buffer(new_lm_password.data, newpassword, STR_UNICODE); - SamOEMhash(new_lm_password.data, old_nt_hash, 516); + arcfour_crypt(new_lm_password.data, old_nt_hash, 516); E_old_pw_hash(new_nt_hash, old_lanman_hash, old_lanman_hash_enc.hash); } else { ZERO_STRUCT(new_lm_password); @@ -124,7 +125,7 @@ NTSTATUS rpccli_samr_chgpasswd_user2(struct rpc_pipe_client *cli, encode_pw_buffer(new_nt_password.data, newpassword, STR_UNICODE); - SamOEMhash(new_nt_password.data, old_nt_hash, 516); + arcfour_crypt(new_nt_password.data, old_nt_hash, 516); E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.hash); result = rpccli_samr_ChangePasswordUser2(cli, mem_ctx, @@ -221,7 +222,7 @@ NTSTATUS rpccli_samr_chgpasswd_user3(struct rpc_pipe_client *cli, encode_pw_buffer(new_lm_password.data, newpassword, STR_UNICODE); - SamOEMhash(new_lm_password.data, old_nt_hash, 516); + arcfour_crypt(new_lm_password.data, old_nt_hash, 516); E_old_pw_hash(new_nt_hash, old_lanman_hash, old_lanman_hash_enc.hash); } else { ZERO_STRUCT(new_lm_password); @@ -230,7 +231,7 @@ NTSTATUS rpccli_samr_chgpasswd_user3(struct rpc_pipe_client *cli, encode_pw_buffer(new_nt_password.data, newpassword, STR_UNICODE); - SamOEMhash(new_nt_password.data, old_nt_hash, 516); + arcfour_crypt(new_nt_password.data, old_nt_hash, 516); E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.hash); status = rpccli_samr_ChangePasswordUser3(cli, mem_ctx, diff --git a/source3/rpc_client/init_netlogon.c b/source3/rpc_client/init_netlogon.c index 793b9c7de5..cb49381eac 100644 --- a/source3/rpc_client/init_netlogon.c +++ b/source3/rpc_client/init_netlogon.c @@ -18,6 +18,7 @@ */ #include "includes.h" +#include "../libcli/auth/libcli_auth.h" /******************************************************************* inits a structure. @@ -259,7 +260,7 @@ NTSTATUS serverinfo_to_SamInfo3(struct auth_serversupplied_info *server_info, MIN(sizeof(user_session_key.key), server_info->user_session_key.length)); if (pipe_session_key) { - SamOEMhash(user_session_key.key, pipe_session_key, 16); + arcfour_crypt(user_session_key.key, pipe_session_key, 16); } } if (server_info->lm_session_key.length) { @@ -268,7 +269,7 @@ NTSTATUS serverinfo_to_SamInfo3(struct auth_serversupplied_info *server_info, MIN(sizeof(lm_session_key.key), server_info->lm_session_key.length)); if (pipe_session_key) { - SamOEMhash(lm_session_key.key, pipe_session_key, 8); + arcfour_crypt(lm_session_key.key, pipe_session_key, 8); } } @@ -418,7 +419,7 @@ void init_netr_CryptPassword(const char *pwd, encode_pw_buffer(password_buf.data, pwd, STR_UNICODE); - SamOEMhash(password_buf.data, session_key, 516); + arcfour_crypt(password_buf.data, session_key, 516); memcpy(pwd_buf->data, password_buf.data, 512); pwd_buf->length = IVAL(password_buf.data, 512); } diff --git a/source3/rpc_client/init_samr.c b/source3/rpc_client/init_samr.c index ecc6310510..6843869965 100644 --- a/source3/rpc_client/init_samr.c +++ b/source3/rpc_client/init_samr.c @@ -18,6 +18,7 @@ */ #include "includes.h" +#include "../libcli/auth/libcli_auth.h" /************************************************************************* inits a samr_CryptPasswordEx structure @@ -44,7 +45,7 @@ void init_samr_CryptPasswordEx(const char *pwd, session_key->length); MD5Final(confounded_session_key.data, &md5_ctx); - SamOEMhashBlob(pwbuf, 516, &confounded_session_key); + arcfour_crypt_blob(pwbuf, 516, &confounded_session_key); memcpy(&pwbuf[516], confounder, 16); memcpy(pwd_buf->data, pwbuf, sizeof(pwbuf)); @@ -62,5 +63,5 @@ void init_samr_CryptPassword(const char *pwd, /* samr_CryptPassword */ encode_pw_buffer(pwd_buf->data, pwd, STR_UNICODE); - SamOEMhashBlob(pwd_buf->data, 516, session_key); + arcfour_crypt_blob(pwd_buf->data, 516, session_key); } diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c index dfbd6dac74..0f4829dec3 100644 --- a/source3/rpc_parse/parse_prs.c +++ b/source3/rpc_parse/parse_prs.c @@ -1373,7 +1373,7 @@ bool prs_hash1(prs_struct *ps, uint32 offset, int len) dump_data(100, (uint8 *)ps->sess_key, 16); dump_data(100, (uint8 *)q, len); #endif - SamOEMhash((uchar *) q, (const unsigned char *)ps->sess_key, len); + arcfour_crypt((uchar *) q, (const unsigned char *)ps->sess_key, len); #ifdef DEBUG_PASSWORD dump_data(100, (uint8 *)q, len); @@ -1468,7 +1468,7 @@ static void schannel_deal_with_seq_num(struct schannel_auth_struct *a, dump_data_pw("sequence_key:\n", sequence_key, sizeof(sequence_key)); dump_data_pw("seq_num (before):\n", verf->seq_num, sizeof(verf->seq_num)); - SamOEMhash(verf->seq_num, sequence_key, 8); + arcfour_crypt(verf->seq_num, sequence_key, 8); dump_data_pw("seq_num (after):\n", verf->seq_num, sizeof(verf->seq_num)); } @@ -1554,13 +1554,13 @@ void schannel_encode(struct schannel_auth_struct *a, enum pipe_auth_level auth_l /* encode the verification data */ dump_data_pw("verf->confounder:\n", verf->confounder, sizeof(verf->confounder)); - SamOEMhash(verf->confounder, sealing_key, 8); + arcfour_crypt(verf->confounder, sealing_key, 8); dump_data_pw("verf->confounder_enc:\n", verf->confounder, sizeof(verf->confounder)); /* encode the packet payload */ dump_data_pw("data:\n", (const unsigned char *)data, data_len); - SamOEMhash((unsigned char *)data, sealing_key, data_len); + arcfour_crypt((unsigned char *)data, sealing_key, data_len); dump_data_pw("data_enc:\n", (const unsigned char *)data, data_len); } @@ -1652,14 +1652,14 @@ bool schannel_decode(struct schannel_auth_struct *a, enum pipe_auth_level auth_l /* extract the verification data */ dump_data_pw("verf->confounder:\n", verf->confounder, sizeof(verf->confounder)); - SamOEMhash(verf->confounder, sealing_key, 8); + arcfour_crypt(verf->confounder, sealing_key, 8); dump_data_pw("verf->confounder_dec:\n", verf->confounder, sizeof(verf->confounder)); /* extract the packet payload */ dump_data_pw("data :\n", (const unsigned char *)data, data_len); - SamOEMhash((unsigned char *)data, sealing_key, data_len); + arcfour_crypt((unsigned char *)data, sealing_key, data_len); dump_data_pw("datadec:\n", (const unsigned char *)data, data_len); } diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c index 0c83144a90..c5e2ca7c71 100644 --- a/source3/rpc_server/srv_netlog_nt.c +++ b/source3/rpc_server/srv_netlog_nt.c @@ -25,6 +25,7 @@ /* This is the implementation of the netlogon pipe. */ #include "includes.h" +#include "../libcli/auth/libcli_auth.h" extern userdom_struct current_user_info; diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index cc25dbb0c0..b54ed717a3 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -32,6 +32,7 @@ */ #include "includes.h" +#include "../libcli/auth/libcli_auth.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV @@ -3773,7 +3774,7 @@ static NTSTATUS set_user_info_23(TALLOC_CTX *mem_ctx, struct samu *pwd) { char *plaintext_buf = NULL; - uint32 len = 0; + size_t len = 0; uint32_t acct_ctrl; NTSTATUS status; @@ -3800,7 +3801,7 @@ static NTSTATUS set_user_info_23(TALLOC_CTX *mem_ctx, id23->password.data, &plaintext_buf, &len, - STR_UNICODE)) { + CH_UTF16)) { return NT_STATUS_WRONG_PASSWORD; } @@ -3862,7 +3863,7 @@ static NTSTATUS set_user_info_23(TALLOC_CTX *mem_ctx, static bool set_user_info_pw(uint8 *pass, struct samu *pwd) { - uint32 len = 0; + size_t len = 0; char *plaintext_buf = NULL; uint32 acct_ctrl; @@ -3875,7 +3876,7 @@ static bool set_user_info_pw(uint8 *pass, struct samu *pwd) pass, &plaintext_buf, &len, - STR_UNICODE)) { + CH_UTF16)) { return False; } @@ -4174,8 +4175,8 @@ NTSTATUS _samr_SetUserInfo(pipes_struct *p, if (!p->server_info->user_session_key.length) { status = NT_STATUS_NO_USER_SESSION_KEY; } - SamOEMhashBlob(info->info23.password.data, 516, - &p->server_info->user_session_key); + arcfour_crypt_blob(info->info23.password.data, 516, + &p->server_info->user_session_key); dump_data(100, info->info23.password.data, 516); @@ -4187,9 +4188,9 @@ NTSTATUS _samr_SetUserInfo(pipes_struct *p, if (!p->server_info->user_session_key.length) { status = NT_STATUS_NO_USER_SESSION_KEY; } - SamOEMhashBlob(info->info24.password.data, - 516, - &p->server_info->user_session_key); + arcfour_crypt_blob(info->info24.password.data, + 516, + &p->server_info->user_session_key); dump_data(100, info->info24.password.data, 516); diff --git a/source3/rpc_server/srv_wkssvc_nt.c b/source3/rpc_server/srv_wkssvc_nt.c index 7071b55e7c..8d2e73b5a5 100644 --- a/source3/rpc_server/srv_wkssvc_nt.c +++ b/source3/rpc_server/srv_wkssvc_nt.c @@ -24,6 +24,7 @@ #include "includes.h" #include "libnet/libnet.h" +#include "../libcli/auth/libcli_auth.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV diff --git a/source3/rpcclient/cmd_lsarpc.c b/source3/rpcclient/cmd_lsarpc.c index 722a0a3832..cf2b1ae563 100644 --- a/source3/rpcclient/cmd_lsarpc.c +++ b/source3/rpcclient/cmd_lsarpc.c @@ -22,6 +22,7 @@ #include "includes.h" #include "rpcclient.h" +#include "../libcli/auth/libcli_auth.h" /* useful function to allow entering a name instead of a SID and * looking it up automatically */ @@ -947,27 +948,22 @@ static NTSTATUS cmd_lsa_query_secobj(struct rpc_pipe_client *cli, } static void display_trust_dom_info_4(struct lsa_TrustDomainInfoPassword *p, - uint8_t nt_hash[16]) + uint8_t session_key[16]) { char *pwd, *pwd_old; - DATA_BLOB data = data_blob(NULL, p->password->length); - DATA_BLOB data_old = data_blob(NULL, p->old_password->length); + DATA_BLOB data = data_blob_const(p->password->data, p->password->length); + DATA_BLOB data_old = data_blob_const(p->old_password->data, p->old_password->length); + DATA_BLOB session_key_blob = data_blob_const(session_key, sizeof(session_key)); - memcpy(data.data, p->password->data, p->password->length); - memcpy(data_old.data, p->old_password->data, p->old_password->length); - - pwd = decrypt_trustdom_secret(nt_hash, &data); - pwd_old = decrypt_trustdom_secret(nt_hash, &data_old); + pwd = sess_decrypt_string(talloc_tos(), &data, &session_key_blob); + pwd_old = sess_decrypt_string(talloc_tos(), &data_old, &session_key_blob); d_printf("Password:\t%s\n", pwd); d_printf("Old Password:\t%s\n", pwd_old); - SAFE_FREE(pwd); - SAFE_FREE(pwd_old); - - data_blob_free(&data); - data_blob_free(&data_old); + talloc_free(pwd); + talloc_free(pwd_old); } static void display_trust_dom_info(TALLOC_CTX *mem_ctx, diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c index 45df488018..aa493214d7 100644 --- a/source3/rpcclient/cmd_netlogon.c +++ b/source3/rpcclient/cmd_netlogon.c @@ -21,6 +21,7 @@ #include "includes.h" #include "rpcclient.h" +#include "../libcli/auth/libcli_auth.h" static WERROR cmd_netlogon_logon_ctrl2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, @@ -584,7 +585,7 @@ static NTSTATUS cmd_netlogon_sam_sync(struct rpc_pipe_client *cli, do { struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; - netlogon_creds_client_step(cli->dc, &credential); + netlogon_creds_client_authenticator(cli->dc, &credential); result = rpccli_netr_DatabaseSync2(cli, mem_ctx, logon_server, @@ -647,7 +648,7 @@ static NTSTATUS cmd_netlogon_sam_deltas(struct rpc_pipe_client *cli, do { struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; - netlogon_creds_client_step(cli->dc, &credential); + netlogon_creds_client_authenticator(cli->dc, &credential); result = rpccli_netr_DatabaseDeltas(cli, mem_ctx, logon_server, @@ -1082,7 +1083,7 @@ static NTSTATUS cmd_netlogon_database_redo(struct rpc_pipe_client *cli, return status; } - netlogon_creds_client_step(cli->dc, &clnt_creds); + netlogon_creds_client_authenticator(cli->dc, &clnt_creds); ZERO_STRUCT(e); @@ -1127,7 +1128,7 @@ static NTSTATUS cmd_netlogon_capabilities(struct rpc_pipe_client *cli, } #if 0 - netlogon_creds_client_step(cli->dc, &credential); + netlogon_creds_client_authenticator(cli->dc, &credential); #else ZERO_STRUCT(credential); #endif diff --git a/source3/rpcclient/cmd_samr.c b/source3/rpcclient/cmd_samr.c index 428984db13..83cec72318 100644 --- a/source3/rpcclient/cmd_samr.c +++ b/source3/rpcclient/cmd_samr.c @@ -24,6 +24,7 @@ #include "includes.h" #include "rpcclient.h" +#include "../libcli/auth/libcli_auth.h" extern DOM_SID domain_sid; diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index a202dcc5f3..6fd6b4f6d9 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -21,6 +21,7 @@ #include "includes.h" #include "rpcclient.h" +#include "../libcli/auth/libcli_auth.h" DOM_SID domain_sid; diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index ccab71c0a2..72f06fb2ed 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -46,6 +46,7 @@ */ #include "includes.h" +#include "../libcli/auth/libcli_auth.h" static NTSTATUS check_oem_password(const char *user, uchar password_encrypted_with_lm_hash[516], @@ -832,7 +833,7 @@ static NTSTATUS check_oem_password(const char *user, const uint8 *encryption_key; const uint8 *lanman_pw, *nt_pw; uint32 acct_ctrl; - uint32 new_pw_len; + size_t new_pw_len; uchar new_nt_hash[16]; uchar new_lm_hash[16]; uchar verifier[16]; @@ -919,13 +920,13 @@ static NTSTATUS check_oem_password(const char *user, /* * Decrypt the password with the key */ - SamOEMhash( password_encrypted, encryption_key, 516); + arcfour_crypt( password_encrypted, encryption_key, 516); if (!decode_pw_buffer(talloc_tos(), password_encrypted, pp_new_passwd, &new_pw_len, - nt_pass_set ? STR_UNICODE : STR_ASCII)) { + nt_pass_set ? CH_UTF16 : CH_DOS)) { TALLOC_FREE(sampass); return NT_STATUS_WRONG_PASSWORD; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 04b1145e58..72b4ba0742 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -26,6 +26,7 @@ #include "includes.h" #include "version.h" #include "smbd/globals.h" +#include "../libcli/auth/libcli_auth.h" extern enum protocol_types Protocol; diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index 0b662819ae..5dd3df9a69 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -22,6 +22,7 @@ #include "includes.h" #include "utils/net.h" +#include "../libcli/auth/libcli_auth.h" static int net_mode_share; static bool sync_files(struct copy_clistate *cp_clistate, const char *mask); @@ -5737,7 +5738,8 @@ static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd, NTSTATUS nt_status; union lsa_TrustedDomainInfo *info = NULL; char *cleartextpwd = NULL; - uint8_t nt_hash[16]; + uint8_t session_key[16]; + DATA_BLOB session_key_blob; DATA_BLOB data; nt_status = rpccli_lsa_QueryTrustedDomainInfoBySid(pipe_hnd, mem_ctx, @@ -5754,12 +5756,13 @@ static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd, data = data_blob(info->password.password->data, info->password.password->length); - if (!rpccli_get_pwd_hash(pipe_hnd, nt_hash)) { + if (!rpccli_get_pwd_hash(pipe_hnd, session_key)) { DEBUG(0, ("Could not retrieve password hash\n")); goto done; } - cleartextpwd = decrypt_trustdom_secret(nt_hash, &data); + session_key_blob = data_blob_const(session_key, sizeof(session_key)); + cleartextpwd = sess_decrypt_string(mem_ctx, &data, &session_key_blob); if (cleartextpwd == NULL) { DEBUG(0,("retrieved NULL password\n")); diff --git a/source3/utils/net_rpc_join.c b/source3/utils/net_rpc_join.c index 1fec140124..78bbce3dfc 100644 --- a/source3/utils/net_rpc_join.c +++ b/source3/utils/net_rpc_join.c @@ -20,6 +20,7 @@ #include "includes.h" #include "utils/net.h" +#include "../libcli/auth/libcli_auth.h" /* Macro for checking RPC error codes to make things more readable */ @@ -101,7 +102,7 @@ NTSTATUS net_rpc_join_ok(struct net_context *c, const char *domain, ntret = cli_rpc_pipe_open_schannel_with_key( cli, &ndr_table_netlogon.syntax_id, PIPE_AUTH_LEVEL_PRIVACY, - domain, netlogon_pipe->dc, &pipe_hnd); + domain, &netlogon_pipe->dc, &pipe_hnd); if (!NT_STATUS_IS_OK(ntret)) { DEBUG(0,("net_rpc_join_ok: failed to open schannel session " diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index e8bd9fbd2b..50688bf698 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -25,6 +25,7 @@ #include "includes.h" #include "utils/ntlm_auth.h" +#include "../libcli/auth/libcli_auth.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND @@ -566,19 +567,19 @@ static NTSTATUS winbind_pw_check(struct ntlmssp_state *ntlmssp_state, DATA_BLOB static NTSTATUS local_pw_check(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key) { NTSTATUS nt_status; - uint8 lm_pw[16], nt_pw[16]; + struct samr_Password lm_pw, nt_pw; - nt_lm_owf_gen (opt_password, nt_pw, lm_pw); + nt_lm_owf_gen (opt_password, nt_pw.hash, lm_pw.hash); nt_status = ntlm_password_check(ntlmssp_state, + true, true, 0, &ntlmssp_state->chal, &ntlmssp_state->lm_resp, &ntlmssp_state->nt_resp, - NULL, NULL, ntlmssp_state->user, ntlmssp_state->user, ntlmssp_state->domain, - lm_pw, nt_pw, user_session_key, lm_session_key); + &lm_pw, &nt_pw, user_session_key, lm_session_key); if (NT_STATUS_IS_OK(nt_status)) { ntlmssp_state->auth_context = talloc_asprintf(ntlmssp_state, @@ -1977,7 +1978,7 @@ static void manage_ntlm_change_password_1_request(struct ntlm_auth_state *state, encode_pw_buffer(new_lm_pswd.data, newpswd, STR_UNICODE); - SamOEMhash(new_lm_pswd.data, old_nt_hash, 516); + arcfour_crypt(new_lm_pswd.data, old_nt_hash, 516); E_old_pw_hash(new_nt_hash, old_lm_hash, old_lm_hash_enc.data); } else { @@ -1990,7 +1991,7 @@ static void manage_ntlm_change_password_1_request(struct ntlm_auth_state *state, encode_pw_buffer(new_nt_pswd.data, newpswd, STR_UNICODE); - SamOEMhash(new_nt_pswd.data, old_nt_hash, 516); + arcfour_crypt(new_nt_pswd.data, old_nt_hash, 516); E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.data); } diff --git a/source3/utils/ntlm_auth_diagnostics.c b/source3/utils/ntlm_auth_diagnostics.c index cea4b084f7..0178823801 100644 --- a/source3/utils/ntlm_auth_diagnostics.c +++ b/source3/utils/ntlm_auth_diagnostics.c @@ -23,6 +23,7 @@ #include "includes.h" #include "utils/ntlm_auth.h" +#include "../libcli/auth/libcli_auth.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND @@ -72,7 +73,7 @@ static bool test_lm_ntlm_broken(enum ntlm_break break_which) SMBNTencrypt(opt_password,chall.data,nt_response.data); E_md4hash(opt_password, nt_hash); - SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); + SMBsesskeygen_ntv1(nt_hash, session_key.data); switch (break_which) { case BREAK_NONE: @@ -257,7 +258,7 @@ static bool test_ntlm_in_both(void) SMBNTencrypt(opt_password,chall.data,nt_response.data); E_md4hash(opt_password, nt_hash); - SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); + SMBsesskeygen_ntv1(nt_hash, session_key.data); E_deshash(opt_password, lm_hash); @@ -316,7 +317,7 @@ static bool test_lmv2_ntlmv2_broken(enum ntlm_break break_which) DATA_BLOB ntlmv2_response = data_blob_null; DATA_BLOB lmv2_response = data_blob_null; DATA_BLOB ntlmv2_session_key = data_blob_null; - DATA_BLOB names_blob = NTLMv2_generate_names_blob(get_winbind_netbios_name(), get_winbind_domain()); + DATA_BLOB names_blob = NTLMv2_generate_names_blob(NULL, get_winbind_netbios_name(), get_winbind_domain()); uchar user_session_key[16]; DATA_BLOB chall = get_challenge(); @@ -326,9 +327,9 @@ static bool test_lmv2_ntlmv2_broken(enum ntlm_break break_which) flags |= WBFLAG_PAM_USER_SESSION_KEY; - if (!SMBNTLMv2encrypt(opt_username, opt_domain, opt_password, &chall, + if (!SMBNTLMv2encrypt(NULL, opt_username, opt_domain, opt_password, &chall, &names_blob, - &lmv2_response, &ntlmv2_response, + &lmv2_response, &ntlmv2_response, NULL, &ntlmv2_session_key)) { data_blob_free(&names_blob); return False; diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index 66166bf292..5c1b71897d 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -26,6 +26,7 @@ #include "includes.h" #include "winbindd.h" #include "tdb_validate.h" +#include "../libcli/auth/libcli_auth.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index ed0a33a5f2..e9cf05e90b 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -60,6 +60,7 @@ #include "includes.h" #include "winbindd.h" +#include "../libcli/auth/libcli_auth.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND @@ -1963,8 +1964,8 @@ static void set_dc_type_and_flags( struct winbindd_domain *domain ) /********************************************************************** ***********************************************************************/ -static bool cm_get_schannel_dcinfo(struct winbindd_domain *domain, - struct dcinfo **ppdc) +static bool cm_get_schannel_creds(struct winbindd_domain *domain, + struct netlogon_creds_CredentialState **ppdc) { NTSTATUS result; struct rpc_pipe_client *netlogon_pipe; @@ -1978,7 +1979,7 @@ static bool cm_get_schannel_dcinfo(struct winbindd_domain *domain, return False; } - /* Return a pointer to the struct dcinfo from the + /* Return a pointer to the struct netlogon_creds_CredentialState from the netlogon pipe. */ if (!domain->conn.netlogon_pipe->dc) { @@ -1994,7 +1995,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, { struct winbindd_cm_conn *conn; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - struct dcinfo *p_dcinfo; + struct netlogon_creds_CredentialState *p_creds; char *machine_password = NULL; char *machine_account = NULL; char *domain_name = NULL; @@ -2081,7 +2082,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, /* Fall back to schannel if it's a W2K pre-SP1 box. */ - if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) { + if (!cm_get_schannel_creds(domain, &p_creds)) { /* If this call fails - conn->cli can now be NULL ! */ DEBUG(10, ("cm_connect_sam: Could not get schannel auth info " "for domain %s, trying anon\n", domain->name)); @@ -2089,7 +2090,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, } result = cli_rpc_pipe_open_schannel_with_key (conn->cli, &ndr_table_samr.syntax_id, PIPE_AUTH_LEVEL_PRIVACY, - domain->name, p_dcinfo, &conn->samr_pipe); + domain->name, &p_creds, &conn->samr_pipe); if (!NT_STATUS_IS_OK(result)) { DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for " @@ -2160,7 +2161,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, { struct winbindd_cm_conn *conn; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - struct dcinfo *p_dcinfo; + struct netlogon_creds_CredentialState *p_creds; result = init_dc_connection(domain); if (!NT_STATUS_IS_OK(result)) @@ -2217,7 +2218,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, /* Fall back to schannel if it's a W2K pre-SP1 box. */ - if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) { + if (!cm_get_schannel_creds(domain, &p_creds)) { /* If this call fails - conn->cli can now be NULL ! */ DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info " "for domain %s, trying anon\n", domain->name)); @@ -2226,7 +2227,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, result = cli_rpc_pipe_open_schannel_with_key (conn->cli, &ndr_table_lsarpc.syntax_id, PIPE_AUTH_LEVEL_PRIVACY, - domain->name, p_dcinfo, &conn->lsa_pipe); + domain->name, p_creds, &conn->lsa_pipe); if (!NT_STATUS_IS_OK(result)) { DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for " diff --git a/source3/winbindd/winbindd_cred_cache.c b/source3/winbindd/winbindd_cred_cache.c index ff6d0f3df7..f11f75762d 100644 --- a/source3/winbindd/winbindd_cred_cache.c +++ b/source3/winbindd/winbindd_cred_cache.c @@ -23,6 +23,7 @@ #include "includes.h" #include "winbindd.h" +#include "../libcli/auth/libcli_auth.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND diff --git a/source3/winbindd/winbindd_creds.c b/source3/winbindd/winbindd_creds.c index 9c7acd64e6..2f64f8b689 100644 --- a/source3/winbindd/winbindd_creds.c +++ b/source3/winbindd/winbindd_creds.c @@ -21,6 +21,7 @@ #include "includes.h" #include "winbindd.h" +#include "../libcli/auth/libcli_auth.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 54bcac2b04..23de20f0d3 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -24,6 +24,7 @@ #include "includes.h" #include "winbindd.h" +#include "../libcli/auth/libcli_auth.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND @@ -1238,13 +1239,13 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, the server's domain at this point. The 'server name' is also dodgy... */ - names_blob = NTLMv2_generate_names_blob(global_myname(), lp_workgroup()); + names_blob = NTLMv2_generate_names_blob(state->mem_ctx, global_myname(), lp_workgroup()); - if (!SMBNTLMv2encrypt(name_user, name_domain, + if (!SMBNTLMv2encrypt(NULL, name_user, name_domain, state->request.data.auth.pass, &server_chal, &names_blob, - &lm_response, &nt_response, NULL)) { + &lm_response, &nt_response, NULL, NULL)) { data_blob_free(&names_blob); data_blob_free(&server_chal); DEBUG(0, ("winbindd_pam_auth: SMBNTLMv2encrypt() failed!\n")); diff --git a/source4/auth/credentials/credentials.c b/source4/auth/credentials/credentials.c index 5fb180d7b1..83901db6a5 100644 --- a/source4/auth/credentials/credentials.c +++ b/source4/auth/credentials/credentials.c @@ -668,7 +668,7 @@ _PUBLIC_ void cli_credentials_guess(struct cli_credentials *cred, */ _PUBLIC_ void cli_credentials_set_netlogon_creds(struct cli_credentials *cred, - struct creds_CredentialState *netlogon_creds) + struct netlogon_creds_CredentialState *netlogon_creds) { cred->netlogon_creds = talloc_reference(cred, netlogon_creds); } @@ -677,7 +677,7 @@ _PUBLIC_ void cli_credentials_set_netlogon_creds(struct cli_credentials *cred, * Return attached NETLOGON credentials */ -struct creds_CredentialState *cli_credentials_get_netlogon_creds(struct cli_credentials *cred) +struct netlogon_creds_CredentialState *cli_credentials_get_netlogon_creds(struct cli_credentials *cred) { return cred->netlogon_creds; } diff --git a/source4/auth/credentials/credentials.h b/source4/auth/credentials/credentials.h index 3c2fb8f2e6..311cdc2450 100644 --- a/source4/auth/credentials/credentials.h +++ b/source4/auth/credentials/credentials.h @@ -102,7 +102,7 @@ struct cli_credentials { /* Private handle for the callback routines to use */ void *priv_data; - struct creds_CredentialState *netlogon_creds; + struct netlogon_creds_CredentialState *netlogon_creds; enum netr_SchannelType secure_channel_type; int kvno; @@ -167,7 +167,7 @@ int cli_credentials_get_keytab(struct cli_credentials *cred, struct loadparm_context *lp_ctx, struct keytab_container **_ktc); const char *cli_credentials_get_domain(struct cli_credentials *cred); -struct creds_CredentialState *cli_credentials_get_netlogon_creds(struct cli_credentials *cred); +struct netlogon_creds_CredentialState *cli_credentials_get_netlogon_creds(struct cli_credentials *cred); void cli_credentials_set_machine_account_pending(struct cli_credentials *cred, struct loadparm_context *lp_ctx); void cli_credentials_set_conf(struct cli_credentials *cred, @@ -210,7 +210,7 @@ bool cli_credentials_set_realm(struct cli_credentials *cred, void cli_credentials_set_secure_channel_type(struct cli_credentials *cred, enum netr_SchannelType secure_channel_type); void cli_credentials_set_netlogon_creds(struct cli_credentials *cred, - struct creds_CredentialState *netlogon_creds); + struct netlogon_creds_CredentialState *netlogon_creds); NTSTATUS cli_credentials_set_krb5_context(struct cli_credentials *cred, struct smb_krb5_context *smb_krb5_context); NTSTATUS cli_credentials_set_stored_principal(struct cli_credentials *cred, diff --git a/source4/auth/gensec/config.mk b/source4/auth/gensec/config.mk index 27cf442b68..a9ce228f12 100644 --- a/source4/auth/gensec/config.mk +++ b/source4/auth/gensec/config.mk @@ -78,7 +78,7 @@ $(eval $(call proto_header_template,$(gensecsrcdir)/schannel_proto.h,$(gensec_sc ################################################ # Start SUBSYSTEM SCHANNELDB [SUBSYSTEM::SCHANNELDB] -PRIVATE_DEPENDENCIES = LDB_WRAP +PRIVATE_DEPENDENCIES = LDB_WRAP COMMON_SCHANNELDB # End SUBSYSTEM SCHANNELDB ################################################ diff --git a/source4/auth/gensec/gensec.h b/source4/auth/gensec/gensec.h index c4e93ee97b..3b27e0f733 100644 --- a/source4/auth/gensec/gensec.h +++ b/source4/auth/gensec/gensec.h @@ -284,10 +284,10 @@ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx, NTSTATUS gensec_session_info(struct gensec_security *gensec_security, struct auth_session_info **session_info); NTSTATUS auth_nt_status_squash(NTSTATUS nt_status); -struct creds_CredentialState; +struct netlogon_creds_CredentialState; NTSTATUS dcerpc_schannel_creds(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, - struct creds_CredentialState **creds); + struct netlogon_creds_CredentialState **creds); NTSTATUS gensec_set_peer_addr(struct gensec_security *gensec_security, struct socket_address *peer_addr); NTSTATUS gensec_set_my_addr(struct gensec_security *gensec_security, struct socket_address *my_addr); diff --git a/source4/auth/gensec/schannel.c b/source4/auth/gensec/schannel.c index e6d38c14a3..08fce2f049 100644 --- a/source4/auth/gensec/schannel.c +++ b/source4/auth/gensec/schannel.c @@ -27,8 +27,6 @@ #include "auth/gensec/gensec.h" #include "auth/gensec/gensec_proto.h" #include "auth/gensec/schannel.h" -#include "auth/gensec/schannel_state.h" -#include "auth/gensec/schannel_proto.h" #include "librpc/rpc/dcerpc.h" #include "param/param.h" #include "auth/session_proto.h" @@ -52,8 +50,8 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ enum ndr_err_code ndr_err; struct schannel_bind bind_schannel; struct schannel_bind_ack bind_schannel_ack; - struct creds_CredentialState *creds; - + struct netlogon_creds_CredentialState *creds; + struct ldb_context *schannel_ldb; const char *workstation; const char *domain; *out = data_blob(NULL, 0); @@ -124,10 +122,22 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ domain = bind_schannel.u.info3.domain; } + if (strcasecmp_m(domain, lp_workgroup(gensec_security->settings->lp_ctx)) != 0) { + DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n", + domain, lp_workgroup(gensec_security->settings->lp_ctx))); + + return NT_STATUS_LOGON_FAILURE; + } + + schannel_ldb = schannel_db_connect(out_mem_ctx, gensec_security->event_ctx, + gensec_security->settings->lp_ctx); + if (!schannel_ldb) { + return NT_STATUS_ACCESS_DENIED; + } /* pull the session key for this client */ - status = schannel_fetch_session_key(out_mem_ctx, gensec_security->event_ctx, - gensec_security->settings->lp_ctx, workstation, - domain, &creds); + status = schannel_fetch_session_key(schannel_ldb, + out_mem_ctx, workstation, &creds); + talloc_free(schannel_ldb); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("Could not find session key for attempted schannel connection from %s: %s\n", workstation, nt_errstr(status))); @@ -161,15 +171,16 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ } /** - * Return the struct creds_CredentialState. + * Return the struct netlogon_creds_CredentialState. * * Make sure not to call this unless gensec is using schannel... */ /* TODO: make this non-public */ + _PUBLIC_ NTSTATUS dcerpc_schannel_creds(struct gensec_security *gensec_security, - TALLOC_CTX *mem_ctx, - struct creds_CredentialState **creds) + TALLOC_CTX *mem_ctx, + struct netlogon_creds_CredentialState **creds) { struct schannel_state *state = talloc_get_type(gensec_security->private_data, struct schannel_state); diff --git a/source4/auth/gensec/schannel.h b/source4/auth/gensec/schannel.h index 2ddea29006..461f6ba2ff 100644 --- a/source4/auth/gensec/schannel.h +++ b/source4/auth/gensec/schannel.h @@ -20,7 +20,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "libcli/auth/credentials.h" +#include "libcli/auth/libcli_auth.h" +#include "auth/gensec/schannel_proto.h" +#include "auth/gensec/schannel_state.h" +#include "libcli/auth/schannel_state.h" enum schannel_position { SCHANNEL_STATE_START = 0, @@ -31,6 +34,6 @@ struct schannel_state { enum schannel_position state; uint32_t seq_num; bool initiator; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; }; diff --git a/source4/auth/gensec/schannel_sign.c b/source4/auth/gensec/schannel_sign.c index 9862a029a4..17a0c17d41 100644 --- a/source4/auth/gensec/schannel_sign.c +++ b/source4/auth/gensec/schannel_sign.c @@ -22,11 +22,9 @@ #include "includes.h" #include "../lib/crypto/crypto.h" -#include "auth/auth.h" -#include "auth/gensec/schannel.h" -#include "auth/credentials/credentials.h" #include "auth/gensec/gensec.h" -#include "auth/gensec/schannel_proto.h" +#include "auth/gensec/gensec_proto.h" +#include "auth/gensec/schannel.h" #define NETSEC_SIGN_SIGNATURE { 0x77, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 } #define NETSEC_SEAL_SIGNATURE { 0x77, 0x00, 0x7a, 0x00, 0xff, 0xff, 0x00, 0x00 } diff --git a/source4/auth/gensec/schannel_state.c b/source4/auth/gensec/schannel_state.c index ca8537cac9..1320db8933 100644 --- a/source4/auth/gensec/schannel_state.c +++ b/source4/auth/gensec/schannel_state.c @@ -21,7 +21,6 @@ #include "includes.h" #include "lib/ldb/include/ldb.h" -#include "librpc/gen_ndr/ndr_security.h" #include "ldb_wrap.h" #include "../lib/util/util_ldb.h" #include "libcli/auth/libcli_auth.h" @@ -29,45 +28,6 @@ #include "param/param.h" #include "auth/gensec/schannel_state.h" -static struct ldb_val *schannel_dom_sid_ldb_val(TALLOC_CTX *mem_ctx, - struct smb_iconv_convenience *smbiconv, - struct dom_sid *sid) -{ - enum ndr_err_code ndr_err; - struct ldb_val *v; - - v = talloc(mem_ctx, struct ldb_val); - if (!v) return NULL; - - ndr_err = ndr_push_struct_blob(v, mem_ctx, smbiconv, sid, - (ndr_push_flags_fn_t)ndr_push_dom_sid); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - talloc_free(v); - return NULL; - } - - return v; -} - -static struct dom_sid *schannel_ldb_val_dom_sid(TALLOC_CTX *mem_ctx, - const struct ldb_val *v) -{ - enum ndr_err_code ndr_err; - struct dom_sid *sid; - - sid = talloc(mem_ctx, struct dom_sid); - if (!sid) return NULL; - - ndr_err = ndr_pull_struct_blob(v, sid, NULL, sid, - (ndr_pull_flags_fn_t)ndr_pull_dom_sid); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - talloc_free(sid); - return NULL; - } - return sid; -} - - /** connect to the schannel ldb */ @@ -104,246 +64,3 @@ struct ldb_context *schannel_db_connect(TALLOC_CTX *mem_ctx, struct tevent_conte return ldb; } -/* - remember an established session key for a netr server authentication - use a simple ldb structure -*/ -NTSTATUS schannel_store_session_key_ldb(TALLOC_CTX *mem_ctx, - struct ldb_context *ldb, - struct creds_CredentialState *creds) -{ - struct ldb_message *msg; - struct ldb_val val, seed, client_state, server_state; - struct smb_iconv_convenience *smbiconv; - struct ldb_val *sid_val; - char *f; - char *sct; - int ret; - - f = talloc_asprintf(mem_ctx, "%u", (unsigned int)creds->negotiate_flags); - - if (f == NULL) { - return NT_STATUS_NO_MEMORY; - } - - sct = talloc_asprintf(mem_ctx, "%u", (unsigned int)creds->secure_channel_type); - - if (sct == NULL) { - return NT_STATUS_NO_MEMORY; - } - - msg = ldb_msg_new(ldb); - if (msg == NULL) { - return NT_STATUS_NO_MEMORY; - } - - msg->dn = ldb_dn_new_fmt(msg, ldb, "computerName=%s", creds->computer_name); - if ( ! msg->dn) { - return NT_STATUS_NO_MEMORY; - } - - smbiconv = lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")); - sid_val = schannel_dom_sid_ldb_val(msg, smbiconv, creds->sid); - if (sid_val == NULL) { - return NT_STATUS_NO_MEMORY; - } - - val.data = creds->session_key; - val.length = sizeof(creds->session_key); - - seed.data = creds->seed.data; - seed.length = sizeof(creds->seed.data); - - client_state.data = creds->client.data; - client_state.length = sizeof(creds->client.data); - server_state.data = creds->server.data; - server_state.length = sizeof(creds->server.data); - - ldb_msg_add_string(msg, "objectClass", "schannelState"); - ldb_msg_add_value(msg, "sessionKey", &val, NULL); - ldb_msg_add_value(msg, "seed", &seed, NULL); - ldb_msg_add_value(msg, "clientState", &client_state, NULL); - ldb_msg_add_value(msg, "serverState", &server_state, NULL); - ldb_msg_add_string(msg, "negotiateFlags", f); - ldb_msg_add_string(msg, "secureChannelType", sct); - ldb_msg_add_string(msg, "accountName", creds->account_name); - ldb_msg_add_string(msg, "computerName", creds->computer_name); - ldb_msg_add_string(msg, "flatname", creds->domain); - ldb_msg_add_value(msg, "objectSid", sid_val, NULL); - - ldb_delete(ldb, msg->dn); - - ret = ldb_add(ldb, msg); - - if (ret != 0) { - DEBUG(0,("Unable to add %s to session key db - %s\n", - ldb_dn_get_linearized(msg->dn), ldb_errstring(ldb))); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - - return NT_STATUS_OK; -} - -NTSTATUS schannel_store_session_key(TALLOC_CTX *mem_ctx, - struct tevent_context *ev_ctx, - struct loadparm_context *lp_ctx, - struct creds_CredentialState *creds) -{ - struct ldb_context *ldb; - NTSTATUS nt_status; - int ret; - - ldb = schannel_db_connect(mem_ctx, ev_ctx, lp_ctx); - if (!ldb) { - return NT_STATUS_ACCESS_DENIED; - } - - ret = ldb_transaction_start(ldb); - if (ret != 0) { - talloc_free(ldb); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - - nt_status = schannel_store_session_key_ldb(mem_ctx, ldb, creds); - - if (NT_STATUS_IS_OK(nt_status)) { - ret = ldb_transaction_commit(ldb); - } else { - ret = ldb_transaction_cancel(ldb); - } - - if (ret != 0) { - DEBUG(0,("Unable to commit adding credentials for %s to schannel key db - %s\n", - creds->computer_name, ldb_errstring(ldb))); - talloc_free(ldb); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - - talloc_free(ldb); - return nt_status; -} - -/* - read back a credentials back for a computer -*/ -NTSTATUS schannel_fetch_session_key_ldb(TALLOC_CTX *mem_ctx, - struct ldb_context *ldb, - const char *computer_name, - const char *domain, - struct creds_CredentialState **creds) -{ - struct ldb_result *res; - int ret; - const struct ldb_val *val; - - *creds = talloc_zero(mem_ctx, struct creds_CredentialState); - if (!*creds) { - return NT_STATUS_NO_MEMORY; - } - - ret = ldb_search(ldb, mem_ctx, &res, - NULL, LDB_SCOPE_SUBTREE, NULL, - "(&(computerName=%s)(flatname=%s))", computer_name, domain); - if (ret != LDB_SUCCESS) { - DEBUG(3,("schannel: Failed to find a record for client %s: %s\n", computer_name, ldb_errstring(ldb))); - return NT_STATUS_INVALID_HANDLE; - } - if (res->count != 1) { - DEBUG(3,("schannel: Failed to find a record for client: %s (found %d records)\n", computer_name, res->count)); - talloc_free(res); - return NT_STATUS_INVALID_HANDLE; - } - - val = ldb_msg_find_ldb_val(res->msgs[0], "sessionKey"); - if (val == NULL || val->length != 16) { - DEBUG(1,("schannel: record in schannel DB must contain a sessionKey of length 16, when searching for client: %s\n", computer_name)); - talloc_free(res); - return NT_STATUS_INTERNAL_ERROR; - } - - memcpy((*creds)->session_key, val->data, 16); - - val = ldb_msg_find_ldb_val(res->msgs[0], "seed"); - if (val == NULL || val->length != 8) { - DEBUG(1,("schannel: record in schannel DB must contain a vaid seed of length 8, when searching for client: %s\n", computer_name)); - talloc_free(res); - return NT_STATUS_INTERNAL_ERROR; - } - - memcpy((*creds)->seed.data, val->data, 8); - - val = ldb_msg_find_ldb_val(res->msgs[0], "clientState"); - if (val == NULL || val->length != 8) { - DEBUG(1,("schannel: record in schannel DB must contain a vaid clientState of length 8, when searching for client: %s\n", computer_name)); - talloc_free(res); - return NT_STATUS_INTERNAL_ERROR; - } - memcpy((*creds)->client.data, val->data, 8); - - val = ldb_msg_find_ldb_val(res->msgs[0], "serverState"); - if (val == NULL || val->length != 8) { - DEBUG(1,("schannel: record in schannel DB must contain a vaid serverState of length 8, when searching for client: %s\n", computer_name)); - talloc_free(res); - return NT_STATUS_INTERNAL_ERROR; - } - memcpy((*creds)->server.data, val->data, 8); - - (*creds)->negotiate_flags = ldb_msg_find_attr_as_int(res->msgs[0], "negotiateFlags", 0); - - (*creds)->secure_channel_type = ldb_msg_find_attr_as_int(res->msgs[0], "secureChannelType", 0); - - (*creds)->account_name = talloc_strdup(*creds, ldb_msg_find_attr_as_string(res->msgs[0], "accountName", NULL)); - if ((*creds)->account_name == NULL) { - talloc_free(res); - return NT_STATUS_NO_MEMORY; - } - - (*creds)->computer_name = talloc_strdup(*creds, ldb_msg_find_attr_as_string(res->msgs[0], "computerName", NULL)); - if ((*creds)->computer_name == NULL) { - talloc_free(res); - return NT_STATUS_NO_MEMORY; - } - - (*creds)->domain = talloc_strdup(*creds, ldb_msg_find_attr_as_string(res->msgs[0], "flatname", NULL)); - if ((*creds)->domain == NULL) { - talloc_free(res); - return NT_STATUS_NO_MEMORY; - } - - val = ldb_msg_find_ldb_val(res->msgs[0], "objectSid"); - if (val == NULL) { - DEBUG(1,("schannel: missing ObjectSid for client: %s\n", computer_name)); - talloc_free(res); - return NT_STATUS_INTERNAL_ERROR; - } - (*creds)->sid = schannel_ldb_val_dom_sid(*creds, val); - if ((*creds)->sid == NULL) { - talloc_free(res); - return NT_STATUS_INTERNAL_ERROR; - } - - talloc_free(res); - return NT_STATUS_OK; -} - -NTSTATUS schannel_fetch_session_key(TALLOC_CTX *mem_ctx, - struct tevent_context *ev_ctx, - struct loadparm_context *lp_ctx, - const char *computer_name, - const char *domain, - struct creds_CredentialState **creds) -{ - NTSTATUS nt_status; - struct ldb_context *ldb; - - ldb = schannel_db_connect(mem_ctx, ev_ctx, lp_ctx); - if (!ldb) { - return NT_STATUS_ACCESS_DENIED; - } - - nt_status = schannel_fetch_session_key_ldb(mem_ctx, ldb, - computer_name, domain, - creds); - talloc_free(ldb); - return nt_status; -} diff --git a/source4/auth/ntlm/auth_sam.c b/source4/auth/ntlm/auth_sam.c index 96a13d5ed9..2b9b92812c 100644 --- a/source4/auth/ntlm/auth_sam.c +++ b/source4/auth/ntlm/auth_sam.c @@ -25,7 +25,7 @@ #include "lib/ldb/include/ldb.h" #include "../lib/util/util_ldb.h" #include "auth/auth.h" -#include "auth/ntlm/ntlm_check.h" +#include "../libcli/auth/ntlm_check.h" #include "auth/ntlm/auth_proto.h" #include "auth/auth_sam.h" #include "dsdb/samdb/samdb.h" diff --git a/source4/auth/ntlm/config.mk b/source4/auth/ntlm/config.mk index 668c528ea9..a9ae18e7c2 100644 --- a/source4/auth/ntlm/config.mk +++ b/source4/auth/ntlm/config.mk @@ -1,10 +1,5 @@ # NTLM auth server subsystem -[SUBSYSTEM::ntlm_check] -PRIVATE_DEPENDENCIES = LIBSAMBA-UTIL - -ntlm_check_OBJ_FILES = $(addprefix $(authsrcdir)/ntlm/, ntlm_check.o) - ####################### # Start MODULE auth_sam [MODULE::auth_sam_module] diff --git a/source4/auth/ntlmssp/config.mk b/source4/auth/ntlmssp/config.mk index c0446bcac1..1be5fa98e7 100644 --- a/source4/auth/ntlmssp/config.mk +++ b/source4/auth/ntlmssp/config.mk @@ -1,9 +1,3 @@ -[SUBSYSTEM::MSRPC_PARSE] - -MSRPC_PARSE_OBJ_FILES = $(addprefix $(authsrcdir)/ntlmssp/, ntlmssp_parse.o) - -$(eval $(call proto_header_template,$(authsrcdir)/ntlmssp/msrpc_parse.h,$(MSRPC_PARSE_OBJ_FILES:.o=.c))) - ################################################ # Start MODULE gensec_ntlmssp [MODULE::gensec_ntlmssp] diff --git a/source4/auth/ntlmssp/ntlmssp.c b/source4/auth/ntlmssp/ntlmssp.c index c4b3a31365..e649bba4db 100644 --- a/source4/auth/ntlmssp/ntlmssp.c +++ b/source4/auth/ntlmssp/ntlmssp.c @@ -23,13 +23,11 @@ #include "includes.h" #include "auth/ntlmssp/ntlmssp.h" -#include "auth/ntlmssp/msrpc_parse.h" +#include "../libcli/auth/libcli_auth.h" #include "librpc/gen_ndr/ndr_dcerpc.h" #include "auth/credentials/credentials.h" #include "auth/gensec/gensec.h" #include "auth/gensec/gensec_proto.h" -#include "auth/auth.h" -#include "auth/ntlm/auth_proto.h" #include "param/param.h" /** diff --git a/source4/auth/ntlmssp/ntlmssp.h b/source4/auth/ntlmssp/ntlmssp.h index df950e4756..ff7225bb3c 100644 --- a/source4/auth/ntlmssp/ntlmssp.h +++ b/source4/auth/ntlmssp/ntlmssp.h @@ -66,11 +66,6 @@ enum ntlmssp_message_type #define NTLMSSP_NEGOTIATE_KEY_EXCH 0x40000000 #define NTLMSSP_NEGOTIATE_56 0x80000000 -#define NTLMSSP_NAME_TYPE_SERVER 0x01 -#define NTLMSSP_NAME_TYPE_DOMAIN 0x02 -#define NTLMSSP_NAME_TYPE_SERVER_DNS 0x03 -#define NTLMSSP_NAME_TYPE_DOMAIN_DNS 0x04 - #define NTLMSSP_SIGN_VERSION 1 #define NTLMSSP_SIG_SIZE 16 diff --git a/source4/auth/ntlmssp/ntlmssp_client.c b/source4/auth/ntlmssp/ntlmssp_client.c index e28d8462d4..d3c1165994 100644 --- a/source4/auth/ntlmssp/ntlmssp_client.c +++ b/source4/auth/ntlmssp/ntlmssp_client.c @@ -23,9 +23,8 @@ #include "includes.h" #include "auth/ntlmssp/ntlmssp.h" -#include "auth/ntlmssp/msrpc_parse.h" #include "../lib/crypto/crypto.h" -#include "libcli/auth/libcli_auth.h" +#include "../libcli/auth/libcli_auth.h" #include "auth/credentials/credentials.h" #include "auth/gensec/gensec.h" #include "param/param.h" diff --git a/source4/auth/ntlmssp/ntlmssp_server.c b/source4/auth/ntlmssp/ntlmssp_server.c index 9215ccac8c..00d3e56171 100644 --- a/source4/auth/ntlmssp/ntlmssp_server.c +++ b/source4/auth/ntlmssp/ntlmssp_server.c @@ -24,10 +24,8 @@ #include "includes.h" #include "system/network.h" #include "auth/ntlmssp/ntlmssp.h" -#include "auth/ntlmssp/msrpc_parse.h" +#include "../libcli/auth/libcli_auth.h" #include "../lib/crypto/crypto.h" -#include "libcli/auth/libcli_auth.h" -#include "auth/credentials/credentials.h" #include "auth/gensec/gensec.h" #include "auth/auth.h" #include "auth/ntlm/auth_proto.h" diff --git a/source4/auth/ntlmssp/ntlmssp_sign.c b/source4/auth/ntlmssp/ntlmssp_sign.c index 3a07d7e7bd..cf9eab67cd 100644 --- a/source4/auth/ntlmssp/ntlmssp_sign.c +++ b/source4/auth/ntlmssp/ntlmssp_sign.c @@ -20,11 +20,9 @@ */ #include "includes.h" -#include "auth/auth.h" #include "auth/ntlmssp/ntlmssp.h" -#include "auth/ntlmssp/msrpc_parse.h" +#include "../libcli/auth/libcli_auth.h" #include "../lib/crypto/crypto.h" -#include "auth/credentials/credentials.h" #include "auth/gensec/gensec.h" #define CLI_SIGN "session key to client-to-server signing key magic constant" diff --git a/source4/dsdb/config.mk b/source4/dsdb/config.mk index 8d1647953f..0895a1dd86 100644 --- a/source4/dsdb/config.mk +++ b/source4/dsdb/config.mk @@ -8,7 +8,8 @@ mkinclude samdb/ldb_modules/config.mk PUBLIC_DEPENDENCIES = HEIMDAL_KRB5 PRIVATE_DEPENDENCIES = LIBNDR NDR_DRSUAPI NDR_DRSBLOBS NSS_WRAPPER \ auth_system_session LDAP_ENCODE LIBCLI_AUTH LIBNDR \ - SAMDB_SCHEMA LDB_WRAP SAMDB_COMMON + SAMDB_SCHEMA LDB_WRAP SAMDB_COMMON \ + LIBCLI_DRSUAPI SAMDB_OBJ_FILES = $(addprefix $(dsdbsrcdir)/, \ diff --git a/source4/dsdb/repl/replicated_objects.c b/source4/dsdb/repl/replicated_objects.c index 560f75da7a..78af3c8f6d 100644 --- a/source4/dsdb/repl/replicated_objects.c +++ b/source4/dsdb/repl/replicated_objects.c @@ -27,166 +27,10 @@ #include "librpc/gen_ndr/ndr_drsuapi.h" #include "librpc/gen_ndr/ndr_drsblobs.h" #include "../lib/crypto/crypto.h" +#include "../libcli/drsuapi/drsuapi.h" #include "libcli/auth/libcli_auth.h" #include "param/param.h" -static WERROR dsdb_decrypt_attribute_value(TALLOC_CTX *mem_ctx, - const DATA_BLOB *gensec_skey, - bool rid_crypt, - uint32_t rid, - DATA_BLOB *in, - DATA_BLOB *out) -{ - DATA_BLOB confounder; - DATA_BLOB enc_buffer; - - struct MD5Context md5; - uint8_t _enc_key[16]; - DATA_BLOB enc_key; - - DATA_BLOB dec_buffer; - - uint32_t crc32_given; - uint32_t crc32_calc; - DATA_BLOB checked_buffer; - - DATA_BLOB plain_buffer; - - /* - * users with rid == 0 should not exist - */ - if (rid_crypt && rid == 0) { - return WERR_DS_DRA_INVALID_PARAMETER; - } - - /* - * the first 16 bytes at the beginning are the confounder - * followed by the 4 byte crc32 checksum - */ - if (in->length < 20) { - return WERR_DS_DRA_INVALID_PARAMETER; - } - confounder = data_blob_const(in->data, 16); - enc_buffer = data_blob_const(in->data + 16, in->length - 16); - - /* - * build the encryption key md5 over the session key followed - * by the confounder - * - * here the gensec session key is used and - * not the dcerpc ncacn_ip_tcp "SystemLibraryDTC" key! - */ - enc_key = data_blob_const(_enc_key, sizeof(_enc_key)); - MD5Init(&md5); - MD5Update(&md5, gensec_skey->data, gensec_skey->length); - MD5Update(&md5, confounder.data, confounder.length); - MD5Final(enc_key.data, &md5); - - /* - * copy the encrypted buffer part and - * decrypt it using the created encryption key using arcfour - */ - dec_buffer = data_blob_const(enc_buffer.data, enc_buffer.length); - arcfour_crypt_blob(dec_buffer.data, dec_buffer.length, &enc_key); - - /* - * the first 4 byte are the crc32 checksum - * of the remaining bytes - */ - crc32_given = IVAL(dec_buffer.data, 0); - crc32_calc = crc32_calc_buffer(dec_buffer.data + 4 , dec_buffer.length - 4); - if (crc32_given != crc32_calc) { - return WERR_SEC_E_DECRYPT_FAILURE; - } - checked_buffer = data_blob_const(dec_buffer.data + 4, dec_buffer.length - 4); - - plain_buffer = data_blob_talloc(mem_ctx, checked_buffer.data, checked_buffer.length); - W_ERROR_HAVE_NO_MEMORY(plain_buffer.data); - - /* - * The following rid_crypt obfuscation isn't session specific - * and not really needed here, because we allways know the rid of the - * user account. - * - * But for the rest of samba it's easier when we remove this static - * obfuscation here - */ - if (rid_crypt) { - uint32_t i, num_hashes; - - if ((checked_buffer.length % 16) != 0) { - return WERR_DS_DRA_INVALID_PARAMETER; - } - - num_hashes = plain_buffer.length / 16; - for (i = 0; i < num_hashes; i++) { - uint32_t offset = i * 16; - sam_rid_crypt(rid, checked_buffer.data + offset, plain_buffer.data + offset, 0); - } - } - - *out = plain_buffer; - return WERR_OK; -} - -static WERROR dsdb_decrypt_attribute(const DATA_BLOB *gensec_skey, - uint32_t rid, - struct drsuapi_DsReplicaAttribute *attr) -{ - WERROR status; - TALLOC_CTX *mem_ctx; - DATA_BLOB *enc_data; - DATA_BLOB plain_data; - bool rid_crypt = false; - - if (attr->value_ctr.num_values == 0) { - return WERR_OK; - } - - switch (attr->attid) { - case DRSUAPI_ATTRIBUTE_dBCSPwd: - case DRSUAPI_ATTRIBUTE_unicodePwd: - case DRSUAPI_ATTRIBUTE_ntPwdHistory: - case DRSUAPI_ATTRIBUTE_lmPwdHistory: - rid_crypt = true; - break; - case DRSUAPI_ATTRIBUTE_supplementalCredentials: - case DRSUAPI_ATTRIBUTE_priorValue: - case DRSUAPI_ATTRIBUTE_currentValue: - case DRSUAPI_ATTRIBUTE_trustAuthOutgoing: - case DRSUAPI_ATTRIBUTE_trustAuthIncoming: - case DRSUAPI_ATTRIBUTE_initialAuthOutgoing: - case DRSUAPI_ATTRIBUTE_initialAuthIncoming: - break; - default: - return WERR_OK; - } - - if (attr->value_ctr.num_values > 1) { - return WERR_DS_DRA_INVALID_PARAMETER; - } - - if (!attr->value_ctr.values[0].blob) { - return WERR_DS_DRA_INVALID_PARAMETER; - } - - mem_ctx = attr->value_ctr.values[0].blob; - enc_data = attr->value_ctr.values[0].blob; - - status = dsdb_decrypt_attribute_value(mem_ctx, - gensec_skey, - rid_crypt, - rid, - enc_data, - &plain_data); - W_ERROR_NOT_OK_RETURN(status); - - talloc_free(attr->value_ctr.values[0].blob->data); - *attr->value_ctr.values[0].blob = plain_data; - - return WERR_OK; -} - static WERROR dsdb_convert_object(struct ldb_context *ldb, const struct dsdb_schema *schema, struct dsdb_extended_replicated_objects *ctr, @@ -279,7 +123,7 @@ static WERROR dsdb_convert_object(struct ldb_context *ldb, m = &md->ctr.ctr1.array[i]; e = &msg->elements[i]; - status = dsdb_decrypt_attribute(gensec_skey, rid, a); + status = drsuapi_decrypt_attribute(a->value_ctr.values[0].blob, gensec_skey, rid, a); W_ERROR_NOT_OK_RETURN(status); status = dsdb_attribute_drsuapi_to_ldb(ldb, schema, a, msg->elements, e); diff --git a/source4/libcli/auth/config.mk b/source4/libcli/auth/config.mk deleted file mode 100644 index 498c2af258..0000000000 --- a/source4/libcli/auth/config.mk +++ /dev/null @@ -1,17 +0,0 @@ -################################# -# Start SUBSYSTEM LIBCLI_AUTH -[SUBSYSTEM::LIBCLI_AUTH] -PUBLIC_DEPENDENCIES = \ - MSRPC_PARSE \ - LIBSAMBA-HOSTCONFIG -# End SUBSYSTEM LIBCLI_AUTH -################################# - -LIBCLI_AUTH_OBJ_FILES = $(addprefix $(libclisrcdir)/auth/, \ - credentials.o \ - session.o \ - smbencrypt.o \ - smbdes.o) - -PUBLIC_HEADERS += $(libclisrcdir)/auth/credentials.h -$(eval $(call proto_header_template,$(libclisrcdir)/auth/proto.h,$(LIBCLI_AUTH_OBJ_FILES:.o=.c))) diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk index 5b50bdfcbe..ad7bc311c2 100644 --- a/source4/libcli/config.mk +++ b/source4/libcli/config.mk @@ -1,4 +1,3 @@ -mkinclude auth/config.mk mkinclude ldap/config.mk mkinclude security/config.mk mkinclude wbclient/config.mk diff --git a/source4/libnet/config.mk b/source4/libnet/config.mk index fac8af18b7..07d5434ebf 100644 --- a/source4/libnet/config.mk +++ b/source4/libnet/config.mk @@ -1,5 +1,5 @@ [SUBSYSTEM::LIBSAMBA-NET] -PUBLIC_DEPENDENCIES = CREDENTIALS dcerpc dcerpc_samr RPC_NDR_LSA RPC_NDR_SRVSVC RPC_NDR_DRSUAPI LIBCLI_COMPOSITE LIBCLI_RESOLVE LIBCLI_FINDDCS LIBCLI_CLDAP LIBCLI_FINDDCS gensec_schannel LIBCLI_AUTH LIBNDR SMBPASSWD PROVISION +PUBLIC_DEPENDENCIES = CREDENTIALS dcerpc dcerpc_samr RPC_NDR_LSA RPC_NDR_SRVSVC RPC_NDR_DRSUAPI LIBCLI_COMPOSITE LIBCLI_RESOLVE LIBCLI_FINDDCS LIBCLI_CLDAP LIBCLI_FINDDCS gensec_schannel LIBCLI_AUTH LIBNDR SMBPASSWD PROVISION LIBCLI_SAMSYNC LIBSAMBA-NET_OBJ_FILES = $(addprefix $(libnetsrcdir)/, \ libnet.o libnet_passwd.o libnet_time.o libnet_rpc.o \ diff --git a/source4/libnet/libnet_samdump.c b/source4/libnet/libnet_samdump.c index 10a14655f3..08a2295169 100644 --- a/source4/libnet/libnet_samdump.c +++ b/source4/libnet/libnet_samdump.c @@ -163,7 +163,6 @@ NTSTATUS libnet_SamDump(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, r2.out.error_string = NULL; r2.in.binding_string = r->in.binding_string; - r2.in.rid_crypt = lp_parm_bool(ctx->lp_ctx, NULL, "vampire", "rid decrypt", true); r2.in.init_fn = NULL; r2.in.delta_fn = libnet_samdump_fn; r2.in.fn_ctx = samdump_state; diff --git a/source4/libnet/libnet_samdump_keytab.c b/source4/libnet/libnet_samdump_keytab.c index a1846b81da..7749aa996c 100644 --- a/source4/libnet/libnet_samdump_keytab.c +++ b/source4/libnet/libnet_samdump_keytab.c @@ -115,7 +115,6 @@ NTSTATUS libnet_SamDump_keytab(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, r2.out.error_string = NULL; r2.in.binding_string = r->in.binding_string; - r2.in.rid_crypt = true; r2.in.init_fn = NULL; r2.in.delta_fn = libnet_samdump_keytab_fn; r2.in.fn_ctx = &data; diff --git a/source4/libnet/libnet_samsync.c b/source4/libnet/libnet_samsync.c index 51e49e94a0..4d512d6034 100644 --- a/source4/libnet/libnet_samsync.c +++ b/source4/libnet/libnet_samsync.c @@ -23,6 +23,7 @@ #include "includes.h" #include "libnet/libnet.h" #include "libcli/auth/libcli_auth.h" +#include "../libcli/samsync/samsync.h" #include "auth/gensec/gensec.h" #include "auth/credentials/credentials.h" #include "auth/gensec/schannel_proto.h" @@ -30,144 +31,11 @@ #include "librpc/gen_ndr/ndr_netlogon_c.h" #include "param/param.h" - -/** - * Decrypt and extract the user's passwords. - * - * The writes decrypted (no longer 'RID encrypted' or arcfour encrypted) passwords back into the structure - */ -static NTSTATUS fix_user(TALLOC_CTX *mem_ctx, - struct creds_CredentialState *creds, - bool rid_crypt, - enum netr_SamDatabaseID database, - struct netr_DELTA_ENUM *delta, - char **error_string) -{ - - uint32_t rid = delta->delta_id_union.rid; - struct netr_DELTA_USER *user = delta->delta_union.user; - struct samr_Password lm_hash; - struct samr_Password nt_hash; - const char *username = user->account_name.string; - - if (rid_crypt) { - if (user->lm_password_present) { - sam_rid_crypt(rid, user->lmpassword.hash, lm_hash.hash, 0); - user->lmpassword = lm_hash; - } - - if (user->nt_password_present) { - sam_rid_crypt(rid, user->ntpassword.hash, nt_hash.hash, 0); - user->ntpassword = nt_hash; - } - } - - if (user->user_private_info.SensitiveData) { - DATA_BLOB data; - struct netr_USER_KEYS keys; - enum ndr_err_code ndr_err; - data.data = user->user_private_info.SensitiveData; - data.length = user->user_private_info.DataLength; - creds_arcfour_crypt(creds, data.data, data.length); - user->user_private_info.SensitiveData = data.data; - user->user_private_info.DataLength = data.length; - - ndr_err = ndr_pull_struct_blob(&data, mem_ctx, NULL, &keys, (ndr_pull_flags_fn_t)ndr_pull_netr_USER_KEYS); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - *error_string = talloc_asprintf(mem_ctx, "Failed to parse Sensitive Data for %s:", username); - dump_data(10, data.data, data.length); - return ndr_map_error2ntstatus(ndr_err); - } - - if (keys.keys.keys2.lmpassword.length == 16) { - if (rid_crypt) { - sam_rid_crypt(rid, keys.keys.keys2.lmpassword.pwd.hash, lm_hash.hash, 0); - user->lmpassword = lm_hash; - } else { - user->lmpassword = keys.keys.keys2.lmpassword.pwd; - } - user->lm_password_present = true; - } - if (keys.keys.keys2.ntpassword.length == 16) { - if (rid_crypt) { - sam_rid_crypt(rid, keys.keys.keys2.ntpassword.pwd.hash, nt_hash.hash, 0); - user->ntpassword = nt_hash; - } else { - user->ntpassword = keys.keys.keys2.ntpassword.pwd; - } - user->nt_password_present = true; - } - /* TODO: rid decrypt history fields */ - } - return NT_STATUS_OK; -} - -/** - * Decrypt and extract the secrets - * - * The writes decrypted secrets back into the structure - */ -static NTSTATUS fix_secret(TALLOC_CTX *mem_ctx, - struct creds_CredentialState *creds, - enum netr_SamDatabaseID database, - struct netr_DELTA_ENUM *delta, - char **error_string) -{ - struct netr_DELTA_SECRET *secret = delta->delta_union.secret; - creds_arcfour_crypt(creds, secret->current_cipher.cipher_data, - secret->current_cipher.maxlen); - - creds_arcfour_crypt(creds, secret->old_cipher.cipher_data, - secret->old_cipher.maxlen); - - return NT_STATUS_OK; -} - -/** - * Fix up the delta, dealing with encryption issues so that the final - * callback need only do the printing or application logic - */ - -static NTSTATUS fix_delta(TALLOC_CTX *mem_ctx, - struct creds_CredentialState *creds, - bool rid_crypt, - enum netr_SamDatabaseID database, - struct netr_DELTA_ENUM *delta, - char **error_string) -{ - NTSTATUS nt_status = NT_STATUS_OK; - *error_string = NULL; - switch (delta->delta_type) { - case NETR_DELTA_USER: - { - nt_status = fix_user(mem_ctx, - creds, - rid_crypt, - database, - delta, - error_string); - break; - } - case NETR_DELTA_SECRET: - { - nt_status = fix_secret(mem_ctx, - creds, - database, - delta, - error_string); - break; - } - default: - break; - } - return nt_status; -} - NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_SamSync *r) { NTSTATUS nt_status, dbsync_nt_status; TALLOC_CTX *samsync_ctx, *loop_ctx, *delta_ctx; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; struct netr_DatabaseSync dbsync; struct netr_Authenticator credential, return_authenticator; struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; @@ -343,7 +211,7 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx do { int d; loop_ctx = talloc_named(samsync_ctx, 0, "DatabaseSync loop context"); - creds_client_authenticator(creds, &credential); + netlogon_creds_client_authenticator(creds, &credential); dbsync.in.credential = &credential; @@ -355,7 +223,7 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx return nt_status; } - if (!creds_client_check(creds, &dbsync.out.return_authenticator->cred)) { + if (!netlogon_creds_client_check(creds, &dbsync.out.return_authenticator->cred)) { r->out.error_string = talloc_strdup(mem_ctx, "Credential chaining on incoming DatabaseSync failed"); talloc_free(samsync_ctx); return NT_STATUS_ACCESS_DENIED; @@ -369,12 +237,10 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx delta_ctx = talloc_named(loop_ctx, 0, "DatabaseSync delta context"); /* 'Fix' elements, by decrypting and * de-obfuscating the data */ - nt_status = fix_delta(delta_ctx, - creds, - r->in.rid_crypt, - dbsync.in.database_id, - &delta_enum_array->delta_enum[d], - &error_string); + nt_status = samsync_fix_delta(delta_ctx, + creds, + dbsync.in.database_id, + &delta_enum_array->delta_enum[d]); if (!NT_STATUS_IS_OK(nt_status)) { r->out.error_string = talloc_steal(mem_ctx, error_string); talloc_free(samsync_ctx); diff --git a/source4/libnet/libnet_samsync.h b/source4/libnet/libnet_samsync.h index c2295f3957..439c3ba162 100644 --- a/source4/libnet/libnet_samsync.h +++ b/source4/libnet/libnet_samsync.h @@ -32,7 +32,6 @@ struct libnet_SamSync_state { struct libnet_SamSync { struct { const char *binding_string; - bool rid_crypt; NTSTATUS (*init_fn)(TALLOC_CTX *mem_ctx, void *private_data, struct libnet_SamSync_state *samsync_state, diff --git a/source4/libnet/libnet_samsync_ldb.c b/source4/libnet/libnet_samsync_ldb.c index e24c54a8c2..5bb75ca30d 100644 --- a/source4/libnet/libnet_samsync_ldb.c +++ b/source4/libnet/libnet_samsync_ldb.c @@ -1233,7 +1233,6 @@ NTSTATUS libnet_samsync_ldb(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, str r2.out.error_string = NULL; r2.in.binding_string = r->in.binding_string; - r2.in.rid_crypt = true; r2.in.init_fn = libnet_samsync_ldb_init; r2.in.delta_fn = libnet_samsync_ldb_fn; r2.in.fn_ctx = state; diff --git a/source4/librpc/idl-deps.pl b/source4/librpc/idl-deps.pl index 4d97139fc5..b3f0451eeb 100644 --- a/source4/librpc/idl-deps.pl +++ b/source4/librpc/idl-deps.pl @@ -1,6 +1,7 @@ #!/usr/bin/perl use strict; use File::Basename; +use Cwd 'abs_path'; sub add($$) { @@ -19,6 +20,7 @@ foreach(@ARGV) { my $gen_ndr = dirname($f); $gen_ndr =~ s/\/idl$/\/gen_ndr/; + $gen_ndr = abs_path($gen_ndr); print "# $f\n"; add("IDL_FILES", $f); diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c index e3add82bf2..c678a674c1 100644 --- a/source4/librpc/rpc/dcerpc_schannel.c +++ b/source4/librpc/rpc/dcerpc_schannel.c @@ -36,7 +36,7 @@ struct schannel_key_state { struct dcerpc_pipe *pipe2; struct dcerpc_binding *binding; struct cli_credentials *credentials; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; uint32_t negotiate_flags; struct netr_Credential credentials1; struct netr_Credential credentials2; @@ -167,9 +167,6 @@ static void continue_srv_challenge(struct rpc_request *req) /* prepare credentials for auth2 request */ s->mach_pwd = cli_credentials_get_nt_hash(s->credentials, c); - creds_client_init(s->creds, &s->credentials1, &s->credentials2, - s->mach_pwd, &s->credentials3, s->negotiate_flags); - /* auth2 request arguments */ s->a.in.server_name = s->r.in.server_name; s->a.in.account_name = cli_credentials_get_username(s->credentials); @@ -181,6 +178,14 @@ static void continue_srv_challenge(struct rpc_request *req) s->a.out.negotiate_flags = &s->negotiate_flags; s->a.out.return_credentials = &s->credentials3; + s->creds = netlogon_creds_client_init(s, + s->a.in.account_name, + s->a.in.computer_name, + &s->credentials1, &s->credentials2, + s->mach_pwd, &s->credentials3, s->negotiate_flags); + if (composite_nomem(s->creds, c)) { + return; + } /* authenticate on the netlogon pipe - a rpc request over secondary pipe */ @@ -208,7 +213,7 @@ static void continue_srv_auth2(struct rpc_request *req) if (!composite_is_ok(c)) return; /* verify credentials */ - if (!creds_client_check(s->creds, s->a.out.return_credentials)) { + if (!netlogon_creds_client_check(s->creds, s->a.out.return_credentials)) { composite_error(c, NT_STATUS_UNSUCCESSFUL); return; } @@ -246,9 +251,6 @@ struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx, s->credentials = credentials; /* allocate credentials */ - s->creds = talloc(c, struct creds_CredentialState); - if (composite_nomem(s->creds, c)) return c; - /* type of authentication depends on schannel type */ if (s->pipe->conn->flags & DCERPC_SCHANNEL_128) { s->negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; diff --git a/source4/main.mk b/source4/main.mk index d7db0580e9..aaae329ed8 100644 --- a/source4/main.mk +++ b/source4/main.mk @@ -53,4 +53,7 @@ mkinclude ../lib/smbconf/config.mk mkinclude ../lib/async_req/config.mk mkinclude ../libcli/security/config.mk mkinclude ../libcli/ldap/config.mk +mkinclude ../libcli/auth/config.mk +mkinclude ../libcli/drsuapi/config.mk +mkinclude ../libcli/samsync/config.mk diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 2efddc74fc..b17ab86e26 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -31,14 +31,14 @@ #include "rpc_server/samr/proto.h" #include "../lib/util/util_ldb.h" #include "libcli/auth/libcli_auth.h" -#include "auth/gensec/schannel_state.h" +#include "auth/gensec/schannel.h" #include "libcli/security/security.h" #include "param/param.h" #include "lib/messaging/irpc.h" #include "librpc/gen_ndr/ndr_irpc.h" #include "librpc/gen_ndr/ndr_netlogon.h" -struct server_pipe_state { +struct netlogon_server_pipe_state { struct netr_Credential client_challenge; struct netr_Credential server_challenge; }; @@ -47,8 +47,8 @@ struct server_pipe_state { static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct netr_ServerReqChallenge *r) { - struct server_pipe_state *pipe_state = - (struct server_pipe_state *)dce_call->context->private_data; + struct netlogon_server_pipe_state *pipe_state = + talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state); ZERO_STRUCTP(r->out.return_credentials); @@ -59,7 +59,7 @@ static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_cal dce_call->context->private_data = NULL; } - pipe_state = talloc(dce_call->context, struct server_pipe_state); + pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state); NT_STATUS_HAVE_NO_MEMORY(pipe_state); pipe_state->client_challenge = *r->in.credentials; @@ -77,10 +77,11 @@ static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_cal static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct netr_ServerAuthenticate3 *r) { - struct server_pipe_state *pipe_state = - (struct server_pipe_state *)dce_call->context->private_data; - struct creds_CredentialState *creds; - void *sam_ctx; + struct netlogon_server_pipe_state *pipe_state = + talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state); + struct netlogon_creds_CredentialState *creds; + struct ldb_context *schannel_ldb; + struct ldb_context *sam_ctx; struct samr_Password *mach_pwd; uint32_t user_account_control; int num_records; @@ -238,31 +239,30 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca return NT_STATUS_ACCESS_DENIED; } - creds = talloc(mem_ctx, struct creds_CredentialState); - NT_STATUS_HAVE_NO_MEMORY(creds); - - creds_server_init(creds, &pipe_state->client_challenge, - &pipe_state->server_challenge, mach_pwd, - r->out.return_credentials, - *r->in.negotiate_flags); + creds = netlogon_creds_server_init(mem_ctx, + r->in.account_name, + r->in.computer_name, + r->in.secure_channel_type, + &pipe_state->client_challenge, + &pipe_state->server_challenge, + mach_pwd, + r->in.credentials, + r->out.return_credentials, + *r->in.negotiate_flags); - if (!creds_server_check(creds, r->in.credentials)) { - talloc_free(creds); + if (!creds) { return NT_STATUS_ACCESS_DENIED; } - creds->account_name = talloc_steal(creds, r->in.account_name); - - creds->computer_name = talloc_steal(creds, r->in.computer_name); - creds->domain = talloc_strdup(creds, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx)); - - creds->secure_channel_type = r->in.secure_channel_type; - creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid"); + schannel_ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx); + if (!schannel_ldb) { + return NT_STATUS_ACCESS_DENIED; + } - /* remember this session key state */ - nt_status = schannel_store_session_key(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, creds); + nt_status = schannel_store_session_key(schannel_ldb, mem_ctx, creds); + talloc_free(schannel_ldb); return nt_status; } @@ -270,8 +270,8 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct netr_ServerAuthenticate *r) { - struct netr_ServerAuthenticate3 r3; - uint32_t rid = 0; + struct netr_ServerAuthenticate3 a; + uint32_t rid; /* TODO: * negotiate_flags is used as an [in] parameter * so it need to be initialised. @@ -281,17 +281,18 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_cal uint32_t negotiate_flags_in = 0; uint32_t negotiate_flags_out = 0; - r3.in.server_name = r->in.server_name; - r3.in.account_name = r->in.account_name; - r3.in.secure_channel_type = r->in.secure_channel_type; - r3.in.computer_name = r->in.computer_name; - r3.in.credentials = r->in.credentials; - r3.out.return_credentials = r->out.return_credentials; - r3.in.negotiate_flags = &negotiate_flags_in; - r3.out.negotiate_flags = &negotiate_flags_out; - r3.out.rid = &rid; - - return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3); + a.in.server_name = r->in.server_name; + a.in.account_name = r->in.account_name; + a.in.secure_channel_type = r->in.secure_channel_type; + a.in.computer_name = r->in.computer_name; + a.in.credentials = r->in.credentials; + a.in.negotiate_flags = &negotiate_flags_in; + + a.out.return_credentials = r->out.return_credentials; + a.out.rid = &rid; + a.out.negotiate_flags = &negotiate_flags_out; + + return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a); } static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, @@ -323,55 +324,31 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_ca the caller needs some of that information. */ -static NTSTATUS dcesrv_netr_creds_server_step_check(struct tevent_context *event_ctx, - struct loadparm_context *lp_ctx, +static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call, + TALLOC_CTX *mem_ctx, const char *computer_name, - TALLOC_CTX *mem_ctx, - struct netr_Authenticator *received_authenticator, - struct netr_Authenticator *return_authenticator, - struct creds_CredentialState **creds_out) + struct netr_Authenticator *received_authenticator, + struct netr_Authenticator *return_authenticator, + struct netlogon_creds_CredentialState **creds_out) { - struct creds_CredentialState *creds; NTSTATUS nt_status; struct ldb_context *ldb; - int ret; + bool schannel_global_required = false; /* Should be lp_schannel_server() == true */ + bool schannel_in_use = dce_call->conn->auth_state.auth_info + && dce_call->conn->auth_state.auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL + && (dce_call->conn->auth_state.auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY + || dce_call->conn->auth_state.auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY); - ldb = schannel_db_connect(mem_ctx, event_ctx, lp_ctx); + ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx); if (!ldb) { return NT_STATUS_ACCESS_DENIED; } - - ret = ldb_transaction_start(ldb); - if (ret != 0) { - talloc_free(ldb); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - - /* Because this is a shared structure (even across - * disconnects) we must update the database every time we - * update the structure */ - - nt_status = schannel_fetch_session_key_ldb(ldb, ldb, computer_name, - lp_workgroup(lp_ctx), - &creds); - if (NT_STATUS_IS_OK(nt_status)) { - nt_status = creds_server_step_check(creds, - received_authenticator, - return_authenticator); - } - if (NT_STATUS_IS_OK(nt_status)) { - nt_status = schannel_store_session_key_ldb(ldb, ldb, creds); - } - - if (NT_STATUS_IS_OK(nt_status)) { - ldb_transaction_commit(ldb); - if (creds_out) { - *creds_out = creds; - talloc_steal(mem_ctx, creds); - } - } else { - ldb_transaction_cancel(ldb); - } + nt_status = schannel_creds_server_step_check(ldb, mem_ctx, + computer_name, + schannel_global_required, + schannel_in_use, + received_authenticator, + return_authenticator, creds_out); talloc_free(ldb); return nt_status; } @@ -384,14 +361,15 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct tevent_context *event static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct netr_ServerPasswordSet *r) { - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; struct ldb_context *sam_ctx; NTSTATUS nt_status; - nt_status = dcesrv_netr_creds_server_step_check(dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, - r->in.computer_name, mem_ctx, - r->in.credential, r->out.return_authenticator, - &creds); + nt_status = dcesrv_netr_creds_server_step_check(dce_call, + mem_ctx, + r->in.computer_name, + r->in.credential, r->out.return_authenticator, + &creds); NT_STATUS_NOT_OK_RETURN(nt_status); sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx)); @@ -399,7 +377,7 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call return NT_STATUS_INVALID_SYSTEM_SERVICE; } - creds_des_decrypt(creds, r->in.new_password); + netlogon_creds_des_decrypt(creds, r->in.new_password); /* Using the sid for the account as the key, set the password */ nt_status = samdb_set_password_sid(sam_ctx, mem_ctx, @@ -418,15 +396,16 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct netr_ServerPasswordSet2 *r) { - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; struct ldb_context *sam_ctx; NTSTATUS nt_status; DATA_BLOB new_password; struct samr_CryptPassword password_buf; - nt_status = dcesrv_netr_creds_server_step_check(dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, - r->in.computer_name, mem_ctx, + nt_status = dcesrv_netr_creds_server_step_check(dce_call, + mem_ctx, + r->in.computer_name, r->in.credential, r->out.return_authenticator, &creds); NT_STATUS_NOT_OK_RETURN(nt_status); @@ -438,7 +417,7 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal memcpy(password_buf.data, r->in.new_password->data, 512); SIVAL(password_buf.data, 512, r->in.new_password->length); - creds_arcfour_crypt(creds, password_buf.data, 516); + netlogon_creds_arcfour_crypt(creds, password_buf.data, 516); if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) { DEBUG(3,("samr: failed to decode password buffer\n")); @@ -484,7 +463,7 @@ static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TAL We can't do the traditional 'wrapping' format completly, as this function must only run under schannel */ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, - struct netr_LogonSamLogonEx *r, struct creds_CredentialState *creds) + struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds) { struct auth_context *auth_context; struct auth_usersupplied_info *user_info; @@ -509,15 +488,15 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal case NetlogonInteractiveTransitiveInformation: case NetlogonServiceTransitiveInformation: if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { - creds_arcfour_crypt(creds, + netlogon_creds_arcfour_crypt(creds, r->in.logon->password->lmpassword.hash, sizeof(r->in.logon->password->lmpassword.hash)); - creds_arcfour_crypt(creds, + netlogon_creds_arcfour_crypt(creds, r->in.logon->password->ntpassword.hash, sizeof(r->in.logon->password->ntpassword.hash)); } else { - creds_des_decrypt(creds, &r->in.logon->password->lmpassword); - creds_des_decrypt(creds, &r->in.logon->password->ntpassword); + netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword); + netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword); } /* TODO: we need to deny anonymous access here */ @@ -572,7 +551,7 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal case NetlogonGenericInformation: { if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { - creds_arcfour_crypt(creds, + netlogon_creds_arcfour_crypt(creds, r->in.logon->generic->data, r->in.logon->generic->length); } else { /* Using DES to verify kerberos tickets makes no sense */ @@ -631,7 +610,7 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) { /* This key is sent unencrypted without the ARCFOUR flag set */ if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { - creds_arcfour_crypt(creds, + netlogon_creds_arcfour_crypt(creds, sam->key.key, sizeof(sam->key.key)); } @@ -642,11 +621,11 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal if ((r->in.validation_level != 6) && memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) { if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { - creds_arcfour_crypt(creds, + netlogon_creds_arcfour_crypt(creds, sam->LMSessKey.key, sizeof(sam->LMSessKey.key)); } else { - creds_des_encrypt_LMKey(creds, + netlogon_creds_des_encrypt_LMKey(creds, &sam->LMSessKey); } } @@ -693,15 +672,20 @@ static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, struct netr_LogonSamLogonEx *r) { NTSTATUS nt_status; - struct creds_CredentialState *creds; - nt_status = schannel_fetch_session_key(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, r->in.computer_name, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx), &creds); + struct netlogon_creds_CredentialState *creds; + struct ldb_context *ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx); + if (!ldb) { + return NT_STATUS_ACCESS_DENIED; + } + + nt_status = schannel_fetch_session_key(ldb, mem_ctx, r->in.computer_name, &creds); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } if (!dce_call->conn->auth_state.auth_info || dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) { - return NT_STATUS_INTERNAL_ERROR; + return NT_STATUS_ACCESS_DENIED; } return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds); } @@ -714,7 +698,7 @@ static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce struct netr_LogonSamLogonWithFlags *r) { NTSTATUS nt_status; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; struct netr_LogonSamLogonEx r2; struct netr_Authenticator *return_authenticator; @@ -722,10 +706,11 @@ static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce return_authenticator = talloc(mem_ctx, struct netr_Authenticator); NT_STATUS_HAVE_NO_MEMORY(return_authenticator); - nt_status = dcesrv_netr_creds_server_step_check(dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, - r->in.computer_name, mem_ctx, - r->in.credential, return_authenticator, - &creds); + nt_status = dcesrv_netr_creds_server_step_check(dce_call, + mem_ctx, + r->in.computer_name, + r->in.credential, return_authenticator, + &creds); NT_STATUS_NOT_OK_RETURN(nt_status); ZERO_STRUCT(r2); @@ -1089,11 +1074,12 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal const char *local_domain; - status = dcesrv_netr_creds_server_step_check(dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, - r->in.computer_name, mem_ctx, - r->in.credential, - r->out.return_authenticator, - NULL); + status = dcesrv_netr_creds_server_step_check(dce_call, + mem_ctx, + r->in.computer_name, + r->in.credential, + r->out.return_authenticator, + NULL); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,(__location__ " Bad credentials - error\n")); } diff --git a/source4/torture/config.mk b/source4/torture/config.mk index 895fef6174..bec2a064dc 100644 --- a/source4/torture/config.mk +++ b/source4/torture/config.mk @@ -111,7 +111,7 @@ PRIVATE_DEPENDENCIES = \ RPC_NDR_SRVSVC RPC_NDR_WKSSVC RPC_NDR_ROT RPC_NDR_DSSETUP \ RPC_NDR_REMACT RPC_NDR_OXIDRESOLVER RPC_NDR_NTSVCS WB_HELPER LIBSAMBA-NET \ LIBCLI_AUTH POPT_CREDENTIALS TORTURE_LDAP TORTURE_LDB TORTURE_UTIL TORTURE_RAP \ - dcerpc_server service process_model ntvfs SERVICE_SMB RPC_NDR_BROWSER + dcerpc_server service process_model ntvfs SERVICE_SMB RPC_NDR_BROWSER LIBCLI_DRSUAPI torture_rpc_OBJ_FILES = $(addprefix $(torturesrcdir)/rpc/, \ join.o lsa.o lsa_lookup.o session_key.o echo.o dfs.o drsuapi.o \ diff --git a/source4/torture/rpc/dssync.c b/source4/torture/rpc/dssync.c index 1aaf914ceb..b47564cc91 100644 --- a/source4/torture/rpc/dssync.c +++ b/source4/torture/rpc/dssync.c @@ -30,6 +30,7 @@ #include "torture/ldap/proto.h" #include "libcli/auth/libcli_auth.h" #include "../lib/crypto/crypto.h" +#include "../libcli/drsuapi/drsuapi.h" #include "auth/credentials/credentials.h" #include "libcli/auth/libcli_auth.h" #include "auth/gensec/gensec.h" @@ -338,119 +339,6 @@ static bool test_GetInfo(struct torture_context *tctx, struct DsSyncTest *ctx) return ret; } -static DATA_BLOB decrypt_blob(TALLOC_CTX *mem_ctx, - const DATA_BLOB *gensec_skey, - bool rcrypt, - struct drsuapi_DsReplicaObjectIdentifier *id, - uint32_t rid, - const DATA_BLOB *buffer) -{ - DATA_BLOB confounder; - DATA_BLOB enc_buffer; - - struct MD5Context md5; - uint8_t _enc_key[16]; - DATA_BLOB enc_key; - - DATA_BLOB dec_buffer; - - uint32_t crc32_given; - uint32_t crc32_calc; - DATA_BLOB checked_buffer; - - DATA_BLOB plain_buffer; - - /* - * the combination "c[3] s[1] e[1] d[0]..." - * was successful!!!!!!!!!!!!!!!!!!!!!!!!!! - */ - - /* - * the first 16 bytes at the beginning are the confounder - * followed by the 4 byte crc32 checksum - */ - if (buffer->length < 20) { - return data_blob_const(NULL, 0); - } - confounder = data_blob_const(buffer->data, 16); - enc_buffer = data_blob_const(buffer->data + 16, buffer->length - 16); - - /* - * build the encryption key md5 over the session key followed - * by the confounder - * - * here the gensec session key is used and - * not the dcerpc ncacn_ip_tcp "SystemLibraryDTC" key! - */ - enc_key = data_blob_const(_enc_key, sizeof(_enc_key)); - MD5Init(&md5); - MD5Update(&md5, gensec_skey->data, gensec_skey->length); - MD5Update(&md5, confounder.data, confounder.length); - MD5Final(enc_key.data, &md5); - - /* - * copy the encrypted buffer part and - * decrypt it using the created encryption key using arcfour - */ - dec_buffer = data_blob_talloc(mem_ctx, enc_buffer.data, enc_buffer.length); - if (!dec_buffer.data) { - return data_blob_const(NULL, 0); - } - arcfour_crypt_blob(dec_buffer.data, dec_buffer.length, &enc_key); - - /* - * the first 4 byte are the crc32 checksum - * of the remaining bytes - */ - crc32_given = IVAL(dec_buffer.data, 0); - crc32_calc = crc32_calc_buffer(dec_buffer.data + 4 , dec_buffer.length - 4); - if (crc32_given != crc32_calc) { - DEBUG(0,("CRC32: given[0x%08X] calc[0x%08X]\n", - crc32_given, crc32_calc)); - return data_blob_const(NULL, 0); - } - checked_buffer = data_blob_talloc(mem_ctx, dec_buffer.data + 4, dec_buffer.length - 4); - if (!checked_buffer.data) { - return data_blob_const(NULL, 0); - } - - /* - * some attributes seem to be in a usable form after this decryption - * (supplementalCredentials, priorValue, currentValue, trustAuthOutgoing, - * trustAuthIncoming, initialAuthOutgoing, initialAuthIncoming) - * At least supplementalCredentials contains plaintext - * like "Primary:Kerberos" (in unicode form) - * - * some attributes seem to have some additional encryption - * dBCSPwd, unicodePwd, ntPwdHistory, lmPwdHistory - * - * it's the sam_rid_crypt() function, as the value is constant, - * so it doesn't depend on sessionkeys. - */ - if (rcrypt) { - uint32_t i, num_hashes; - - if ((checked_buffer.length % 16) != 0) { - return data_blob_const(NULL, 0); - } - - plain_buffer = data_blob_talloc(mem_ctx, checked_buffer.data, checked_buffer.length); - if (!plain_buffer.data) { - return data_blob_const(NULL, 0); - } - - num_hashes = plain_buffer.length / 16; - for (i = 0; i < num_hashes; i++) { - uint32_t offset = i * 16; - sam_rid_crypt(rid, checked_buffer.data + offset, plain_buffer.data + offset, 0); - } - } else { - plain_buffer = checked_buffer; - } - - return plain_buffer; -} - static void test_analyse_objects(struct torture_context *tctx, struct DsSyncTest *ctx, const DATA_BLOB *gensec_skey, @@ -481,6 +369,7 @@ static void test_analyse_objects(struct torture_context *tctx, } for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) { + WERROR werr; const char *name = NULL; bool rcrypt = false; DATA_BLOB *enc_data = NULL; @@ -549,9 +438,13 @@ static void test_analyse_objects(struct torture_context *tctx, enc_data = attr->value_ctr.values[0].blob; ZERO_STRUCT(plain_data); - plain_data = decrypt_blob(ctx, gensec_skey, rcrypt, - cur->object.identifier, rid, - enc_data); + werr = drsuapi_decrypt_attribute_value(ctx, gensec_skey, rcrypt, + rid, + enc_data, &plain_data); + if (!W_ERROR_IS_OK(werr)) { + DEBUG(0, ("Failed to decrypt %s\n", name)); + continue; + } if (!dn_printed) { object_id++; DEBUG(0,("DN[%u] %s\n", object_id, dn)); diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c index ad94add071..23443cc9d1 100644 --- a/source4/torture/rpc/netlogon.c +++ b/source4/torture/rpc/netlogon.c @@ -77,13 +77,13 @@ static bool test_LogonUasLogoff(struct torture_context *tctx, bool test_SetupCredentials(struct dcerpc_pipe *p, struct torture_context *tctx, struct cli_credentials *credentials, - struct creds_CredentialState **creds_out) + struct netlogon_creds_CredentialState **creds_out) { NTSTATUS status; struct netr_ServerReqChallenge r; struct netr_ServerAuthenticate a; struct netr_Credential credentials1, credentials2, credentials3; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; const struct samr_Password *mach_password; const char *machine_name; @@ -92,9 +92,6 @@ bool test_SetupCredentials(struct dcerpc_pipe *p, struct torture_context *tctx, torture_comment(tctx, "Testing ServerReqChallenge\n"); - creds = talloc(tctx, struct creds_CredentialState); - torture_assert(tctx, creds != NULL, "memory allocation"); - r.in.server_name = NULL; r.in.computer_name = machine_name; r.in.credentials = &credentials1; @@ -112,9 +109,13 @@ bool test_SetupCredentials(struct dcerpc_pipe *p, struct torture_context *tctx, a.in.credentials = &credentials3; a.out.return_credentials = &credentials3; - creds_client_init(creds, &credentials1, &credentials2, - mach_password, &credentials3, - 0); + creds = netlogon_creds_client_init(tctx, a.in.account_name, + a.in.computer_name, + &credentials1, &credentials2, + mach_password, &credentials3, + 0); + torture_assert(tctx, creds != NULL, "memory allocation"); + torture_comment(tctx, "Testing ServerAuthenticate\n"); @@ -128,7 +129,7 @@ bool test_SetupCredentials(struct dcerpc_pipe *p, struct torture_context *tctx, torture_assert_ntstatus_ok(tctx, status, "ServerAuthenticate"); - torture_assert(tctx, creds_client_check(creds, &credentials3), + torture_assert(tctx, netlogon_creds_client_check(creds, &credentials3), "Credential chaining failed"); *creds_out = creds; @@ -139,13 +140,13 @@ bool test_SetupCredentials2(struct dcerpc_pipe *p, struct torture_context *tctx, uint32_t negotiate_flags, struct cli_credentials *machine_credentials, int sec_chan_type, - struct creds_CredentialState **creds_out) + struct netlogon_creds_CredentialState **creds_out) { NTSTATUS status; struct netr_ServerReqChallenge r; struct netr_ServerAuthenticate2 a; struct netr_Credential credentials1, credentials2, credentials3; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; const struct samr_Password *mach_password; const char *machine_name; @@ -154,8 +155,6 @@ bool test_SetupCredentials2(struct dcerpc_pipe *p, struct torture_context *tctx, torture_comment(tctx, "Testing ServerReqChallenge\n"); - creds = talloc(tctx, struct creds_CredentialState); - torture_assert(tctx, creds != NULL, "memory allocation"); r.in.server_name = NULL; r.in.computer_name = machine_name; @@ -176,16 +175,20 @@ bool test_SetupCredentials2(struct dcerpc_pipe *p, struct torture_context *tctx, a.in.credentials = &credentials3; a.out.return_credentials = &credentials3; - creds_client_init(creds, &credentials1, &credentials2, - mach_password, &credentials3, - negotiate_flags); + creds = netlogon_creds_client_init(tctx, a.in.account_name, + a.in.computer_name, + &credentials1, &credentials2, + mach_password, &credentials3, + negotiate_flags); + + torture_assert(tctx, creds != NULL, "memory allocation"); torture_comment(tctx, "Testing ServerAuthenticate2\n"); status = dcerpc_netr_ServerAuthenticate2(p, tctx, &a); torture_assert_ntstatus_ok(tctx, status, "ServerAuthenticate2"); - torture_assert(tctx, creds_client_check(creds, &credentials3), + torture_assert(tctx, netlogon_creds_client_check(creds, &credentials3), "Credential chaining failed"); torture_comment(tctx, "negotiate_flags=0x%08x\n", negotiate_flags); @@ -198,13 +201,13 @@ bool test_SetupCredentials2(struct dcerpc_pipe *p, struct torture_context *tctx, static bool test_SetupCredentials3(struct dcerpc_pipe *p, struct torture_context *tctx, uint32_t negotiate_flags, struct cli_credentials *machine_credentials, - struct creds_CredentialState **creds_out) + struct netlogon_creds_CredentialState **creds_out) { NTSTATUS status; struct netr_ServerReqChallenge r; struct netr_ServerAuthenticate3 a; struct netr_Credential credentials1, credentials2, credentials3; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; struct samr_Password mach_password; uint32_t rid; const char *machine_name; @@ -215,9 +218,6 @@ static bool test_SetupCredentials3(struct dcerpc_pipe *p, struct torture_context torture_comment(tctx, "Testing ServerReqChallenge\n"); - creds = talloc(tctx, struct creds_CredentialState); - torture_assert(tctx, creds != NULL, "memory allocation"); - r.in.server_name = NULL; r.in.computer_name = machine_name; r.in.credentials = &credentials1; @@ -240,15 +240,19 @@ static bool test_SetupCredentials3(struct dcerpc_pipe *p, struct torture_context a.out.negotiate_flags = &negotiate_flags; a.out.rid = &rid; - creds_client_init(creds, &credentials1, &credentials2, - &mach_password, &credentials3, - negotiate_flags); + creds = netlogon_creds_client_init(tctx, a.in.account_name, + a.in.computer_name, + &credentials1, &credentials2, + &mach_password, &credentials3, + negotiate_flags); + + torture_assert(tctx, creds != NULL, "memory allocation"); torture_comment(tctx, "Testing ServerAuthenticate3\n"); status = dcerpc_netr_ServerAuthenticate3(p, tctx, &a); torture_assert_ntstatus_ok(tctx, status, "ServerAuthenticate3"); - torture_assert(tctx, creds_client_check(creds, &credentials3), "Credential chaining failed"); + torture_assert(tctx, netlogon_creds_client_check(creds, &credentials3), "Credential chaining failed"); torture_comment(tctx, "negotiate_flags=0x%08x\n", negotiate_flags); @@ -270,7 +274,7 @@ static bool test_SetPassword(struct torture_context *tctx, NTSTATUS status; struct netr_ServerPasswordSet r; const char *password; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; struct netr_Authenticator credential, return_authenticator; struct samr_Password new_password; @@ -289,18 +293,18 @@ static bool test_SetPassword(struct torture_context *tctx, password = generate_random_str(tctx, 8); E_md4hash(password, new_password.hash); - creds_des_encrypt(creds, &new_password); + netlogon_creds_des_encrypt(creds, &new_password); torture_comment(tctx, "Testing ServerPasswordSet on machine account\n"); torture_comment(tctx, "Changing machine account password to '%s'\n", password); - creds_client_authenticator(creds, &credential); + netlogon_creds_client_authenticator(creds, &credential); status = dcerpc_netr_ServerPasswordSet(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "ServerPasswordSet"); - if (!creds_client_check(creds, &r.out.return_authenticator->cred)) { + if (!netlogon_creds_client_check(creds, &r.out.return_authenticator->cred)) { torture_comment(tctx, "Credential chaining failed\n"); } @@ -313,12 +317,12 @@ static bool test_SetPassword(struct torture_context *tctx, torture_comment(tctx, "Changing machine account password to '%s' (same as previous run)\n", password); - creds_client_authenticator(creds, &credential); + netlogon_creds_client_authenticator(creds, &credential); status = dcerpc_netr_ServerPasswordSet(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "ServerPasswordSet (2)"); - if (!creds_client_check(creds, &r.out.return_authenticator->cred)) { + if (!netlogon_creds_client_check(creds, &r.out.return_authenticator->cred)) { torture_comment(tctx, "Credential chaining failed\n"); } @@ -360,7 +364,7 @@ static bool test_SetPassword2(struct torture_context *tctx, struct netr_ServerPasswordSet2 r; const char *password; DATA_BLOB new_random_pass; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; struct samr_CryptPassword password_buf; struct samr_Password nt_hash; struct netr_Authenticator credential, return_authenticator; @@ -380,7 +384,7 @@ static bool test_SetPassword2(struct torture_context *tctx, password = generate_random_str(tctx, 8); encode_pw_buffer(password_buf.data, password, STR_UNICODE); - creds_arcfour_crypt(creds, password_buf.data, 516); + netlogon_creds_arcfour_crypt(creds, password_buf.data, 516); memcpy(new_password.data, password_buf.data, 512); new_password.length = IVAL(password_buf.data, 512); @@ -388,12 +392,12 @@ static bool test_SetPassword2(struct torture_context *tctx, torture_comment(tctx, "Testing ServerPasswordSet2 on machine account\n"); torture_comment(tctx, "Changing machine account password to '%s'\n", password); - creds_client_authenticator(creds, &credential); + netlogon_creds_client_authenticator(creds, &credential); status = dcerpc_netr_ServerPasswordSet2(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "ServerPasswordSet2"); - if (!creds_client_check(creds, &r.out.return_authenticator->cred)) { + if (!netlogon_creds_client_check(creds, &r.out.return_authenticator->cred)) { torture_comment(tctx, "Credential chaining failed\n"); } @@ -410,7 +414,7 @@ static bool test_SetPassword2(struct torture_context *tctx, */ password = ""; encode_pw_buffer(password_buf.data, password, STR_UNICODE); - creds_arcfour_crypt(creds, password_buf.data, 516); + netlogon_creds_arcfour_crypt(creds, password_buf.data, 516); memcpy(new_password.data, password_buf.data, 512); new_password.length = IVAL(password_buf.data, 512); @@ -420,12 +424,12 @@ static bool test_SetPassword2(struct torture_context *tctx, torture_comment(tctx, "Changing machine account password to '%s'\n", password); - creds_client_authenticator(creds, &credential); + netlogon_creds_client_authenticator(creds, &credential); status = dcerpc_netr_ServerPasswordSet2(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "ServerPasswordSet2"); - if (!creds_client_check(creds, &r.out.return_authenticator->cred)) { + if (!netlogon_creds_client_check(creds, &r.out.return_authenticator->cred)) { torture_comment(tctx, "Credential chaining failed\n"); } @@ -438,7 +442,7 @@ static bool test_SetPassword2(struct torture_context *tctx, /* now try a random password */ password = generate_random_str(tctx, 8); encode_pw_buffer(password_buf.data, password, STR_UNICODE); - creds_arcfour_crypt(creds, password_buf.data, 516); + netlogon_creds_arcfour_crypt(creds, password_buf.data, 516); memcpy(new_password.data, password_buf.data, 512); new_password.length = IVAL(password_buf.data, 512); @@ -446,12 +450,12 @@ static bool test_SetPassword2(struct torture_context *tctx, torture_comment(tctx, "Testing second ServerPasswordSet2 on machine account\n"); torture_comment(tctx, "Changing machine account password to '%s'\n", password); - creds_client_authenticator(creds, &credential); + netlogon_creds_client_authenticator(creds, &credential); status = dcerpc_netr_ServerPasswordSet2(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "ServerPasswordSet2 (2)"); - if (!creds_client_check(creds, &r.out.return_authenticator->cred)) { + if (!netlogon_creds_client_check(creds, &r.out.return_authenticator->cred)) { torture_comment(tctx, "Credential chaining failed\n"); } @@ -464,12 +468,12 @@ static bool test_SetPassword2(struct torture_context *tctx, torture_comment(tctx, "Changing machine account password to '%s' (same as previous run)\n", password); - creds_client_authenticator(creds, &credential); + netlogon_creds_client_authenticator(creds, &credential); status = dcerpc_netr_ServerPasswordSet2(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "ServerPasswordSet (3)"); - if (!creds_client_check(creds, &r.out.return_authenticator->cred)) { + if (!netlogon_creds_client_check(creds, &r.out.return_authenticator->cred)) { torture_comment(tctx, "Credential chaining failed\n"); } @@ -484,7 +488,7 @@ static bool test_SetPassword2(struct torture_context *tctx, /* now try a random stream of bytes for a password */ set_pw_in_buffer(password_buf.data, &new_random_pass); - creds_arcfour_crypt(creds, password_buf.data, 516); + netlogon_creds_arcfour_crypt(creds, password_buf.data, 516); memcpy(new_password.data, password_buf.data, 512); new_password.length = IVAL(password_buf.data, 512); @@ -492,12 +496,12 @@ static bool test_SetPassword2(struct torture_context *tctx, torture_comment(tctx, "Testing a third ServerPasswordSet2 on machine account, with a compleatly random password\n"); - creds_client_authenticator(creds, &credential); + netlogon_creds_client_authenticator(creds, &credential); status = dcerpc_netr_ServerPasswordSet2(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "ServerPasswordSet (3)"); - if (!creds_client_check(creds, &r.out.return_authenticator->cred)) { + if (!netlogon_creds_client_check(creds, &r.out.return_authenticator->cred)) { torture_comment(tctx, "Credential chaining failed\n"); } @@ -518,7 +522,7 @@ static bool test_GetPassword(struct torture_context *tctx, struct cli_credentials *machine_credentials) { struct netr_ServerPasswordGet r; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; struct netr_Authenticator credential; NTSTATUS status; struct netr_Authenticator return_authenticator; @@ -528,7 +532,7 @@ static bool test_GetPassword(struct torture_context *tctx, return false; } - creds_client_authenticator(creds, &credential); + netlogon_creds_client_authenticator(creds, &credential); r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); r.in.account_name = talloc_asprintf(tctx, "%s$", TEST_MACHINE_NAME); @@ -549,7 +553,7 @@ static bool test_GetTrustPasswords(struct torture_context *tctx, struct cli_credentials *machine_credentials) { struct netr_ServerTrustPasswordsGet r; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; struct netr_Authenticator credential; NTSTATUS status; struct netr_Authenticator return_authenticator; @@ -559,7 +563,7 @@ static bool test_GetTrustPasswords(struct torture_context *tctx, return false; } - creds_client_authenticator(creds, &credential); + netlogon_creds_client_authenticator(creds, &credential); r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); r.in.account_name = talloc_asprintf(tctx, "%s$", TEST_MACHINE_NAME); @@ -581,7 +585,7 @@ static bool test_GetTrustPasswords(struct torture_context *tctx, */ bool test_netlogon_ops(struct dcerpc_pipe *p, struct torture_context *tctx, struct cli_credentials *credentials, - struct creds_CredentialState *creds) + struct netlogon_creds_CredentialState *creds) { NTSTATUS status; struct netr_LogonSamLogon r; @@ -647,14 +651,15 @@ bool test_netlogon_ops(struct dcerpc_pipe *p, struct torture_context *tctx, for (i=2;i<3;i++) { ZERO_STRUCT(auth2); - creds_client_authenticator(creds, &auth); + netlogon_creds_client_authenticator(creds, &auth); r.in.validation_level = i; status = dcerpc_netr_LogonSamLogon(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "LogonSamLogon failed"); - torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), + torture_assert(tctx, netlogon_creds_client_check(creds, + &r.out.return_authenticator->cred), "Credential chaining failed"); } @@ -682,7 +687,7 @@ static bool test_SamLogon(struct torture_context *tctx, struct dcerpc_pipe *p, struct cli_credentials *credentials) { - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; if (!test_SetupCredentials(p, tctx, credentials, &creds)) { return false; @@ -703,7 +708,7 @@ static bool test_DatabaseSync(struct torture_context *tctx, { NTSTATUS status; struct netr_DatabaseSync r; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; const uint32_t database_ids[] = {SAM_DATABASE_DOMAIN, SAM_DATABASE_BUILTIN, SAM_DATABASE_PRIVS}; int i; struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; @@ -733,7 +738,7 @@ static bool test_DatabaseSync(struct torture_context *tctx, torture_comment(tctx, "Testing DatabaseSync of id %d\n", r.in.database_id); do { - creds_client_authenticator(creds, &credential); + netlogon_creds_client_authenticator(creds, &credential); r.in.credential = &credential; @@ -747,7 +752,7 @@ static bool test_DatabaseSync(struct torture_context *tctx, } torture_assert_ntstatus_ok(tctx, status, "DatabaseSync"); - if (!creds_client_check(creds, &r.out.return_authenticator->cred)) { + if (!netlogon_creds_client_check(creds, &r.out.return_authenticator->cred)) { torture_comment(tctx, "Credential chaining failed\n"); } @@ -777,7 +782,7 @@ static bool test_DatabaseDeltas(struct torture_context *tctx, { NTSTATUS status; struct netr_DatabaseDeltas r; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; struct netr_Authenticator credential; struct netr_Authenticator return_authenticator; struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; @@ -807,7 +812,7 @@ static bool test_DatabaseDeltas(struct torture_context *tctx, r.in.database_id, (unsigned long long)*r.in.sequence_num); do { - creds_client_authenticator(creds, &credential); + netlogon_creds_client_authenticator(creds, &credential); status = dcerpc_netr_DatabaseDeltas(p, tctx, &r); if (NT_STATUS_EQUAL(status, @@ -821,7 +826,7 @@ static bool test_DatabaseDeltas(struct torture_context *tctx, torture_assert_ntstatus_ok(tctx, status, "DatabaseDeltas"); - if (!creds_client_check(creds, &return_authenticator.cred)) { + if (!netlogon_creds_client_check(creds, &return_authenticator.cred)) { torture_comment(tctx, "Credential chaining failed\n"); } @@ -838,7 +843,7 @@ static bool test_DatabaseRedo(struct torture_context *tctx, { NTSTATUS status; struct netr_DatabaseRedo r; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; struct netr_Authenticator credential; struct netr_Authenticator return_authenticator; struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; @@ -1300,7 +1305,7 @@ static bool test_DatabaseRedo(struct torture_context *tctx, continue; } - creds_client_authenticator(creds, &credential); + netlogon_creds_client_authenticator(creds, &credential); r.in.credential = &credential; @@ -1352,7 +1357,7 @@ static bool test_DatabaseRedo(struct torture_context *tctx, } } - if (!creds_client_check(creds, &return_authenticator.cred)) { + if (!netlogon_creds_client_check(creds, &return_authenticator.cred)) { torture_comment(tctx, "Credential chaining failed\n"); if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) { return false; @@ -1374,7 +1379,7 @@ static bool test_AccountDeltas(struct torture_context *tctx, { NTSTATUS status; struct netr_AccountDeltas r; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; struct netr_AccountBuffer buffer; uint32_t count_returned = 0; @@ -1391,7 +1396,7 @@ static bool test_AccountDeltas(struct torture_context *tctx, r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); r.in.computername = TEST_MACHINE_NAME; r.in.return_authenticator = &return_authenticator; - creds_client_authenticator(creds, &r.in.credential); + netlogon_creds_client_authenticator(creds, &r.in.credential); ZERO_STRUCT(r.in.uas); r.in.count=10; r.in.level=0; @@ -1417,7 +1422,7 @@ static bool test_AccountSync(struct torture_context *tctx, struct dcerpc_pipe *p { NTSTATUS status; struct netr_AccountSync r; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; struct netr_AccountBuffer buffer; uint32_t count_returned = 0; @@ -1436,7 +1441,7 @@ static bool test_AccountSync(struct torture_context *tctx, struct dcerpc_pipe *p r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); r.in.computername = TEST_MACHINE_NAME; r.in.return_authenticator = &return_authenticator; - creds_client_authenticator(creds, &r.in.credential); + netlogon_creds_client_authenticator(creds, &r.in.credential); r.in.recordid = &recordid; r.in.reference=0; r.in.level=0; @@ -1622,7 +1627,7 @@ static bool test_DatabaseSync2(struct torture_context *tctx, struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; struct netr_Authenticator return_authenticator, credential; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; const uint32_t database_ids[] = {0, 1, 2}; int i; @@ -1653,7 +1658,7 @@ static bool test_DatabaseSync2(struct torture_context *tctx, torture_comment(tctx, "Testing DatabaseSync2 of id %d\n", r.in.database_id); do { - creds_client_authenticator(creds, &credential); + netlogon_creds_client_authenticator(creds, &credential); r.in.credential = &credential; @@ -1668,7 +1673,7 @@ static bool test_DatabaseSync2(struct torture_context *tctx, torture_assert_ntstatus_ok(tctx, status, "DatabaseSync2"); - if (!creds_client_check(creds, &r.out.return_authenticator->cred)) { + if (!netlogon_creds_client_check(creds, &r.out.return_authenticator->cred)) { torture_comment(tctx, "Credential chaining failed\n"); } @@ -2072,14 +2077,14 @@ static bool test_netr_ServerGetTrustInfo(struct torture_context *tctx, struct samr_Password old_owf_password; struct netr_TrustInfo *trust_info; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; if (!test_SetupCredentials3(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, machine_credentials, &creds)) { return false; } - creds_client_authenticator(creds, &a); + netlogon_creds_client_authenticator(creds, &a); r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); r.in.account_name = talloc_asprintf(tctx, "%s$", TEST_MACHINE_NAME); @@ -2094,7 +2099,7 @@ static bool test_netr_ServerGetTrustInfo(struct torture_context *tctx, status = dcerpc_netr_ServerGetTrustInfo(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "failed"); - torture_assert(tctx, creds_client_check(creds, &return_authenticator.cred), "Credential chaining failed"); + torture_assert(tctx, netlogon_creds_client_check(creds, &return_authenticator.cred), "Credential chaining failed"); return true; } @@ -2108,7 +2113,7 @@ static bool test_GetDomainInfo(struct torture_context *tctx, struct netr_LogonGetDomainInfo r; struct netr_DomainQuery1 q1; struct netr_Authenticator a; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; union netr_DomainInfo info; if (!test_SetupCredentials3(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, @@ -2118,7 +2123,7 @@ static bool test_GetDomainInfo(struct torture_context *tctx, ZERO_STRUCT(r); - creds_client_authenticator(creds, &a); + netlogon_creds_client_authenticator(creds, &a); r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); r.in.computer_name = TEST_MACHINE_NAME; @@ -2143,14 +2148,14 @@ static bool test_GetDomainInfo(struct torture_context *tctx, status = dcerpc_netr_LogonGetDomainInfo(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "netr_LogonGetDomainInfo"); - torture_assert(tctx, creds_client_check(creds, &a.cred), "Credential chaining failed"); + torture_assert(tctx, netlogon_creds_client_check(creds, &a.cred), "Credential chaining failed"); torture_comment(tctx, "Testing netr_LogonGetDomainInfo 2nd call\n"); - creds_client_authenticator(creds, &a); + netlogon_creds_client_authenticator(creds, &a); status = dcerpc_netr_LogonGetDomainInfo(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "netr_LogonGetDomainInfo"); - torture_assert(tctx, creds_client_check(creds, &a.cred), "Credential chaining failed"); + torture_assert(tctx, netlogon_creds_client_check(creds, &a.cred), "Credential chaining failed"); return true; } @@ -2173,8 +2178,8 @@ static bool test_GetDomainInfo_async(struct torture_context *tctx, struct netr_DomainQuery1 q1; struct netr_Authenticator a; #define ASYNC_COUNT 100 - struct creds_CredentialState *creds; - struct creds_CredentialState *creds_async[ASYNC_COUNT]; + struct netlogon_creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds_async[ASYNC_COUNT]; struct rpc_request *req[ASYNC_COUNT]; int i; int *async_counter = talloc(tctx, int); @@ -2210,9 +2215,9 @@ static bool test_GetDomainInfo_async(struct torture_context *tctx, *async_counter = 0; for (i=0;i<ASYNC_COUNT;i++) { - creds_client_authenticator(creds, &a); + netlogon_creds_client_authenticator(creds, &a); - creds_async[i] = (struct creds_CredentialState *)talloc_memdup(creds, creds, sizeof(*creds)); + creds_async[i] = (struct netlogon_creds_CredentialState *)talloc_memdup(creds, creds, sizeof(*creds)); req[i] = dcerpc_netr_LogonGetDomainInfo_send(p, tctx, &r); req[i]->async.callback = async_callback; @@ -2230,7 +2235,7 @@ static bool test_GetDomainInfo_async(struct torture_context *tctx, torture_assert_ntstatus_ok(tctx, status, "netr_LogonGetDomainInfo_async"); torture_assert_ntstatus_ok(tctx, r.out.result, "netr_LogonGetDomainInfo_async"); - torture_assert(tctx, creds_client_check(creds_async[i], &a.cred), + torture_assert(tctx, netlogon_creds_client_check(creds_async[i], &a.cred), "Credential chaining failed at async"); } diff --git a/source4/torture/rpc/netlogon.h b/source4/torture/rpc/netlogon.h index 92d366b46a..9038286ded 100644 --- a/source4/torture/rpc/netlogon.h +++ b/source4/torture/rpc/netlogon.h @@ -3,4 +3,4 @@ bool test_SetupCredentials2(struct dcerpc_pipe *p, struct torture_context *tctx, uint32_t negotiate_flags, struct cli_credentials *machine_credentials, int sec_chan_type, - struct creds_CredentialState **creds_out); + struct netlogon_creds_CredentialState **creds_out); diff --git a/source4/torture/rpc/remote_pac.c b/source4/torture/rpc/remote_pac.c index 53754e02af..6d638d1868 100644 --- a/source4/torture/rpc/remote_pac.c +++ b/source4/torture/rpc/remote_pac.c @@ -57,7 +57,7 @@ static bool test_PACVerify(struct torture_context *tctx, struct netr_Authenticator auth, auth2; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; struct gensec_security *gensec_client_context; struct gensec_security *gensec_server_context; @@ -149,7 +149,7 @@ static bool test_PACVerify(struct torture_context *tctx, torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed"); torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption"); - creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length); + netlogon_creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length); generic.length = pac_wrapped.length; generic.data = pac_wrapped.data; @@ -168,7 +168,7 @@ static bool test_PACVerify(struct torture_context *tctx, logon.generic = &generic; ZERO_STRUCT(auth2); - creds_client_authenticator(creds, &auth); + netlogon_creds_client_authenticator(creds, &auth); r.in.credential = &auth; r.in.return_authenticator = &auth2; r.in.logon = &logon; @@ -190,7 +190,7 @@ static bool test_PACVerify(struct torture_context *tctx, logon.generic = &generic; ZERO_STRUCT(auth2); - creds_client_authenticator(creds, &auth); + netlogon_creds_client_authenticator(creds, &auth); r.in.credential = &auth; r.in.return_authenticator = &auth2; r.in.logon_level = NetlogonGenericInformation; @@ -203,7 +203,7 @@ static bool test_PACVerify(struct torture_context *tctx, torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOGON_FAILURE, "LogonSamLogon failed"); - torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), + torture_assert(tctx, netlogon_creds_client_check(creds, &r.out.return_authenticator->cred), "Credential chaining failed"); /* This will break the parsing nicely (even in the crypto wrapping), check we get INVALID_PARAMETER */ @@ -212,7 +212,7 @@ static bool test_PACVerify(struct torture_context *tctx, logon.generic = &generic; ZERO_STRUCT(auth2); - creds_client_authenticator(creds, &auth); + netlogon_creds_client_authenticator(creds, &auth); r.in.credential = &auth; r.in.return_authenticator = &auth2; r.in.logon_level = NetlogonGenericInformation; @@ -225,7 +225,8 @@ static bool test_PACVerify(struct torture_context *tctx, torture_assert_ntstatus_equal(tctx, status, NT_STATUS_INVALID_PARAMETER, "LogonSamLogon failed"); - torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), + torture_assert(tctx, netlogon_creds_client_check(creds, + &r.out.return_authenticator->cred), "Credential chaining failed"); pac_wrapped_struct.ChecksumLength = session_info->server_info->pac_srv_sig.signature.length; @@ -251,7 +252,7 @@ static bool test_PACVerify(struct torture_context *tctx, torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed"); torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption"); - creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length); + netlogon_creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length); generic.length = pac_wrapped.length; generic.data = pac_wrapped.data; @@ -259,7 +260,7 @@ static bool test_PACVerify(struct torture_context *tctx, logon.generic = &generic; ZERO_STRUCT(auth2); - creds_client_authenticator(creds, &auth); + netlogon_creds_client_authenticator(creds, &auth); r.in.credential = &auth; r.in.return_authenticator = &auth2; r.in.logon_level = NetlogonGenericInformation; @@ -272,7 +273,7 @@ static bool test_PACVerify(struct torture_context *tctx, torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOGON_FAILURE, "LogonSamLogon failed"); - torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), + torture_assert(tctx, netlogon_creds_client_check(creds, &r.out.return_authenticator->cred), "Credential chaining failed"); pac_wrapped_struct.ChecksumLength = session_info->server_info->pac_srv_sig.signature.length; @@ -298,7 +299,7 @@ static bool test_PACVerify(struct torture_context *tctx, torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed"); torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption"); - creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length); + netlogon_creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length); generic.length = pac_wrapped.length; generic.data = pac_wrapped.data; @@ -306,7 +307,7 @@ static bool test_PACVerify(struct torture_context *tctx, logon.generic = &generic; ZERO_STRUCT(auth2); - creds_client_authenticator(creds, &auth); + netlogon_creds_client_authenticator(creds, &auth); r.in.credential = &auth; r.in.return_authenticator = &auth2; r.in.logon_level = NetlogonGenericInformation; @@ -319,7 +320,7 @@ static bool test_PACVerify(struct torture_context *tctx, torture_assert_ntstatus_equal(tctx, status, NT_STATUS_INVALID_PARAMETER, "LogonSamLogon failed"); - torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), + torture_assert(tctx, netlogon_creds_client_check(creds, &r.out.return_authenticator->cred), "Credential chaining failed"); return true; } diff --git a/source4/torture/rpc/samba3rpc.c b/source4/torture/rpc/samba3rpc.c index fe128fea52..e31135c0de 100644 --- a/source4/torture/rpc/samba3rpc.c +++ b/source4/torture/rpc/samba3rpc.c @@ -904,7 +904,7 @@ static bool auth2(struct smbcli_state *cli, struct netr_Credential netr_srv_creds; uint32_t negotiate_flags; struct netr_ServerAuthenticate2 a; - struct creds_CredentialState *creds_state; + struct netlogon_creds_CredentialState *creds_state; struct netr_Credential netr_cred; struct samr_Password mach_pw; @@ -958,11 +958,6 @@ static bool auth2(struct smbcli_state *cli, negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS; E_md4hash(cli_credentials_get_password(wks_cred), mach_pw.hash); - creds_state = talloc(mem_ctx, struct creds_CredentialState); - creds_client_init(creds_state, r.in.credentials, - r.out.return_credentials, &mach_pw, - &netr_cred, negotiate_flags); - a.in.server_name = talloc_asprintf( mem_ctx, "\\\\%s", dcerpc_server_name(net_pipe)); a.in.account_name = talloc_asprintf( @@ -974,6 +969,13 @@ static bool auth2(struct smbcli_state *cli, a.in.credentials = &netr_cred; a.out.return_credentials = &netr_cred; + creds_state = netlogon_creds_client_init(mem_ctx, + a.in.account_name, + a.in.computer_name, + r.in.credentials, + r.out.return_credentials, &mach_pw, + &netr_cred, negotiate_flags); + status = dcerpc_netr_ServerAuthenticate2(net_pipe, mem_ctx, &a); if (!NT_STATUS_IS_OK(status)) { d_printf("netr_ServerServerAuthenticate2 failed: %s\n", @@ -981,7 +983,7 @@ static bool auth2(struct smbcli_state *cli, goto done; } - if (!creds_client_check(creds_state, a.out.return_credentials)) { + if (!netlogon_creds_client_check(creds_state, a.out.return_credentials)) { d_printf("creds_client_check failed\n"); goto done; } @@ -1054,7 +1056,7 @@ static bool schan(struct smbcli_state *cli, for (i=2; i<4; i++) { int flags; DATA_BLOB chal, nt_resp, lm_resp, names_blob, session_key; - struct creds_CredentialState *creds_state; + struct netlogon_creds_CredentialState *creds_state; struct netr_Authenticator netr_auth, netr_auth2; struct netr_NetworkInfo ninfo; struct netr_PasswordInfo pinfo; @@ -1088,7 +1090,7 @@ static bool schan(struct smbcli_state *cli, } creds_state = cli_credentials_get_netlogon_creds(wks_creds); - creds_client_authenticator(creds_state, &netr_auth); + netlogon_creds_client_authenticator(creds_state, &netr_auth); ninfo.identity_info.account_name.string = cli_credentials_get_username(user_creds); @@ -1129,13 +1131,13 @@ static bool schan(struct smbcli_state *cli, } if ((r.out.return_authenticator == NULL) || - (!creds_client_check(creds_state, + (!netlogon_creds_client_check(creds_state, &r.out.return_authenticator->cred))) { d_printf("Credentials check failed!\n"); goto done; } - creds_client_authenticator(creds_state, &netr_auth); + netlogon_creds_client_authenticator(creds_state, &netr_auth); pinfo.identity_info = ninfo.identity_info; ZERO_STRUCT(pinfo.lmpassword.hash); @@ -1161,7 +1163,7 @@ static bool schan(struct smbcli_state *cli, } if ((r.out.return_authenticator == NULL) || - (!creds_client_check(creds_state, + (!netlogon_creds_client_check(creds_state, &r.out.return_authenticator->cred))) { d_printf("Credentials check failed!\n"); goto done; @@ -1171,7 +1173,7 @@ static bool schan(struct smbcli_state *cli, { struct netr_ServerPasswordSet s; char *password = generate_random_str(wks_creds, 8); - struct creds_CredentialState *creds_state; + struct netlogon_creds_CredentialState *creds_state; struct netr_Authenticator credential, return_authenticator; struct samr_Password new_password; @@ -1188,8 +1190,8 @@ static bool schan(struct smbcli_state *cli, E_md4hash(password, new_password.hash); creds_state = cli_credentials_get_netlogon_creds(wks_creds); - creds_des_encrypt(creds_state, &new_password); - creds_client_authenticator(creds_state, &credential); + netlogon_creds_des_encrypt(creds_state, &new_password); + netlogon_creds_client_authenticator(creds_state, &credential); status = dcerpc_netr_ServerPasswordSet(net_pipe, mem_ctx, &s); if (!NT_STATUS_IS_OK(status)) { @@ -1197,8 +1199,8 @@ static bool schan(struct smbcli_state *cli, goto done; } - if (!creds_client_check(creds_state, - &s.out.return_authenticator->cred)) { + if (!netlogon_creds_client_check(creds_state, + &s.out.return_authenticator->cred)) { printf("Credential chaining failed\n"); } @@ -2088,7 +2090,7 @@ bool torture_samba3_rpc_randomauth2(struct torture_context *torture) struct netr_Credential netr_srv_creds; uint32_t negotiate_flags; struct netr_ServerAuthenticate2 a; - struct creds_CredentialState *creds_state; + struct netlogon_creds_CredentialState *creds_state; struct netr_Credential netr_cred; struct samr_Password mach_pw; struct smbcli_state *cli; @@ -2155,11 +2157,6 @@ bool torture_samba3_rpc_randomauth2(struct torture_context *torture) negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS; E_md4hash("foobar", mach_pw.hash); - creds_state = talloc(mem_ctx, struct creds_CredentialState); - creds_client_init(creds_state, r.in.credentials, - r.out.return_credentials, &mach_pw, - &netr_cred, negotiate_flags); - a.in.server_name = talloc_asprintf( mem_ctx, "\\\\%s", dcerpc_server_name(net_pipe)); a.in.account_name = talloc_asprintf( @@ -2171,6 +2168,14 @@ bool torture_samba3_rpc_randomauth2(struct torture_context *torture) a.in.credentials = &netr_cred; a.out.return_credentials = &netr_cred; + creds_state = netlogon_creds_client_init(mem_ctx, + a.in.account_name, + a.in.computer_name, + r.in.credentials, + r.out.return_credentials, &mach_pw, + &netr_cred, negotiate_flags); + + status = dcerpc_netr_ServerAuthenticate2(net_pipe, mem_ctx, &a); if (!NT_STATUS_EQUAL(status, NT_STATUS_NO_TRUST_SAM_ACCOUNT)) { diff --git a/source4/torture/rpc/samlogon.c b/source4/torture/rpc/samlogon.c index ce9bf5ea6e..8318930989 100644 --- a/source4/torture/rpc/samlogon.c +++ b/source4/torture/rpc/samlogon.c @@ -63,7 +63,7 @@ struct samlogon_state { struct netr_LogonSamLogonEx r_ex; struct netr_LogonSamLogonWithFlags r_flags; struct netr_Authenticator auth, auth2; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; NTSTATUS expected_error; bool old_password; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */ DATA_BLOB chall; @@ -153,12 +153,12 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, switch (samlogon_state->function_level) { case NDR_NETR_LOGONSAMLOGON: ZERO_STRUCT(samlogon_state->auth2); - creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth); + netlogon_creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth); r->out.return_authenticator = NULL; status = dcerpc_netr_LogonSamLogon(samlogon_state->p, samlogon_state->mem_ctx, r); if (!r->out.return_authenticator || - !creds_client_check(samlogon_state->creds, &r->out.return_authenticator->cred)) { + !netlogon_creds_client_check(samlogon_state->creds, &r->out.return_authenticator->cred)) { d_printf("Credential chaining failed\n"); } if (!NT_STATUS_IS_OK(status)) { @@ -170,7 +170,7 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, validation_level = r->in.validation_level; - creds_decrypt_samlogon(samlogon_state->creds, validation_level, r->out.validation); + netlogon_creds_decrypt_samlogon(samlogon_state->creds, validation_level, r->out.validation); switch (validation_level) { case 2: @@ -195,7 +195,7 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, validation_level = r_ex->in.validation_level; - creds_decrypt_samlogon(samlogon_state->creds, validation_level, r_ex->out.validation); + netlogon_creds_decrypt_samlogon(samlogon_state->creds, validation_level, r_ex->out.validation); switch (validation_level) { case 2: @@ -211,12 +211,12 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, break; case NDR_NETR_LOGONSAMLOGONWITHFLAGS: ZERO_STRUCT(samlogon_state->auth2); - creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth); + netlogon_creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth); r_flags->out.return_authenticator = NULL; status = dcerpc_netr_LogonSamLogonWithFlags(samlogon_state->p, samlogon_state->mem_ctx, r_flags); if (!r_flags->out.return_authenticator || - !creds_client_check(samlogon_state->creds, &r_flags->out.return_authenticator->cred)) { + !netlogon_creds_client_check(samlogon_state->creds, &r_flags->out.return_authenticator->cred)) { d_printf("Credential chaining failed\n"); } if (!NT_STATUS_IS_OK(status)) { @@ -228,7 +228,7 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, validation_level = r_flags->in.validation_level; - creds_decrypt_samlogon(samlogon_state->creds, validation_level, r_flags->out.validation); + netlogon_creds_decrypt_samlogon(samlogon_state->creds, validation_level, r_flags->out.validation); switch (validation_level) { case 2: @@ -1314,7 +1314,7 @@ static const struct ntlm_tests { */ static bool test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct torture_context *tctx, - struct creds_CredentialState *creds, + struct netlogon_creds_CredentialState *creds, const char *comment, const char *account_domain, const char *account_name, const char *plain_pass, uint32_t parameter_control, @@ -1429,7 +1429,7 @@ static bool test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, test an ADS style interactive domain logon */ bool test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, - struct creds_CredentialState *creds, + struct netlogon_creds_CredentialState *creds, const char *comment, const char *workstation_name, const char *account_domain, const char *account_name, @@ -1454,7 +1454,7 @@ bool test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, ZERO_STRUCT(logon); ZERO_STRUCT(validation); - creds_client_authenticator(creds, &a); + netlogon_creds_client_authenticator(creds, &a); logon.password = &pinfo; @@ -1483,18 +1483,18 @@ bool test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, E_md4hash(plain_pass, pinfo.ntpassword.hash); if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { - creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16); - creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16); + netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16); + netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16); } else { - creds_des_encrypt(creds, &pinfo.lmpassword); - creds_des_encrypt(creds, &pinfo.ntpassword); + netlogon_creds_des_encrypt(creds, &pinfo.lmpassword); + netlogon_creds_des_encrypt(creds, &pinfo.ntpassword); } d_printf("Testing netr_LogonSamLogonWithFlags '%s' (Interactive Logon)\n", comment); status = dcerpc_netr_LogonSamLogonWithFlags(p, fn_ctx, &r); if (!r.out.return_authenticator - || !creds_client_check(creds, &r.out.return_authenticator->cred)) { + || !netlogon_creds_client_check(creds, &r.out.return_authenticator->cred)) { d_printf("Credential chaining failed\n"); talloc_free(fn_ctx); return false; @@ -1540,7 +1540,7 @@ bool torture_rpc_samlogon(struct torture_context *torture) 0 /* yes, this is a valid flag, causes the use of DES */ }; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; test_machine_account = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME); /* We only need to join as a workstation here, and in future, diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c index 9c867fd5e4..9483ae2a9a 100644 --- a/source4/torture/rpc/samr.c +++ b/source4/torture/rpc/samr.c @@ -2632,7 +2632,7 @@ static bool test_QueryUserInfo_pwdlastset(struct dcerpc_pipe *p, static bool test_SamLogon_Creds(struct dcerpc_pipe *p, struct torture_context *tctx, struct cli_credentials *machine_credentials, struct cli_credentials *test_credentials, - struct creds_CredentialState *creds, + struct netlogon_creds_CredentialState *creds, NTSTATUS expected_result) { NTSTATUS status; @@ -2700,7 +2700,7 @@ static bool test_SamLogon_Creds(struct dcerpc_pipe *p, struct torture_context *t d_printf("Testing LogonSamLogon with name %s\n", ninfo.identity_info.account_name.string); ZERO_STRUCT(auth2); - creds_client_authenticator(creds, &auth); + netlogon_creds_client_authenticator(creds, &auth); r.in.validation_level = 2; @@ -2712,7 +2712,7 @@ static bool test_SamLogon_Creds(struct dcerpc_pipe *p, struct torture_context *t torture_assert_ntstatus_ok(tctx, status, "LogonSamLogon failed"); } - torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), + torture_assert(tctx, netlogon_creds_client_check(creds, &r.out.return_authenticator->cred), "Credential chaining failed"); return true; @@ -2724,7 +2724,7 @@ static bool test_SamLogon(struct torture_context *tctx, struct cli_credentials *test_credentials, NTSTATUS expected_result) { - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) { return false; diff --git a/source4/torture/rpc/samsync.c b/source4/torture/rpc/samsync.c index 00798214f3..ee11ede83f 100644 --- a/source4/torture/rpc/samsync.c +++ b/source4/torture/rpc/samsync.c @@ -47,7 +47,7 @@ try a netlogon SamLogon */ static NTSTATUS test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, - struct creds_CredentialState *creds, + struct netlogon_creds_CredentialState *creds, const char *domain, const char *account_name, const char *workstation, struct samr_Password *lm_hash, @@ -100,13 +100,13 @@ static NTSTATUS test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, r.out.authoritative = &authoritative; ZERO_STRUCT(auth2); - creds_client_authenticator(creds, &auth); + netlogon_creds_client_authenticator(creds, &auth); r.in.validation_level = 3; status = dcerpc_netr_LogonSamLogon(p, mem_ctx, &r); - if (!creds_client_check(creds, &r.out.return_authenticator->cred)) { + if (!netlogon_creds_client_check(creds, &r.out.return_authenticator->cred)) { printf("Credential chaining failed\n"); } @@ -123,8 +123,8 @@ struct samsync_state { const char *domain_name[2]; struct samsync_secret *secrets; struct samsync_trusted_domain *trusted_domains; - struct creds_CredentialState *creds; - struct creds_CredentialState *creds_netlogon_wksta; + struct netlogon_creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds_netlogon_wksta; struct policy_handle *connect_handle; struct policy_handle *domain_handle[2]; struct dom_sid *sid[2]; @@ -578,7 +578,7 @@ static bool samsync_handle_user(struct torture_context *tctx, TALLOC_CTX *mem_ct enum ndr_err_code ndr_err; data.data = user->user_private_info.SensitiveData; data.length = user->user_private_info.DataLength; - creds_arcfour_crypt(samsync_state->creds, data.data, data.length); + netlogon_creds_arcfour_crypt(samsync_state->creds, data.data, data.length); ndr_err = ndr_pull_struct_blob(&data, mem_ctx, lp_iconv_convenience(tctx->lp_ctx), &keys, (ndr_pull_flags_fn_t)ndr_pull_netr_USER_KEYS); if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { if (keys.keys.keys2.lmpassword.length == 16) { @@ -843,10 +843,10 @@ static bool samsync_handle_secret(TALLOC_CTX *mem_ctx, struct samsync_state *sam DATA_BLOB lsa_blob1, lsa_blob_out, session_key; NTSTATUS status; - creds_arcfour_crypt(samsync_state->creds, secret->current_cipher.cipher_data, + netlogon_creds_arcfour_crypt(samsync_state->creds, secret->current_cipher.cipher_data, secret->current_cipher.maxlen); - creds_arcfour_crypt(samsync_state->creds, secret->old_cipher.cipher_data, + netlogon_creds_arcfour_crypt(samsync_state->creds, secret->old_cipher.cipher_data, secret->old_cipher.maxlen); nsec->name = talloc_reference(nsec, name); @@ -1182,7 +1182,7 @@ static bool test_DatabaseSync(struct torture_context *tctx, do { loop_ctx = talloc_named(mem_ctx, 0, "DatabaseSync loop context"); - creds_client_authenticator(samsync_state->creds, &credential); + netlogon_creds_client_authenticator(samsync_state->creds, &credential); r.in.credential = &credential; @@ -1194,7 +1194,7 @@ static bool test_DatabaseSync(struct torture_context *tctx, break; } - if (!creds_client_check(samsync_state->creds, &r.out.return_authenticator->cred)) { + if (!netlogon_creds_client_check(samsync_state->creds, &r.out.return_authenticator->cred)) { printf("Credential chaining failed\n"); } @@ -1395,7 +1395,7 @@ static bool test_DatabaseDeltas(struct samsync_state *samsync_state, TALLOC_CTX do { loop_ctx = talloc_named(mem_ctx, 0, "test_DatabaseDeltas loop context"); - creds_client_authenticator(samsync_state->creds, &credential); + netlogon_creds_client_authenticator(samsync_state->creds, &credential); status = dcerpc_netr_DatabaseDeltas(samsync_state->p, loop_ctx, &r); if (!NT_STATUS_IS_OK(status) && @@ -1405,7 +1405,7 @@ static bool test_DatabaseDeltas(struct samsync_state *samsync_state, TALLOC_CTX ret = false; } - if (!creds_client_check(samsync_state->creds, &return_authenticator.cred)) { + if (!netlogon_creds_client_check(samsync_state->creds, &return_authenticator.cred)) { printf("Credential chaining failed\n"); } @@ -1422,7 +1422,7 @@ static bool test_DatabaseDeltas(struct samsync_state *samsync_state, TALLOC_CTX try a netlogon DatabaseSync2 */ static bool test_DatabaseSync2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, - struct creds_CredentialState *creds) + struct netlogon_creds_CredentialState *creds) { NTSTATUS status; TALLOC_CTX *loop_ctx; @@ -1455,7 +1455,7 @@ static bool test_DatabaseSync2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, do { loop_ctx = talloc_named(mem_ctx, 0, "test_DatabaseSync2 loop context"); - creds_client_authenticator(creds, &credential); + netlogon_creds_client_authenticator(creds, &credential); r.in.credential = &credential; @@ -1466,7 +1466,7 @@ static bool test_DatabaseSync2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, ret = false; } - if (!creds_client_check(creds, &r.out.return_authenticator->cred)) { + if (!netlogon_creds_client_check(creds, &r.out.return_authenticator->cred)) { printf("Credential chaining failed\n"); } diff --git a/source4/torture/rpc/schannel.c b/source4/torture/rpc/schannel.c index bc3cbeac3b..fc0087e4d3 100644 --- a/source4/torture/rpc/schannel.c +++ b/source4/torture/rpc/schannel.c @@ -43,7 +43,7 @@ */ bool test_netlogon_ex_ops(struct dcerpc_pipe *p, struct torture_context *tctx, struct cli_credentials *credentials, - struct creds_CredentialState *creds) + struct netlogon_creds_CredentialState *creds) { NTSTATUS status; struct netr_LogonSamLogonEx r; @@ -259,7 +259,7 @@ static bool test_schannel(struct torture_context *tctx, struct dcerpc_pipe *p_netlogon3 = NULL; struct dcerpc_pipe *p_samr2 = NULL; struct dcerpc_pipe *p_lsa = NULL; - struct creds_CredentialState *creds; + struct netlogon_creds_CredentialState *creds; struct cli_credentials *credentials; join_ctx = torture_join_domain(tctx, @@ -765,7 +765,7 @@ bool torture_rpc_schannel_bench1(struct torture_context *torture) { struct netr_ServerPasswordSet pwset; char *password = generate_random_str(s->join_ctx1, 8); - struct creds_CredentialState *creds_state; + struct netlogon_creds_CredentialState *creds_state; struct dcerpc_pipe *net_pipe; struct netr_Authenticator credential, return_authenticator; struct samr_Password new_password; @@ -793,14 +793,14 @@ bool torture_rpc_schannel_bench1(struct torture_context *torture) creds_state = cli_credentials_get_netlogon_creds( s->wks_creds1); - creds_des_encrypt(creds_state, &new_password); - creds_client_authenticator(creds_state, &credential); + netlogon_creds_des_encrypt(creds_state, &new_password); + netlogon_creds_client_authenticator(creds_state, &credential); status = dcerpc_netr_ServerPasswordSet(net_pipe, torture, &pwset); torture_assert_ntstatus_ok(torture, status, "ServerPasswordSet failed"); - if (!creds_client_check(creds_state, + if (!netlogon_creds_client_check(creds_state, &pwset.out.return_authenticator->cred)) { printf("Credential chaining failed\n"); } diff --git a/source4/torture/rpc/wkssvc.c b/source4/torture/rpc/wkssvc.c index 3c34229dff..06b1d05ee4 100644 --- a/source4/torture/rpc/wkssvc.c +++ b/source4/torture/rpc/wkssvc.c @@ -1148,43 +1148,6 @@ static bool test_NetrJoinDomain(struct torture_context *tctx, return true; } -/* encode a wkssvc_PasswordBuffer for remote joining/unjoining: - * - * similar to samr_CryptPasswordEx. Different: 8byte confounder (instead of - * 16byte), confounder in front of the 516 byte buffer (instead of after that - * buffer), calling MD5Update() first with session_key and then with confounder - * (vice versa in samr) - Guenther */ - -static void encode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx, - const char *pwd, - DATA_BLOB *session_key, - struct wkssvc_PasswordBuffer *pwd_buf) -{ - uint8_t buffer[516]; - struct MD5Context ctx; - - DATA_BLOB confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16); - - int confounder_len = 8; - uint8_t confounder[8]; - - encode_pw_buffer(buffer, pwd, STR_UNICODE); - - generate_random_buffer((uint8_t *)confounder, confounder_len); - - MD5Init(&ctx); - MD5Update(&ctx, session_key->data, session_key->length); - MD5Update(&ctx, confounder, confounder_len); - MD5Final(confounded_session_key.data, &ctx); - - arcfour_crypt_blob(buffer, 516, &confounded_session_key); - - memcpy(&pwd_buf->data[0], confounder, confounder_len); - memcpy(&pwd_buf->data[8], buffer, 516); - - data_blob_free(&confounded_session_key); -} - /* * prerequisites for remotely joining an unjoined XP SP2 workstation: * - firewall needs to be disabled (or open for ncacn_np access) @@ -1202,7 +1165,7 @@ static bool test_NetrJoinDomain2(struct torture_context *tctx, const char *domain_admin_account = NULL; const char *domain_admin_password = NULL; const char *domain_name = NULL; - struct wkssvc_PasswordBuffer pwd_buf; + struct wkssvc_PasswordBuffer *pwd_buf; enum wkssvc_NetJoinStatus join_status; const char *join_name = NULL; WERROR expected_err; @@ -1253,7 +1216,7 @@ static bool test_NetrJoinDomain2(struct torture_context *tctx, r.in.domain_name = domain_name; r.in.account_ou = NULL; r.in.admin_account = domain_admin_account; - r.in.encrypted_password = &pwd_buf; + r.in.encrypted_password = pwd_buf; r.in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE | WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE; @@ -1286,7 +1249,7 @@ static bool test_NetrUnjoinDomain2(struct torture_context *tctx, struct wkssvc_NetrUnjoinDomain2 r; const char *domain_admin_account = NULL; const char *domain_admin_password = NULL; - struct wkssvc_PasswordBuffer pwd_buf; + struct wkssvc_PasswordBuffer *pwd_buf; enum wkssvc_NetJoinStatus join_status; const char *join_name = NULL; WERROR expected_err; @@ -1332,7 +1295,7 @@ static bool test_NetrUnjoinDomain2(struct torture_context *tctx, r.in.server_name = dcerpc_server_name(p); r.in.account = domain_admin_account; - r.in.encrypted_password = &pwd_buf; + r.in.encrypted_password = pwd_buf; r.in.unjoin_flags = 0; torture_comment(tctx, "testing NetrUnjoinDomain2 (assuming non-DC)\n"); diff --git a/source4/utils/ntlm_auth.c b/source4/utils/ntlm_auth.c index 2c6f353252..1c9eabe09a 100644 --- a/source4/utils/ntlm_auth.c +++ b/source4/utils/ntlm_auth.c @@ -30,7 +30,6 @@ #include "auth/auth.h" #include "librpc/gen_ndr/ndr_netlogon.h" #include "auth/auth_sam.h" -#include "auth/ntlm/ntlm_check.h" #include "libcli/auth/libcli_auth.h" #include "libcli/security/security.h" #include "lib/events/events.h" diff --git a/source4/winbind/wb_sam_logon.c b/source4/winbind/wb_sam_logon.c index 5ceb6e4af0..fa3d6032c8 100644 --- a/source4/winbind/wb_sam_logon.c +++ b/source4/winbind/wb_sam_logon.c @@ -36,7 +36,7 @@ struct wb_sam_logon_state { struct winbind_SamLogon *req; - struct creds_CredentialState *creds_state; + struct netlogon_creds_CredentialState *creds_state; struct netr_Authenticator auth1, auth2; TALLOC_CTX *r_mem_ctx; @@ -86,7 +86,7 @@ static void wb_sam_logon_recv_domain(struct composite_context *creq) if (!composite_is_ok(s->ctx)) return; s->creds_state = cli_credentials_get_netlogon_creds(domain->libnet_ctx->cred); - creds_client_authenticator(s->creds_state, &s->auth1); + netlogon_creds_client_authenticator(s->creds_state, &s->auth1); s->r.in.server_name = talloc_asprintf(s, "\\\\%s", dcerpc_server_name(domain->netlogon_pipe)); @@ -135,8 +135,8 @@ static void wb_sam_logon_recv_samlogon(struct rpc_request *req) if (!composite_is_ok(s->ctx)) return; if ((s->r.out.return_authenticator == NULL) || - (!creds_client_check(s->creds_state, - &s->r.out.return_authenticator->cred))) { + (!netlogon_creds_client_check(s->creds_state, + &s->r.out.return_authenticator->cred))) { DEBUG(0, ("Credentials check failed!\n")); composite_error(s->ctx, NT_STATUS_ACCESS_DENIED); return; @@ -145,9 +145,9 @@ static void wb_sam_logon_recv_samlogon(struct rpc_request *req) /* Decrypt the session keys before we reform the info3, so the * person on the other end of winbindd pipe doesn't have to. * They won't have the encryption key anyway */ - creds_decrypt_samlogon(s->creds_state, - s->r.in.validation_level, - s->r.out.validation); + netlogon_creds_decrypt_samlogon(s->creds_state, + s->r.in.validation_level, + s->r.out.validation); composite_done(s->ctx); } |