summaryrefslogtreecommitdiff
path: root/source3/libsmb/smbencrypt.c
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2004-01-26 08:45:02 +0000
committerAndrew Bartlett <abartlet@samba.org>2004-01-26 08:45:02 +0000
commit784b05c4895fa8d7f5215d4444bc74e91a918114 (patch)
treed5de5096447ed8b44e8605fbf35090729bd25e13 /source3/libsmb/smbencrypt.c
parent8be4584979e0ad5ae4b4da59c032b462eebf9021 (diff)
downloadsamba-784b05c4895fa8d7f5215d4444bc74e91a918114.tar.gz
samba-784b05c4895fa8d7f5215d4444bc74e91a918114.tar.bz2
samba-784b05c4895fa8d7f5215d4444bc74e91a918114.zip
This adds client-side support for the unicode/SAMR password change scheme.
As well as avoiding DOS charset issues, this scheme returns useful error codes, that we can map back via the pam interface. This patch also cleans up the interfaces used for password buffers, to avoid duplication of code. Andrew Bartlett (This used to be commit 2a2b1f0c872d154fbcce71a250e23dfad085ba1e)
Diffstat (limited to 'source3/libsmb/smbencrypt.c')
-rw-r--r--source3/libsmb/smbencrypt.c68
1 files changed, 35 insertions, 33 deletions
diff --git a/source3/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c
index cfcc24a1df..1d192b816a 100644
--- a/source3/libsmb/smbencrypt.c
+++ b/source3/libsmb/smbencrypt.c
@@ -70,20 +70,29 @@ void E_md4hash(const char *passwd, uchar p16[16])
* 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
+ * @note p16 is filled in regardless
*/
-void E_deshash(const char *passwd, uchar p16[16])
+BOOL E_deshash(const char *passwd, uchar p16[16])
{
+ BOOL ret = True;
fstring dospwd;
ZERO_STRUCT(dospwd);
/* Password must be converted to DOS charset - null terminated, uppercase. */
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);
+ if (strlen(dospwd) > 14) {
+ ret = False;
+ }
+
ZERO_STRUCT(dospwd);
+
+ return ret;
}
/**
@@ -219,24 +228,7 @@ void SMBNTencrypt(const char *passwd, uchar *c8, uchar *p24)
BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[16], BOOL unicode)
{
- int new_pw_len = strlen(passwd) * (unicode ? 2 : 1);
-
- if (new_pw_len > 512)
- {
- DEBUG(0,("make_oem_passwd_hash: new password is too long.\n"));
- return False;
- }
-
- /*
- * Now setup the data area.
- * We need to generate a random fill
- * for this area to make it harder to
- * decrypt. JRA.
- */
- generate_random_buffer((unsigned char *)data, 516, False);
- push_string(NULL, &data[512 - new_pw_len], passwd, new_pw_len,
- STR_NOALIGN | (unicode?STR_UNICODE:STR_ASCII));
- SIVAL(data, 512, new_pw_len);
+ encode_pw_buffer(data, passwd, (unicode?STR_UNICODE:STR_ASCII));
#ifdef DEBUG_PASSWORD
DEBUG(100,("make_oem_passwd_hash\n"));
@@ -473,37 +465,46 @@ BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password
}
/***********************************************************
- encode a password buffer. The caller gets to figure out
- what to put in it.
+ 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], char *new_pw, int new_pw_length)
+BOOL encode_pw_buffer(char buffer[516], const char *password, int string_flags)
{
- generate_random_buffer((unsigned char *)buffer, 516, True);
+ uchar new_pw[512];
+ size_t new_pw_len;
- memcpy(&buffer[512 - new_pw_length], new_pw, new_pw_length);
+ 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, True);
/*
* The length of the new password is in the last 4 bytes of
* the data buffer.
*/
- SIVAL(buffer, 512, new_pw_length);
-
+ SIVAL(buffer, 512, new_pw_len);
+ ZERO_STRUCT(new_pw);
return True;
}
+
/***********************************************************
decode a password buffer
*new_pw_len is the length in bytes of the possibly mulitbyte
returned password including termination.
************************************************************/
BOOL decode_pw_buffer(char in_buffer[516], char *new_pwrd,
- int new_pwrd_size, uint32 *new_pw_len)
+ int new_pwrd_size, uint32 *new_pw_len,
+ int string_flags)
{
int byte_len=0;
/*
Warning !!! : This function is called from some rpc call.
- The password IN the buffer is a UNICODE string.
+ The password IN the buffer may be a UNICODE string.
The password IN new_pwrd is an ASCII string
If you reuse that code somewhere else check first.
*/
@@ -516,15 +517,16 @@ BOOL decode_pw_buffer(char in_buffer[516], char *new_pwrd,
dump_data(100, in_buffer, 516);
#endif
- /* Password cannot be longer than 128 characters */
- if ( (byte_len < 0) || (byte_len > new_pwrd_size - 1)) {
+ /* Password cannot be longer than the size of the password buffer */
+ 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;
}
- /* decode into the return buffer. Buffer must be a pstring */
- *new_pw_len = pull_string(NULL, new_pwrd, &in_buffer[512 - byte_len], new_pwrd_size, byte_len, STR_UNICODE);
+ /* decode into the return buffer. Buffer length supplied */
+ *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: "));