FreeRDP
utils/ntlm.c
1 
20 #include <winpr/config.h>
21 
22 #include <winpr/ntlm.h>
23 #include <winpr/assert.h>
24 
25 #include <winpr/crt.h>
26 #include <winpr/crypto.h>
27 
34 BOOL NTOWFv1W(LPWSTR Password, UINT32 PasswordLength, BYTE* NtHash)
35 {
36  if (!Password || !NtHash)
37  return FALSE;
38 
39  if (!winpr_Digest(WINPR_MD_MD4, (BYTE*)Password, (size_t)PasswordLength, NtHash,
40  WINPR_MD4_DIGEST_LENGTH))
41  return FALSE;
42 
43  return TRUE;
44 }
45 
46 BOOL NTOWFv1A(LPSTR Password, UINT32 PasswordLength, BYTE* NtHash)
47 {
48  LPWSTR PasswordW = NULL;
49  BOOL result = FALSE;
50  size_t pwdCharLength = 0;
51 
52  if (!NtHash)
53  return FALSE;
54 
55  PasswordW = ConvertUtf8NToWCharAlloc(Password, PasswordLength, &pwdCharLength);
56  if (!PasswordW)
57  return FALSE;
58 
59  if (!NTOWFv1W(PasswordW, (UINT32)pwdCharLength * sizeof(WCHAR), NtHash))
60  goto out_fail;
61 
62  result = TRUE;
63 out_fail:
64  free(PasswordW);
65  return result;
66 }
67 
75 BOOL NTOWFv2W(LPWSTR Password, UINT32 PasswordLength, LPWSTR User, UINT32 UserLength, LPWSTR Domain,
76  UINT32 DomainLength, BYTE* NtHash)
77 {
78  BYTE NtHashV1[WINPR_MD5_DIGEST_LENGTH];
79 
80  if ((!User) || (!Password) || (!NtHash))
81  return FALSE;
82 
83  if (!NTOWFv1W(Password, PasswordLength, NtHashV1))
84  return FALSE;
85 
86  return NTOWFv2FromHashW(NtHashV1, User, UserLength, Domain, DomainLength, NtHash);
87 }
88 
89 BOOL NTOWFv2A(LPSTR Password, UINT32 PasswordLength, LPSTR User, UINT32 UserLength, LPSTR Domain,
90  UINT32 DomainLength, BYTE* NtHash)
91 {
92  LPWSTR UserW = NULL;
93  LPWSTR DomainW = NULL;
94  LPWSTR PasswordW = NULL;
95  BOOL result = FALSE;
96  size_t userCharLength = 0;
97  size_t domainCharLength = 0;
98  size_t pwdCharLength = 0;
99 
100  if (!NtHash)
101  return FALSE;
102 
103  UserW = ConvertUtf8NToWCharAlloc(User, UserLength, &userCharLength);
104  DomainW = ConvertUtf8NToWCharAlloc(Domain, DomainLength, &domainCharLength);
105  PasswordW = ConvertUtf8NToWCharAlloc(Password, PasswordLength, &pwdCharLength);
106 
107  if (!UserW || !DomainW || !PasswordW)
108  goto out_fail;
109 
110  if (!NTOWFv2W(PasswordW, (UINT32)pwdCharLength * sizeof(WCHAR), UserW,
111  (UINT32)userCharLength * sizeof(WCHAR), DomainW,
112  (UINT32)domainCharLength * sizeof(WCHAR), NtHash))
113  goto out_fail;
114 
115  result = TRUE;
116 out_fail:
117  free(UserW);
118  free(DomainW);
119  free(PasswordW);
120  return result;
121 }
122 
123 BOOL NTOWFv2FromHashW(BYTE* NtHashV1, LPWSTR User, UINT32 UserLength, LPWSTR Domain,
124  UINT32 DomainLength, BYTE* NtHash)
125 {
126  BYTE* buffer = NULL;
127  BYTE result = FALSE;
128 
129  if (!User || !NtHash)
130  return FALSE;
131 
132  if (!(buffer = (BYTE*)malloc(UserLength + DomainLength)))
133  return FALSE;
134 
135  /* Concatenate(UpperCase(User), Domain) */
136  CopyMemory(buffer, User, UserLength);
137  CharUpperBuffW((LPWSTR)buffer, UserLength / 2);
138 
139  if (DomainLength > 0)
140  {
141  CopyMemory(&buffer[UserLength], Domain, DomainLength);
142  }
143 
144  /* Compute the HMAC-MD5 hash of the above value using the NTLMv1 hash as the key, the result is
145  * the NTLMv2 hash */
146  if (!winpr_HMAC(WINPR_MD_MD5, NtHashV1, 16, buffer, UserLength + DomainLength, NtHash,
147  WINPR_MD5_DIGEST_LENGTH))
148  goto out_fail;
149 
150  result = TRUE;
151 out_fail:
152  free(buffer);
153  return result;
154 }
155 
156 BOOL NTOWFv2FromHashA(BYTE* NtHashV1, LPSTR User, UINT32 UserLength, LPSTR Domain,
157  UINT32 DomainLength, BYTE* NtHash)
158 {
159  LPWSTR UserW = NULL;
160  LPWSTR DomainW = NULL;
161  BOOL result = FALSE;
162  size_t userCharLength = 0;
163  size_t domainCharLength = 0;
164  if (!NtHash)
165  return FALSE;
166 
167  UserW = ConvertUtf8NToWCharAlloc(User, UserLength, &userCharLength);
168  DomainW = ConvertUtf8NToWCharAlloc(Domain, DomainLength, &domainCharLength);
169 
170  if (!UserW || !DomainW)
171  goto out_fail;
172 
173  if (!NTOWFv2FromHashW(NtHashV1, UserW, (UINT32)userCharLength * sizeof(WCHAR), DomainW,
174  (UINT32)domainCharLength * sizeof(WCHAR), NtHash))
175  goto out_fail;
176 
177  result = TRUE;
178 out_fail:
179  free(UserW);
180  free(DomainW);
181  return result;
182 }