r3900: fix compiler warning
[samba.git] / source4 / libcli / util / smbencrypt.c
index fa29059585b7bbc1dddc09663bbdfb3f956d1f37..f0ff3ee08de4db060c2fc46aeef005777f7cf1ec 100644 (file)
@@ -23,7 +23,9 @@
 */
 
 #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
 
    Returns False if password must have been truncated to create LM hash
 */
-BOOL SMBencrypt(const char *passwd, const uchar *c8, uchar p24[24])
+BOOL SMBencrypt(const char *passwd, const uint8_t *c8, uint8_t p24[24])
 {
        BOOL ret;
-       uchar p21[21];
+       uint8_t p21[21];
 
        memset(p21,'\0',21);
        ret = E_deshash(passwd, p21); 
@@ -44,9 +46,9 @@ BOOL SMBencrypt(const char *passwd, const uchar *c8, uchar p24[24])
 
 #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;
@@ -58,18 +60,18 @@ BOOL SMBencrypt(const char *passwd, const uchar *c8, uchar p24[24])
  * @param p16 return password hashed with md4, caller allocated 16 byte buffer
  */
  
-void E_md4hash(const char *passwd, uchar p16[16])
+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, (unsigned char *)wpwd, len);
-       ZERO_STRUCT(wpwd);      
+       talloc_free(wpwd);
 }
 
 /**
@@ -80,7 +82,7 @@ void E_md4hash(const char *passwd, uchar p16[16])
  * @note p16 is filled in regardless
  */
  
-BOOL E_deshash(const char *passwd, uchar p16[16])
+BOOL E_deshash(const char *passwd, uint8_t p16[16])
 {
        BOOL ret = True;
        fstring dospwd; 
@@ -90,7 +92,7 @@ BOOL E_deshash(const char *passwd, uchar p16[16])
        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);
+       E_P16((const uint8_t *)dospwd, p16);
 
        if (strlen(dospwd) > 14) {
                ret = False;
@@ -101,66 +103,50 @@ BOOL E_deshash(const char *passwd, uchar 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, 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, 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
-}
-
 /* Does both the NTLMv2 owfs of a user's password */
-BOOL ntv2_owf_gen(const uchar owf[16],
+BOOL ntv2_owf_gen(const uint8_t owf[16],
                  const char *user_in, const char *domain_in,
                  BOOL upper_case_domain, /* Transform the domain into UPPER case */
-                 uchar kr_buf[16])
+                 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;
+               }
+       }
+
+       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;
+       }
 
-       if (upper_case_domain)
-               strupper_w(domain);
+       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);
@@ -170,27 +156,26 @@ BOOL ntv2_owf_gen(const uchar owf[16],
        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_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;
 }
 
 /* Does the des encryption from the NT or LM MD4 hash. */
