secur32: Get rid of builtin NTLM support.

Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Hans Leidekker 2021-04-30 16:42:21 +02:00 committed by Alexandre Julliard
parent 8a9c3b1e54
commit 1565a12a55
9 changed files with 13 additions and 2983 deletions

View file

@ -1,21 +1,16 @@
MODULE = secur32.dll
IMPORTLIB = secur32
IMPORTS = netapi32 advapi32
IMPORTS = advapi32
DELAYIMPORTS = crypt32
EXTRAINCL = $(GNUTLS_CFLAGS)
EXTRALIBS = $(SECURITY_LIBS)
C_SRCS = \
base64_codec.c \
dispatcher.c \
hmac_md5.c \
lsa.c \
negotiate.c \
ntlm.c \
schannel.c \
schannel_gnutls.c \
schannel_macosx.c \
secur32.c \
thunks.c \
util.c \
wrapper.c

View file

@ -1,192 +0,0 @@
/*
* base64 encoder/decoder
*
* Copyright 2005 by Kai Blin
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "windef.h"
#include "winerror.h"
#include "sspi.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(ntlm);
static const char b64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
SECURITY_STATUS encodeBase64(PBYTE in_buf, int in_len, char* out_buf,
int max_len, int *out_len)
{
int div, i;
PBYTE d = in_buf;
int bytes = (in_len*8 + 5)/6, pad_bytes = (bytes % 4) ? 4 - (bytes % 4) : 0;
TRACE("bytes is %d, pad bytes is %d\n", bytes, pad_bytes);
*out_len = bytes + pad_bytes;
if(bytes + pad_bytes + 1 > max_len)
return SEC_E_BUFFER_TOO_SMALL;
/* Three bytes of input give 4 chars of output */
div = in_len / 3;
i = 0;
while(div > 0)
{
/* first char is the first 6 bits of the first byte*/
out_buf[i + 0] = b64[ ( d[0] >> 2) & 0x3f ];
/* second char is the last 2 bits of the first byte and the first 4
* bits of the second byte */
out_buf[i + 1] = b64[ ((d[0] << 4) & 0x30) | (d[1] >> 4 & 0x0f)];
/* third char is the last 4 bits of the second byte and the first 2
* bits of the third byte */
out_buf[i + 2] = b64[ ((d[1] << 2) & 0x3c) | (d[2] >> 6 & 0x03)];
/* fourth char is the remaining 6 bits of the third byte */
out_buf[i + 3] = b64[ d[2] & 0x3f];
i += 4;
d += 3;
div--;
}
switch(pad_bytes)
{
case 1:
/* first char is the first 6 bits of the first byte*/
out_buf[i + 0] = b64[ ( d[0] >> 2) & 0x3f ];
/* second char is the last 2 bits of the first byte and the first 4
* bits of the second byte */
out_buf[i + 1] = b64[ ((d[0] << 4) & 0x30) | (d[1] >> 4 & 0x0f)];
/* third char is the last 4 bits of the second byte padded with
* two zeroes */
out_buf[i + 2] = b64[ ((d[1] << 2) & 0x3c) ];
/* fourth char is a = to indicate one byte of padding */
out_buf[i + 3] = '=';
out_buf[i + 4] = 0;
break;
case 2:
/* first char is the first 6 bits of the first byte*/
out_buf[i + 0] = b64[ ( d[0] >> 2) & 0x3f ];
/* second char is the last 2 bits of the first byte padded with
* four zeroes*/
out_buf[i + 1] = b64[ ((d[0] << 4) & 0x30)];
/* third char is = to indicate padding */
out_buf[i + 2] = '=';
/* fourth char is = to indicate padding */
out_buf[i + 3] = '=';
out_buf[i + 4] = 0;
break;
default:
out_buf[i] = 0;
}
return SEC_E_OK;
}
static inline BYTE decode(char c)
{
if( c >= 'A' && c <= 'Z')
return c - 'A';
if( c >= 'a' && c <= 'z')
return c - 'a' + 26;
if( c >= '0' && c <= '9')
return c - '0' + 52;
if( c == '+')
return 62;
if( c == '/')
return 63;
else
return 64;
}
SECURITY_STATUS decodeBase64(char *in_buf, int in_len, PBYTE out_buf,
int max_len, int *out_len)
{
int len = in_len, i;
char *d = in_buf;
int ip0, ip1, ip2, ip3;
TRACE("in_len: %d\n", in_len);
if((in_len % 4) != 0)
return SEC_E_INVALID_TOKEN;
if(in_len > max_len)
return SEC_E_BUFFER_TOO_SMALL;
i = 0;
while(len > 4)
{
if((ip0 = decode(d[0])) > 63)
return SEC_E_INVALID_TOKEN;
if((ip1 = decode(d[1])) > 63)
return SEC_E_INVALID_TOKEN;
if((ip2 = decode(d[2])) > 63)
return SEC_E_INVALID_TOKEN;
if((ip3 = decode(d[3])) > 63)
return SEC_E_INVALID_TOKEN;
out_buf[i + 0] = (ip0 << 2) | (ip1 >> 4);
out_buf[i + 1] = (ip1 << 4) | (ip2 >> 2);
out_buf[i + 2] = (ip2 << 6) | ip3;
len -= 4;
i += 3;
d += 4;
}
if(d[2] == '=')
{
if((ip0 = decode(d[0])) > 63)
return SEC_E_INVALID_TOKEN;
if((ip1 = decode(d[1])) > 63)
return SEC_E_INVALID_TOKEN;
out_buf[i] = (ip0 << 2) | (ip1 >> 4);
i++;
}
else if(d[3] == '=')
{
if((ip0 = decode(d[0])) > 63)
return SEC_E_INVALID_TOKEN;
if((ip1 = decode(d[1])) > 63)
return SEC_E_INVALID_TOKEN;
if((ip2 = decode(d[2])) > 63)
return SEC_E_INVALID_TOKEN;
out_buf[i + 0] = (ip0 << 2) | (ip1 >> 4);
out_buf[i + 1] = (ip1 << 4) | (ip2 >> 2);
i += 2;
}
else
{
if((ip0 = decode(d[0])) > 63)
return SEC_E_INVALID_TOKEN;
if((ip1 = decode(d[1])) > 63)
return SEC_E_INVALID_TOKEN;
if((ip2 = decode(d[2])) > 63)
return SEC_E_INVALID_TOKEN;
if((ip3 = decode(d[3])) > 63)
return SEC_E_INVALID_TOKEN;
out_buf[i + 0] = (ip0 << 2) | (ip1 >> 4);
out_buf[i + 1] = (ip1 << 4) | (ip2 >> 2);
out_buf[i + 2] = (ip2 << 6) | ip3;
i += 3;
}
*out_len = i;
return SEC_E_OK;
}

