Wine-devel
Threads by month
- ----- 2026 -----
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
April 2021
- 70 participants
- 697 discussions
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/ws2_32/tests/sock.c | 66 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 66 insertions(+)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index 5bd18586e51..9cf271d0fea 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -8373,6 +8373,71 @@ static void test_wsaioctl(void)
closesocket(s);
}
+static void test_bind(void)
+{
+ const struct sockaddr_in invalid_addr = {.sin_family = AF_INET, .sin_addr.s_addr = inet_addr("192.0.2.0")};
+ const struct sockaddr_in bind_addr = {.sin_family = AF_INET, .sin_addr.s_addr = htonl(INADDR_LOOPBACK)};
+ struct sockaddr addr;
+ SOCKET s, s2;
+ int ret, len;
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+ WSASetLastError(0xdeadbeef);
+ ret = bind(s, NULL, 0);
+ ok(ret == -1, "expected failure\n");
+ todo_wine ok(WSAGetLastError() == WSAEFAULT, "got error %u\n", WSAGetLastError());
+
+ addr.sa_family = 0xdead;
+ WSASetLastError(0xdeadbeef);
+ ret = bind(s, &addr, sizeof(addr));
+ ok(ret == -1, "expected failure\n");
+ ok(WSAGetLastError() == WSAEAFNOSUPPORT, "got error %u\n", WSAGetLastError());
+
+ WSASetLastError(0xdeadbeef);
+ ret = bind(s, (const struct sockaddr *)&bind_addr, sizeof(bind_addr) - 1);
+ ok(ret == -1, "expected failure\n");
+ ok(WSAGetLastError() == WSAEFAULT, "got error %u\n", WSAGetLastError());
+
+ WSASetLastError(0xdeadbeef);
+ ret = bind(s, (const struct sockaddr *)&invalid_addr, sizeof(invalid_addr));
+ ok(ret == -1, "expected failure\n");
+ todo_wine ok(WSAGetLastError() == WSAEADDRNOTAVAIL, "got error %u\n", WSAGetLastError());
+
+ WSASetLastError(0xdeadbeef);
+ ret = bind(s, (const struct sockaddr *)&bind_addr, sizeof(bind_addr));
+ ok(!ret, "expected success\n");
+ ok(!WSAGetLastError() || WSAGetLastError() == 0xdeadbeef /* win <7 */, "got error %u\n", WSAGetLastError());
+
+ WSASetLastError(0xdeadbeef);
+ ret = bind(s, (const struct sockaddr *)&bind_addr, sizeof(bind_addr));
+ ok(ret == -1, "expected failure\n");
+ ok(WSAGetLastError() == WSAEINVAL, "got error %u\n", WSAGetLastError());
+
+ len = sizeof(addr);
+ ret = getsockname(s, &addr, &len);
+ ok(!ret, "got error %u\n", WSAGetLastError());
+
+ s2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+ WSASetLastError(0xdeadbeef);
+ ret = bind(s2, &addr, sizeof(addr));
+ ok(ret == -1, "expected failure\n");
+ ok(WSAGetLastError() == WSAEADDRINUSE, "got error %u\n", WSAGetLastError());
+
+ closesocket(s2);
+ closesocket(s);
+
+ s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+
+ WSASetLastError(0xdeadbeef);
+ ret = bind(s, (const struct sockaddr *)&bind_addr, sizeof(bind_addr));
+ ok(!ret, "expected success\n");
+ ok(!WSAGetLastError() || WSAGetLastError() == 0xdeadbeef /* win <7 */, "got error %u\n", WSAGetLastError());
+
+ closesocket(s);
+}
+
START_TEST( sock )
{
int i;
@@ -8427,6 +8492,7 @@ START_TEST( sock )
test_completion_port();
test_address_list_query();
+ test_bind();
/* this is an io heavy test, do it at the end so the kernel doesn't start dropping packets */
test_send();
--
2.30.2
2
7
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/secur32/Makefile.in | 7 +-
dlls/secur32/base64_codec.c | 192 ----
dlls/secur32/dispatcher.c | 335 ------
dlls/secur32/hmac_md5.c | 77 --
dlls/secur32/hmac_md5.h | 48 -
dlls/secur32/negotiate.c | 13 +-
dlls/secur32/ntlm.c | 2029 -----------------------------------
dlls/secur32/secur32_priv.h | 108 --
dlls/secur32/util.c | 187 ----
9 files changed, 13 insertions(+), 2983 deletions(-)
delete mode 100644 dlls/secur32/base64_codec.c
delete mode 100644 dlls/secur32/dispatcher.c
delete mode 100644 dlls/secur32/hmac_md5.c
delete mode 100644 dlls/secur32/hmac_md5.h
delete mode 100644 dlls/secur32/ntlm.c
delete mode 100644 dlls/secur32/util.c
diff --git a/dlls/secur32/Makefile.in b/dlls/secur32/Makefile.in
index c9acdee4572..89a7c8bd078 100644
--- a/dlls/secur32/Makefile.in
+++ b/dlls/secur32/Makefile.in
@@ -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
diff --git a/dlls/secur32/base64_codec.c b/dlls/secur32/base64_codec.c
deleted file mode 100644
index 9f5eaecc3d4..00000000000
--- a/dlls/secur32/base64_codec.c
+++ /dev/null
@@ -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;
-}
diff --git a/dlls/secur32/dispatcher.c b/dlls/secur32/dispatcher.c
deleted file mode 100644
index 0871576848e..00000000000
--- a/dlls/secur32/dispatcher.c
+++ /dev/null
@@ -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, µ);
- 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;
- }
- }
- }
-}
diff --git a/dlls/secur32/hmac_md5.c b/dlls/secur32/hmac_md5.c
deleted file mode 100644
index 3479178132d..00000000000
--- a/dlls/secur32/hmac_md5.c
+++ /dev/null
@@ -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);
-}
diff --git a/dlls/secur32/hmac_md5.h b/dlls/secur32/hmac_md5.h
deleted file mode 100644
index 2bb46dc55ad..00000000000
--- a/dlls/secur32/hmac_md5.h
+++ /dev/null
@@ -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_*/
diff --git a/dlls/secur32/negotiate.c b/dlls/secur32/negotiate.c
index 0df950093e4..6767790d09f 100644
--- a/dlls/secur32/negotiate.c
+++ b/dlls/secur32/negotiate.c
@@ -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;
}
diff --git a/dlls/secur32/ntlm.c b/dlls/secur32/ntlm.c
deleted file mode 100644
index 4e3fda3ea98..00000000000
--- a/dlls/secur32/ntlm.c
+++ /dev/null
@@ -1,2029 +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
- *
- * This file implements the NTLM security provider.
- */
-
-#include <assert.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include "windef.h"
-#include "winbase.h"
-#include "winnls.h"
-#include "wincred.h"
-#include "winternl.h"
-#include "rpc.h"
-#include "sspi.h"
-#include "lm.h"
-#include "secur32_priv.h"
-#include "hmac_md5.h"
-#include "wine/unicode.h"
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(ntlm);
-WINE_DECLARE_DEBUG_CHANNEL(winediag);
-
-#define NTLM_MAX_BUF 1904
-#define MIN_NTLM_AUTH_MAJOR_VERSION 3
-#define MIN_NTLM_AUTH_MINOR_VERSION 0
-#define MIN_NTLM_AUTH_MICRO_VERSION 25
-
-static CHAR ntlm_auth[] = "ntlm_auth";
-
-/***********************************************************************
- * QueryCredentialsAttributesA
- */
-static SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesA(
- PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer)
-{
- SECURITY_STATUS ret;
-
- TRACE("(%p, %d, %p)\n", phCredential, ulAttribute, pBuffer);
-
- if(ulAttribute == SECPKG_ATTR_NAMES)
- {
- FIXME("SECPKG_CRED_ATTR_NAMES: stub\n");
- ret = SEC_E_UNSUPPORTED_FUNCTION;
- }
- else
- ret = SEC_E_UNSUPPORTED_FUNCTION;
-
- return ret;
-}
-
-/***********************************************************************
- * QueryCredentialsAttributesW
- */
-static SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesW(
- PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer)
-{
- SECURITY_STATUS ret;
-
- TRACE("(%p, %d, %p)\n", phCredential, ulAttribute, pBuffer);
-
- if(ulAttribute == SECPKG_ATTR_NAMES)
- {
- FIXME("SECPKG_CRED_ATTR_NAMES: stub\n");
- ret = SEC_E_UNSUPPORTED_FUNCTION;
- }
- else
- ret = SEC_E_UNSUPPORTED_FUNCTION;
-
- return ret;
-}
-
-static char *ntlm_GetUsernameArg(LPCWSTR userW, INT userW_length)
-{
- static const char username_arg[] = "--username=";
- char *user;
- int unixcp_size;
-
- unixcp_size = WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS,
- userW, userW_length, NULL, 0, NULL, NULL) + sizeof(username_arg);
- if (!(user = heap_alloc(unixcp_size))) return NULL;
- memcpy(user, username_arg, sizeof(username_arg) - 1);
- WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS, userW, userW_length,
- user + sizeof(username_arg) - 1,
- unixcp_size - sizeof(username_arg) + 1, NULL, NULL);
- user[unixcp_size - 1] = '\0';
- return user;
-}
-
-static char *ntlm_GetDomainArg(LPCWSTR domainW, INT domainW_length)
-{
- static const char domain_arg[] = "--domain=";
- char *domain;
- int unixcp_size;
-
- unixcp_size = WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS,
- domainW, domainW_length, NULL, 0, NULL, NULL) + sizeof(domain_arg);
- if (!(domain = heap_alloc(unixcp_size))) return NULL;
- memcpy(domain, domain_arg, sizeof(domain_arg) - 1);
- WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS, domainW,
- domainW_length, domain + sizeof(domain_arg) - 1,
- unixcp_size - sizeof(domain) + 1, NULL, NULL);
- domain[unixcp_size - 1] = '\0';
- return domain;
-}
-
-/***********************************************************************
- * AcquireCredentialsHandleW
- */
-static SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleW(
- SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialUse,
- PLUID pLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn,
- PVOID pGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
-{
- SECURITY_STATUS ret = SEC_E_INSUFFICIENT_MEMORY;
- PNtlmCredentials ntlm_cred = NULL;
- LPWSTR domain = NULL, user = NULL, password = NULL;
- PSEC_WINNT_AUTH_IDENTITY_W auth_data = NULL;
-
- TRACE("(%s, %s, 0x%08x, %p, %p, %p, %p, %p, %p)\n",
- debugstr_w(pszPrincipal), debugstr_w(pszPackage), fCredentialUse,
- pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry);
-
- switch (fCredentialUse)
- {
- case SECPKG_CRED_INBOUND:
- if (!(ntlm_cred = heap_alloc(sizeof(*ntlm_cred)))) return SEC_E_INSUFFICIENT_MEMORY;
- ntlm_cred->mode = NTLM_SERVER;
- ntlm_cred->username_arg = NULL;
- ntlm_cred->domain_arg = NULL;
- ntlm_cred->password = NULL;
- ntlm_cred->pwlen = 0;
- ntlm_cred->no_cached_credentials = 0;
-
- phCredential->dwUpper = fCredentialUse;
- phCredential->dwLower = (ULONG_PTR)ntlm_cred;
- ret = SEC_E_OK;
- break;
-
- case SECPKG_CRED_OUTBOUND:
- auth_data = pAuthData;
- if (!(ntlm_cred = heap_alloc(sizeof(*ntlm_cred)))) return SEC_E_INSUFFICIENT_MEMORY;
-
- ntlm_cred->mode = NTLM_CLIENT;
- ntlm_cred->username_arg = NULL;
- ntlm_cred->domain_arg = NULL;
- ntlm_cred->password = NULL;
- ntlm_cred->pwlen = 0;
- ntlm_cred->no_cached_credentials = 0;
-
- if (pAuthData)
- {
- int domain_len = 0, user_len = 0, password_len = 0;
-
- if (auth_data->Flags & SEC_WINNT_AUTH_IDENTITY_ANSI)
- {
- if (auth_data->DomainLength)
- {
- domain_len = MultiByteToWideChar(CP_ACP, 0, (char *)auth_data->Domain,
- auth_data->DomainLength, NULL, 0);
- if (!(domain = heap_alloc(sizeof(WCHAR) * domain_len))) goto done;
- MultiByteToWideChar(CP_ACP, 0, (char *)auth_data->Domain, auth_data->DomainLength,
- domain, domain_len);
- }
- if (auth_data->UserLength)
- {
- user_len = MultiByteToWideChar(CP_ACP, 0, (char *)auth_data->User,
- auth_data->UserLength, NULL, 0);
- if (!(user = heap_alloc(sizeof(WCHAR) * user_len))) goto done;
- MultiByteToWideChar(CP_ACP, 0, (char *)auth_data->User, auth_data->UserLength,
- user, user_len);
- }
- if (auth_data->PasswordLength)
- {
- password_len = MultiByteToWideChar(CP_ACP, 0,(char *)auth_data->Password,
- auth_data->PasswordLength, NULL, 0);
- if (!(password = heap_alloc(sizeof(WCHAR) * password_len))) goto done;
- MultiByteToWideChar(CP_ACP, 0, (char *)auth_data->Password, auth_data->PasswordLength,
- password, password_len);
- }
- }
- else
- {
- domain = auth_data->Domain;
- domain_len = auth_data->DomainLength;
-
- user = auth_data->User;
- user_len = auth_data->UserLength;
-
- password = auth_data->Password;
- password_len = auth_data->PasswordLength;
- }
-
- TRACE("Username is %s\n", debugstr_wn(user, user_len));
- TRACE("Domain name is %s\n", debugstr_wn(domain, domain_len));
-
- ntlm_cred->username_arg = ntlm_GetUsernameArg(user, user_len);
- ntlm_cred->domain_arg = ntlm_GetDomainArg(domain, domain_len);
-
- if (password_len)
- {
- ntlm_cred->pwlen = WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS, password,
- password_len, NULL, 0, NULL, NULL);
- if (!(ntlm_cred->password = heap_alloc(ntlm_cred->pwlen))) goto done;
- WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS, password, password_len,
- ntlm_cred->password, ntlm_cred->pwlen, NULL, NULL);
- }
- }
-
- phCredential->dwUpper = fCredentialUse;
- phCredential->dwLower = (ULONG_PTR)ntlm_cred;
- TRACE("ACH phCredential->dwUpper: 0x%08lx, dwLower: 0x%08lx\n", phCredential->dwUpper,
- phCredential->dwLower);
- ret = SEC_E_OK;
- break;
-
- case SECPKG_CRED_BOTH:
- FIXME("AcquireCredentialsHandle: SECPKG_CRED_BOTH stub\n");
- ret = SEC_E_UNSUPPORTED_FUNCTION;
- break;
-
- default:
- ret = SEC_E_UNKNOWN_CREDENTIALS;
- }
-
-done:
- if (auth_data && (auth_data->Flags & SEC_WINNT_AUTH_IDENTITY_ANSI))
- {
- heap_free(domain);
- heap_free(user);
- heap_free(password);
- }
- if (ret != SEC_E_OK) heap_free( ntlm_cred );
-
- return ret;
-}
-
-/***********************************************************************
- * AcquireCredentialsHandleA
- */
-static SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleA(
- SEC_CHAR *pszPrincipal, SEC_CHAR *pszPackage, ULONG fCredentialUse,
- PLUID pLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn,
- PVOID pGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
-{
- SECURITY_STATUS ret = SEC_E_INSUFFICIENT_MEMORY;
- int user_sizeW, domain_sizeW, passwd_sizeW;
- SEC_WCHAR *user = NULL, *domain = NULL, *passwd = NULL, *package = NULL;
- PSEC_WINNT_AUTH_IDENTITY_W pAuthDataW = NULL;
- PSEC_WINNT_AUTH_IDENTITY_A id = NULL;
-
- TRACE("(%s, %s, 0x%08x, %p, %p, %p, %p, %p, %p)\n",
- debugstr_a(pszPrincipal), debugstr_a(pszPackage), fCredentialUse,
- pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry);
-
- if (pszPackage)
- {
- int package_sizeW = MultiByteToWideChar(CP_ACP, 0, pszPackage, -1, NULL, 0);
- if (!(package = heap_alloc(package_sizeW * sizeof(SEC_WCHAR)))) return SEC_E_INSUFFICIENT_MEMORY;
- MultiByteToWideChar(CP_ACP, 0, pszPackage, -1, package, package_sizeW);
- }
-
- if (pAuthData)
- {
- id = pAuthData;
- if (id->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI)
- {
- if (!(pAuthDataW = heap_alloc(sizeof(SEC_WINNT_AUTH_IDENTITY_W)))) goto done;
-
- if (!id->UserLength) user_sizeW = 0;
- else
- {
- user_sizeW = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)id->User, id->UserLength, NULL, 0);
- if (!(user = heap_alloc(user_sizeW * sizeof(SEC_WCHAR)))) goto done;
- MultiByteToWideChar(CP_ACP, 0, (LPCSTR)id->User, id->UserLength, user, user_sizeW);
- }
-
- if (!id->DomainLength) domain_sizeW = 0;
- else
- {
- domain_sizeW = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)id->Domain, id->DomainLength, NULL, 0);
- if (!(domain = heap_alloc(domain_sizeW * sizeof(SEC_WCHAR)))) goto done;
- MultiByteToWideChar(CP_ACP, 0, (LPCSTR)id->Domain, id->DomainLength, domain, domain_sizeW);
- }
-
- if (!id->PasswordLength) passwd_sizeW = 0;
- else
- {
- passwd_sizeW = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)id->Password, id->PasswordLength, NULL, 0);
- if (!(passwd = heap_alloc(passwd_sizeW * sizeof(SEC_WCHAR)))) goto done;
- MultiByteToWideChar(CP_ACP, 0, (LPCSTR)id->Password, id->PasswordLength, passwd, passwd_sizeW);
- }
-
- pAuthDataW->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
- pAuthDataW->User = user;
- pAuthDataW->UserLength = user_sizeW;
- pAuthDataW->Domain = domain;
- pAuthDataW->DomainLength = domain_sizeW;
- pAuthDataW->Password = passwd;
- pAuthDataW->PasswordLength = passwd_sizeW;
- }
- else pAuthDataW = (PSEC_WINNT_AUTH_IDENTITY_W)id;
- }
-
- ret = ntlm_AcquireCredentialsHandleW(NULL, package, fCredentialUse,
- pLogonID, pAuthDataW, pGetKeyFn, pGetKeyArgument, phCredential,
- ptsExpiry);
-
-done:
- heap_free(package);
- heap_free(user);
- heap_free(domain);
- heap_free(passwd);
- if (pAuthDataW != (PSEC_WINNT_AUTH_IDENTITY_W)id) heap_free(pAuthDataW);
-
- return ret;
-}
-
-/*************************************************************************
- * ntlm_GetTokenBufferIndex
- * Calculates the index of the secbuffer with BufferType == SECBUFFER_TOKEN
- * Returns index if found or -1 if not found.
- */
-static int ntlm_GetTokenBufferIndex(PSecBufferDesc pMessage)
-{
- UINT i;
-
- TRACE("%p\n", pMessage);
-
- for( i = 0; i < pMessage->cBuffers; ++i )
- {
- if(pMessage->pBuffers[i].BufferType == SECBUFFER_TOKEN)
- return i;
- }
-
- return -1;
-}
-
-/*************************************************************************
- * ntlm_GetDataBufferIndex
- * Calculates the index of the first secbuffer with BufferType == SECBUFFER_DATA
- * Returns index if found or -1 if not found.
- */
-static int ntlm_GetDataBufferIndex(PSecBufferDesc pMessage)
-{
- UINT i;
-
- TRACE("%p\n", pMessage);
-
- for( i = 0; i < pMessage->cBuffers; ++i )
- {
- if(pMessage->pBuffers[i].BufferType == SECBUFFER_DATA)
- return i;
- }
-
- return -1;
-}
-
-static BOOL ntlm_GetCachedCredential(const SEC_WCHAR *pszTargetName, PCREDENTIALW *cred)
-{
- LPCWSTR p;
- LPCWSTR pszHost;
- LPWSTR pszHostOnly;
- BOOL ret;
-
- if (!pszTargetName)
- return FALSE;
-
- /* try to get the start of the hostname from service principal name (SPN) */
- pszHost = strchrW(pszTargetName, '/');
- if (pszHost)
- {
- /* skip slash character */
- pszHost++;
-
- /* find end of host by detecting start of instance port or start of referrer */
- p = strchrW(pszHost, ':');
- if (!p)
- p = strchrW(pszHost, '/');
- if (!p)
- p = pszHost + strlenW(pszHost);
- }
- else /* otherwise not an SPN, just a host */
- {
- pszHost = pszTargetName;
- p = pszHost + strlenW(pszHost);
- }
-
- if (!(pszHostOnly = heap_alloc((p - pszHost + 1) * sizeof(WCHAR)))) return FALSE;
- memcpy(pszHostOnly, pszHost, (p - pszHost) * sizeof(WCHAR));
- pszHostOnly[p - pszHost] = '\0';
-
- ret = CredReadW(pszHostOnly, CRED_TYPE_DOMAIN_PASSWORD, 0, cred);
-
- heap_free(pszHostOnly);
- return ret;
-}
-
-/***********************************************************************
- * InitializeSecurityContextW
- */
-static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(
- PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR *pszTargetName,
- ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
- PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
- PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
-{
- SECURITY_STATUS ret;
- PNtlmCredentials ntlm_cred;
- PNegoHelper helper = NULL;
- ULONG ctxt_attr = 0;
- char* buffer, *want_flags = NULL;
- PBYTE bin;
- int buffer_len, bin_len, max_len = NTLM_MAX_BUF;
- int token_idx;
- SEC_CHAR *username = NULL;
- SEC_CHAR *domain = NULL;
- SEC_CHAR *password = NULL;
-
- TRACE("%p %p %s 0x%08x %d %d %p %d %p %p %p %p\n", phCredential, phContext,
- debugstr_w(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput,
- Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry);
-
- /****************************************
- * When communicating with the client, there can be the
- * following reply packets:
- * YR <base64 blob> should be sent to the server
- * PW should be sent back to helper with
- * base64 encoded password
- * AF <base64 blob> client is done, blob should be
- * sent to server with KK prefixed
- * GF <string list> A string list of negotiated flags
- * GK <base64 blob> base64 encoded session key
- * BH <char reason> something broke
- */
- /* The squid cache size is 2010 chars, and that's what ntlm_auth uses */
-
- if(TargetDataRep == SECURITY_NETWORK_DREP){
- TRACE("Setting SECURITY_NETWORK_DREP\n");
- }
-
- buffer = heap_alloc(sizeof(char) * NTLM_MAX_BUF);
- bin = heap_alloc(sizeof(BYTE) * NTLM_MAX_BUF);
-
- if((phContext == NULL) && (pInput == NULL))
- {
- static char helper_protocol[] = "--helper-protocol=ntlmssp-client-1";
- static CHAR credentials_argv[] = "--use-cached-creds";
- SEC_CHAR *client_argv[5];
- int pwlen = 0;
-
- TRACE("First time in ISC()\n");
-
- if(!phCredential)
- {
- ret = SEC_E_INVALID_HANDLE;
- goto isc_end;
- }
-
- /* As the server side of sspi never calls this, make sure that
- * the handler is a client handler.
- */
- ntlm_cred = (PNtlmCredentials)phCredential->dwLower;
- if(ntlm_cred->mode != NTLM_CLIENT)
- {
- TRACE("Cred mode = %d\n", ntlm_cred->mode);
- ret = SEC_E_INVALID_HANDLE;
- goto isc_end;
- }
-
- client_argv[0] = ntlm_auth;
- client_argv[1] = helper_protocol;
- if (!ntlm_cred->username_arg && !ntlm_cred->domain_arg)
- {
- LPWKSTA_USER_INFO_1 ui = NULL;
- NET_API_STATUS status;
- PCREDENTIALW cred;
-
- if (ntlm_GetCachedCredential(pszTargetName, &cred))
- {
- LPWSTR p;
- p = strchrW(cred->UserName, '\\');
- if (p)
- {
- domain = ntlm_GetDomainArg(cred->UserName, p - cred->UserName);
- p++;
- }
- else
- {
- domain = ntlm_GetDomainArg(NULL, 0);
- p = cred->UserName;
- }
-
- username = ntlm_GetUsernameArg(p, -1);
-
- if(cred->CredentialBlobSize != 0)
- {
- pwlen = WideCharToMultiByte(CP_UNIXCP,
- WC_NO_BEST_FIT_CHARS, (LPWSTR)cred->CredentialBlob,
- cred->CredentialBlobSize / sizeof(WCHAR), NULL, 0,
- NULL, NULL);
-
- password = heap_alloc(pwlen);
- WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS,
- (LPWSTR)cred->CredentialBlob,
- cred->CredentialBlobSize / sizeof(WCHAR),
- password, pwlen, NULL, NULL);
- }
-
- CredFree(cred);
-
- client_argv[2] = username;
- client_argv[3] = domain;
- client_argv[4] = NULL;
- }
- else
- {
- status = NetWkstaUserGetInfo(NULL, 1, (LPBYTE *)&ui);
- if (status != NERR_Success || ui == NULL || ntlm_cred->no_cached_credentials)
- {
- ret = SEC_E_NO_CREDENTIALS;
- goto isc_end;
- }
- username = ntlm_GetUsernameArg(ui->wkui1_username, -1);
- NetApiBufferFree(ui);
-
- TRACE("using cached credentials\n");
-
- client_argv[2] = username;
- client_argv[3] = credentials_argv;
- client_argv[4] = NULL;
- }
- }
- else
- {
- client_argv[2] = ntlm_cred->username_arg;
- client_argv[3] = ntlm_cred->domain_arg;
- client_argv[4] = NULL;
- }
-
- if((ret = fork_helper(&helper, ntlm_auth, client_argv)) != SEC_E_OK)
- goto isc_end;
-
- helper->mode = NTLM_CLIENT;
- helper->session_key = heap_alloc(16);
- if (!helper->session_key)
- {
- cleanup_helper(helper);
- ret = SEC_E_INSUFFICIENT_MEMORY;
- goto isc_end;
- }
-
- /* Generate the dummy session key = MD4(MD4(password))*/
- if(password || ntlm_cred->password)
- {
- SEC_WCHAR *unicode_password;
- int passwd_lenW;
-
- TRACE("Converting password to unicode.\n");
- passwd_lenW = MultiByteToWideChar(CP_ACP, 0,
- password ? password : ntlm_cred->password,
- password ? pwlen : ntlm_cred->pwlen,
- NULL, 0);
- unicode_password = heap_alloc(passwd_lenW * sizeof(SEC_WCHAR));
- MultiByteToWideChar(CP_ACP, 0, password ? password : ntlm_cred->password,
- password ? pwlen : ntlm_cred->pwlen, unicode_password, passwd_lenW);
-
- SECUR32_CreateNTLM1SessionKey((PBYTE)unicode_password,
- passwd_lenW * sizeof(SEC_WCHAR), helper->session_key);
- heap_free(unicode_password);
- }
- else
- memset(helper->session_key, 0, 16);
-
- /* Allocate space for a maximal string of
- * "SF NTLMSSP_FEATURE_SIGN NTLMSSP_FEATURE_SEAL
- * NTLMSSP_FEATURE_SESSION_KEY"
- */
- if (!(want_flags = heap_alloc(73)))
- {
- cleanup_helper(helper);
- ret = SEC_E_INSUFFICIENT_MEMORY;
- goto isc_end;
- }
- lstrcpyA(want_flags, "SF");
- if(fContextReq & ISC_REQ_CONFIDENTIALITY)
- {
- if(strstr(want_flags, "NTLMSSP_FEATURE_SEAL") == NULL)
- lstrcatA(want_flags, " NTLMSSP_FEATURE_SEAL");
- }
- if(fContextReq & ISC_REQ_CONNECTION)
- ctxt_attr |= ISC_RET_CONNECTION;
- if(fContextReq & ISC_REQ_EXTENDED_ERROR)
- ctxt_attr |= ISC_RET_EXTENDED_ERROR;
- if(fContextReq & ISC_REQ_INTEGRITY)
- {
- if(strstr(want_flags, "NTLMSSP_FEATURE_SIGN") == NULL)
- lstrcatA(want_flags, " NTLMSSP_FEATURE_SIGN");
- }
- if(fContextReq & ISC_REQ_MUTUAL_AUTH)
- ctxt_attr |= ISC_RET_MUTUAL_AUTH;
- if(fContextReq & ISC_REQ_REPLAY_DETECT)
- {
- if(strstr(want_flags, "NTLMSSP_FEATURE_SIGN") == NULL)
- lstrcatA(want_flags, " NTLMSSP_FEATURE_SIGN");
- }
- if(fContextReq & ISC_REQ_SEQUENCE_DETECT)
- {
- if(strstr(want_flags, "NTLMSSP_FEATURE_SIGN") == NULL)
- lstrcatA(want_flags, " NTLMSSP_FEATURE_SIGN");
- }
- if(fContextReq & ISC_REQ_STREAM)
- FIXME("ISC_REQ_STREAM\n");
- if(fContextReq & ISC_REQ_USE_DCE_STYLE)
- ctxt_attr |= ISC_RET_USED_DCE_STYLE;
- if(fContextReq & ISC_REQ_DELEGATE)
- ctxt_attr |= ISC_RET_DELEGATE;
-
- /* If no password is given, try to use cached credentials. Fall back to an empty
- * password if this failed. */
- if(!password && !ntlm_cred->password)
- {
- lstrcpynA(buffer, "OK", max_len-1);
- if((ret = run_helper(helper, buffer, max_len, &buffer_len)) != SEC_E_OK)
- {
- cleanup_helper(helper);
- goto isc_end;
- }
- /* If the helper replied with "PW", using cached credentials failed */
- if(!strncmp(buffer, "PW", 2))
- {
- TRACE("Using cached credentials failed.\n");
- lstrcpynA(buffer, "PW AA==", max_len-1);
- }
- else /* Just do a noop on the next run */
- lstrcpynA(buffer, "OK", max_len-1);
- }
- else
- {
- lstrcpynA(buffer, "PW ", max_len-1);
- if((ret = encodeBase64(password ? (unsigned char *)password : (unsigned char *)ntlm_cred->password,
- password ? pwlen : ntlm_cred->pwlen, buffer+3,
- max_len-3, &buffer_len)) != SEC_E_OK)
- {
- cleanup_helper(helper);
- goto isc_end;
- }
-
- }
-
- TRACE("Sending to helper: %s\n", debugstr_a(buffer));
- if((ret = run_helper(helper, buffer, max_len, &buffer_len)) != SEC_E_OK)
- {
- cleanup_helper(helper);
- goto isc_end;
- }
-
- TRACE("Helper returned %s\n", debugstr_a(buffer));
-
- if(lstrlenA(want_flags) > 2)
- {
- TRACE("Want flags are %s\n", debugstr_a(want_flags));
- lstrcpynA(buffer, want_flags, max_len-1);
- if((ret = run_helper(helper, buffer, max_len, &buffer_len))
- != SEC_E_OK)
- {
- cleanup_helper(helper);
- goto isc_end;
- }
- if(!strncmp(buffer, "BH", 2))
- ERR("Helper doesn't understand new command set. Expect more things to fail.\n");
- }
-
- lstrcpynA(buffer, "YR", max_len-1);
-
- if((ret = run_helper(helper, buffer, max_len, &buffer_len)) != SEC_E_OK)
- {
- cleanup_helper(helper);
- goto isc_end;
- }
-
- TRACE("%s\n", buffer);
-
- if(strncmp(buffer, "YR ", 3) != 0)
- {
- /* Something borked */
- TRACE("Helper returned %c%c\n", buffer[0], buffer[1]);
- ret = SEC_E_INTERNAL_ERROR;
- cleanup_helper(helper);
- goto isc_end;
- }
- if((ret = decodeBase64(buffer+3, buffer_len-3, bin,
- max_len-1, &bin_len)) != SEC_E_OK)
- {
- cleanup_helper(helper);
- goto isc_end;
- }
-
- /* put the decoded client blob into the out buffer */
-
- phNewContext->dwUpper = ctxt_attr;
- phNewContext->dwLower = (ULONG_PTR)helper;
-
- ret = SEC_I_CONTINUE_NEEDED;
- }
- else
- {
- int input_token_idx;
-
- /* handle second call here */
- /* encode server data to base64 */
- if (!pInput || ((input_token_idx = ntlm_GetTokenBufferIndex(pInput)) == -1))
- {
- ret = SEC_E_INVALID_TOKEN;
- goto isc_end;
- }
-
- if(!phContext)
- {
- ret = SEC_E_INVALID_HANDLE;
- goto isc_end;
- }
-
- /* As the server side of sspi never calls this, make sure that
- * the handler is a client handler.
- */
- helper = (PNegoHelper)phContext->dwLower;
- if(helper->mode != NTLM_CLIENT)
- {
- TRACE("Helper mode = %d\n", helper->mode);
- ret = SEC_E_INVALID_HANDLE;
- goto isc_end;
- }
-
- if (!pInput->pBuffers[input_token_idx].pvBuffer)
- {
- ret = SEC_E_INTERNAL_ERROR;
- goto isc_end;
- }
-
- if(pInput->pBuffers[input_token_idx].cbBuffer > max_len)
- {
- TRACE("pInput->pBuffers[%d].cbBuffer is: %d\n",
- input_token_idx,
- pInput->pBuffers[input_token_idx].cbBuffer);
- ret = SEC_E_INVALID_TOKEN;
- goto isc_end;
- }
- else
- bin_len = pInput->pBuffers[input_token_idx].cbBuffer;
-
- memcpy(bin, pInput->pBuffers[input_token_idx].pvBuffer, bin_len);
-
- lstrcpynA(buffer, "TT ", max_len-1);
-
- if((ret = encodeBase64(bin, bin_len, buffer+3,
- max_len-3, &buffer_len)) != SEC_E_OK)
- goto isc_end;
-
- TRACE("Server sent: %s\n", debugstr_a(buffer));
-
- /* send TT base64 blob to ntlm_auth */
- if((ret = run_helper(helper, buffer, max_len, &buffer_len)) != SEC_E_OK)
- goto isc_end;
-
- TRACE("Helper replied: %s\n", debugstr_a(buffer));
-
- if( (strncmp(buffer, "KK ", 3) != 0) &&
- (strncmp(buffer, "AF ", 3) !=0))
- {
- TRACE("Helper returned %c%c\n", buffer[0], buffer[1]);
- ret = SEC_E_INVALID_TOKEN;
- goto isc_end;
- }
-
- /* decode the blob and send it to server */
- if((ret = decodeBase64(buffer+3, buffer_len-3, bin, max_len,
- &bin_len)) != SEC_E_OK)
- {
- goto isc_end;
- }
-
- phNewContext->dwUpper = ctxt_attr;
- phNewContext->dwLower = (ULONG_PTR)helper;
-
- ret = SEC_E_OK;
- }
-
- /* put the decoded client blob into the out buffer */
-
- if (!pOutput || ((token_idx = ntlm_GetTokenBufferIndex(pOutput)) == -1))
- {
- TRACE("no SECBUFFER_TOKEN buffer could be found\n");
- ret = SEC_E_BUFFER_TOO_SMALL;
- if ((phContext == NULL) && (pInput == NULL))
- {
- cleanup_helper(helper);
- phNewContext->dwUpper = 0;
- phNewContext->dwLower = 0;
- }
- goto isc_end;
- }
-
- if (fContextReq & ISC_REQ_ALLOCATE_MEMORY)
- {
- pOutput->pBuffers[token_idx].pvBuffer = heap_alloc(bin_len);
- pOutput->pBuffers[token_idx].cbBuffer = bin_len;
- }
- else if (pOutput->pBuffers[token_idx].cbBuffer < bin_len)
- {
- TRACE("out buffer is NULL or has not enough space\n");
- ret = SEC_E_BUFFER_TOO_SMALL;
- if ((phContext == NULL) && (pInput == NULL))
- {
- cleanup_helper(helper);
- phNewContext->dwUpper = 0;
- phNewContext->dwLower = 0;
- }
- goto isc_end;
- }
-
- if (!pOutput->pBuffers[token_idx].pvBuffer)
- {
- TRACE("out buffer is NULL\n");
- ret = SEC_E_INTERNAL_ERROR;
- if ((phContext == NULL) && (pInput == NULL))
- {
- cleanup_helper(helper);
- phNewContext->dwUpper = 0;
- phNewContext->dwLower = 0;
- }
- goto isc_end;
- }
-
- pOutput->pBuffers[token_idx].cbBuffer = bin_len;
- memcpy(pOutput->pBuffers[token_idx].pvBuffer, bin, bin_len);
-
- if(ret == SEC_E_OK)
- {
- TRACE("Getting negotiated flags\n");
- lstrcpynA(buffer, "GF", max_len - 1);
- if((ret = run_helper(helper, buffer, max_len, &buffer_len)) != SEC_E_OK)
- goto isc_end;
-
- if(buffer_len < 3)
- {
- TRACE("No flags negotiated.\n");
- helper->neg_flags = 0l;
- }
- else
- {
- TRACE("Negotiated %s\n", debugstr_a(buffer));
- sscanf(buffer + 3, "%x", &(helper->neg_flags));
- TRACE("Stored 0x%08x as flags\n", helper->neg_flags);
- }
-
- TRACE("Getting session key\n");
- lstrcpynA(buffer, "GK", max_len - 1);
- if((ret = run_helper(helper, buffer, max_len, &buffer_len)) != SEC_E_OK)
- goto isc_end;
-
- if(strncmp(buffer, "BH", 2) == 0)
- TRACE("No key negotiated.\n");
- else if(strncmp(buffer, "GK ", 3) == 0)
- {
- if((ret = decodeBase64(buffer+3, buffer_len-3, bin, max_len,
- &bin_len)) != SEC_E_OK)
- {
- TRACE("Failed to decode session key\n");
- }
- TRACE("Session key is %s\n", debugstr_a(buffer+3));
- heap_free(helper->session_key);
- if (!(helper->session_key = heap_alloc(bin_len)))
- {
- ret = SEC_E_INSUFFICIENT_MEMORY;
- goto isc_end;
- }
- memcpy(helper->session_key, bin, bin_len);
- }
-
- helper->crypt.ntlm.a4i = SECUR32_arc4Alloc();
- SECUR32_arc4Init(helper->crypt.ntlm.a4i, helper->session_key, 16);
- helper->crypt.ntlm.seq_num = 0l;
- SECUR32_CreateNTLM2SubKeys(helper);
- helper->crypt.ntlm2.send_a4i = SECUR32_arc4Alloc();
- helper->crypt.ntlm2.recv_a4i = SECUR32_arc4Alloc();
- SECUR32_arc4Init(helper->crypt.ntlm2.send_a4i,
- helper->crypt.ntlm2.send_seal_key, 16);
- SECUR32_arc4Init(helper->crypt.ntlm2.recv_a4i,
- helper->crypt.ntlm2.recv_seal_key, 16);
- helper->crypt.ntlm2.send_seq_no = 0l;
- helper->crypt.ntlm2.recv_seq_no = 0l;
- }
-
-isc_end:
- heap_free(username);
- heap_free(domain);
- heap_free(password);
- heap_free(want_flags);
- heap_free(buffer);
- heap_free(bin);
- return ret;
-}
-
-/***********************************************************************
- * InitializeSecurityContextA
- */
-static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA(
- PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR *pszTargetName,
- ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
- PSecBufferDesc pInput,ULONG Reserved2, PCtxtHandle phNewContext,
- PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
-{
- SECURITY_STATUS ret;
- SEC_WCHAR *target = NULL;
-
- TRACE("%p %p %s %d %d %d %p %d %p %p %p %p\n", phCredential, phContext,
- debugstr_a(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput,
- Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry);
-
- if (pszTargetName)
- {
- int target_size = MultiByteToWideChar(CP_ACP, 0, pszTargetName, -1, NULL, 0);
- if (!(target = heap_alloc(target_size * sizeof(SEC_WCHAR)))) return SEC_E_INSUFFICIENT_MEMORY;
- MultiByteToWideChar(CP_ACP, 0, pszTargetName, -1, target, target_size);
- }
-
- ret = ntlm_InitializeSecurityContextW(phCredential, phContext, target,
- fContextReq, Reserved1, TargetDataRep, pInput, Reserved2,
- phNewContext, pOutput, pfContextAttr, ptsExpiry);
-
- heap_free(target);
- return ret;
-}
-
-/***********************************************************************
- * AcceptSecurityContext
- */
-static SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(
- PCredHandle phCredential, PCtxtHandle phContext, PSecBufferDesc pInput,
- ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext,
- PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
-{
- SECURITY_STATUS ret;
- char *buffer, *want_flags = NULL;
- PBYTE bin;
- int buffer_len, bin_len, max_len = NTLM_MAX_BUF;
- ULONG ctxt_attr = 0;
- PNegoHelper helper;
- PNtlmCredentials ntlm_cred;
-
- TRACE("%p %p %p %d %d %p %p %p %p\n", phCredential, phContext, pInput,
- fContextReq, TargetDataRep, phNewContext, pOutput, pfContextAttr,
- ptsExpiry);
-
- buffer = heap_alloc(sizeof(char) * NTLM_MAX_BUF);
- bin = heap_alloc(sizeof(BYTE) * NTLM_MAX_BUF);
-
- if(TargetDataRep == SECURITY_NETWORK_DREP){
- TRACE("Using SECURITY_NETWORK_DREP\n");
- }
-
- if(phContext == NULL)
- {
- static CHAR server_helper_protocol[] = "--helper-protocol=squid-2.5-ntlmssp";
- SEC_CHAR *server_argv[] = { ntlm_auth,
- server_helper_protocol,
- NULL };
-
- if (!phCredential)
- {
- ret = SEC_E_INVALID_HANDLE;
- goto asc_end;
- }
-
- ntlm_cred = (PNtlmCredentials)phCredential->dwLower;
-
- if(ntlm_cred->mode != NTLM_SERVER)
- {
- ret = SEC_E_INVALID_HANDLE;
- goto asc_end;
- }
-
- /* This is the first call to AcceptSecurityHandle */
- if(pInput == NULL)
- {
- ret = SEC_E_INCOMPLETE_MESSAGE;
- goto asc_end;
- }
-
- if(pInput->cBuffers < 1)
- {
- ret = SEC_E_INCOMPLETE_MESSAGE;
- goto asc_end;
- }
-
- if(pInput->pBuffers[0].cbBuffer > max_len)
- {
- ret = SEC_E_INVALID_TOKEN;
- goto asc_end;
- }
- else
- bin_len = pInput->pBuffers[0].cbBuffer;
-
- if( (ret = fork_helper(&helper, ntlm_auth, server_argv)) !=
- SEC_E_OK)
- {
- ret = SEC_E_INTERNAL_ERROR;
- goto asc_end;
- }
- helper->mode = NTLM_SERVER;
-
- /* Handle all the flags */
- if (!(want_flags = heap_alloc(73)))
- {
- TRACE("Failed to allocate memory for the want_flags!\n");
- ret = SEC_E_INSUFFICIENT_MEMORY;
- cleanup_helper(helper);
- goto asc_end;
- }
- lstrcpyA(want_flags, "SF");
- if(fContextReq & ASC_REQ_ALLOCATE_MEMORY)
- {
- FIXME("ASC_REQ_ALLOCATE_MEMORY stub\n");
- }
- if(fContextReq & ASC_REQ_CONFIDENTIALITY)
- {
- lstrcatA(want_flags, " NTLMSSP_FEATURE_SEAL");
- }
- if(fContextReq & ASC_REQ_CONNECTION)
- {
- /* This is default, so we'll enable it */
- lstrcatA(want_flags, " NTLMSSP_FEATURE_SESSION_KEY");
- ctxt_attr |= ASC_RET_CONNECTION;
- }
- if(fContextReq & ASC_REQ_EXTENDED_ERROR)
- {
- FIXME("ASC_REQ_EXTENDED_ERROR stub\n");
- }
- if(fContextReq & ASC_REQ_INTEGRITY)
- {
- lstrcatA(want_flags, " NTLMSSP_FEATURE_SIGN");
- }
- if(fContextReq & ASC_REQ_MUTUAL_AUTH)
- {
- FIXME("ASC_REQ_MUTUAL_AUTH stub\n");
- }
- if(fContextReq & ASC_REQ_REPLAY_DETECT)
- {
- FIXME("ASC_REQ_REPLAY_DETECT stub\n");
- }
- if(fContextReq & ISC_REQ_SEQUENCE_DETECT)
- {
- FIXME("ASC_REQ_SEQUENCE_DETECT stub\n");
- }
- if(fContextReq & ISC_REQ_STREAM)
- {
- FIXME("ASC_REQ_STREAM stub\n");
- }
- /* Done with the flags */
-
- if(lstrlenA(want_flags) > 3)
- {
- TRACE("Server set want_flags: %s\n", debugstr_a(want_flags));
- lstrcpynA(buffer, want_flags, max_len - 1);
- if((ret = run_helper(helper, buffer, max_len, &buffer_len)) !=
- SEC_E_OK)
- {
- cleanup_helper(helper);
- goto asc_end;
- }
- if(!strncmp(buffer, "BH", 2))
- TRACE("Helper doesn't understand new command set\n");
- }
-
- /* This is the YR request from the client, encode to base64 */
-
- memcpy(bin, pInput->pBuffers[0].pvBuffer, bin_len);
-
- lstrcpynA(buffer, "YR ", max_len-1);
-
- if((ret = encodeBase64(bin, bin_len, buffer+3, max_len-3,
- &buffer_len)) != SEC_E_OK)
- {
- cleanup_helper(helper);
- goto asc_end;
- }
-
- TRACE("Client sent: %s\n", debugstr_a(buffer));
-
- if((ret = run_helper(helper, buffer, max_len, &buffer_len)) !=
- SEC_E_OK)
- {
- cleanup_helper(helper);
- goto asc_end;
- }
-
- TRACE("Reply from ntlm_auth: %s\n", debugstr_a(buffer));
- /* The expected answer is TT <base64 blob> */
-
- if(strncmp(buffer, "TT ", 3) != 0)
- {
- ret = SEC_E_INTERNAL_ERROR;
- cleanup_helper(helper);
- goto asc_end;
- }
-
- if((ret = decodeBase64(buffer+3, buffer_len-3, bin, max_len,
- &bin_len)) != SEC_E_OK)
- {
- cleanup_helper(helper);
- goto asc_end;
- }
-
- /* send this to the client */
- if(pOutput == NULL)
- {
- ret = SEC_E_INSUFFICIENT_MEMORY;
- cleanup_helper(helper);
- goto asc_end;
- }
-
- if(pOutput->cBuffers < 1)
- {
- ret = SEC_E_INSUFFICIENT_MEMORY;
- cleanup_helper(helper);
- goto asc_end;
- }
-
- pOutput->pBuffers[0].cbBuffer = bin_len;
- pOutput->pBuffers[0].BufferType = SECBUFFER_DATA;
- memcpy(pOutput->pBuffers[0].pvBuffer, bin, bin_len);
- ret = SEC_I_CONTINUE_NEEDED;
-
- }
- else
- {
- /* we expect a KK request from client */
- if(pInput == NULL)
- {
- ret = SEC_E_INCOMPLETE_MESSAGE;
- goto asc_end;
- }
-
- if(pInput->cBuffers < 1)
- {
- ret = SEC_E_INCOMPLETE_MESSAGE;
- goto asc_end;
- }
-
- helper = (PNegoHelper)phContext->dwLower;
-
- if(helper->mode != NTLM_SERVER)
- {
- ret = SEC_E_INVALID_HANDLE;
- goto asc_end;
- }
-
- if(pInput->pBuffers[0].cbBuffer > max_len)
- {
- ret = SEC_E_INVALID_TOKEN;
- goto asc_end;
- }
- else
- bin_len = pInput->pBuffers[0].cbBuffer;
-
- memcpy(bin, pInput->pBuffers[0].pvBuffer, bin_len);
-
- lstrcpynA(buffer, "KK ", max_len-1);
-
- if((ret = encodeBase64(bin, bin_len, buffer+3, max_len-3,
- &buffer_len)) != SEC_E_OK)
- {
- goto asc_end;
- }
-
- TRACE("Client sent: %s\n", debugstr_a(buffer));
-
- if((ret = run_helper(helper, buffer, max_len, &buffer_len)) !=
- SEC_E_OK)
- {
- goto asc_end;
- }
-
- TRACE("Reply from ntlm_auth: %s\n", debugstr_a(buffer));
-
- /* At this point, we get a NA if the user didn't authenticate, but a BH
- * if ntlm_auth could not connect to winbindd. Apart from running Wine
- * as root, there is no way to fix this for now, so just handle this as
- * a failed login. */
- if(strncmp(buffer, "AF ", 3) != 0)
- {
- if(strncmp(buffer, "NA ", 3) == 0)
- {
- ret = SEC_E_LOGON_DENIED;
- goto asc_end;
- }
- else
- {
- size_t ntlm_pipe_err_v3_len = strlen("BH NT_STATUS_ACCESS_DENIED");
- size_t ntlm_pipe_err_v4_len = strlen("BH NT_STATUS_UNSUCCESSFUL");
-
- if( (buffer_len >= ntlm_pipe_err_v3_len &&
- strncmp(buffer, "BH NT_STATUS_ACCESS_DENIED", ntlm_pipe_err_v3_len) == 0) ||
- (buffer_len >= ntlm_pipe_err_v4_len &&
- strncmp(buffer, "BH NT_STATUS_UNSUCCESSFUL", ntlm_pipe_err_v4_len) == 0) )
- {
- TRACE("Connection to winbindd failed\n");
- ret = SEC_E_LOGON_DENIED;
- }
- else
- ret = SEC_E_INTERNAL_ERROR;
-
- goto asc_end;
- }
- }
- pOutput->pBuffers[0].cbBuffer = 0;
-
- TRACE("Getting negotiated flags\n");
- lstrcpynA(buffer, "GF", max_len - 1);
- if((ret = run_helper(helper, buffer, max_len, &buffer_len)) != SEC_E_OK)
- goto asc_end;
-
- if(buffer_len < 3)
- {
- TRACE("No flags negotiated, or helper does not support GF command\n");
- }
- else
- {
- TRACE("Negotiated %s\n", debugstr_a(buffer));
- sscanf(buffer + 3, "%x", &(helper->neg_flags));
- TRACE("Stored 0x%08x as flags\n", helper->neg_flags);
- }
-
- TRACE("Getting session key\n");
- lstrcpynA(buffer, "GK", max_len - 1);
- if((ret = run_helper(helper, buffer, max_len, &buffer_len)) != SEC_E_OK)
- goto asc_end;
-
- if(buffer_len < 3)
- TRACE("Helper does not support GK command\n");
- else
- {
- if(strncmp(buffer, "BH ", 3) == 0)
- {
- TRACE("Helper sent %s\n", debugstr_a(buffer+3));
- heap_free(helper->session_key);
- if (!(helper->session_key = heap_alloc(16)))
- {
- ret = SEC_E_INSUFFICIENT_MEMORY;
- goto asc_end;
- }
- /*FIXME: Generate the dummy session key = MD4(MD4(password))*/
- memset(helper->session_key, 0 , 16);
- }
- else if(strncmp(buffer, "GK ", 3) == 0)
- {
- if((ret = decodeBase64(buffer+3, buffer_len-3, bin, max_len,
- &bin_len)) != SEC_E_OK)
- {
- TRACE("Failed to decode session key\n");
- }
- TRACE("Session key is %s\n", debugstr_a(buffer+3));
- heap_free(helper->session_key);
- if (!(helper->session_key = heap_alloc(16)))
- {
- ret = SEC_E_INSUFFICIENT_MEMORY;
- goto asc_end;
- }
- memcpy(helper->session_key, bin, 16);
- }
- }
- helper->crypt.ntlm.a4i = SECUR32_arc4Alloc();
- SECUR32_arc4Init(helper->crypt.ntlm.a4i, helper->session_key, 16);
- helper->crypt.ntlm.seq_num = 0l;
- }
-
- phNewContext->dwUpper = ctxt_attr;
- phNewContext->dwLower = (ULONG_PTR)helper;
-
-asc_end:
- heap_free(want_flags);
- heap_free(buffer);
- heap_free(bin);
- return ret;
-}
-
-/***********************************************************************
- * CompleteAuthToken
- */
-static SECURITY_STATUS SEC_ENTRY ntlm_CompleteAuthToken(PCtxtHandle phContext,
- PSecBufferDesc pToken)
-{
- /* We never need to call CompleteAuthToken anyway */
- TRACE("%p %p\n", phContext, pToken);
- if (!phContext)
- return SEC_E_INVALID_HANDLE;
-
- return SEC_E_OK;
-}
-
-/***********************************************************************
- * DeleteSecurityContext
- */
-static SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(PCtxtHandle phContext)
-{
- PNegoHelper helper;
-
- TRACE("%p\n", phContext);
- if (!phContext)
- return SEC_E_INVALID_HANDLE;
-
- helper = (PNegoHelper)phContext->dwLower;
-
- phContext->dwUpper = 0;
- phContext->dwLower = 0;
-
- SECUR32_arc4Cleanup(helper->crypt.ntlm.a4i);
- SECUR32_arc4Cleanup(helper->crypt.ntlm2.send_a4i);
- SECUR32_arc4Cleanup(helper->crypt.ntlm2.recv_a4i);
- heap_free(helper->crypt.ntlm2.send_sign_key);
- heap_free(helper->crypt.ntlm2.send_seal_key);
- heap_free(helper->crypt.ntlm2.recv_sign_key);
- heap_free(helper->crypt.ntlm2.recv_seal_key);
-
- cleanup_helper(helper);
-
- return SEC_E_OK;
-}
-
-#define NTLM_COMMENT \
- { 'N', 'T', 'L', 'M', ' ', \
- 'S', 'e', 'c', 'u', 'r', 'i', 't', 'y', ' ', \
- 'P', 'a', 'c', 'k', 'a', 'g', 'e', 0}
-
-static CHAR ntlm_comment_A[] = NTLM_COMMENT;
-static WCHAR ntlm_comment_W[] = NTLM_COMMENT;
-
-#define NTLM_NAME {'N', 'T', 'L', 'M', 0}
-
-static char ntlm_name_A[] = NTLM_NAME;
-static WCHAR ntlm_name_W[] = NTLM_NAME;
-
-#define NTLM_CAPS ( \
- SECPKG_FLAG_INTEGRITY | \
- SECPKG_FLAG_PRIVACY | \
- SECPKG_FLAG_TOKEN_ONLY | \
- SECPKG_FLAG_CONNECTION | \
- SECPKG_FLAG_MULTI_REQUIRED | \
- SECPKG_FLAG_IMPERSONATION | \
- SECPKG_FLAG_ACCEPT_WIN32_NAME | \
- SECPKG_FLAG_NEGOTIABLE | \
- SECPKG_FLAG_LOGON | \
- SECPKG_FLAG_RESTRICTED_TOKENS )
-
-static const SecPkgInfoW infoW = {
- NTLM_CAPS,
- 1,
- RPC_C_AUTHN_WINNT,
- NTLM_MAX_BUF,
- ntlm_name_W,
- ntlm_comment_W
-};
-
-static const SecPkgInfoA infoA = {
- NTLM_CAPS,
- 1,
- RPC_C_AUTHN_WINNT,
- NTLM_MAX_BUF,
- ntlm_name_A,
- ntlm_comment_A
-};
-
-static SecPkgInfoA *ntlm_package_infoA = (SecPkgInfoA *)&infoA;
-static SecPkgInfoW *ntlm_package_infoW = (SecPkgInfoW *)&infoW;
-
-static SecPkgInfoW *build_package_infoW( const SecPkgInfoW *info )
-{
- SecPkgInfoW *ret;
- DWORD size_name = (strlenW(info->Name) + 1) * sizeof(WCHAR);
- DWORD size_comment = (strlenW(info->Comment) + 1) * sizeof(WCHAR);
-
- if (!(ret = heap_alloc( sizeof(*ret) + size_name + size_comment ))) return NULL;
- ret->fCapabilities = info->fCapabilities;
- ret->wVersion = info->wVersion;
- ret->wRPCID = info->wRPCID;
- ret->cbMaxToken = info->cbMaxToken;
- ret->Name = (SEC_WCHAR *)(ret + 1);
- memcpy( ret->Name, info->Name, size_name );
- ret->Comment = (SEC_WCHAR *)((char *)ret->Name + size_name);
- memcpy( ret->Comment, info->Comment, size_comment );
- return ret;
-}
-
-static SecPkgInfoA *build_package_infoA( const SecPkgInfoA *info )
-{
- SecPkgInfoA *ret;
- DWORD size_name = strlen(info->Name) + 1, size_comment = strlen(info->Comment) + 1;
-
- if (!(ret = heap_alloc( sizeof(*ret) + size_name + size_comment ))) return NULL;
- ret->fCapabilities = info->fCapabilities;
- ret->wVersion = info->wVersion;
- ret->wRPCID = info->wRPCID;
- ret->cbMaxToken = info->cbMaxToken;
- ret->Name = (SEC_CHAR *)(ret + 1);
- memcpy( ret->Name, info->Name, size_name );
- ret->Comment = ret->Name + size_name;
- memcpy( ret->Comment, info->Comment, size_comment );
- return ret;
-}
-
-/***********************************************************************
- * QueryContextAttributesW
- */
-static SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext,
- ULONG ulAttribute, void *pBuffer)
-{
- TRACE("%p %d %p\n", phContext, ulAttribute, pBuffer);
- if (!phContext)
- return SEC_E_INVALID_HANDLE;
-
- switch(ulAttribute)
- {
-#define _x(x) case (x) : FIXME(#x" stub\n"); break
- _x(SECPKG_ATTR_ACCESS_TOKEN);
- _x(SECPKG_ATTR_AUTHORITY);
- _x(SECPKG_ATTR_DCE_INFO);
- case SECPKG_ATTR_FLAGS:
- {
- PSecPkgContext_Flags spcf = (PSecPkgContext_Flags)pBuffer;
- PNegoHelper helper = (PNegoHelper)phContext->dwLower;
-
- spcf->Flags = 0;
- if(helper->neg_flags & NTLMSSP_NEGOTIATE_SIGN)
- spcf->Flags |= ISC_RET_INTEGRITY;
- if(helper->neg_flags & NTLMSSP_NEGOTIATE_SEAL)
- spcf->Flags |= ISC_RET_CONFIDENTIALITY;
- return SEC_E_OK;
- }
- _x(SECPKG_ATTR_KEY_INFO);
- _x(SECPKG_ATTR_LIFESPAN);
- _x(SECPKG_ATTR_NAMES);
- _x(SECPKG_ATTR_NATIVE_NAMES);
- case SECPKG_ATTR_NEGOTIATION_INFO:
- {
- SecPkgContext_NegotiationInfoW *info = (SecPkgContext_NegotiationInfoW *)pBuffer;
- if (!(info->PackageInfo = build_package_infoW( &infoW ))) return SEC_E_INSUFFICIENT_MEMORY;
- info->NegotiationState = SECPKG_NEGOTIATION_COMPLETE;
- return SEC_E_OK;
- }
- _x(SECPKG_ATTR_PACKAGE_INFO);
- _x(SECPKG_ATTR_PASSWORD_EXPIRY);
- _x(SECPKG_ATTR_SESSION_KEY);
- case SECPKG_ATTR_SIZES:
- {
- PSecPkgContext_Sizes spcs = (PSecPkgContext_Sizes)pBuffer;
- spcs->cbMaxToken = NTLM_MAX_BUF;
- spcs->cbMaxSignature = 16;
- spcs->cbBlockSize = 0;
- spcs->cbSecurityTrailer = 16;
- return SEC_E_OK;
- }
- _x(SECPKG_ATTR_STREAM_SIZES);
- _x(SECPKG_ATTR_TARGET_INFORMATION);
-#undef _x
- default:
- TRACE("Unknown value %d passed for ulAttribute\n", ulAttribute);
- }
-
- return SEC_E_UNSUPPORTED_FUNCTION;
-}
-
-/***********************************************************************
- * QueryContextAttributesA
- */
-static SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesA(PCtxtHandle phContext,
- ULONG ulAttribute, void *pBuffer)
-{
- switch(ulAttribute)
- {
- case SECPKG_ATTR_NEGOTIATION_INFO:
- {
- SecPkgContext_NegotiationInfoA *info = (SecPkgContext_NegotiationInfoA *)pBuffer;
- if (!(info->PackageInfo = build_package_infoA( &infoA ))) return SEC_E_INSUFFICIENT_MEMORY;
- info->NegotiationState = SECPKG_NEGOTIATION_COMPLETE;
- return SEC_E_OK;
- }
- default:
- return ntlm_QueryContextAttributesW( phContext, ulAttribute, pBuffer );
- }
-}
-
-/***********************************************************************
- * ImpersonateSecurityContext
- */
-static SECURITY_STATUS SEC_ENTRY ntlm_ImpersonateSecurityContext(PCtxtHandle phContext)
-{
- SECURITY_STATUS ret;
-
- TRACE("%p\n", phContext);
- if (phContext)
- {
- ret = SEC_E_UNSUPPORTED_FUNCTION;
- }
- else
- {
- ret = SEC_E_INVALID_HANDLE;
- }
- return ret;
-}
-
-/***********************************************************************
- * RevertSecurityContext
- */
-static SECURITY_STATUS SEC_ENTRY ntlm_RevertSecurityContext(PCtxtHandle phContext)
-{
- SECURITY_STATUS ret;
-
- TRACE("%p\n", phContext);
- if (phContext)
- {
- ret = SEC_E_UNSUPPORTED_FUNCTION;
- }
- else
- {
- ret = SEC_E_INVALID_HANDLE;
- }
- return ret;
-}
-
-/***********************************************************************
- * ntlm_CreateSignature
- * As both MakeSignature and VerifySignature need this, but different keys
- * are needed for NTLM2, the logic goes into a helper function.
- * To ensure maximal reusability, we can specify the direction as NTLM_SEND for
- * signing/encrypting and NTLM_RECV for verifying/decrypting. When encrypting,
- * the signature is encrypted after the message was encrypted, so
- * CreateSignature shouldn't do it. In this case, encrypt_sig can be set to
- * false.
- */
-static SECURITY_STATUS ntlm_CreateSignature(PNegoHelper helper, PSecBufferDesc pMessage,
- int token_idx, SignDirection direction, BOOL encrypt_sig)
-{
- ULONG sign_version = 1;
- UINT i;
- PBYTE sig;
- TRACE("%p, %p, %d, %d, %d\n", helper, pMessage, token_idx, direction,
- encrypt_sig);
-
- sig = pMessage->pBuffers[token_idx].pvBuffer;
-
- if(helper->neg_flags & NTLMSSP_NEGOTIATE_NTLM2 &&
- helper->neg_flags & NTLMSSP_NEGOTIATE_SIGN)
- {
- BYTE digest[16];
- BYTE seq_no[4];
- HMAC_MD5_CTX hmac_md5_ctx;
-
- TRACE("Signing NTLM2 style\n");
-
- if(direction == NTLM_SEND)
- {
- 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);
-
- HMACMD5Init(&hmac_md5_ctx, helper->crypt.ntlm2.send_sign_key, 16);
- }
- 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);
- }
-
- 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, pMessage->pBuffers[i].pvBuffer,
- pMessage->pBuffers[i].cbBuffer);
- }
-
- HMACMD5Final(&hmac_md5_ctx, digest);
-
- if(encrypt_sig && 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)
- {
- ULONG crc = 0U;
- TRACE("Signing NTLM1 style\n");
-
- for(i=0; i < pMessage->cBuffers; ++i)
- {
- if(pMessage->pBuffers[i].BufferType & SECBUFFER_DATA)
- crc = RtlComputeCrc32(crc, pMessage->pBuffers[i].pvBuffer, pMessage->pBuffers[i].cbBuffer);
- }
-
- sig[ 0] = (sign_version >> 0) & 0xff;
- sig[ 1] = (sign_version >> 8) & 0xff;
- sig[ 2] = (sign_version >> 16) & 0xff;
- sig[ 3] = (sign_version >> 24) & 0xff;
- memset(sig+4, 0, 4);
- sig[ 8] = (crc >> 0) & 0xff;
- sig[ 9] = (crc >> 8) & 0xff;
- sig[10] = (crc >> 16) & 0xff;
- sig[11] = (crc >> 24) & 0xff;
- sig[12] = (helper->crypt.ntlm.seq_num >> 0) & 0xff;
- sig[13] = (helper->crypt.ntlm.seq_num >> 8) & 0xff;
- sig[14] = (helper->crypt.ntlm.seq_num >> 16) & 0xff;
- sig[15] = (helper->crypt.ntlm.seq_num >> 24) & 0xff;
-
- ++(helper->crypt.ntlm.seq_num);
-
- if(encrypt_sig)
- SECUR32_arc4Process(helper->crypt.ntlm.a4i, sig+4, 12);
- return SEC_E_OK;
- }
-
- if(helper->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN || helper->neg_flags == 0)
- {
- TRACE("Creating a dummy signature.\n");
- /* A dummy signature is 0x01 followed by 15 bytes of 0x00 */
- memset(pMessage->pBuffers[token_idx].pvBuffer, 0, 16);
- memset(pMessage->pBuffers[token_idx].pvBuffer, 0x01, 1);
- pMessage->pBuffers[token_idx].cbBuffer = 16;
- return SEC_E_OK;
- }
-
- return SEC_E_UNSUPPORTED_FUNCTION;
-}
-
-/***********************************************************************
- * MakeSignature
- */
-static SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext,
- ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
-{
- PNegoHelper helper;
- int token_idx;
-
- TRACE("%p %d %p %d\n", phContext, fQOP, pMessage, MessageSeqNo);
- if (!phContext)
- return SEC_E_INVALID_HANDLE;
-
- if(fQOP)
- FIXME("Ignoring fQOP 0x%08x\n", fQOP);
-
- if(MessageSeqNo)
- FIXME("Ignoring MessageSeqNo\n");
-
- if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2)
- return SEC_E_INVALID_TOKEN;
-
- /* If we didn't find a SECBUFFER_TOKEN type buffer */
- if((token_idx = ntlm_GetTokenBufferIndex(pMessage)) == -1)
- return SEC_E_INVALID_TOKEN;
-
- if(pMessage->pBuffers[token_idx].cbBuffer < 16)
- return SEC_E_BUFFER_TOO_SMALL;
-
- helper = (PNegoHelper)phContext->dwLower;
- TRACE("Negotiated flags are: 0x%08x\n", helper->neg_flags);
-
- return ntlm_CreateSignature(helper, pMessage, token_idx, NTLM_SEND, TRUE);
-}
-
-/***********************************************************************
- * VerifySignature
- */
-static SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext,
- PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP)
-{
- PNegoHelper helper;
- UINT i;
- int token_idx;
- SECURITY_STATUS ret;
- SecBufferDesc local_desc;
- PSecBuffer local_buff;
- BYTE local_sig[16];
-
- TRACE("%p %p %d %p\n", phContext, pMessage, MessageSeqNo, pfQOP);
- if(!phContext)
- return SEC_E_INVALID_HANDLE;
-
- if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2)
- return SEC_E_INVALID_TOKEN;
-
- if((token_idx = ntlm_GetTokenBufferIndex(pMessage)) == -1)
- return SEC_E_INVALID_TOKEN;
-
- if(pMessage->pBuffers[token_idx].cbBuffer < 16)
- return SEC_E_BUFFER_TOO_SMALL;
-
- if(MessageSeqNo)
- FIXME("Ignoring MessageSeqNo\n");
-
- helper = (PNegoHelper)phContext->dwLower;
- TRACE("Negotiated flags: 0x%08x\n", helper->neg_flags);
-
- local_buff = heap_alloc(pMessage->cBuffers * sizeof(SecBuffer));
-
- local_desc.ulVersion = SECBUFFER_VERSION;
- local_desc.cBuffers = pMessage->cBuffers;
- local_desc.pBuffers = local_buff;
-
- for(i=0; i < pMessage->cBuffers; ++i)
- {
- if(pMessage->pBuffers[i].BufferType == SECBUFFER_TOKEN)
- {
- local_buff[i].BufferType = SECBUFFER_TOKEN;
- local_buff[i].cbBuffer = 16;
- local_buff[i].pvBuffer = local_sig;
- }
- else
- {
- local_buff[i].BufferType = pMessage->pBuffers[i].BufferType;
- local_buff[i].cbBuffer = pMessage->pBuffers[i].cbBuffer;
- local_buff[i].pvBuffer = pMessage->pBuffers[i].pvBuffer;
- }
- }
-
- if((ret = ntlm_CreateSignature(helper, &local_desc, token_idx, NTLM_RECV, TRUE)) != SEC_E_OK)
- return ret;
-
- if(memcmp(((PBYTE)local_buff[token_idx].pvBuffer) + 8,
- ((PBYTE)pMessage->pBuffers[token_idx].pvBuffer) + 8, 8))
- ret = SEC_E_MESSAGE_ALTERED;
- else
- ret = SEC_E_OK;
-
- heap_free(local_buff);
- return ret;
-
-}
-
-/***********************************************************************
- * FreeCredentialsHandle
- */
-static SECURITY_STATUS SEC_ENTRY ntlm_FreeCredentialsHandle(PCredHandle phCredential)
-{
- if (phCredential)
- {
- PNtlmCredentials ntlm_cred = (PNtlmCredentials) phCredential->dwLower;
- phCredential->dwUpper = 0;
- phCredential->dwLower = 0;
- if (ntlm_cred->password) memset(ntlm_cred->password, 0, ntlm_cred->pwlen);
- heap_free(ntlm_cred->password);
- heap_free(ntlm_cred->username_arg);
- heap_free(ntlm_cred->domain_arg);
- heap_free(ntlm_cred);
- }
-
- return SEC_E_OK;
-}
-
-/***********************************************************************
- * EncryptMessage
- */
-static SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext,
- ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
-{
- PNegoHelper helper;
- int token_idx, data_idx;
-
- TRACE("(%p %d %p %d)\n", phContext, fQOP, pMessage, MessageSeqNo);
-
- if(!phContext)
- return SEC_E_INVALID_HANDLE;
-
- if(fQOP)
- FIXME("Ignoring fQOP\n");
-
- if(MessageSeqNo)
- FIXME("Ignoring MessageSeqNo\n");
-
- if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2)
- return SEC_E_INVALID_TOKEN;
-
- if((token_idx = ntlm_GetTokenBufferIndex(pMessage)) == -1)
- return SEC_E_INVALID_TOKEN;
-
- if((data_idx = ntlm_GetDataBufferIndex(pMessage)) ==-1 )
- return SEC_E_INVALID_TOKEN;
-
- if(pMessage->pBuffers[token_idx].cbBuffer < 16)
- return SEC_E_BUFFER_TOO_SMALL;
-
- helper = (PNegoHelper) phContext->dwLower;
-
- if(helper->neg_flags & NTLMSSP_NEGOTIATE_NTLM2 &&
- helper->neg_flags & NTLMSSP_NEGOTIATE_SEAL)
- {
- ntlm_CreateSignature(helper, pMessage, token_idx, NTLM_SEND, FALSE);
- SECUR32_arc4Process(helper->crypt.ntlm2.send_a4i,
- pMessage->pBuffers[data_idx].pvBuffer,
- pMessage->pBuffers[data_idx].cbBuffer);
-
- if(helper->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCHANGE)
- SECUR32_arc4Process(helper->crypt.ntlm2.send_a4i,
- ((BYTE *)pMessage->pBuffers[token_idx].pvBuffer)+4, 8);
- }
- else
- {
- PBYTE sig;
- ULONG save_flags;
-
- /* EncryptMessage always produces real signatures, so make sure
- * NTLMSSP_NEGOTIATE_SIGN is set*/
- save_flags = helper->neg_flags;
- helper->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
- ntlm_CreateSignature(helper, pMessage, token_idx, NTLM_SEND, FALSE);
- helper->neg_flags = save_flags;
-
- sig = pMessage->pBuffers[token_idx].pvBuffer;
-
- SECUR32_arc4Process(helper->crypt.ntlm.a4i,
- pMessage->pBuffers[data_idx].pvBuffer,
- pMessage->pBuffers[data_idx].cbBuffer);
- SECUR32_arc4Process(helper->crypt.ntlm.a4i, sig+4, 12);
-
- if(helper->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN || helper->neg_flags == 0)
- memset(sig+4, 0, 4);
- }
- return SEC_E_OK;
-}
-
-/***********************************************************************
- * DecryptMessage
- */
-static SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext,
- PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP)
-{
- SECURITY_STATUS ret;
- ULONG ntlmssp_flags_save;
- PNegoHelper helper;
- int token_idx, data_idx;
- TRACE("(%p %p %d %p)\n", phContext, pMessage, MessageSeqNo, pfQOP);
-
- if(!phContext)
- return SEC_E_INVALID_HANDLE;
-
- if(MessageSeqNo)
- FIXME("Ignoring MessageSeqNo\n");
-
- if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2)
- return SEC_E_INVALID_TOKEN;
-
- if((token_idx = ntlm_GetTokenBufferIndex(pMessage)) == -1)
- return SEC_E_INVALID_TOKEN;
-
- if((data_idx = ntlm_GetDataBufferIndex(pMessage)) ==-1)
- return SEC_E_INVALID_TOKEN;
-
- if(pMessage->pBuffers[token_idx].cbBuffer < 16)
- return SEC_E_BUFFER_TOO_SMALL;
-
- helper = (PNegoHelper) phContext->dwLower;
-
- if(helper->neg_flags & NTLMSSP_NEGOTIATE_NTLM2 && helper->neg_flags & NTLMSSP_NEGOTIATE_SEAL)
- {
- SECUR32_arc4Process(helper->crypt.ntlm2.recv_a4i,
- pMessage->pBuffers[data_idx].pvBuffer,
- pMessage->pBuffers[data_idx].cbBuffer);
- }
- else
- {
- SECUR32_arc4Process(helper->crypt.ntlm.a4i,
- pMessage->pBuffers[data_idx].pvBuffer,
- pMessage->pBuffers[data_idx].cbBuffer);
- }
-
- /* Make sure we use a session key for the signature check, EncryptMessage
- * always does that, even in the dummy case */
- ntlmssp_flags_save = helper->neg_flags;
-
- helper->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
- ret = ntlm_VerifySignature(phContext, pMessage, MessageSeqNo, pfQOP);
-
- helper->neg_flags = ntlmssp_flags_save;
-
- return ret;
-}
-
-static const SecurityFunctionTableA ntlmTableA = {
- 1,
- NULL, /* EnumerateSecurityPackagesA */
- ntlm_QueryCredentialsAttributesA, /* QueryCredentialsAttributesA */
- ntlm_AcquireCredentialsHandleA, /* AcquireCredentialsHandleA */
- ntlm_FreeCredentialsHandle, /* FreeCredentialsHandle */
- NULL, /* Reserved2 */
- ntlm_InitializeSecurityContextA, /* InitializeSecurityContextA */
- ntlm_AcceptSecurityContext, /* AcceptSecurityContext */
- ntlm_CompleteAuthToken, /* CompleteAuthToken */
- ntlm_DeleteSecurityContext, /* DeleteSecurityContext */
- NULL, /* ApplyControlToken */
- ntlm_QueryContextAttributesA, /* QueryContextAttributesA */
- ntlm_ImpersonateSecurityContext, /* ImpersonateSecurityContext */
- ntlm_RevertSecurityContext, /* RevertSecurityContext */
- ntlm_MakeSignature, /* MakeSignature */
- ntlm_VerifySignature, /* VerifySignature */
- FreeContextBuffer, /* FreeContextBuffer */
- NULL, /* QuerySecurityPackageInfoA */
- NULL, /* Reserved3 */
- NULL, /* Reserved4 */
- NULL, /* ExportSecurityContext */
- NULL, /* ImportSecurityContextA */
- NULL, /* AddCredentialsA */
- NULL, /* Reserved8 */
- NULL, /* QuerySecurityContextToken */
- ntlm_EncryptMessage, /* EncryptMessage */
- ntlm_DecryptMessage, /* DecryptMessage */
- NULL, /* SetContextAttributesA */
-};
-
-static const SecurityFunctionTableW ntlmTableW = {
- 1,
- NULL, /* EnumerateSecurityPackagesW */
- ntlm_QueryCredentialsAttributesW, /* QueryCredentialsAttributesW */
- ntlm_AcquireCredentialsHandleW, /* AcquireCredentialsHandleW */
- ntlm_FreeCredentialsHandle, /* FreeCredentialsHandle */
- NULL, /* Reserved2 */
- ntlm_InitializeSecurityContextW, /* InitializeSecurityContextW */
- ntlm_AcceptSecurityContext, /* AcceptSecurityContext */
- ntlm_CompleteAuthToken, /* CompleteAuthToken */
- ntlm_DeleteSecurityContext, /* DeleteSecurityContext */
- NULL, /* ApplyControlToken */
- ntlm_QueryContextAttributesW, /* QueryContextAttributesW */
- ntlm_ImpersonateSecurityContext, /* ImpersonateSecurityContext */
- ntlm_RevertSecurityContext, /* RevertSecurityContext */
- ntlm_MakeSignature, /* MakeSignature */
- ntlm_VerifySignature, /* VerifySignature */
- FreeContextBuffer, /* FreeContextBuffer */
- NULL, /* QuerySecurityPackageInfoW */
- NULL, /* Reserved3 */
- NULL, /* Reserved4 */
- NULL, /* ExportSecurityContext */
- NULL, /* ImportSecurityContextW */
- NULL, /* AddCredentialsW */
- NULL, /* Reserved8 */
- NULL, /* QuerySecurityContextToken */
- ntlm_EncryptMessage, /* EncryptMessage */
- ntlm_DecryptMessage, /* DecryptMessage */
- NULL, /* SetContextAttributesW */
-};
-
-void SECUR32_initNTLMSP(void)
-{
- PNegoHelper helper;
- static CHAR version[] = "--version";
-
- SEC_CHAR *args[] = {
- ntlm_auth,
- version,
- NULL };
-
- if(fork_helper(&helper, ntlm_auth, args) != SEC_E_OK)
- helper = NULL;
- else
- check_version(helper);
-
- if( helper &&
- ((helper->major > MIN_NTLM_AUTH_MAJOR_VERSION) ||
- (helper->major == MIN_NTLM_AUTH_MAJOR_VERSION &&
- helper->minor > MIN_NTLM_AUTH_MINOR_VERSION) ||
- (helper->major == MIN_NTLM_AUTH_MAJOR_VERSION &&
- helper->minor == MIN_NTLM_AUTH_MINOR_VERSION &&
- helper->micro >= MIN_NTLM_AUTH_MICRO_VERSION)) )
- {
- SecureProvider *provider = SECUR32_addProvider(&ntlmTableA, &ntlmTableW, NULL);
- SECUR32_addPackages(provider, 1L, ntlm_package_infoA, ntlm_package_infoW);
- }
- else
- {
- ERR_(winediag)("%s was not found or is outdated. "
- "Make sure that ntlm_auth >= %d.%d.%d is in your path. "
- "Usually, you can find it in the winbind package of your distribution.\n",
- ntlm_auth,
- MIN_NTLM_AUTH_MAJOR_VERSION,
- MIN_NTLM_AUTH_MINOR_VERSION,
- MIN_NTLM_AUTH_MICRO_VERSION);
-
- }
- cleanup_helper(helper);
-}
diff --git a/dlls/secur32/secur32_priv.h b/dlls/secur32/secur32_priv.h
index ca0062056d6..5571ac290e1 100644
--- a/dlls/secur32/secur32_priv.h
+++ b/dlls/secur32/secur32_priv.h
@@ -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;
diff --git a/dlls/secur32/util.c b/dlls/secur32/util.c
deleted file mode 100644
index b5cac5b6c06..00000000000
--- a/dlls/secur32/util.c
+++ /dev/null
@@ -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);
-}
--
2.30.2
2
1
[PATCH 1/2] secur32: Load the MSV1_0 provider instead of using builtin support for NTLM.
by Hans Leidekker 30 Apr '21
by Hans Leidekker 30 Apr '21
30 Apr '21
To apply after the last msv1_0 series.
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/secur32/secur32.c | 1 -
loader/wine.inf.in | 1 +
2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/secur32/secur32.c b/dlls/secur32/secur32.c
index 8288286c615..4382ec55174 100644
--- a/dlls/secur32/secur32.c
+++ b/dlls/secur32/secur32.c
@@ -563,7 +563,6 @@ static void SECUR32_initializeProviders(void)
TRACE("\n");
/* First load built-in providers */
SECUR32_initSchannelSP();
- SECUR32_initNTLMSP();
/* Load SSP/AP packages (Kerberos and others) */
load_auth_packages();
/* Load the Negotiate provider last so apps stumble over the working NTLM
diff --git a/loader/wine.inf.in b/loader/wine.inf.in
index 6ae4e96e37f..a20efbcce3e 100644
--- a/loader/wine.inf.in
+++ b/loader/wine.inf.in
@@ -750,6 +750,7 @@ HKLM,Software\Registered Applications,,16
HKLM,System\CurrentControlSet\Control\hivelist,,16
HKLM,System\CurrentControlSet\Control\Lsa,"Security Packages",0x10002,kerberos,schannel
HKLM,System\CurrentControlSet\Control\Lsa\Kerberos,,16
+HKLM,System\CurrentControlSet\Control\Lsa\MSV1_0,,16
HKLM,System\CurrentControlSet\Control\SecurityProviders\Schannel\Protocols\SSL 2.0\Client,"DisabledByDefault",0x10003,1
HKLM,System\CurrentControlSet\Control\ServiceGroupOrder,"List",0x00010000,"TDI"
HKLM,System\CurrentControlSet\Control\TimeZoneInformation,"StandardName",2,""
--
2.30.2
2
1
30 Apr '21
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
---
For Red Dead Redemption 2.
dlls/vulkan-1/tests/vulkan.c | 112 ++++++++++++++++++++++++++++++++++-
dlls/winex11.drv/vulkan.c | 38 +++++++++---
dlls/winex11.drv/window.c | 20 +++++++
dlls/winex11.drv/x11drv.h | 1 +
4 files changed, 160 insertions(+), 11 deletions(-)
diff --git a/dlls/vulkan-1/tests/vulkan.c b/dlls/vulkan-1/tests/vulkan.c
index 9061b2b6db8..e516d0d61c8 100644
--- a/dlls/vulkan-1/tests/vulkan.c
+++ b/dlls/vulkan-1/tests/vulkan.c
@@ -437,7 +437,102 @@ static void test_private_data(VkPhysicalDevice vk_physical_device)
vkDestroyDevice(vk_device, NULL);
}
-static void for_each_device(void (*test_func)(VkPhysicalDevice))
+static const char *test_null_hwnd_extensions[] =
+{
+ "VK_KHR_surface",
+ "VK_KHR_win32_surface",
+};
+
+static void test_null_hwnd(VkInstance vk_instance, VkPhysicalDevice vk_physical_device)
+{
+ PFN_vkGetPhysicalDeviceSurfacePresentModesKHR pvkGetPhysicalDeviceSurfacePresentModesKHR;
+ VkDeviceGroupPresentModeFlagsKHR present_mode_flags;
+ VkWin32SurfaceCreateInfoKHR surface_create_info;
+ VkSurfaceCapabilitiesKHR surf_caps;
+ VkSurfaceFormatKHR *formats;
+ uint32_t queue_family_index;
+ VkPresentModeKHR *modes;
+ VkSurfaceKHR surface;
+ VkDevice vk_device;
+ uint32_t count;
+ VkRect2D rect;
+ VkBool32 bval;
+ VkResult vr;
+
+ pvkGetPhysicalDeviceSurfacePresentModesKHR = (void *)vkGetInstanceProcAddr(vk_instance,
+ "vkGetPhysicalDeviceSurfacePresentModesKHR");
+ surface_create_info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
+ surface_create_info.pNext = NULL;
+ surface_create_info.flags = 0;
+ surface_create_info.hinstance = NULL;
+ surface_create_info.hwnd = NULL;
+
+ bval = find_queue_family(vk_physical_device, VK_QUEUE_GRAPHICS_BIT, &queue_family_index);
+ ok(bval, "Could not find presentation queue.\n");
+
+ surface = 0xdeadbeef;
+ vr = vkCreateWin32SurfaceKHR(vk_instance, &surface_create_info, NULL, &surface);
+ ok(vr == VK_SUCCESS, "Got unexpected vr %d.\n", vr);
+ ok(surface != 0xdeadbeef, "Surface not created.\n");
+
+ count = 0;
+ vr = vkGetPhysicalDeviceSurfaceFormatsKHR(vk_physical_device, surface, &count, NULL);
+ ok(vr == VK_SUCCESS, "Got unexpected vr %d.\n", vr);
+ ok(count, "Got zero count.\n");
+ formats = heap_alloc(sizeof(*formats) * count);
+ vr = vkGetPhysicalDeviceSurfaceFormatsKHR(vk_physical_device, surface, &count, formats);
+ ok(vr == VK_SUCCESS, "Got unexpected vr %d.\n", vr);
+ heap_free(formats);
+
+ vr = vkGetPhysicalDeviceSurfaceSupportKHR(vk_physical_device, queue_family_index, surface, &bval);
+ ok(vr == VK_SUCCESS, "Got unexpected vr %d.\n", vr);
+
+ vr = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk_physical_device, surface, &surf_caps);
+ ok(vr, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR succeeded.\n");
+
+ count = 0;
+ vr = pvkGetPhysicalDeviceSurfacePresentModesKHR(vk_physical_device, surface, &count, NULL);
+ ok(vr == VK_SUCCESS, "Got unexpected vr %d.\n", vr);
+ ok(count, "Got zero count.\n");
+ modes = heap_alloc(sizeof(*modes) * count);
+ vr = pvkGetPhysicalDeviceSurfacePresentModesKHR(vk_physical_device, surface, &count, modes);
+ ok(vr == VK_SUCCESS, "Got unexpected vr %d.\n", vr);
+ heap_free(modes);
+
+ count = 0;
+ vr = vkGetPhysicalDevicePresentRectanglesKHR(vk_physical_device, surface, &count, NULL);
+ ok(vr == VK_SUCCESS, "Got unexpected vr %d.\n", vr);
+ ok(count == 1, "Got unexpected count %u.\n", count);
+ memset(&rect, 0xcc, sizeof(rect));
+ vr = vkGetPhysicalDevicePresentRectanglesKHR(vk_physical_device, surface, &count, &rect);
+ if (vr == VK_SUCCESS) /* Fails on AMD, succeeds on Nvidia. */
+ {
+ ok(count == 1, "Got unexpected count %u.\n", count);
+ ok(!rect.offset.x && !rect.offset.y && !rect.extent.width && !rect.extent.height,
+ "Got unexpected rect %d, %d, %u, %u.\n",
+ rect.offset.x, rect.offset.y, rect.extent.width, rect.extent.height);
+ }
+
+ if ((vr = create_device(vk_physical_device, 0, NULL, NULL, &vk_device)) < 0)
+ {
+ skip("Failed to create device, vr %d.\n", vr);
+ vkDestroySurfaceKHR(vk_instance, surface, NULL);
+ return;
+ }
+
+ if (0)
+ {
+ /* Causes access violation on Windows. */
+ vr = vkGetDeviceGroupSurfacePresentModesKHR(vk_device, surface, &present_mode_flags);
+ ok(vr == VK_SUCCESS, "Got unexpected vr %d.\n", vr);
+ }
+
+ vkDestroyDevice(vk_device, NULL);
+ vkDestroySurfaceKHR(vk_instance, surface, NULL);
+}
+
+static void for_each_device_instance(uint32_t extension_count, const char * const *enabled_extensions,
+ void (*test_func_instance)(VkInstance, VkPhysicalDevice), void (*test_func)(VkPhysicalDevice))
{
VkPhysicalDevice *vk_physical_devices;
VkInstance vk_instance;
@@ -445,7 +540,7 @@ static void for_each_device(void (*test_func)(VkPhysicalDevice))
uint32_t count;
VkResult vr;
- if ((vr = create_instance_skip(0, NULL, &vk_instance)) < 0)
+ if ((vr = create_instance_skip(extension_count, enabled_extensions, &vk_instance)) < 0)
return;
ok(vr == VK_SUCCESS, "Got unexpected VkResult %d.\n", vr);
@@ -463,13 +558,23 @@ static void for_each_device(void (*test_func)(VkPhysicalDevice))
ok(vr == VK_SUCCESS, "Got unexpected VkResult %d.\n", vr);
for (i = 0; i < count; ++i)
- test_func(vk_physical_devices[i]);
+ {
+ if (test_func_instance)
+ test_func_instance(vk_instance, vk_physical_devices[i]);
+ else
+ test_func(vk_physical_devices[i]);
+ }
heap_free(vk_physical_devices);
vkDestroyInstance(vk_instance, NULL);
}
+static void for_each_device(void (*test_func)(VkPhysicalDevice))
+{
+ for_each_device_instance(0, NULL, NULL, test_func);
+}
+
START_TEST(vulkan)
{
test_instance_version();
@@ -481,4 +586,5 @@ START_TEST(vulkan)
test_unsupported_instance_extensions();
for_each_device(test_unsupported_device_extensions);
for_each_device(test_private_data);
+ for_each_device_instance(ARRAY_SIZE(test_null_hwnd_extensions), test_null_hwnd_extensions, test_null_hwnd, NULL);
}
diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c
index 139faf6b407..c8ba68c888f 100644
--- a/dlls/winex11.drv/vulkan.c
+++ b/dlls/winex11.drv/vulkan.c
@@ -62,6 +62,7 @@ struct wine_vk_surface
LONG ref;
Window window;
VkSurfaceKHR surface; /* native surface */
+ BOOL dummy_surface;
};
typedef struct VkXlibSurfaceCreateInfoKHR
@@ -255,14 +256,18 @@ static VkResult X11DRV_vkCreateSwapchainKHR(VkDevice device,
const VkSwapchainCreateInfoKHR *create_info,
const VkAllocationCallbacks *allocator, VkSwapchainKHR *swapchain)
{
+ struct wine_vk_surface *x11_surface = surface_from_handle(create_info->surface);
VkSwapchainCreateInfoKHR create_info_host;
TRACE("%p %p %p %p\n", device, create_info, allocator, swapchain);
if (allocator)
FIXME("Support for allocation callbacks not implemented yet\n");
+ if (x11_surface->dummy_surface)
+ return VK_ERROR_SURFACE_LOST_KHR;
+
create_info_host = *create_info;
- create_info_host.surface = surface_from_handle(create_info->surface)->surface;
+ create_info_host.surface = x11_surface->surface;
return pvkCreateSwapchainKHR(device, &create_info_host, NULL /* allocator */, swapchain);
}
@@ -281,7 +286,7 @@ static VkResult X11DRV_vkCreateWin32SurfaceKHR(VkInstance instance,
FIXME("Support for allocation callbacks not implemented yet\n");
/* TODO: support child window rendering. */
- if (GetAncestor(create_info->hwnd, GA_PARENT) != GetDesktopWindow())
+ if (create_info->hwnd && GetAncestor(create_info->hwnd, GA_PARENT) != GetDesktopWindow())
{
FIXME("Application requires child window rendering, which is not implemented yet!\n");
return VK_ERROR_INCOMPATIBLE_DRIVER;
@@ -292,8 +297,10 @@ static VkResult X11DRV_vkCreateWin32SurfaceKHR(VkInstance instance,
return VK_ERROR_OUT_OF_HOST_MEMORY;
x11_surface->ref = 1;
+ x11_surface->dummy_surface = !create_info->hwnd;
+ x11_surface->window = x11_surface->dummy_surface ? create_dummy_client_window()
+ : create_client_window(create_info->hwnd, &default_visual);
- x11_surface->window = create_client_window(create_info->hwnd, &default_visual);
if (!x11_surface->window)
{
ERR("Failed to allocate client window for hwnd=%p\n", create_info->hwnd);
@@ -316,13 +323,16 @@ static VkResult X11DRV_vkCreateWin32SurfaceKHR(VkInstance instance,
goto err;
}
- EnterCriticalSection(&context_section);
- if (!XFindContext(gdi_display, (XID)create_info->hwnd, vulkan_hwnd_context, (char **)&prev))
+ if (!x11_surface->dummy_surface)
{
- wine_vk_surface_release(prev);
+ EnterCriticalSection(&context_section);
+ if (!XFindContext(gdi_display, (XID)create_info->hwnd, vulkan_hwnd_context, (char **)&prev))
+ {
+ wine_vk_surface_release(prev);
+ }
+ XSaveContext(gdi_display, (XID)create_info->hwnd, vulkan_hwnd_context, (char *)wine_vk_surface_grab(x11_surface));
+ LeaveCriticalSection(&context_section);
}
- XSaveContext(gdi_display, (XID)create_info->hwnd, vulkan_hwnd_context, (char *)wine_vk_surface_grab(x11_surface));
- LeaveCriticalSection(&context_section);
*surface = (uintptr_t)x11_surface;
@@ -456,6 +466,15 @@ static VkResult X11DRV_vkGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice
TRACE("%p, 0x%s, %p, %p\n", phys_dev, wine_dbgstr_longlong(surface), count, rects);
+ if (x11_surface->dummy_surface)
+ {
+ if (rects)
+ return VK_ERROR_SURFACE_LOST_KHR;
+
+ *count = 1;
+ return VK_SUCCESS;
+ }
+
return pvkGetPhysicalDevicePresentRectanglesKHR(phys_dev, x11_surface->surface, count, rects);
}
@@ -485,6 +504,9 @@ static VkResult X11DRV_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevic
TRACE("%p, 0x%s, %p\n", phys_dev, wine_dbgstr_longlong(surface), capabilities);
+ if (x11_surface->dummy_surface)
+ return VK_ERROR_SURFACE_LOST_KHR;
+
return pvkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev, x11_surface->surface, capabilities);
}
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index baaa30d74e3..1f0d636a142 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -1466,6 +1466,26 @@ static Window get_dummy_parent(void)
}
+/**********************************************************************
+ * create_dummy_window
+ */
+Window create_dummy_client_window(void)
+{
+ XSetWindowAttributes attr;
+
+ attr.colormap = default_colormap;
+ attr.bit_gravity = NorthWestGravity;
+ attr.win_gravity = NorthWestGravity;
+ attr.backing_store = NotUseful;
+ attr.border_pixel = 0;
+
+ return XCreateWindow( gdi_display,
+ get_dummy_parent(),
+ 0, 0, 1, 1, 0, default_visual.depth, InputOutput,
+ default_visual.visual, CWBitGravity | CWWinGravity |
+ CWBackingStore | CWColormap | CWBorderPixel, &attr );
+}
+
/**********************************************************************
* create_client_window
*/
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 45855976607..2362dfd9563 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -601,6 +601,7 @@ extern void update_user_time( Time time ) DECLSPEC_HIDDEN;
extern void read_net_wm_states( Display *display, struct x11drv_win_data *data ) DECLSPEC_HIDDEN;
extern void update_net_wm_states( struct x11drv_win_data *data ) DECLSPEC_HIDDEN;
extern void make_window_embedded( struct x11drv_win_data *data ) DECLSPEC_HIDDEN;
+extern Window create_dummy_client_window(void) DECLSPEC_HIDDEN;
extern Window create_client_window( HWND hwnd, const XVisualInfo *visual ) DECLSPEC_HIDDEN;
extern void set_window_visual( struct x11drv_win_data *data, const XVisualInfo *vis, BOOL use_alpha ) DECLSPEC_HIDDEN;
extern void change_systray_owner( Display *display, Window systray_window ) DECLSPEC_HIDDEN;
--
2.31.1
2
3
30 Apr '21
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/msado15/connection.c | 78 ++++++++--------------------------
dlls/msado15/msado15_private.h | 2 -
dlls/msado15/recordset.c | 42 ++++++++++++++++++
3 files changed, 59 insertions(+), 63 deletions(-)
diff --git a/dlls/msado15/connection.c b/dlls/msado15/connection.c
index a3c9a450be6..ce7750fef66 100644
--- a/dlls/msado15/connection.c
+++ b/dlls/msado15/connection.c
@@ -292,98 +292,54 @@ static HRESULT WINAPI connection_Close( _Connection *iface )
return S_OK;
}
-HRESULT create_command_text(IUnknown *session, BSTR command, ICommandText **cmd_text)
-{
- HRESULT hr;
- IOpenRowset *openrowset;
- ICommandText *command_text;
- ICommand *cmd;
- IDBCreateCommand *create_command;
-
- hr = IUnknown_QueryInterface(session, &IID_IOpenRowset, (void**)&openrowset);
- if (FAILED(hr))
- return hr;
-
- hr = IOpenRowset_QueryInterface(openrowset, &IID_IDBCreateCommand, (void**)&create_command);
- IOpenRowset_Release(openrowset);
- if (FAILED(hr))
- return hr;
-
- hr = IDBCreateCommand_CreateCommand(create_command, NULL, &IID_IUnknown, (IUnknown **)&cmd);
- IDBCreateCommand_Release(create_command);
- if (FAILED(hr))
- return hr;
-
- hr = ICommand_QueryInterface(cmd, &IID_ICommandText, (void**)&command_text);
- ICommand_Release(cmd);
- if (FAILED(hr))
- {
- FIXME("Currently only ICommandText interface is support\n");
- return hr;
- }
-
- hr = ICommandText_SetCommandText(command_text, &DBGUID_DEFAULT, command);
- if (FAILED(hr))
- {
- ICommandText_Release(command_text);
- return hr;
- }
-
- *cmd_text = command_text;
-
- return S_OK;
-}
-
static HRESULT WINAPI connection_Execute( _Connection *iface, BSTR command, VARIANT *records_affected,
LONG options, _Recordset **record_set )
{
struct connection *connection = impl_from_Connection( iface );
HRESULT hr;
- ICommandText *command_text;
- DBROWCOUNT affected;
- IUnknown *rowset;
_Recordset *recordset;
- ADORecordsetConstruction *construct;
+ VARIANT source, active;
+ IDispatch *dispatch;
FIXME( "%p, %s, %p, 0x%08x, %p Semi-stub\n", iface, debugstr_w(command), records_affected, options, record_set );
if (connection->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
- hr = create_command_text(connection->session, command, &command_text);
+ hr = Recordset_create( (void**)&recordset);
if (FAILED(hr))
+ {
return hr;
+ }
- hr = ICommandText_Execute(command_text, NULL, &IID_IUnknown, NULL, &affected, &rowset);
- ICommandText_Release(command_text);
- if (FAILED(hr))
- return hr;
+ _Recordset_put_CursorLocation(recordset, connection->location);
- hr = Recordset_create( (void**)&recordset);
+ V_VT(&source) = VT_BSTR;
+ V_BSTR(&source) = command;
+
+ hr = _Connection_QueryInterface(&connection->Connection_iface, &IID_IDispatch, (void**)&dispatch);
if (FAILED(hr))
{
- IUnknown_Release(rowset);
+ _Recordset_Release(recordset);
return hr;
}
- hr = _Recordset_QueryInterface(recordset, &IID_ADORecordsetConstruction, (void**)&construct);
+ V_VT(&active) = VT_DISPATCH;
+ V_DISPATCH(&active) = dispatch;
+
+ hr = _Recordset_Open(recordset, source, active, adOpenDynamic, adLockPessimistic, 0);
+ VariantClear(&active);
if (FAILED(hr))
{
- IUnknown_Release(rowset);
_Recordset_Release(recordset);
return hr;
}
- ADORecordsetConstruction_put_Rowset(construct, rowset);
- ADORecordsetConstruction_Release(construct);
- IUnknown_Release(rowset);
-
if (records_affected)
{
V_VT(records_affected) = VT_I4;
- V_I4(records_affected) = affected;
+ _Recordset_get_RecordCount(recordset, &V_I4(records_affected));
}
- _Recordset_put_CursorLocation(recordset, connection->location);
*record_set = recordset;
return hr;
diff --git a/dlls/msado15/msado15_private.h b/dlls/msado15/msado15_private.h
index 600dcb90a97..bb55eaaa3aa 100644
--- a/dlls/msado15/msado15_private.h
+++ b/dlls/msado15/msado15_private.h
@@ -26,8 +26,6 @@ HRESULT Connection_create( void ** ) DECLSPEC_HIDDEN;
HRESULT Recordset_create( void ** ) DECLSPEC_HIDDEN;
HRESULT Stream_create( void ** ) DECLSPEC_HIDDEN;
-HRESULT create_command_text(IUnknown *session, BSTR command, ICommandText **cmd_text) DECLSPEC_HIDDEN;
-
static inline void *heap_realloc_zero( void *mem, SIZE_T len )
{
if (!mem) return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len );
diff --git a/dlls/msado15/recordset.c b/dlls/msado15/recordset.c
index d71904193c9..2b32dc6cf94 100644
--- a/dlls/msado15/recordset.c
+++ b/dlls/msado15/recordset.c
@@ -1417,6 +1417,48 @@ static HRESULT WINAPI recordset_MoveLast( _Recordset *iface )
return S_OK;
}
+static HRESULT create_command_text(IUnknown *session, BSTR command, ICommandText **cmd_text)
+{
+ HRESULT hr;
+ IOpenRowset *openrowset;
+ ICommandText *command_text;
+ ICommand *cmd;
+ IDBCreateCommand *create_command;
+
+ hr = IUnknown_QueryInterface(session, &IID_IOpenRowset, (void**)&openrowset);
+ if (FAILED(hr))
+ return hr;
+
+ hr = IOpenRowset_QueryInterface(openrowset, &IID_IDBCreateCommand, (void**)&create_command);
+ IOpenRowset_Release(openrowset);
+ if (FAILED(hr))
+ return hr;
+
+ hr = IDBCreateCommand_CreateCommand(create_command, NULL, &IID_IUnknown, (IUnknown **)&cmd);
+ IDBCreateCommand_Release(create_command);
+ if (FAILED(hr))
+ return hr;
+
+ hr = ICommand_QueryInterface(cmd, &IID_ICommandText, (void**)&command_text);
+ ICommand_Release(cmd);
+ if (FAILED(hr))
+ {
+ FIXME("Currently only ICommandText interface is support\n");
+ return hr;
+ }
+
+ hr = ICommandText_SetCommandText(command_text, &DBGUID_DEFAULT, command);
+ if (FAILED(hr))
+ {
+ ICommandText_Release(command_text);
+ return hr;
+ }
+
+ *cmd_text = command_text;
+
+ return S_OK;
+}
+
static HRESULT WINAPI recordset_Open( _Recordset *iface, VARIANT source, VARIANT active_connection,
CursorTypeEnum cursor_type, LockTypeEnum lock_type, LONG options )
{
--
2.30.2
2
1
[PATCH v9 1/2] ntdll: Strip trailing slashes after looking up unix name.
by Gabriel Ivăncescu 30 Apr '21
by Gabriel Ivăncescu 30 Apr '21
30 Apr '21
As they are useless anyway, and have inconsistencies, plus not useful
to new code that assumes there's not any on the unix side. See:
https://www.winehq.org/pipermail/wine-devel/2021-April/185850.html
Note that the root / is not stripped, which is still correct.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
winepath still reports multiple slashes, but I checked the trace from this,
it doesn't return trailing slash anymore (except for / root component),
so that's an unrelated problem in winepath, I think.
dlls/ntdll/unix/file.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index 2f18325..ec0beaa 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -3155,6 +3155,8 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
char *p;
unix_name[pos + 1 + ret] = 0;
for (p = unix_name + pos ; *p; p++) if (*p == '\\') *p = '/';
+ while (p - 1 > unix_name && p[-1] == '/') p--;
+ *p = 0;
if (!stat( unix_name, &st ))
{
if (disposition == FILE_CREATE) return STATUS_OBJECT_NAME_COLLISION;
@@ -3221,6 +3223,12 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
name = next;
}
+ if (status == STATUS_SUCCESS || status == STATUS_NO_SUCH_FILE)
+ {
+ char *p = unix_name + strlen( unix_name );
+ while (p - 1 > unix_name && p[-1] == '/') p--;
+ *p = 0;
+ }
return status;
}
--
2.30.0
2
4
[tools 1/2] winetest/build-patterns: Detect fixed failures at the report level.
by Francois Gouget 30 Apr '21
by Francois Gouget 30 Apr '21
30 Apr '21
If a test configuration had a high failure rate and no longer has any
failure, it is not necessary to wait for $patternbuilds builds to
consider the failure fixed.
Then if the failures are fixed in all test configurations, the test unit
can be moved to the old/fixed failures list.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
winetest/build-patterns | 81 ++++++++++++++++++++++++++++++++++++++++-
winetest/winetest.conf | 3 ++
2 files changed, 82 insertions(+), 2 deletions(-)
diff --git a/winetest/build-patterns b/winetest/build-patterns
index 32bae6b31..6a14fc372 100755
--- a/winetest/build-patterns
+++ b/winetest/build-patterns
@@ -31,7 +31,7 @@ sub BEGIN
}
unshift @INC, $1 if ($0 =~ m=^(/.*)/[^/]+$=);
}
-use vars qw/$workdir $gitdir $patternbuilds/;
+use vars qw/$workdir $gitdir $patternbuilds $fixed_threshold/;
require "winetest.conf";
my $name0=$0;
@@ -275,6 +275,20 @@ my %reports;
# The @sortedbuilds index of the most recent build with a failure.
# -1 if there is none.
#
+# - failures
+# The number of builds that had a failure between the first and last failure
+# builds.
+#
+# - failruns
+# The number of test results between the first and last failure builds.
+# Note that if there are builds for which WineTest was not run this will be
+# different from last-first+1.
+#
+# - fixedruns
+# The number of successful test results following last. Note that if
+# WineTest was not run (yet?) for some builds this will be different from
+# @sortedbuilds-last.
+#
# - status
# A hashtable of test results indexed by the build name.
my %tests;
@@ -389,6 +403,34 @@ sub fail_type($)
"random";
}
+sub get_fix_probability($$$)
+{
+ my ($failures, $failruns, $fixedruns) = @_;
+
+ # We want a lower bound on the failure rate so we get a lower bound on the
+ # probability that a failure is fixed.
+ # So ideally we would compute the lowest failure rate that has a
+ # probability greater than some arbitrary value of giving us $failures in
+ # $failruns runs.
+ # - For instance a failure rate of 100% would obviously give us 2 failures
+ # out of 2 runs. But there is also a 49% chance for a 70% failure rate to
+ # have the same result. So the lowest failure rate that has more than
+ # an arbitrary 50% chance of matching this result is ~71%.
+ # - But that's hard to compute in the general case.
+ # - So instead just convert one failure to success and compute the ratio.
+ # - This gives a 0% failure rate for the 1/1 case which is fine because
+ # this case really does not have not enough data to derive a failure rate.
+ # - For the 2/2 case this gives 50% instead of a more likely value like 71%.
+ # But that's still good enough for our purpose.
+ # - The results continue on the low side up to at least $failruns=10 and
+ # then the difference is pretty small anyway.
+ my $failrate = ($failures - 1) / $failruns;
+
+ # Then compute the probability of getting $fixedruns successes in a row.
+ # The complement is the probability that the failure has been fixed.
+ return 1 - (1 - $failrate) ** $fixedruns;
+}
+
foreach my $testname (keys %tests)
{
my $test = $tests{$testname};
@@ -404,6 +446,11 @@ foreach my $testname (keys %tests)
$testreport->{last} = -1;
# - Type of failure: random or not (missing dll, etc.)
$testreport->{failtype} = "";
+ # - Statistics to compute the failure rate
+ $testreport->{failures} = 0;
+ $testreport->{failruns} = 0;
+ # - And the number of successful runs after the last failure
+ $testreport->{fixedruns} = 0;
for my $i (0..(a)sortedbuilds-1)
{
@@ -415,6 +462,7 @@ foreach my $testname (keys %tests)
$build->{hastest}->{$testname})
{
$testreport->{failtype} ||= 0; # success
+ $testreport->{fixedruns}++;
}
# else WineTest was not run for this build
next;
@@ -437,12 +485,39 @@ foreach my $testname (keys %tests)
$testreport->{first} = $i;
$testreport->{last} = $i;
$testreport->{failtype} = $failtype;
+ $testreport->{failures} = 1;
+ # Assume the bug was introduced with the first failure and thus
+ # ignore successful runs that preceded it.
+ $testreport->{failruns} = 1;
+ $testreport->{fixedruns} = 0;
}
else
{
$testreport->{last} = $i;
+ $testreport->{failures}++;
+ $testreport->{failruns} += $testreport->{fixedruns} + 1;
+ $testreport->{fixedruns} = 0;
}
}
+ next if (!$testreport->{failed});
+ next if (!$testreport->{fixedruns});
+
+ if ($testreport->{failtype} eq "random")
+ {
+ # - failruns counts the number of runs from the first to the last
+ # failure.
+ # - Both failruns and fixedruns account for the builds where the
+ # test was not run.
+ # - So for instance '...eeeF._F.._' gives failures=2 (not 5),
+ # failruns=3 (not 4, 9 or 10), and fixedruns=2 (not 3).
+ $testreport->{fixed} = get_fix_probability($testreport->{failures}, $testreport->{failruns}, $testreport->{fixedruns});
+ }
+ else
+ {
+ # Since this failure is not random, even a single success means
+ # it is fixed.
+ $testreport->{fixed} = 1;
+ }
}
}
@@ -710,11 +785,13 @@ EOF
my $first = @sortedbuilds;
my $last = -1;
+ my $fixed = 1;
foreach my $reportdir (keys %$pagereports)
{
my $testreport = $test->{testreports}->{$reportdir};
next if (!$testreport->{failed});
+ $fixed = 0 if (($testreport->{fixed} || 0) < $fixed_threshold);
$first = $testreport->{first} if ($testreport->{first} < $first);
# For non-random failures we only care about the transition to
# the failure state, which is recorded in 'first'.
@@ -732,7 +809,7 @@ EOF
}
next if ($last == -1); # no report had a pattern of interest
- my $listid = ($last < @sortedbuilds - $patternbuilds) ? "old" :
+ my $listid = ($fixed or $last < @sortedbuilds - $patternbuilds) ? "old" :
($first > $patternbuilds) ? "recent" :
"regular";
push @{$lists{$listid}->{testnames}}, $testname;
diff --git a/winetest/winetest.conf b/winetest/winetest.conf
index f193f8eed..1f587b3bc 100644
--- a/winetest/winetest.conf
+++ b/winetest/winetest.conf
@@ -27,4 +27,7 @@ $maxfilesize = 1.5 * 1024 * 1024;
# The number of builds after which a failure is considered old / new
$patternbuilds = 10;
+# Probability above which a failure is considered to be fixed (0..1)
+$fixed_threshold = 0.99;
+
1; # keep require happy
--
2.20.1
1
1
30 Apr '21
Signed-off-by: Francois Gouget <fgouget(a)free.fr>
---
dlls/kernel32/tests/process.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index b932a3c2a15..f960efb05a8 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -3857,7 +3857,7 @@ static void test_GetSystemCpuSetInformation(void)
ok(ret && GetLastError() == 0xdeadbeef, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
ok(size == expected_size, "Got unexpected size %u.\n", size);
- ok(!memcmp(info, info_nt, expected_size), "Info does not match NtQuerySystemInformationEx().");
+ ok(!memcmp(info, info_nt, expected_size), "Info does not match NtQuerySystemInformationEx().\n");
heap_free(info_nt);
heap_free(info);
--
2.20.1
2
1
30 Apr '21
Signed-off-by: Hugh McMaster <hugh.mcmaster(a)outlook.com>
---
programs/reg/tests/add.c | 71 ++++++++++++++++++++++++++++------------
1 file changed, 50 insertions(+), 21 deletions(-)
diff --git a/programs/reg/tests/add.c b/programs/reg/tests/add.c
index fdd09c885bc..3ac4ca800dd 100644
--- a/programs/reg/tests/add.c
+++ b/programs/reg/tests/add.c
@@ -404,6 +404,16 @@ static void test_reg_none(void)
add_key(HKEY_CURRENT_USER, KEY_BASE, &hkey);
+ run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_NONE /f", &r);
+ ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
+ todo_wine verify_reg(hkey, NULL, REG_NONE, "\0", 2, 0);
+
+ todo_wine delete_value(hkey, NULL);
+
+ run_reg_exe("reg add HKCU\\" KEY_BASE " /ve /t REG_NONE /f", &r);
+ ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
+ verify_reg(hkey, NULL, REG_NONE, "\0", 2, 0);
+
run_reg_exe("reg add HKCU\\" KEY_BASE " /v none0 /d deadbeef /t REG_NONE /f", &r);
ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
verify_reg(hkey, "none0", REG_NONE, "d\0e\0a\0d\0b\0e\0e\0f\0\0", 18, 0);
@@ -412,10 +422,6 @@ static void test_reg_none(void)
ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
verify_reg(hkey, "none1", REG_NONE, "\0", 2, 0);
- run_reg_exe("reg add HKCU\\" KEY_BASE " /ve /t REG_NONE /f", &r);
- ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
- verify_reg(hkey, NULL, REG_NONE, "\0", 2, 0);
-
close_key(hkey);
delete_key(HKEY_CURRENT_USER, KEY_BASE);
}
@@ -427,6 +433,10 @@ static void test_reg_sz(void)
add_key(HKEY_CURRENT_USER, KEY_BASE, &hkey);
+ run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_SZ /f", &r);
+ ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
+ todo_wine verify_reg(hkey, NULL, REG_SZ, "", 1, 0);
+
run_reg_exe("reg add HKCU\\" KEY_BASE " /d WineTest /f", &r);
ok(r == REG_EXIT_SUCCESS || broken(r == REG_EXIT_FAILURE /* WinXP */),
"got exit code %d, expected 0\n", r);
@@ -501,6 +511,16 @@ static void test_reg_expand_sz(void)
add_key(HKEY_CURRENT_USER, KEY_BASE, &hkey);
+ run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_EXPAND_SZ /f", &r);
+ ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
+ todo_wine verify_reg(hkey, NULL, REG_EXPAND_SZ, "", 1, 0);
+
+ todo_wine delete_value(hkey, NULL);
+
+ run_reg_exe("reg add HKCU\\" KEY_BASE " /ve /t REG_EXPAND_SZ /f", &r);
+ ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
+ verify_reg(hkey, NULL, REG_EXPAND_SZ, "", 1, 0);
+
run_reg_exe("reg add HKCU\\" KEY_BASE " /v expand0 /t REG_EXpand_sz /d \"dead%PATH%beef\" /f", &r);
ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
verify_reg(hkey, "expand0", REG_EXPAND_SZ, "dead%PATH%beef", 15, 0);
@@ -521,10 +541,6 @@ static void test_reg_expand_sz(void)
ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
verify_reg(hkey, "expand3", REG_EXPAND_SZ, "", 1, 0);
- run_reg_exe("reg add HKCU\\" KEY_BASE " /ve /t REG_EXPAND_SZ /f", &r);
- ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
- verify_reg(hkey, NULL, REG_EXPAND_SZ, "", 1, 0);
-
close_key(hkey);
delete_key(HKEY_CURRENT_USER, KEY_BASE);
}
@@ -538,15 +554,25 @@ static void test_reg_binary(void)
add_key(HKEY_CURRENT_USER, KEY_BASE, &hkey);
- run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_BINARY /v bin0 /f", &r);
+ run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_BINARY /f", &r);
ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
- verify_reg(hkey, "bin0", REG_BINARY, buffer, 0, 0);
+ todo_wine verify_reg(hkey, NULL, REG_BINARY, buffer, 0, 0);
+
+ todo_wine delete_value(hkey, NULL);
+
+ run_reg_exe("reg add HKCU\\" KEY_BASE " /ve /t REG_BINARY /f", &r);
+ ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
+ verify_reg(hkey, NULL, REG_BINARY, buffer, 0, 0);
run_reg_exe("reg add HKEY_CURRENT_USER\\" KEY_BASE " /ve /t REG_BINARY /d deadbeef /f", &r);
ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
dword = 0xefbeadde;
verify_reg(hkey, "", REG_BINARY, &dword, sizeof(DWORD), 0);
+ run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_BINARY /v bin0 /f", &r);
+ ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
+ verify_reg(hkey, "bin0", REG_BINARY, buffer, 0, 0);
+
run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_BINARY /v bin1 /f /d 0xDeAdBeEf", &r);
ok(r == REG_EXIT_FAILURE, "got exit code %u, expected 1\n", r);
@@ -579,10 +605,6 @@ static void test_reg_binary(void)
run_reg_exe("reg add HKCU\\" KEY_BASE " /v bin6 /t REG_BINARY /f /d", &r);
ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
- run_reg_exe("reg add HKCU\\" KEY_BASE " /ve /t REG_BINARY /f", &r);
- ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
- verify_reg(hkey, NULL, REG_BINARY, buffer, 0, 0);
-
close_key(hkey);
delete_key(HKEY_CURRENT_USER, KEY_BASE);
}
@@ -604,6 +626,9 @@ static void test_reg_dword(void)
else
win_skip("broken reg.exe detected\n");
+ run_reg_exe("reg add HKCU\\" KEY_BASE " /ve /t REG_DWORD /f", &r);
+ ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS /* WinXP */), "got exit code %u, expected 1\n", r);
+
run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword0 /t REG_DWORD /f /d", &r);
ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
@@ -667,9 +692,6 @@ static void test_reg_dword(void)
run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword15 /t REG_DWORD /d 4294967296 /f", &r);
ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS /* WinXP */), "got exit code %u, expected 1\n", r);
- run_reg_exe("reg add HKCU\\" KEY_BASE " /ve /t REG_DWORD /f", &r);
- ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS /* WinXP */), "got exit code %u, expected 1\n", r);
-
/* REG_DWORD_LITTLE_ENDIAN */
run_reg_exe("reg add HKCU\\" KEY_BASE " /v DWORD_LE /t REG_DWORD_LITTLE_ENDIAN /d 456 /f", &r);
ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
@@ -705,6 +727,17 @@ static void test_reg_multi_sz(void)
add_key(HKEY_CURRENT_USER, KEY_BASE, &hkey);
+ run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /f", &r);
+ ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
+ buffer[0] = 0;
+ todo_wine verify_reg(hkey, NULL, REG_MULTI_SZ, buffer, 1, 0);
+
+ todo_wine delete_value(hkey, NULL);
+
+ run_reg_exe("reg add HKCU\\" KEY_BASE " /ve /t REG_MULTI_SZ /f", &r);
+ ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
+ verify_reg(hkey, NULL, REG_MULTI_SZ, buffer, 1, 0);
+
run_reg_exe("reg add HKCU\\" KEY_BASE " /v multi0 /t REG_MULTI_SZ /d \"three\\0little\\0strings\" /f", &r);
ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
memcpy(buffer, "three\0little\0strings\0", 22);
@@ -786,10 +819,6 @@ static void test_reg_multi_sz(void)
ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
verify_reg(hkey, "multi21", REG_MULTI_SZ, "two\\0\\0strings\0", 16, 0);
- run_reg_exe("reg add HKCU\\" KEY_BASE " /ve /t REG_MULTI_SZ /f", &r);
- ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
- verify_reg(hkey, NULL, REG_MULTI_SZ, buffer, 1, 0);
-
close_key(hkey);
delete_key(HKEY_CURRENT_USER, KEY_BASE);
}
--
2.31.1
1
6
Signed-off-by: Nipun Garg <nipung271(a)gmail.com>
---
dlls/pdh/tests/pdh.c | 21 +++++++++++++++++++++
include/pdh.h | 19 +++++++++++++++++++
2 files changed, 40 insertions(+)
diff --git a/dlls/pdh/tests/pdh.c b/dlls/pdh/tests/pdh.c
index 71603f8c6ba..74fc0a20d80 100644
--- a/dlls/pdh/tests/pdh.c
+++ b/dlls/pdh/tests/pdh.c
@@ -126,6 +126,27 @@ static void test_PdhOpenQueryW( void )
ok(ret == PDH_INVALID_HANDLE, "PdhCloseQuery failed 0x%08x\n", ret);
}
+static void test_PdhOpenLogA( void )
+{
+ PDH_STATUS ret;
+ PDH_HLOG log;
+
+ ret = PdhOpenLogA( NULL, PDH_LOG_READ_ACCESS, PDH_LOG_TYPE_CSV, NULL, 0, NULL, NULL );
+ ok(ret == PDH_INVALID_HANDLE, "PdhOpenLogA failed 0x%08x\n", ret);
+
+ ret = PdhOpenLogA( NULL, PDH_LOG_READ_ACCESS, PDH_LOG_TYPE_CSV, NULL, 0, NULL, log );
+ ok(ret == ERROR_SUCCESS, "PdhOpenLogA failed 0x%08x\n", ret);
+
+ ret = PdhCloseLog( NULL, 0 );
+ ok(ret == PDH_INVALID_HANDLE, "PdhCloseLog failed 0x%08x\n", ret);
+
+ ret = PdhCloseLog( log, 0 );
+ ok(ret == ERROR_SUCCESS, "PdhCloseLog failed 0x%08x\n", ret);
+
+ ret = PdhCloseLog( log, 0 );
+ ok(ret == PDH_INVALID_HANDLE, "PdhCloseLog failed 0x%08x\n", ret);
+}
+
static void test_PdhAddCounterA( void )
{
PDH_STATUS ret;
diff --git a/include/pdh.h b/include/pdh.h
index 3d688bd8ded..f3ea6ec7c1b 100644
--- a/include/pdh.h
+++ b/include/pdh.h
@@ -57,6 +57,25 @@ typedef PDH_HLOG HLOG;
#define DATA_SOURCE_LOGFILE 0x00000002
#define DATA_SOURCE_WBEM 0x00000004
+#define PDH_LOG_READ_ACCESS 0x00010000
+#define PDH_LOG_WRITE_ACCESS 0x00020000
+#define PDH_LOG_UPDATE_ACCESS 0x00040000
+
+#define PDH_LOG_CREATE_NEW 0x00000001
+#define PDH_LOG_CREATE_ALWAYS 0x00000002
+#define PDH_LOG_OPEN_ALWAYS 0x00000003
+#define PDH_LOG_OPEN_EXISTING 0x00000004
+#define PDH_LOG_OPT_USER_STRING 0x01000000
+#define PDH_LOG_OPT_CIRCULAR 0x02000000
+
+#define PDH_LOG_TYPE_UNDEFINED 0x00000000
+#define PDH_LOG_TYPE_CSV 0x00000001
+#define PDH_LOG_TYPE_TSV 0x00000002
+#define PDH_LOG_TYPE_SQL 0x00000007
+#define PDH_LOG_TYPE_BINARY 0x00000008
+
+#define PDH_FLAG_CLOSE_QUERY 0x00000001
+
#ifdef WINE_NO_UNICODE_MACROS
# define DECL_PDH_TYPE_AW(name) /* nothing */
#else /* WINE_NO_UNICODE_MACROS */
--
2.30.0
2
1