*/
#include "includes.h"
-#include "byteorder.h"
+#include "system/time.h"
+#include "auth/auth.h"
+#include "lib/crypto/crypto.h"
/*
This implements the X/Open SMB password encryption
#ifdef DEBUG_PASSWORD
DEBUG(100,("SMBencrypt: lm#, challenge, response\n"));
- dump_data(100, (char *)p21, 16);
- dump_data(100, (const char *)c8, 8);
- dump_data(100, (char *)p24, 24);
+ dump_data(100, p21, 16);
+ dump_data(100, c8, 8);
+ dump_data(100, p24, 24);
#endif
return ret;
void E_md4hash(const char *passwd, uint8_t p16[16])
{
int len;
- smb_ucs2_t wpwd[129];
+ void *wpwd;
+
+ len = push_ucs2_talloc(NULL, &wpwd, passwd);
+ SMB_ASSERT(len >= 2);
- /* 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_t);
+ len -= 2;
+ mdfour(p16, wpwd, len);
- mdfour(p16, (uint8_t *)wpwd, len);
- ZERO_STRUCT(wpwd);
+ talloc_free(wpwd);
}
/**
BOOL upper_case_domain, /* Transform the domain into UPPER case */
uint8_t kr_buf[16])
{
- smb_ucs2_t *user;
- smb_ucs2_t *domain;
-
+ void *user;
+ void *domain;
size_t user_byte_len;
size_t domain_byte_len;
HMACMD5Context ctx;
-
- user_byte_len = push_ucs2_allocate(&user, user_in);
- if (user_byte_len == (size_t)-1) {
- DEBUG(0, ("push_uss2_allocate() for user returned -1 (probably malloc() failure)\n"));
+ TALLOC_CTX *mem_ctx = talloc_init("ntv2_owf_gen for %s\\%s", domain_in, user_in);
+ if (!mem_ctx) {
return False;
}
- domain_byte_len = push_ucs2_allocate(&domain, domain_in);
- if (domain_byte_len == (size_t)-1) {
- DEBUG(0, ("push_uss2_allocate() for domain returned -1 (probably malloc() failure)\n"));
+ user_in = strupper_talloc(mem_ctx, user_in);
+ if (user_in == NULL) {
+ talloc_free(mem_ctx);
return False;
}
- strupper_w(user);
+ if (upper_case_domain) {
+ domain_in = strupper_talloc(mem_ctx, domain_in);
+ if (domain_in == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+ }
- if (upper_case_domain)
- strupper_w(domain);
+ user_byte_len = push_ucs2_talloc(mem_ctx, &user, user_in);
+ if (user_byte_len == (ssize_t)-1) {
+ DEBUG(0, ("push_uss2_talloc() for user returned -1 (probably talloc() failure)\n"));
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ domain_byte_len = push_ucs2_talloc(mem_ctx, &domain, domain_in);
+ if (domain_byte_len == (ssize_t)-1) {
+ DEBUG(0, ("push_ucs2_talloc() for domain returned -1 (probably talloc() failure)\n"));
+ talloc_free(mem_ctx);
+ return False;
+ }
SMB_ASSERT(user_byte_len >= 2);
SMB_ASSERT(domain_byte_len >= 2);
domain_byte_len = domain_byte_len - 2;
hmac_md5_init_limK_to_64(owf, 16, &ctx);
- hmac_md5_update((const uint8_t *)user, user_byte_len, &ctx);
- hmac_md5_update((const uint8_t *)domain, domain_byte_len, &ctx);
+ hmac_md5_update(user, user_byte_len, &ctx);
+ hmac_md5_update(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, (const char *)user, user_byte_len);
- dump_data(100, (const char *)domain, domain_byte_len);
+ dump_data(100, user, user_byte_len);
+ dump_data(100, domain, domain_byte_len);
dump_data(100, owf, 16);
dump_data(100, kr_buf, 16);
#endif
- SAFE_FREE(user);
- SAFE_FREE(domain);
+ talloc_free(mem_ctx);
return True;
}
#ifdef DEBUG_PASSWORD
DEBUG(100,("SMBNTencrypt: nt#, challenge, response\n"));
- dump_data(100, (char *)p21, 16);
- dump_data(100, (char *)c8, 8);
- dump_data(100, (char *)p24, 24);
+ dump_data(100, p21, 16);
+ dump_data(100, c8, 8);
+ dump_data(100, p24, 24);
#endif
}
/* Does the md5 encryption from the Key Response for NTLMv2. */
void SMBOWFencrypt_ntv2(const uint8_t kr[16],
const DATA_BLOB *srv_chal,
- const DATA_BLOB *cli_chal,
+ const DATA_BLOB *smbcli_chal,
uint8_t 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_update(smbcli_chal->data, smbcli_chal->length, &ctx);
hmac_md5_final(resp_buf, &ctx);
#ifdef DEBUG_PASSWORD
- DEBUG(100, ("SMBOWFencrypt_ntv2: srv_chal, cli_chal, resp_buf\n"));
+ DEBUG(100, ("SMBOWFencrypt_ntv2: srv_chal, smbcli_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, smbcli_chal->data, smbcli_chal->length);
dump_data(100, resp_buf, 16);
#endif
}
unix_to_nt_time(&nttime, time(NULL));
- generate_random_buffer(client_chal, sizeof(client_chal), False);
+ generate_random_buffer(client_chal, sizeof(client_chal));
push_nttime(long_date, 0, nttime);
/* LMv2 */
/* client-supplied random data */
- generate_random_buffer(lmv2_client_data.data, lmv2_client_data.length, False);
+ 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);
return final_response;
}
-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 SMBNTLMv2encrypt_hash(const char *user, const char *domain, const uint8_t nt_hash[16],
+ const DATA_BLOB *server_chal,
+ const DATA_BLOB *names_blob,
+ DATA_BLOB *lm_response, DATA_BLOB *nt_response,
+ DATA_BLOB *lm_session_key, DATA_BLOB *user_session_key)
{
- uint8_t nt_hash[16];
uint8_t ntlm_v2_hash[16];
- E_md4hash(password, nt_hash);
/* We don't use the NT# directly. Instead we use it mashed up with
the username and domain.
if (lm_response) {
*lm_response = LMv2_generate_response(ntlm_v2_hash, server_chal);
+ if (lm_session_key) {
+ *lm_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 lm_response for session key */
+ SMBsesskeygen_ntv2(ntlm_v2_hash, lm_response->data, lm_session_key->data);
+ }
}
return True;
}
+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 *lm_session_key, DATA_BLOB *user_session_key)
+{
+ uint8_t nt_hash[16];
+ E_md4hash(password, nt_hash);
+
+ return SMBNTLMv2encrypt_hash(user, domain, nt_hash, server_chal, names_blob,
+ lm_response, nt_response, lm_session_key, 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(char buffer[516], const char *password, int string_flags)
+BOOL encode_pw_buffer(uint8_t buffer[516], const char *password, int string_flags)
{
uint8_t new_pw[512];
size_t new_pw_len;
- new_pw_len = push_string(NULL, new_pw,
+ new_pw_len = push_string(new_pw,
password,
sizeof(new_pw), string_flags);
memcpy(&buffer[512 - new_pw_len], new_pw, new_pw_len);
- generate_random_buffer((uint8_t *)buffer, 512 - new_pw_len, False);
+ generate_random_buffer(buffer, 512 - new_pw_len);
/*
* The length of the new password is in the last 4 bytes of
}
/* decode into the return buffer. Buffer length supplied */
- *new_pw_len = pull_string(NULL, new_pwrd, &in_buffer[512 - byte_len], new_pwrd_size,
+ *new_pw_len = pull_string(new_pwrd, &in_buffer[512 - byte_len], new_pwrd_size,
byte_len, string_flags);
#ifdef DEBUG_PASSWORD