View file

@ -1,335 +0,0 @@
/*
* Copyright 2005, 2006 Kai Blin
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
* A dispatcher to run ntlm_auth for wine's sspi module.
*/
#include "config.h"
#include "wine/port.h"
#include <stdarg.h>
#include <stdio.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/types.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "sspi.h"
#include "secur32_priv.h"
#include "wine/debug.h"
#define INITIAL_BUFFER_SIZE 200
WINE_DEFAULT_DEBUG_CHANNEL(ntlm);
SECURITY_STATUS fork_helper(PNegoHelper *new_helper, const char *prog,
char* const argv[])
{
#ifdef HAVE_FORK
int pipe_in[2];
int pipe_out[2];
int i;
PNegoHelper helper;
TRACE("%s ", debugstr_a(prog));
for(i = 0; argv[i] != NULL; ++i)
{
TRACE("%s ", debugstr_a(argv[i]));
}
TRACE("\n");
#ifdef HAVE_PIPE2
if (pipe2( pipe_in, O_CLOEXEC ) < 0 )
#endif
{
if( pipe(pipe_in) < 0 ) return SEC_E_INTERNAL_ERROR;
fcntl( pipe_in[0], F_SETFD, FD_CLOEXEC );
fcntl( pipe_in[1], F_SETFD, FD_CLOEXEC );
}
#ifdef HAVE_PIPE2
if (pipe2( pipe_out, O_CLOEXEC ) < 0 )
#endif
{
if( pipe(pipe_out) < 0 )
{
close(pipe_in[0]);
close(pipe_in[1]);
return SEC_E_INTERNAL_ERROR;
}
fcntl( pipe_out[0], F_SETFD, FD_CLOEXEC );
fcntl( pipe_out[1], F_SETFD, FD_CLOEXEC );
}
if (!(helper = heap_alloc( sizeof(NegoHelper) )))
{
close(pipe_in[0]);
close(pipe_in[1]);
close(pipe_out[0]);
close(pipe_out[1]);
return SEC_E_INSUFFICIENT_MEMORY;
}
helper->helper_pid = fork();
if(helper->helper_pid == -1)
{
close(pipe_in[0]);
close(pipe_in[1]);
close(pipe_out[0]);
close(pipe_out[1]);
heap_free( helper );
return SEC_E_INTERNAL_ERROR;
}
if(helper->helper_pid == 0)
{
/* We're in the child now */
dup2(pipe_out[0], 0);
close(pipe_out[0]);
close(pipe_out[1]);
dup2(pipe_in[1], 1);
close(pipe_in[0]);
close(pipe_in[1]);
execvp(prog, argv);
/* Whoops, we shouldn't get here. Big badaboom.*/
write(STDOUT_FILENO, "BH\n", 3);
_exit(1);
}
else
{
*new_helper = helper;
helper->major = helper->minor = helper->micro = -1;
helper->com_buf = NULL;
helper->com_buf_size = 0;
helper->com_buf_offset = 0;
helper->session_key = NULL;
helper->neg_flags = 0;
helper->crypt.ntlm.a4i = NULL;
helper->crypt.ntlm2.send_a4i = NULL;
helper->crypt.ntlm2.recv_a4i = NULL;
helper->crypt.ntlm2.send_sign_key = NULL;
helper->crypt.ntlm2.send_seal_key = NULL;
helper->crypt.ntlm2.recv_sign_key = NULL;
helper->crypt.ntlm2.recv_seal_key = NULL;
helper->pipe_in = pipe_in[0];
close(pipe_in[1]);
helper->pipe_out = pipe_out[1];
close(pipe_out[0]);
}
return SEC_E_OK;
#else
ERR( "no fork support on this platform\n" );
return SEC_E_INTERNAL_ERROR;
#endif
}
static SECURITY_STATUS read_line(PNegoHelper helper, int *offset_len)
{
char *newline;
int read_size;
if(helper->com_buf == NULL)
{
TRACE("Creating a new buffer for the helper\n");
if (!(helper->com_buf = heap_alloc(INITIAL_BUFFER_SIZE)))
return SEC_E_INSUFFICIENT_MEMORY;
/* Created a new buffer, size is INITIAL_BUFFER_SIZE, offset is 0 */
helper->com_buf_size = INITIAL_BUFFER_SIZE;
helper->com_buf_offset = 0;
}
do
{
TRACE("offset = %d, size = %d\n", helper->com_buf_offset, helper->com_buf_size);
if(helper->com_buf_offset + INITIAL_BUFFER_SIZE > helper->com_buf_size)
{
/* increment buffer size in INITIAL_BUFFER_SIZE steps */
char *buf = heap_realloc(helper->com_buf, helper->com_buf_size + INITIAL_BUFFER_SIZE);
TRACE("Resizing buffer!\n");
if (!buf) return SEC_E_INSUFFICIENT_MEMORY;
helper->com_buf_size += INITIAL_BUFFER_SIZE;
helper->com_buf = buf;
}
if((read_size = read(helper->pipe_in, helper->com_buf + helper->com_buf_offset,
helper->com_buf_size - helper->com_buf_offset)) <= 0)
{
return SEC_E_INTERNAL_ERROR;
}
TRACE("read_size = %d, read: %s\n", read_size,
debugstr_a(helper->com_buf + helper->com_buf_offset));
helper->com_buf_offset += read_size;
newline = memchr(helper->com_buf, '\n', helper->com_buf_offset);
}while(newline == NULL);
/* Now, if there's a newline character, and we read more than that newline,
* we have to store the offset so we can preserve the additional data.*/
if( newline != helper->com_buf + helper->com_buf_offset)
{
TRACE("offset_len is calculated from %p - %p\n",
(helper->com_buf + helper->com_buf_offset), newline+1);
/* the length of the offset is the number of chars after the newline */
*offset_len = (helper->com_buf + helper->com_buf_offset) - (newline + 1);
}
else
{
*offset_len = 0;
}
*newline = '\0';
return SEC_E_OK;
}
static SECURITY_STATUS preserve_unused(PNegoHelper helper, int offset_len)
{
TRACE("offset_len = %d\n", offset_len);
if(offset_len > 0)
{
memmove(helper->com_buf, helper->com_buf + helper->com_buf_offset,
offset_len);
helper->com_buf_offset = offset_len;
}
else
{
helper->com_buf_offset = 0;
}
TRACE("helper->com_buf_offset was set to: %d\n", helper->com_buf_offset);
return SEC_E_OK;
}
SECURITY_STATUS run_helper(PNegoHelper helper, char *buffer,
unsigned int max_buflen, int *buflen)
{
int offset_len;
SECURITY_STATUS sec_status = SEC_E_OK;
TRACE("In helper: sending %s\n", debugstr_a(buffer));
/* buffer + '\n' */
write(helper->pipe_out, buffer, lstrlenA(buffer));
write(helper->pipe_out, "\n", 1);
if((sec_status = read_line(helper, &offset_len)) != SEC_E_OK)
{
return sec_status;
}
TRACE("In helper: received %s\n", debugstr_a(helper->com_buf));
*buflen = lstrlenA(helper->com_buf);
if( *buflen > max_buflen)
{
ERR("Buffer size too small(%d given, %d required) dropping data!\n",
max_buflen, *buflen);
return SEC_E_BUFFER_TOO_SMALL;
}
if( *buflen < 2 )
{
return SEC_E_ILLEGAL_MESSAGE;
}
/* We only get ERR if the input size is too big. On a GENSEC error,
* ntlm_auth will return BH */
if(strncmp(helper->com_buf, "ERR", 3) == 0)
{
return SEC_E_INVALID_TOKEN;
}
memcpy(buffer, helper->com_buf, *buflen+1);
sec_status = preserve_unused(helper, offset_len);
return sec_status;
}
void cleanup_helper(PNegoHelper helper)
{
TRACE("Killing helper %p\n", helper);
if(helper == NULL)
return;
heap_free(helper->com_buf);
heap_free(helper->session_key);
/* closing stdin will terminate ntlm_auth */
close(helper->pipe_out);
close(helper->pipe_in);
#ifdef HAVE_FORK
if (helper->helper_pid > 0) /* reap child */
{
pid_t wret;
do {
wret = waitpid(helper->helper_pid, NULL, 0);
} while (wret < 0 && errno == EINTR);
}
#endif
heap_free(helper);
}
void check_version(PNegoHelper helper)
{
char temp[80];
char *newline;
int major = 0, minor = 0, micro = 0, ret;
TRACE("Checking version of helper\n");
if(helper != NULL)
{
int len = read(helper->pipe_in, temp, sizeof(temp)-1);
if (len > 8)
{
if((newline = memchr(temp, '\n', len)) != NULL)
*newline = '\0';
else
temp[len] = 0;
TRACE("Exact version is %s\n", debugstr_a(temp));
ret = sscanf(temp, "Version %d.%d.%d", &major, &minor, &micro);
if(ret != 3)
{
ERR("Failed to get the helper version.\n");
helper->major = helper->minor = helper->micro = -1;
}
else
{
TRACE("Version recognized: %d.%d.%d\n", major, minor, micro);
helper->major = major;
helper->minor = minor;
helper->micro = micro;
}
}
}
}

