Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
13603394
Commit
13603394
authored
Nov 08, 2006
by
Kai Blin
Committed by
Alexandre Julliard
Nov 09, 2006
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
secur32: Implement ntlmv2 signing.
parent
78bcfdfc
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
161 additions
and
8 deletions
+161
-8
ntlm.c
dlls/secur32/ntlm.c
+88
-8
secur32_priv.h
dlls/secur32/secur32_priv.h
+11
-0
util.c
dlls/secur32/util.c
+62
-0
No files found.
dlls/secur32/ntlm.c
View file @
13603394
...
...
@@ -28,6 +28,7 @@
#include "sspi.h"
#include "lm.h"
#include "secur32_priv.h"
#include "hmac_md5.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
secur32
);
...
...
@@ -528,10 +529,6 @@ static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(
max_len
-
1
,
&
bin_len
))
!=
SEC_E_OK
)
goto
isc_end
;
/* Mask away the NTLMv2 flag, as well as the key exchange flag */
bin
[
14
]
&=
~
0x08
;
bin
[
15
]
&=
~
0x40
;
/* put the decoded client blob into the out buffer */
ret
=
SEC_I_CONTINUE_NEEDED
;
...
...
@@ -703,6 +700,15 @@ static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(
helper
->
crypt
.
ntlm
.
a4i
=
SECUR32_arc4Alloc
();
SECUR32_arc4Init
(
helper
->
crypt
.
ntlm
.
a4i
,
helper
->
session_key
,
16
);
helper
->
crypt
.
ntlm
.
seq_num
=
0l
;
SECUR32_CreateNTLMv2SubKeys
(
helper
);
helper
->
crypt
.
ntlm2
.
send_a4i
=
SECUR32_arc4Alloc
();
helper
->
crypt
.
ntlm2
.
recv_a4i
=
SECUR32_arc4Alloc
();
SECUR32_arc4Init
(
helper
->
crypt
.
ntlm2
.
send_a4i
,
(
BYTE
*
)
helper
->
crypt
.
ntlm2
.
send_seal_key
,
16
);
SECUR32_arc4Init
(
helper
->
crypt
.
ntlm2
.
recv_a4i
,
(
BYTE
*
)
helper
->
crypt
.
ntlm2
.
recv_seal_key
,
16
);
helper
->
crypt
.
ntlm2
.
send_seq_no
=
0l
;
helper
->
crypt
.
ntlm2
.
recv_seq_no
=
0l
;
}
if
(
ret
!=
SEC_I_CONTINUE_NEEDED
)
...
...
@@ -1093,6 +1099,12 @@ static SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(PCtxtHandle phContex
SECUR32_arc4Cleanup
(
helper
->
crypt
.
ntlm
.
a4i
);
HeapFree
(
GetProcessHeap
(),
0
,
helper
->
session_key
);
helper
->
valid_session_key
=
FALSE
;
SECUR32_arc4Cleanup
(
helper
->
crypt
.
ntlm2
.
send_a4i
);
SECUR32_arc4Cleanup
(
helper
->
crypt
.
ntlm2
.
recv_a4i
);
HeapFree
(
GetProcessHeap
(),
0
,
helper
->
crypt
.
ntlm2
.
send_sign_key
);
HeapFree
(
GetProcessHeap
(),
0
,
helper
->
crypt
.
ntlm2
.
send_seal_key
);
HeapFree
(
GetProcessHeap
(),
0
,
helper
->
crypt
.
ntlm2
.
recv_sign_key
);
HeapFree
(
GetProcessHeap
(),
0
,
helper
->
crypt
.
ntlm2
.
recv_seal_key
);
return
SEC_E_OK
;
}
...
...
@@ -1229,16 +1241,84 @@ static SECURITY_STATUS ntlm_CreateSignature(PNegoHelper helper, PSecBufferDesc p
{
ULONG
sign_version
=
1
;
UINT
i
;
TRACE
(
"%p, %p, %d
\n
"
,
helper
,
pMessage
,
direction
);
PBYTE
sig
;
TRACE
(
"%p, %p, %d, %d
\n
"
,
helper
,
pMessage
,
token_idx
,
direction
);
sig
=
pMessage
->
pBuffers
[
token_idx
].
pvBuffer
;
if
(
helper
->
neg_flags
&
NTLMSSP_NEGOTIATE_NTLM2
&&
if
(
helper
->
neg_flags
&
NTLMSSP_NEGOTIATE_NTLM2
&&
helper
->
neg_flags
&
NTLMSSP_NEGOTIATE_SIGN
)
{
return
SEC_E_UNSUPPORTED_FUNCTION
;
BYTE
digest
[
16
];
BYTE
seq_no
[
4
];
HMAC_MD5_CTX
hmac_md5_ctx
;
TRACE
(
"Encrypting NTLM2 style
\n
"
);
if
(
direction
==
NTLM_SEND
)
{
TRACE
(
"Signing for sending
\n
"
);
seq_no
[
0
]
=
(
helper
->
crypt
.
ntlm2
.
send_seq_no
>>
0
)
&
0xff
;
seq_no
[
1
]
=
(
helper
->
crypt
.
ntlm2
.
send_seq_no
>>
8
)
&
0xff
;
seq_no
[
2
]
=
(
helper
->
crypt
.
ntlm2
.
send_seq_no
>>
16
)
&
0xff
;
seq_no
[
3
]
=
(
helper
->
crypt
.
ntlm2
.
send_seq_no
>>
24
)
&
0xff
;
++
(
helper
->
crypt
.
ntlm2
.
send_seq_no
);
TRACE
(
"HMACMD5Init...
\n
"
);
HMACMD5Init
(
&
hmac_md5_ctx
,
helper
->
crypt
.
ntlm2
.
send_sign_key
,
16
);
TRACE
(
"Done
\n
"
);
}
else
{
seq_no
[
0
]
=
(
helper
->
crypt
.
ntlm2
.
recv_seq_no
>>
0
)
&
0xff
;
seq_no
[
1
]
=
(
helper
->
crypt
.
ntlm2
.
recv_seq_no
>>
8
)
&
0xff
;
seq_no
[
2
]
=
(
helper
->
crypt
.
ntlm2
.
recv_seq_no
>>
16
)
&
0xff
;
seq_no
[
3
]
=
(
helper
->
crypt
.
ntlm2
.
recv_seq_no
>>
24
)
&
0xff
;
++
(
helper
->
crypt
.
ntlm2
.
recv_seq_no
);
HMACMD5Init
(
&
hmac_md5_ctx
,
helper
->
crypt
.
ntlm2
.
recv_sign_key
,
16
);
}
TRACE
(
"Starting the update loop
\n
"
);
HMACMD5Update
(
&
hmac_md5_ctx
,
seq_no
,
4
);
for
(
i
=
0
;
i
<
pMessage
->
cBuffers
;
++
i
)
{
if
(
pMessage
->
pBuffers
[
i
].
BufferType
&
SECBUFFER_DATA
)
HMACMD5Update
(
&
hmac_md5_ctx
,
(
BYTE
*
)
pMessage
->
pBuffers
[
i
].
pvBuffer
,
pMessage
->
pBuffers
[
i
].
cbBuffer
);
}
HMACMD5Final
(
&
hmac_md5_ctx
,
digest
);
TRACE
(
"After HMACMD5Final
\n
"
);
if
(
helper
->
neg_flags
&
NTLMSSP_NEGOTIATE_KEY_EXCHANGE
)
{
if
(
direction
==
NTLM_SEND
)
SECUR32_arc4Process
(
helper
->
crypt
.
ntlm2
.
send_a4i
,
digest
,
8
);
else
SECUR32_arc4Process
(
helper
->
crypt
.
ntlm2
.
recv_a4i
,
digest
,
8
);
}
/* The NTLM2 signature is the sign version */
sig
[
0
]
=
(
sign_version
>>
0
)
&
0xff
;
sig
[
1
]
=
(
sign_version
>>
8
)
&
0xff
;
sig
[
2
]
=
(
sign_version
>>
16
)
&
0xff
;
sig
[
3
]
=
(
sign_version
>>
24
)
&
0xff
;
/* The first 8 bytes of the digest */
memcpy
(
sig
+
4
,
digest
,
8
);
/* And the sequence number */
memcpy
(
sig
+
12
,
seq_no
,
4
);
pMessage
->
pBuffers
[
token_idx
].
cbBuffer
=
16
;
return
SEC_E_OK
;
}
if
(
helper
->
neg_flags
&
NTLMSSP_NEGOTIATE_SIGN
)
{
PBYTE
sig
=
pMessage
->
pBuffers
[
token_idx
].
pvBuffer
;
ULONG
crc
=
0U
;
for
(
i
=
0
;
i
<
pMessage
->
cBuffers
;
++
i
)
...
...
dlls/secur32/secur32_priv.h
View file @
13603394
...
...
@@ -77,6 +77,16 @@ typedef struct _NegoHelper {
ULONG
seq_num
;
arc4_info
*
a4i
;
}
ntlm
;
struct
{
BYTE
*
send_sign_key
;
BYTE
*
send_seal_key
;
BYTE
*
recv_sign_key
;
BYTE
*
recv_seal_key
;
ULONG
send_seq_no
;
ULONG
recv_seq_no
;
arc4_info
*
send_a4i
;
arc4_info
*
recv_a4i
;
}
ntlm2
;
}
crypt
;
}
NegoHelper
,
*
PNegoHelper
;
...
...
@@ -141,6 +151,7 @@ SECURITY_STATUS decodeBase64(char *in_buf, int in_len, BYTE *out_buf,
/* Functions from util.c */
ULONG
ComputeCrc32
(
const
BYTE
*
pData
,
INT
iLen
,
ULONG
initial_crc
);
SECURITY_STATUS
SECUR32_CreateNTLMv1SessionKey
(
PBYTE
password
,
int
len
,
PBYTE
session_key
);
SECURITY_STATUS
SECUR32_CreateNTLMv2SubKeys
(
PNegoHelper
helper
);
arc4_info
*
SECUR32_arc4Alloc
(
void
);
void
SECUR32_arc4Init
(
arc4_info
*
a4i
,
const
BYTE
*
key
,
unsigned
int
keyLen
);
void
SECUR32_arc4Process
(
arc4_info
*
a4i
,
BYTE
*
inoutString
,
unsigned
int
length
);
...
...
dlls/secur32/util.c
View file @
13603394
...
...
@@ -81,6 +81,11 @@ static const ULONG CRC_table[256] =
0xb40bbe37
,
0xc30c8ea1
,
0x5a05df1b
,
0x2d02ef8d
};
static
const
char
client_to_server_sign_constant
[]
=
"session key to client-to-server signing key magic constant"
;
static
const
char
client_to_server_seal_constant
[]
=
"session key to client-to-server sealing key magic constant"
;
static
const
char
server_to_client_sign_constant
[]
=
"session key to server-to-client signing key magic constant"
;
static
const
char
server_to_client_seal_constant
[]
=
"session key to server-to-client sealing key magic constant"
;
typedef
struct
{
unsigned
int
buf
[
4
];
...
...
@@ -89,9 +94,21 @@ typedef struct
unsigned
char
digest
[
16
];
}
MD4_CTX
;
/* And now the same with a different memory layout. */
typedef
struct
{
unsigned
int
i
[
2
];
unsigned
int
buf
[
4
];
unsigned
char
in
[
64
];
unsigned
char
digest
[
16
];
}
MD5_CTX
;
VOID
WINAPI
MD4Init
(
MD4_CTX
*
ctx
);
VOID
WINAPI
MD4Update
(
MD4_CTX
*
ctx
,
const
unsigned
char
*
buf
,
unsigned
int
len
);
VOID
WINAPI
MD4Final
(
MD4_CTX
*
ctx
);
VOID
WINAPI
MD5Init
(
MD5_CTX
*
ctx
);
VOID
WINAPI
MD5Update
(
MD5_CTX
*
ctx
,
const
unsigned
char
*
buf
,
unsigned
int
len
);
VOID
WINAPI
MD5Final
(
MD5_CTX
*
ctx
);
ULONG
ComputeCrc32
(
const
BYTE
*
pData
,
INT
iLen
,
ULONG
initial_crc
)
{
...
...
@@ -128,6 +145,51 @@ SECURITY_STATUS SECUR32_CreateNTLMv1SessionKey(PBYTE password, int len, PBYTE se
return
SEC_E_OK
;
}
void
SECUR32_CalcNTLMv2Subkey
(
PBYTE
session_key
,
const
char
*
magic
,
PBYTE
subkey
)
{
MD5_CTX
ctx
;
MD5Init
(
&
ctx
);
MD5Update
(
&
ctx
,
session_key
,
16
);
MD5Update
(
&
ctx
,
(
unsigned
char
*
)
magic
,
lstrlenA
(
magic
)
+
1
);
MD5Final
(
&
ctx
);
memcpy
(
subkey
,
ctx
.
digest
,
16
);
}
/* This assumes we do have a valid NTLM2 user session key */
SECURITY_STATUS
SECUR32_CreateNTLMv2SubKeys
(
PNegoHelper
helper
)
{
helper
->
crypt
.
ntlm2
.
send_sign_key
=
HeapAlloc
(
GetProcessHeap
(),
0
,
16
);
helper
->
crypt
.
ntlm2
.
send_seal_key
=
HeapAlloc
(
GetProcessHeap
(),
0
,
16
);
helper
->
crypt
.
ntlm2
.
recv_sign_key
=
HeapAlloc
(
GetProcessHeap
(),
0
,
16
);
helper
->
crypt
.
ntlm2
.
recv_seal_key
=
HeapAlloc
(
GetProcessHeap
(),
0
,
16
);
if
(
helper
->
mode
==
NTLM_CLIENT
)
{
SECUR32_CalcNTLMv2Subkey
(
helper
->
session_key
,
client_to_server_sign_constant
,
helper
->
crypt
.
ntlm2
.
send_sign_key
);
SECUR32_CalcNTLMv2Subkey
(
helper
->
session_key
,
client_to_server_seal_constant
,
helper
->
crypt
.
ntlm2
.
send_seal_key
);
SECUR32_CalcNTLMv2Subkey
(
helper
->
session_key
,
server_to_client_sign_constant
,
helper
->
crypt
.
ntlm2
.
recv_sign_key
);
SECUR32_CalcNTLMv2Subkey
(
helper
->
session_key
,
server_to_client_seal_constant
,
helper
->
crypt
.
ntlm2
.
recv_seal_key
);
}
else
{
SECUR32_CalcNTLMv2Subkey
(
helper
->
session_key
,
server_to_client_sign_constant
,
helper
->
crypt
.
ntlm2
.
send_sign_key
);
SECUR32_CalcNTLMv2Subkey
(
helper
->
session_key
,
server_to_client_seal_constant
,
helper
->
crypt
.
ntlm2
.
send_seal_key
);
SECUR32_CalcNTLMv2Subkey
(
helper
->
session_key
,
client_to_server_sign_constant
,
helper
->
crypt
.
ntlm2
.
recv_sign_key
);
SECUR32_CalcNTLMv2Subkey
(
helper
->
session_key
,
client_to_server_seal_constant
,
helper
->
crypt
.
ntlm2
.
recv_seal_key
);
}
return
SEC_E_OK
;
}
arc4_info
*
SECUR32_arc4Alloc
(
void
)
{
arc4_info
*
a4i
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
arc4_info
));
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment