Fix failures setting a random password
[kai/samba.git] / source4 / libcli / auth / smbencrypt.c
index 1f940fb79d1453be518b4415dbb2e21be8c72a98..bbb363e0dd42019f42b8c5f0fba2d476a3f47200 100644 (file)
 #include "system/time.h"
 #include "auth/ntlmssp/ntlmssp.h"
 #include "auth/ntlmssp/msrpc_parse.h"
-#include "lib/crypto/crypto.h"
+#include "../lib/crypto/crypto.h"
 #include "libcli/auth/libcli_auth.h"
-#include "pstring.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
+   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 SMBencrypt(const char *passwd, const uint8_t *c8, uint8_t p24[24])
 {
-       BOOL ret;
+       bool ret;
        uint8_t p21[21];
 
        memset(p21,'\0',21);
@@ -62,7 +61,7 @@ BOOL SMBencrypt(const char *passwd, const uint8_t *c8, uint8_t p24[24])
  * @param p16 return password hashed with md4, caller allocated 16 byte buffer
  */
  
-_PUBLIC_ BOOL E_md4hash(const char *passwd, uint8_t p16[16])
+bool E_md4hash(const char *passwd, uint8_t p16[16])
 {
        int len;
        void *wpwd;
@@ -72,38 +71,38 @@ _PUBLIC_ BOOL E_md4hash(const char *passwd, uint8_t p16[16])
                /* We don't want to return fixed data, as most callers
                 * don't check */
                mdfour(p16, (const uint8_t *)passwd, strlen(passwd));
-               return False;
+               return false;
        }
        
        len -= 2;
        mdfour(p16, wpwd, len);
 
        talloc_free(wpwd);
-       return True;
+       return true;
 }
 
 /**
  * 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
+ * @return false if password was > 14 characters, and therefore may be incorrect, otherwise true
  * @note p16 is filled in regardless
  */
  
-_PUBLIC_ BOOL E_deshash(const char *passwd, uint8_t p16[16])
+bool E_deshash(const char *passwd, uint8_t p16[16])
 {
-       BOOL ret = True;
-       fstring dospwd; 
+       bool ret = true;
+       char dospwd[256];
        ZERO_STRUCT(dospwd);
 
        /* Password must be converted to DOS charset - null terminated, uppercase. */
        push_string(dospwd, passwd, sizeof(dospwd), STR_ASCII|STR_UPPER|STR_TERMINATE);
 
-       /* Only the fisrt 14 chars are considered, password need not be null terminated. */
+       /* Only the first 14 chars are considered, password need not be null terminated. */
        E_P16((const uint8_t *)dospwd, p16);
 
        if (strlen(dospwd) > 14) {
-               ret = False;
+               ret = false;
        }
 
        ZERO_STRUCT(dospwd);    
@@ -112,9 +111,9 @@ _PUBLIC_ BOOL E_deshash(const char *passwd, uint8_t p16[16])
 }
 
 /* Does both the NTLMv2 owfs of a user's password */