View file

@ -1,77 +0,0 @@
/*
* Copyright 2006 Kai Blin
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
* This file implements RFC 2104 (HMAC) for the MD5 provider.
* It is needed for NTLM2 signing and sealing.
*/
#include "hmac_md5.h"
void HMACMD5Init(HMAC_MD5_CTX *ctx, const unsigned char *key, unsigned int key_len)
{
int i;
unsigned char inner_padding[64];
unsigned char temp_key[16];
if(key_len > 64)
{
MD5_CTX temp_ctx;
MD5Init(&temp_ctx);
MD5Update(&temp_ctx, key, key_len);
MD5Final(&temp_ctx);
memcpy(temp_key, temp_ctx.digest, 16);
key = temp_key;
key_len = 16;
}
memset(inner_padding, 0, 64);
memset(ctx->outer_padding, 0, 64);
memcpy(inner_padding, key, key_len);
memcpy(ctx->outer_padding, key, key_len);
for(i = 0; i < 64; ++i)
{
inner_padding[i] ^= 0x36;
ctx->outer_padding[i] ^= 0x5c;
}
MD5Init(&(ctx->ctx));
MD5Update(&(ctx->ctx), inner_padding, 64);
}
void HMACMD5Update(HMAC_MD5_CTX *ctx, const unsigned char *data, unsigned int data_len)
{
MD5Update(&(ctx->ctx), data, data_len);
}
void HMACMD5Final(HMAC_MD5_CTX *ctx, unsigned char *digest)
{
MD5_CTX outer_ctx;
unsigned char inner_digest[16];
MD5Final(&(ctx->ctx));
memcpy(inner_digest, ctx->ctx.digest, 16);
MD5Init(&outer_ctx);
MD5Update(&outer_ctx, ctx->outer_padding, 64);
MD5Update(&outer_ctx, inner_digest, 16);
MD5Final(&outer_ctx);
memcpy(digest, outer_ctx.digest, 16);
}