-void SMBOWFencrypt(const uchar passwd[16], const uchar *c8, uchar p24[24])
+void SMBOWFencrypt(const uint8_t passwd[16], const uint8_t *c8, uint8_t p24[24])
 {
-       uchar p21[21];
+       uint8_t p21[21];
 
        ZERO_STRUCT(p21);
  
@@ -200,9 +185,9 @@ void SMBOWFencrypt(const uchar passwd[16], const uchar *c8, uchar p24[24])
 
 /* Does the NT MD4 hash then des encryption. */
  
-void SMBNTencrypt(const char *passwd, uchar *c8, uchar *p24)
+void SMBNTencrypt(const char *passwd, uint8_t *c8, uint8_t *p24)
 {
-       uchar p21[21];
+       uint8_t p21[21];
  
        memset(p21,'\0',21);
  
@@ -211,35 +196,35 @@ void SMBNTencrypt(const char *passwd, uchar *c8, uchar *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);
+       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 uchar kr[16],
+void SMBOWFencrypt_ntv2(const uint8_t kr[16],
                        const DATA_BLOB *srv_chal,
-                       const DATA_BLOB *cli_chal,
-                       uchar resp_buf[16])
+                       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
 }
 
-void SMBsesskeygen_ntv2(const uchar kr[16],
-                       const uchar * nt_resp, uint8 sess_key[16])
+void SMBsesskeygen_ntv2(const uint8_t kr[16],
+                       const uint8_t * nt_resp, uint8_t sess_key[16])
 {
        /* a very nice, 128 bit, variable session key */
        
@@ -247,7 +232,7 @@ void SMBsesskeygen_ntv2(const uchar kr[16],
 
        hmac_md5_init_limK_to_64(kr, 16, &ctx);
        hmac_md5_update(nt_resp, 16, &ctx);
-       hmac_md5_final((unsigned char *)sess_key, &ctx);
+       hmac_md5_final((uint8_t *)sess_key, &ctx);
 
 #ifdef DEBUG_PASSWORD
        DEBUG(100, ("SMBsesskeygen_ntv2:\n"));
@@ -255,12 +240,12 @@ void SMBsesskeygen_ntv2(const uchar kr[16],
 #endif
 }
 
-void SMBsesskeygen_ntv1(const uchar kr[16], uint8 sess_key[16])
+void SMBsesskeygen_ntv1(const uint8_t kr[16], uint8_t 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);
+       mdfour((uint8_t *)sess_key, kr, 16);
 
 #ifdef DEBUG_PASSWORD
        DEBUG(100, ("SMBsesskeygen_ntv1:\n"));
@@ -268,14 +253,14 @@ void SMBsesskeygen_ntv1(const uchar kr[16], uint8 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])
+void SMBsesskeygen_lm_sess_key(const uint8_t lm_hash[16],
+                              const uint8_t lm_resp[24], /* only uses 8 */ 
+                              uint8_t sess_key[16])
 {
        /* Calculate the LM session key (effective length 40 bits,
           but changes with each session) */
-       uchar p24[24];
-       uchar p21[21];
+       uint8_t p24[24];
+       uint8_t p21[21];
  
        memset(p21,'\0',21);
        memcpy(p21, lm_hash, 8);    
@@ -306,14 +291,14 @@ DATA_BLOB NTLMv2_generate_names_blob(TALLOC_CTX *mem_ctx,
 
 static DATA_BLOB NTLMv2_generate_client_data(TALLOC_CTX *mem_ctx, const DATA_BLOB *names_blob) 
 {
-       uchar client_chal[8];
+       uint8_t client_chal[8];
        DATA_BLOB response = data_blob(NULL, 0);
        char long_date[8];
        NTTIME nttime;
 
        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);
 
@@ -330,11 +315,11 @@ static DATA_BLOB NTLMv2_generate_client_data(TALLOC_CTX *mem_ctx, const DATA_BLO
        return response;
 }
 
-static DATA_BLOB NTLMv2_generate_response(const uchar ntlm_v2_hash[16],
+static DATA_BLOB NTLMv2_generate_response(const uint8_t ntlm_v2_hash[16],
                                          const DATA_BLOB *server_chal,
                                          const DATA_BLOB *names_blob)
 {
-       uchar ntlmv2_response[16];
+       uint8_t ntlmv2_response[16];
        DATA_BLOB ntlmv2_client_data;
        DATA_BLOB final_response;
        
@@ -364,16 +349,16 @@ static DATA_BLOB NTLMv2_generate_response(const uchar ntlm_v2_hash[16],
        return final_response;
 }
 
-static DATA_BLOB LMv2_generate_response(const uchar ntlm_v2_hash[16],
+static DATA_BLOB LMv2_generate_response(const uint8_t ntlm_v2_hash[16],
                                        const DATA_BLOB *server_chal)
 {
-       uchar lmv2_response[16];
+       uint8_t 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, 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);
@@ -389,15 +374,13 @@ static DATA_BLOB LMv2_generate_response(const uchar ntlm_v2_hash[16],
        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) 
 {
-       uchar nt_hash[16];
-       uchar ntlm_v2_hash[16];
-       E_md4hash(password, nt_hash);
+       uint8_t ntlm_v2_hash[16];
 
        /* We don't use the NT# directly.  Instead we use it mashed up with
           the username and domain.
@@ -423,27 +406,47 @@ BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password
        
        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)
 {
-       uchar new_pw[512];
+       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((unsigned char *)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
@@ -489,7 +492,7 @@ BOOL decode_pw_buffer(char in_buffer[516], char *new_pwrd,
        }
 
        /* 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