#include "includes.h"
#include "byteorder.h"
BOOL SMBencrypt(const char *passwd, const uchar *c8, uchar p24[24])
{
BOOL ret;
uchar p21[21];
memset(p21,'\0',21);
ret = E_deshash(passwd, p21);
SMBOWFencrypt(p21, c8, p24);
#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);
#endif
return ret;
}
void E_md4hash(const char *passwd, uchar p16[16])
{
int len;
smb_ucs2_t wpwd[129];
push_ucs2(NULL, wpwd, (const char *)passwd, 256, STR_UNICODE|STR_NOALIGN|STR_TERMINATE);
len = strlen_w(wpwd) * sizeof(int16);
mdfour(p16, (unsigned char *)wpwd, len);
ZERO_STRUCT(wpwd);
}
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);
}
BOOL E_deshash(const char *passwd, uchar p16[16])
{
BOOL ret = True;
fstring dospwd;
ZERO_STRUCT(dospwd);
push_ascii(dospwd, passwd, sizeof(dospwd), STR_UPPER|STR_TERMINATE);
E_P16((const unsigned char *)dospwd, p16);
if (strlen(dospwd) > 14) {
ret = False;
}
ZERO_STRUCT(dospwd);
return ret;
}
void nt_lm_owf_gen(const char *pwd, uchar nt_p16[16], uchar p16[16])
{
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, pwd, strlen(pwd));
dump_data(100, (char *)nt_p16, 16);
#endif
E_deshash(pwd, (uchar *)p16);
#ifdef DEBUG_PASSWORD
DEBUG(100,("nt_lm_owf_gen: pwd, lm#\n"));
dump_data(120, pwd, strlen(pwd));
dump_data(100, (char *)p16, 16);
#endif
}
BOOL ntv2_owf_gen(const uchar owf[16],
const char *user_in, const char *domain_in,
BOOL upper_case_domain,
uchar kr_buf[16])
{
smb_ucs2_t *user;
smb_ucs2_t *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"));
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"));
return False;
}
strupper_w(user);
if (upper_case_domain)
strupper_w(domain);
SMB_ASSERT(user_byte_len >= 2);
SMB_ASSERT(domain_byte_len >= 2);
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, (const char *)user, user_byte_len);
dump_data(100, (const char *)domain, domain_byte_len);
dump_data(100, owf, 16);
dump_data(100, kr_buf, 16);
#endif
SAFE_FREE(user);
SAFE_FREE(domain);
return True;
}
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);
}
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, (char *)p21, 21);
dump_data(100, (const char *)ntlmchalresp, 8);
dump_data(100, (char *)p24, 24);
#endif
}
void SMBNTencrypt(const char *passwd, uchar *c8, uchar *p24)
{
uchar p21[21];
memset(p21,'\0',21);
E_md4hash(passwd, p21);
SMBOWFencrypt(p21, c8, p24);
#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);
#endif
}
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])
{
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])
{
mdfour((unsigned char *)sess_key, kr, 16);
#ifdef DEBUG_PASSWORD
DEBUG(100, ("SMBsesskeygen_ntv1:\n"));
dump_data(100, sess_key, 16);
#endif
}
void SMBsesskeygen_lmv1(const uchar lm_hash[16],
const uchar lm_resp[24],
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(lm_hash, lm_resp, p24);
memcpy(sess_key, p24, 16);
sess_key[5] = 0xe5;
sess_key[6] = 0x38;
sess_key[7] = 0xb0;
#ifdef DEBUG_PASSWORD
DEBUG(100, ("SMBsesskeygen_lmv1:\n"));
dump_data(100, sess_key, 16);
#endif
}
void SMBsesskeygen_lm_sess_key(const uchar lm_hash[16],
const uchar lm_resp[24],
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, 0);
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, 0);
char long_date[8];
generate_random_buffer(client_chal, sizeof(client_chal));
put_long_date(long_date, time(NULL));
msrpc_gen(&response, "ddbbdb",
0x00000101,
0,
long_date, 8,
client_chal, 8,
0,
names_blob->data, names_blob->length);
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_client_data = NTLMv2_generate_client_data(names_blob);
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);
generate_random_buffer(lmv2_client_data.data, lmv2_client_data.length);
SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, &lmv2_client_data, lmv2_response);
memcpy(final_response.data, lmv2_response, sizeof(lmv2_response));
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(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];
uchar ntlm_v2_hash[16];
E_md4hash(password, nt_hash);
if (!ntv2_owf_gen(nt_hash, user, domain, True, 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);
SMBsesskeygen_ntv2(ntlm_v2_hash, nt_response->data, user_session_key->data);
}
}
if (lm_response) {
*lm_response = LMv2_generate_response(ntlm_v2_hash, server_chal);
}
return True;
}
BOOL encode_pw_buffer(char buffer[516], const char *password, int string_flags)
{
uchar new_pw[512];
size_t new_pw_len;
new_pw_len = push_string(NULL, new_pw,
password,
sizeof(new_pw), string_flags);
memcpy(&buffer[512 - new_pw_len], new_pw, new_pw_len);
generate_random_buffer((unsigned char *)buffer, 512 - new_pw_len);
SIVAL(buffer, 512, new_pw_len);
ZERO_STRUCT(new_pw);
return True;
}
BOOL decode_pw_buffer(char in_buffer[516], char *new_pwrd,
int new_pwrd_size, uint32 *new_pw_len,
int string_flags)
{
int byte_len=0;
byte_len = IVAL(in_buffer, 512);
#ifdef DEBUG_PASSWORD
dump_data(100, in_buffer, 516);
#endif
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;
}
*new_pw_len = pull_string(NULL, new_pwrd, &in_buffer[512 - byte_len], new_pwrd_size,
byte_len, string_flags);
#ifdef DEBUG_PASSWORD
DEBUG(100,("decode_pw_buffer: new_pwrd: "));
dump_data(100, (char *)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;
}