View file

@ -1,48 +0,0 @@
/*
* Copyright 2006 Kai Blin
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
* This file holds the declarations needed for HMAC-MD5.
*/
#ifndef _HMAC_MD5_H_
#define _HMAC_MD5_H_
#include <string.h>
#include "windef.h"
typedef struct
{
unsigned int i[2];
unsigned int buf[4];
unsigned char in[64];
unsigned char digest[16];
} MD5_CTX;
typedef struct
{
MD5_CTX ctx;
unsigned char outer_padding[64];
} HMAC_MD5_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 );
void HMACMD5Init(HMAC_MD5_CTX *ctx, const unsigned char *key, unsigned int key_len) DECLSPEC_HIDDEN;
void HMACMD5Update(HMAC_MD5_CTX *ctx, const unsigned char *data, unsigned int data_len) DECLSPEC_HIDDEN;
void HMACMD5Final(HMAC_MD5_CTX *ctx, unsigned char *digest) DECLSPEC_HIDDEN;
#endif /*_HMAC_MD5_H_*/

View file

@ -58,6 +58,17 @@ struct sec_handle
SecHandle handle_ntlm;
};
/* matches layout from msv1_0 */
struct ntlm_cred
{
int mode;
char *username_arg;
char *domain_arg;
char *password;
int password_len;
int no_cached_credentials; /* don't try to use cached Samba credentials */
};
/***********************************************************************
* AcquireCredentialsHandleW
*/
@ -92,7 +103,7 @@ static SECURITY_STATUS SEC_ENTRY nego_AcquireCredentialsHandleW(
fCredentialUse, pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, &cred->handle_ntlm, ptsExpiry );
if (ret == SEC_E_OK)
{
NtlmCredentials *ntlm_cred = (NtlmCredentials *)cred->handle_ntlm.dwLower;
struct ntlm_cred *ntlm_cred = (struct ntlm_cred *)cred->handle_ntlm.dwLower;
ntlm_cred->no_cached_credentials = (pAuthData == NULL);
cred->ntlm = package->provider;
}