-BOOL ntv2_owf_gen(const uint8_t 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 */
+                 bool upper_case_domain, /* Transform the domain into UPPER case */
                  uint8_t kr_buf[16])
 {
        void *user;
@@ -124,8 +123,9 @@ BOOL ntv2_owf_gen(const uint8_t owf[16],
 
        HMACMD5Context ctx;
        TALLOC_CTX *mem_ctx = talloc_init("ntv2_owf_gen for %s\\%s", domain_in, user_in); 
+
        if (!mem_ctx) {
-               return False;
+               return false;
        }
 
        if (!user_in) {
@@ -139,14 +139,14 @@ BOOL ntv2_owf_gen(const uint8_t owf[16],
        user_in = strupper_talloc(mem_ctx, user_in);
        if (user_in == NULL) {
                talloc_free(mem_ctx);
-               return False;
+               return false;
        }
 
        if (upper_case_domain) {
                domain_in = strupper_talloc(mem_ctx, domain_in);
                if (domain_in == NULL) {
                        talloc_free(mem_ctx);
-                       return False;
+                       return false;
                }
        }
 
@@ -154,14 +154,14 @@ BOOL ntv2_owf_gen(const uint8_t owf[16],
        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;
+               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;
+               return false;
        }
 
        SMB_ASSERT(user_byte_len >= 2);
@@ -185,7 +185,7 @@ BOOL ntv2_owf_gen(const uint8_t owf[16],
 #endif
 
        talloc_free(mem_ctx);
-       return True;
+       return true;
 }
 
 /* Does the des encryption from the NT or LM MD4 hash. */
@@ -298,7 +298,8 @@ DATA_BLOB NTLMv2_generate_names_blob(TALLOC_CTX *mem_ctx,
 {
        DATA_BLOB names_blob = data_blob_talloc(mem_ctx, NULL, 0);
        
-       msrpc_gen(mem_ctx, &names_blob, "aaa", 
+       msrpc_gen(mem_ctx, &names_blob, 
+                 "aaa", 
                  NTLMSSP_NAME_TYPE_DOMAIN, domain,
                  NTLMSSP_NAME_TYPE_SERVER, hostname,
                  0, "");
@@ -393,7 +394,7 @@ static DATA_BLOB LMv2_generate_response(TALLOC_CTX *mem_ctx,
        return final_response;
 }
 
-BOOL SMBNTLMv2encrypt_hash(TALLOC_CTX *mem_ctx, 
+bool SMBNTLMv2encrypt_hash(TALLOC_CTX *mem_ctx, 
                           const char *user, const char *domain, const uint8_t nt_hash[16],
                           const DATA_BLOB *server_chal, 
                           const DATA_BLOB *names_blob,
@@ -406,8 +407,8 @@ BOOL SMBNTLMv2encrypt_hash(TALLOC_CTX *mem_ctx,
           the username and domain.
           This prevents username swapping during the auth exchange
        */
-       if (!ntv2_owf_gen(nt_hash, user, domain, True, ntlm_v2_hash)) {
-               return False;
+       if (!ntv2_owf_gen(nt_hash, user, domain, true, ntlm_v2_hash)) {
+               return false;
        }
        
        if (nt_response) {
@@ -437,10 +438,10 @@ BOOL SMBNTLMv2encrypt_hash(TALLOC_CTX *mem_ctx,
                }
        }
        
-       return True;
+       return true;
 }
 
-BOOL SMBNTLMv2encrypt(TALLOC_CTX *mem_ctx, 
+bool SMBNTLMv2encrypt(TALLOC_CTX *mem_ctx, 
                      const char *user, const char *domain, 
                      const char *password, 
                      const DATA_BLOB *server_chal, 
@@ -460,7 +461,7 @@ BOOL SMBNTLMv2encrypt(TALLOC_CTX *mem_ctx,
  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_t 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;
@@ -482,7 +483,7 @@ BOOL encode_pw_buffer(uint8_t buffer[516], const char *password, int string_flag
         */
        SIVAL(buffer, 512, new_pw_len);
        ZERO_STRUCT(new_pw);
-       return True;
+       return true;
 }
 
 
@@ -491,11 +492,11 @@ 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, uint32_t *new_pw_len,
-                     int string_flags)
+bool decode_pw_buffer(uint8_t in_buffer[516], char *new_pwrd,
+                     int new_pwrd_size, int string_flags)
 {
        int byte_len=0;
+       ssize_t converted_pw_len;
 
        /* the incoming buffer can be any alignment. */
        string_flags |= STR_NOALIGN;
@@ -517,19 +518,76 @@ 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)) {
-               return False;
+               return false;
        }
 
        /* decode into the return buffer.  Buffer length supplied */
-       *new_pw_len = pull_string(new_pwrd, &in_buffer[512 - byte_len], new_pwrd_size, 
+       converted_pw_len = pull_string(new_pwrd, &in_buffer[512 - byte_len], new_pwrd_size, 
                                  byte_len, string_flags);
 
+       if (converted_pw_len == -1) {
+               return false;
+       }
+
 #ifdef DEBUG_PASSWORD
        DEBUG(100,("decode_pw_buffer: new_pwrd: "));
-       dump_data(100, (const uint8_t *)new_pwrd, *new_pw_len);
-       DEBUG(100,("multibyte len:%d\n", *new_pw_len));
+       dump_data(100, (const uint8_t *)new_pwrd, converted_pw_len);
+       DEBUG(100,("multibyte len:%d\n", (int)converted_pw_len));
        DEBUG(100,("original char len:%d\n", byte_len/2));
 #endif
        
-       return True;
+       return true;
+}
+
+/***********************************************************
+ 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.
+************************************************************/
+bool set_pw_in_buffer(uint8_t buffer[516], DATA_BLOB *password)
+{
+       if (password->length > 512) {
+               return false;
+       }
+
+       memcpy(&buffer[512 - password->length], password->data, password->length);
+
+       generate_random_buffer(buffer, 512 - password->length);
+
+       /* 
+        * The length of the new password is in the last 4 bytes of
+        * the data buffer.
+        */
+       SIVAL(buffer, 512, password->length);
+       return true;
+}
+
+/***********************************************************
+ decode a password buffer
+ *new_pw_size is the length in bytes of the extracted unicode password
+************************************************************/
+bool extract_pw_from_buffer(TALLOC_CTX *mem_ctx, 
+                           uint8_t in_buffer[516], DATA_BLOB *new_pass)
+{
+       int byte_len=0;
+
+       /* 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)) {
+               return false;
+       }
+
+       *new_pass = data_blob_talloc(mem_ctx, &in_buffer[512 - byte_len], byte_len);
+
+       if (!new_pass->data) {
+               return false;
+       }
+
+       return true;
 }