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 */
-void SMBencrypt(const uchar *passwd, const uchar *c8, uchar *p24)
+void SMBencrypt(const char *passwd, const uchar *c8, uchar p24[24])
{
uchar p21[21];
}
/**
- * Creates the MD4 Hash of the users password in NT UNICODE.
+ * 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 md4, caller allocated 16 byte buffer
+ * @param p16 return password hashed with DES, caller allocated 16 byte buffer
*/
void E_deshash(const char *passwd, uchar p16[16])
ZERO_STRUCT(dospwd);
ZERO_STRUCTP(p16);
- /* Password must be converted to DOS charset - null terminated. */
+ /* Password must be converted to DOS charset - null terminated, uppercase. */
push_ascii(dospwd, (const char *)passwd, sizeof(dospwd), STR_UPPER|STR_TERMINATE);
E_P16(dospwd, p16);
}
/* Does both the NTLMv2 owfs of a user's password */
-void ntv2_owf_gen(const uchar owf[16],
- const char *user_n, const char *domain_n, uchar kr_buf[16])
+BOOL ntv2_owf_gen(const uchar owf[16],
+ const char *user_in, const char *domain_in, uchar kr_buf[16])
{
- pstring user_u;
- pstring dom_u;
+ smb_ucs2_t *user;
+ smb_ucs2_t *domain;
+
+ int user_byte_len;
+ int domain_byte_len;
+
HMACMD5Context ctx;
- int user_l = strlen(user_n);
- int domain_l = strlen(domain_n);
+ user_byte_len = push_ucs2_allocate(&user, user_in);
+ if (user_byte_len < 0) {
+ DEBUG(0, ("push_uss2_allocate() for user returned %d (probably malloc() failure)\n", user_byte_len));
+ return False;
+ }
+
+ domain_byte_len = push_ucs2_allocate(&domain, domain_in);
+ if (domain_byte_len < 0) {
+ DEBUG(0, ("push_uss2_allocate() for domain returned %d (probably malloc() failure)\n", user_byte_len));
+ return False;
+ }
- push_ucs2(NULL, user_u, user_n, (user_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
- push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
+ strupper_w(user);
+ strupper_w(domain);
+
+ /* We don't want null termination */
+ user_byte_len = user_byte_len - 2;
+ domain_byte_len = domain_byte_len - 2;
+
+ SMB_ASSERT(user_byte_len >= 0);
+ SMB_ASSERT(domain_byte_len >= 0);
hmac_md5_init_limK_to_64(owf, 16, &ctx);
- hmac_md5_update((const unsigned char *)user_u, user_l * 2, &ctx);
- hmac_md5_update((const unsigned char *)dom_u, domain_l * 2, &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, user_u, user_l * 2);
- dump_data(100, dom_u, domain_l * 2);
+ 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;
}
/* 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];
-
- memset(p21,'\0',21);
+
+ ZERO_STRUCT(p21);
memcpy(p21, passwd, 16);
E_P24(p21, c8, p24);
/* Does the NT MD4 hash then des encryption. */
-void SMBNTencrypt(const uchar *passwd, uchar *c8, uchar *p24)
+void SMBNTencrypt(const char *passwd, uchar *c8, uchar *p24)
{
uchar p21[21];
void SMBOWFencrypt_ntv2(const uchar kr[16],
const DATA_BLOB srv_chal,
const DATA_BLOB cli_chal,
- char resp_buf[16])
+ 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((unsigned char *)resp_buf, &ctx);
+ hmac_md5_final(resp_buf, &ctx);
#ifdef DEBUG_PASSWORD
DEBUG(100, ("SMBOWFencrypt_ntv2: srv_chal, cli_chal, resp_buf\n"));
#endif
return True;
+}
+/***********************************************************
+ SMB signing - setup the MAC key.
+************************************************************/
+
+void cli_calculate_mac_key(struct cli_state *cli, const char *ntpasswd, const uchar resp[24])
+{
+ /* Get first 16 bytes. */
+ E_md4hash(ntpasswd,&cli->sign_info.mac_key[0]);
+ memcpy(&cli->sign_info.mac_key[16],resp,24);
+ cli->sign_info.mac_key_len = 40;
+ cli->sign_info.use_smb_signing = True;
+
+ /* These calls are INCONPATIBLE with SMB signing */
+ cli->readbraw_supported = False;
+ cli->writebraw_supported = False;
+
+ /* Reset the sequence number in case we had a previous (aborted) attempt */
+ cli->sign_info.send_seq_num = 0;
+}
+
+/***********************************************************
+ SMB signing - calculate a MAC to send.
+************************************************************/
+
+void cli_caclulate_sign_mac(struct cli_state *cli)
+{
+ unsigned char calc_md5_mac[16];
+ struct MD5Context md5_ctx;
+
+ if (cli->sign_info.temp_smb_signing) {
+ memcpy(&cli->outbuf[smb_ss_field], "SignRequest", 8);
+ cli->sign_info.temp_smb_signing = False;
+ return;
+ }
+
+ if (!cli->sign_info.use_smb_signing) {
+ return;
+ }
+
+ /*
+ * Firstly put the sequence number into the first 4 bytes.
+ * and zero out the next 4 bytes.
+ */
+ SIVAL(cli->outbuf, smb_ss_field, cli->sign_info.send_seq_num);
+ SIVAL(cli->outbuf, smb_ss_field + 4, 0);
+
+ /* Calculate the 16 byte MAC and place first 8 bytes into the field. */
+ MD5Init(&md5_ctx);
+ MD5Update(&md5_ctx, cli->sign_info.mac_key, cli->sign_info.mac_key_len);
+ MD5Update(&md5_ctx, cli->outbuf + 4, smb_len(cli->outbuf));
+ MD5Final(calc_md5_mac, &md5_ctx);
+
+ memcpy(&cli->outbuf[smb_ss_field], calc_md5_mac, 8);
+/* cli->outbuf[smb_ss_field+2]=0;
+ Uncomment this to test if the remote server actually verifies signitures...*/
+ cli->sign_info.send_seq_num++;
+ cli->sign_info.reply_seq_num = cli->sign_info.send_seq_num;
+ cli->sign_info.send_seq_num++;
}