File diff suppressed because it is too large Load diff

View file

@ -44,65 +44,6 @@ typedef struct _SecurePackage
SecureProvider *provider;
} SecurePackage;
typedef enum _helper_mode {
NTLM_SERVER,
NTLM_CLIENT,
NUM_HELPER_MODES
} HelperMode;
typedef struct tag_arc4_info {
unsigned char x, y;
unsigned char state[256];
} arc4_info;
typedef struct _NegoHelper {
pid_t helper_pid;
HelperMode mode;
int pipe_in;
int pipe_out;
int major;
int minor;
int micro;
char *com_buf;
int com_buf_size;
int com_buf_offset;
BYTE *session_key;
ULONG neg_flags;
struct {
struct {
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;
typedef struct _NtlmCredentials
{
HelperMode mode;
/* these are all in the Unix codepage */
char *username_arg;
char *domain_arg;
char *password; /* not nul-terminated */
int pwlen;
int no_cached_credentials; /* don't try to use cached Samba credentials */
} NtlmCredentials, *PNtlmCredentials;
typedef enum _sign_direction {
NTLM_SEND,
NTLM_RECV
} SignDirection;
/* Allocates space for and initializes a new provider. If fnTableA or fnTableW
* is non-NULL, assumes the provider is built-in, and if moduleName is non-NULL,
* means must load the LSA/user mode functions tables from external SSP/AP module.
@ -136,60 +77,11 @@ PSTR SECUR32_AllocMultiByteFromWide(PCWSTR str) DECLSPEC_HIDDEN;
/* Initialization functions for built-in providers */
void SECUR32_initSchannelSP(void) DECLSPEC_HIDDEN;
void SECUR32_initNegotiateSP(void) DECLSPEC_HIDDEN;
void SECUR32_initNTLMSP(void) DECLSPEC_HIDDEN;
void load_auth_packages(void) DECLSPEC_HIDDEN;
/* Cleanup functions for built-in providers */
void SECUR32_deinitSchannelSP(void) DECLSPEC_HIDDEN;
/* Functions from dispatcher.c used elsewhere in the code */
SECURITY_STATUS fork_helper(PNegoHelper *new_helper, const char *prog,
char * const argv[]) DECLSPEC_HIDDEN;
SECURITY_STATUS run_helper(PNegoHelper helper, char *buffer,
unsigned int max_buflen, int *buflen) DECLSPEC_HIDDEN;
void cleanup_helper(PNegoHelper helper) DECLSPEC_HIDDEN;
void check_version(PNegoHelper helper) DECLSPEC_HIDDEN;
/* Functions from base64_codec.c used elsewhere */
SECURITY_STATUS encodeBase64(PBYTE in_buf, int in_len, char* out_buf,
int max_len, int *out_len) DECLSPEC_HIDDEN;
SECURITY_STATUS decodeBase64(char *in_buf, int in_len, BYTE *out_buf,
int max_len, int *out_len) DECLSPEC_HIDDEN;
/* Functions from util.c */
SECURITY_STATUS SECUR32_CreateNTLM1SessionKey(PBYTE password, int len, PBYTE session_key) DECLSPEC_HIDDEN;
SECURITY_STATUS SECUR32_CreateNTLM2SubKeys(PNegoHelper helper) DECLSPEC_HIDDEN;
arc4_info *SECUR32_arc4Alloc(void) DECLSPEC_HIDDEN;
void SECUR32_arc4Init(arc4_info *a4i, const BYTE *key, unsigned int keyLen) DECLSPEC_HIDDEN;
void SECUR32_arc4Process(arc4_info *a4i, BYTE *inoutString, unsigned int length) DECLSPEC_HIDDEN;
void SECUR32_arc4Cleanup(arc4_info *a4i) DECLSPEC_HIDDEN;
/* NTLMSSP flags indicating the negotiated features */
#define NTLMSSP_NEGOTIATE_UNICODE 0x00000001
#define NTLMSSP_NEGOTIATE_OEM 0x00000002
#define NTLMSSP_REQUEST_TARGET 0x00000004
#define NTLMSSP_NEGOTIATE_SIGN 0x00000010
#define NTLMSSP_NEGOTIATE_SEAL 0x00000020
#define NTLMSSP_NEGOTIATE_DATAGRAM_STYLE 0x00000040
#define NTLMSSP_NEGOTIATE_LM_SESSION_KEY 0x00000080
#define NTLMSSP_NEGOTIATE_NTLM 0x00000200
#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x00001000
#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x00002000
#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x00004000
#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x00008000
#define NTLMSSP_NEGOTIATE_TARGET_TYPE_DOMAIN 0x00010000
#define NTLMSSP_NEGOTIATE_TARGET_TYPE_SERVER 0x00020000
#define NTLMSSP_NEGOTIATE_NTLM2 0x00080000
#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x00800000
#define NTLMSSP_NEGOTIATE_128 0x20000000
#define NTLMSSP_NEGOTIATE_KEY_EXCHANGE 0x40000000
#define NTLMSSP_NEGOTIATE_56 0x80000000
/* schannel internal interface */
typedef struct schan_imp_session_opaque *schan_imp_session;

View file

@ -1,187 +0,0 @@
/*
* Copyright 2006 Kai Blin
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
* This file contains various helper functions needed for NTLM and maybe others
*/
#include <stdarg.h>
#include <stdio.h>
#include "windef.h"
#include "winbase.h"
#include "rpc.h"
#include "sspi.h"
#include "secur32_priv.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(ntlm);
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];
unsigned int i[2];
unsigned char in[64];
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 );
SECURITY_STATUS SECUR32_CreateNTLM1SessionKey(PBYTE password, int len, PBYTE session_key)
{
MD4_CTX ctx;
BYTE ntlm_hash[16];
TRACE("(%p, %p)\n", password, session_key);
MD4Init(&ctx);
MD4Update(&ctx, password, len);
MD4Final(&ctx);
memcpy(ntlm_hash, ctx.digest, 0x10);
MD4Init(&ctx);
MD4Update(&ctx, ntlm_hash, 0x10u);
MD4Final(&ctx);
memcpy(session_key, ctx.digest, 0x10);
return SEC_E_OK;
}
static void SECUR32_CalcNTLM2Subkey(const BYTE *session_key, const char *magic, PBYTE subkey)
{
MD5_CTX ctx;
MD5Init(&ctx);
MD5Update(&ctx, session_key, 16);
MD5Update(&ctx, (const 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_CreateNTLM2SubKeys(PNegoHelper helper)
{
helper->crypt.ntlm2.send_sign_key = heap_alloc(16);
helper->crypt.ntlm2.send_seal_key = heap_alloc(16);
helper->crypt.ntlm2.recv_sign_key = heap_alloc(16);
helper->crypt.ntlm2.recv_seal_key = heap_alloc(16);
if(helper->mode == NTLM_CLIENT)
{
SECUR32_CalcNTLM2Subkey(helper->session_key, client_to_server_sign_constant,
helper->crypt.ntlm2.send_sign_key);
SECUR32_CalcNTLM2Subkey(helper->session_key, client_to_server_seal_constant,
helper->crypt.ntlm2.send_seal_key);
SECUR32_CalcNTLM2Subkey(helper->session_key, server_to_client_sign_constant,
helper->crypt.ntlm2.recv_sign_key);
SECUR32_CalcNTLM2Subkey(helper->session_key, server_to_client_seal_constant,
helper->crypt.ntlm2.recv_seal_key);
}
else
{
SECUR32_CalcNTLM2Subkey(helper->session_key, server_to_client_sign_constant,
helper->crypt.ntlm2.send_sign_key);
SECUR32_CalcNTLM2Subkey(helper->session_key, server_to_client_seal_constant,
helper->crypt.ntlm2.send_seal_key);
SECUR32_CalcNTLM2Subkey(helper->session_key, client_to_server_sign_constant,
helper->crypt.ntlm2.recv_sign_key);
SECUR32_CalcNTLM2Subkey(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 = heap_alloc(sizeof(arc4_info));
return a4i;
}
/*
* The arc4 code is based on dlls/advapi32/crypt_arc4.c by Mike McCormack,
* which in turn is based on public domain code by Wei Dai
*/
void SECUR32_arc4Init(arc4_info *a4i, const BYTE *key, unsigned int keyLen)
{
unsigned int keyIndex = 0, stateIndex = 0;
unsigned int i, a;
TRACE("(%p, %p, %d)\n", a4i, key, keyLen);
a4i->x = a4i->y = 0;
for (i=0; i<256; i++)
a4i->state[i] = i;
for (i=0; i<256; i++)
{
a = a4i->state[i];
stateIndex += key[keyIndex] + a;
stateIndex &= 0xff;
a4i->state[i] = a4i->state[stateIndex];
a4i->state[stateIndex] = a;
if (++keyIndex >= keyLen)
keyIndex = 0;
}
}
void SECUR32_arc4Process(arc4_info *a4i, BYTE *inoutString, unsigned int length)
{
BYTE *const s=a4i->state;
unsigned int x = a4i->x;
unsigned int y = a4i->y;
unsigned int a, b;
while(length--)
{
x = (x+1) & 0xff;
a = s[x];
y = (y+a) & 0xff;
b = s[y];
s[x] = b;
s[y] = a;
*inoutString++ ^= s[(a+b) & 0xff];
}
a4i->x = x;
a4i->y = y;
}
void SECUR32_arc4Cleanup(arc4_info *a4i)
{
heap_free(a4i);
}