aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES6
-rw-r--r--lib/Makefile.vc625
-rw-r--r--lib/http.c6
-rw-r--r--lib/http_ntlm.c182
-rw-r--r--lib/http_ntlm.h14
-rw-r--r--lib/url.c6
-rw-r--r--lib/urldata.h20
-rw-r--r--lib/version.c4
-rw-r--r--src/Makefile.vc624
9 files changed, 272 insertions, 15 deletions
diff --git a/CHANGES b/CHANGES
index 7a5f4581e..2d686399b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -7,6 +7,12 @@
Changelog
+Daniel (11 March 2005)
+- Christopher R. Palmer made it possible to build libcurl with the
+ USE_WINDOWS_SSPI on Windows, and then libcurl will be built to use the
+ native way to do NTLM. SSPI also allows libcurl to pass on the current user
+ and its password in the request.
+
Daniel (9 March 2005)
- Dan F improved the SSL lib setup in configure.
diff --git a/lib/Makefile.vc6 b/lib/Makefile.vc6
index 3b65abf74..a8d4379af 100644
--- a/lib/Makefile.vc6
+++ b/lib/Makefile.vc6
@@ -42,7 +42,25 @@ OPENSSL_PATH = ../../openssl-0.9.7e
ZLIB_PATH = ../../zlib-1.2.1
!ENDIF
-# Use the high resolution time by default. Comment this out to use low
+# USE_WINDOWS_SSPI uses windows libraries to allow NTLM authentication
+# without an openssl installation and offers the ability to authenticate
+# using the "current logged in user". It does however require that the
+# Windows SDK be installed.
+#
+# If, for some reason the Windows SDK is installed but not installed
+# in the default location, you can specify WINDOWS_SDK_PATH.
+# It can be downloaded from:
+# http://www.microsoft.com/msdownload/platformsdk/sdkupdate/
+
+# USE_WINDOWS_SSPI = 1
+
+!IFDEF WINDOWS_SSPI
+!IFNDEF WINDOWS_SDK_PATH
+WINDOWS_SDK_PATH = "C:\Program Files\Microsoft SDK"
+!ENDIF
+!ENDIF
+
+Use the high resolution time by default. Comment this out to use low
# resolution time and not require winmm.lib
USEMM_LIBS = YES
@@ -69,6 +87,11 @@ CFLAGS = $(CFLAGS) /DWITHOUT_MM_LIB
# RSAglue.lib was formerly needed in the SSLLIBS
CFGSET = FALSE
+!IFDEF WINDOWS_SSPI
+CFLAGS = $(CFLAGS) /DUSE_WINDOWS_SSPI /I$(WINDOWS_SDK_PATH)\include
+LFLAGS = $(LFLAGS) $(WINDOWS_SDK_PATH)\lib\secur32.lib
+!ENDIF
+
######################
# release
diff --git a/lib/http.c b/lib/http.c
index ae2594737..28799a6a4 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -406,7 +406,7 @@ Curl_http_output_auth(struct connectdata *conn,
/* Send proxy authentication header if needed */
if (conn->bits.httpproxy &&
(conn->bits.tunnel_proxy == proxytunnel)) {
-#ifdef USE_SSLEAY
+#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI)
if(authproxy->want == CURLAUTH_NTLM) {
auth=(char *)"NTLM";
result = Curl_output_ntlm(conn, TRUE);
@@ -474,7 +474,7 @@ Curl_http_output_auth(struct connectdata *conn,
}
else
#endif
-#ifdef USE_SSLEAY
+#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI)
if(authhost->picked == CURLAUTH_NTLM) {
auth=(char *)"NTLM";
result = Curl_output_ntlm(conn, FALSE);
@@ -587,7 +587,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
}
else
#endif
-#ifdef USE_SSLEAY
+#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI)
/* NTLM support requires the SSL crypto libs */
if(checkprefix("NTLM", start)) {
*availp |= CURLAUTH_NTLM;
diff --git a/lib/http_ntlm.c b/lib/http_ntlm.c
index 63a1126f9..fa719774c 100644
--- a/lib/http_ntlm.c
+++ b/lib/http_ntlm.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,7 +30,7 @@
*/
#ifndef CURL_DISABLE_HTTP
-#ifdef USE_SSLEAY
+#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI)
/* We need OpenSSL for the crypto lib to provide us with MD4 and DES */
/* -- WIN32 approved -- */
@@ -51,6 +51,8 @@
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
+#ifndef USE_WINDOWS_SSPI
+
#include <openssl/des.h>
#include <openssl/md4.h>
#include <openssl/ssl.h>
@@ -71,6 +73,12 @@
#define DESKEY(x) &x
#endif
+#else
+
+#include <rpc.h>
+
+#endif
+
/* The last #include file should be: */
#include "memdebug.h"
@@ -130,6 +138,14 @@ CURLntlm Curl_input_ntlm(struct connectdata *conn,
ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */
+#ifdef USE_WINDOWS_SSPI
+ if ((ntlm->type_2 = malloc(size+1)) == NULL) {
+ free(buffer);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ ntlm->n_type_2 = size;
+ memcpy(ntlm->type_2, buffer, size);
+#else
if(size >= 48)
/* the nonce of interest is index [24 .. 31], 8 bytes */
memcpy(ntlm->nonce, &buffer[24], 8);
@@ -138,6 +154,7 @@ CURLntlm Curl_input_ntlm(struct connectdata *conn,
/* at index decimal 20, there's a 32bit NTLM flag field */
free(buffer);
+#endif
}
else {
if(ntlm->state >= NTLMSTATE_TYPE1)
@@ -149,6 +166,8 @@ CURLntlm Curl_input_ntlm(struct connectdata *conn,
return CURLNTLM_FINE;
}
+#ifndef USE_WINDOWS_SSPI
+
/*
* Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The
* key schedule ks is also set.
@@ -275,6 +294,32 @@ static void mkhash(char *password,
free(pw);
}
+#endif
+
+#ifdef USE_WINDOWS_SSPI
+
+static void
+ntlm_sspi_cleanup(struct ntlmdata *ntlm)
+{
+ if (ntlm->type_2) {
+ free(ntlm->type_2);
+ ntlm->type_2 = NULL;
+ }
+ if (ntlm->has_handles) {
+ DeleteSecurityContext(&ntlm->c_handle);
+ FreeCredentialsHandle(&ntlm->handle);
+ ntlm->has_handles = 0;
+ }
+ if (ntlm->p_identity) {
+ if (ntlm->identity.User) free(ntlm->identity.User);
+ if (ntlm->identity.Password) free(ntlm->identity.Password);
+ if (ntlm->identity.Domain) free(ntlm->identity.Domain);
+ ntlm->p_identity = NULL;
+ }
+}
+
+#endif
+
#define SHORTPAIR(x) ((x) & 0xff), ((x) >> 8)
#define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \
(((x) >>16)&0xff), ((x)>>24)
@@ -333,6 +378,90 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
switch(ntlm->state) {
case NTLMSTATE_TYPE1:
default: /* for the weird cases we (re)start here */
+#ifdef USE_WINDOWS_SSPI
+ {
+ SecBuffer buf;
+ SecBufferDesc desc;
+ SECURITY_STATUS status;
+ ULONG attrs;
+ const char *user;
+ int domlen;
+
+ ntlm_sspi_cleanup(ntlm);
+
+ user = strchr(userp, '\\');
+ if (!user)
+ user = strchr(userp, '/');
+
+ if (user) {
+ domain = userp;
+ domlen = user - userp;
+ user++;
+ }
+ else {
+ user = userp;
+ domain = "";
+ domlen = 0;
+ }
+
+ if (user && *user) {
+ /* note: initialize all of this before doing the mallocs so that
+ * it can be cleaned up later without leaking memory.
+ */
+ ntlm->p_identity = &ntlm->identity;
+ memset(ntlm->p_identity, 0, sizeof(*ntlm->p_identity));
+ if ((ntlm->identity.User = strdup(user)) == NULL)
+ return CURLE_OUT_OF_MEMORY;
+ ntlm->identity.UserLength = strlen(user);
+ if ((ntlm->identity.Password = strdup(passwdp)) == NULL)
+ return CURLE_OUT_OF_MEMORY;
+ ntlm->identity.PasswordLength = strlen(passwdp);
+ if ((ntlm->identity.Domain = malloc(domlen+1)) == NULL)
+ return CURLE_OUT_OF_MEMORY;
+ strncpy(ntlm->identity.Domain, domain, domlen);
+ ntlm->identity.Domain[domlen] = '\0';
+ ntlm->identity.DomainLength = domlen;
+ ntlm->identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
+ }
+ else {
+ ntlm->p_identity = NULL;
+ }
+
+ if (AcquireCredentialsHandle(
+ NULL, "NTLM", SECPKG_CRED_OUTBOUND, NULL, ntlm->p_identity,
+ NULL, NULL, &ntlm->handle, NULL
+ ) != SEC_E_OK) {
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ desc.ulVersion = SECBUFFER_VERSION;
+ desc.cBuffers = 1;
+ desc.pBuffers = &buf;
+ buf.cbBuffer = sizeof(ntlmbuf);
+ buf.BufferType = SECBUFFER_TOKEN;
+ buf.pvBuffer = ntlmbuf;
+
+ status = InitializeSecurityContext(&ntlm->handle, NULL, (char *) host,
+ ISC_REQ_CONFIDENTIALITY |
+ ISC_REQ_REPLAY_DETECT |
+ ISC_REQ_CONNECTION,
+ 0, SECURITY_NETWORK_DREP, NULL, 0,
+ &ntlm->c_handle, &desc, &attrs, NULL
+ );
+
+ if (status == SEC_I_COMPLETE_AND_CONTINUE ||
+ status == SEC_I_CONTINUE_NEEDED) {
+ CompleteAuthToken(&ntlm->c_handle, &desc);
+ }
+ else if (status != SEC_E_OK) {
+ FreeCredentialsHandle(&ntlm->handle);
+ return CURLE_RECV_ERROR;
+ }
+
+ ntlm->has_handles = 1;
+ size = buf.cbBuffer;
+ }
+#else
hostoff = 32;
domoff = hostoff + hostlen;
@@ -382,6 +511,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
/* initial packet length */
size = 32 + hostlen + domlen;
+#endif
/* now keeper of the base64 encoded package size */
size = Curl_base64_encode((char *)ntlmbuf, size, &base64);
@@ -417,6 +547,41 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
*/
{
+#ifdef USE_WINDOWS_SSPI
+ SecBuffer type_2, type_3;
+ SecBufferDesc type_2_desc, type_3_desc;
+ SECURITY_STATUS status;
+ ULONG attrs;
+
+ type_2_desc.ulVersion = type_3_desc.ulVersion = SECBUFFER_VERSION;
+ type_2_desc.cBuffers = type_3_desc.cBuffers = 1;
+ type_2_desc.pBuffers = &type_2;
+ type_3_desc.pBuffers = &type_3;
+
+ type_2.BufferType = SECBUFFER_TOKEN;
+ type_2.pvBuffer = ntlm->type_2;
+ type_2.cbBuffer = ntlm->n_type_2;
+ type_3.BufferType = SECBUFFER_TOKEN;
+ type_3.pvBuffer = ntlmbuf;
+ type_3.cbBuffer = sizeof(ntlmbuf);
+
+ status = InitializeSecurityContext(&ntlm->handle, &ntlm->c_handle,
+ (char *) host,
+ ISC_REQ_CONFIDENTIALITY |
+ ISC_REQ_REPLAY_DETECT |
+ ISC_REQ_CONNECTION,
+ 0, SECURITY_NETWORK_DREP, &type_2_desc,
+ 0, &ntlm->c_handle, &type_3_desc,
+ &attrs, NULL);
+
+ if (status != SEC_E_OK)
+ return CURLE_RECV_ERROR;
+
+ size = type_3.cbBuffer;
+
+ ntlm_sspi_cleanup(ntlm);
+
+#else
int lmrespoff;
int ntrespoff;
int useroff;
@@ -556,6 +721,8 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
ntlmbuf[56] = (unsigned char)(size & 0xff);
ntlmbuf[57] = (unsigned char)(size >> 8);
+#endif
+
/* convert the binary blob into base64 */
size = Curl_base64_encode((char *)ntlmbuf, size, &base64);
@@ -587,5 +754,16 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
return CURLE_OK;
}
+
+
+void
+Curl_ntlm_cleanup(struct connectdata *conn)
+{
+#ifdef USE_WINDOWS_SSPI
+ ntlm_sspi_cleanup(&conn->ntlm);
+ ntlm_sspi_cleanup(&conn->proxyntlm);
+#endif
+}
+
#endif /* USE_SSLEAY */
#endif /* !CURL_DISABLE_HTTP */
diff --git a/lib/http_ntlm.h b/lib/http_ntlm.h
index 4386a1cbf..84feee25f 100644
--- a/lib/http_ntlm.h
+++ b/lib/http_ntlm.h
@@ -1,18 +1,18 @@
#ifndef __HTTP_NTLM_H
#define __HTTP_NTLM_H
/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
- *
+ *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
@@ -38,7 +38,7 @@ CURLntlm Curl_input_ntlm(struct connectdata *conn, bool proxy, char *header);
/* this is for creating ntlm header output */
CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy);
-void Curl_ntlm_cleanup(struct SessionHandle *data);
+void Curl_ntlm_cleanup(struct connectdata *conn);
/* Flag bits definitions based on http://davenport.sourceforge.net/ntlm.html */
diff --git a/lib/url.c b/lib/url.c
index a6e60a92a..06b330391 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -832,7 +832,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
{
long auth = va_arg(param, long);
/* switch off bits we can't support */
-#ifndef USE_SSLEAY
+#if ! defined(USE_SSLEAY) && !defined(USE_WINDOWS_SSPI)
auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */
#endif
#ifndef HAVE_GSSAPI
@@ -1449,6 +1449,10 @@ CURLcode Curl_disconnect(struct connectdata *conn)
data->state.authhost.want;
data->state.authproblem = FALSE;
+
+#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI)
+ Curl_ntlm_cleanup(conn);
+#endif
}
if(conn->curl_disconnect)
diff --git a/lib/urldata.h b/lib/urldata.h
index e270334c0..4540f05c8 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -188,10 +188,30 @@ typedef enum {
NTLMSTATE_LAST
} curlntlm;
+#ifdef USE_WINDOWS_SSPI
+/* When including these headers, you must define either SECURITY_WIN32
+ * or SECURITY_KERNEL, indicating who is compiling the code.
+ */
+#define SECURITY_WIN32 1
+#include <sspi.h>
+#include <Security.h>
+#include <rpc.h>
+#endif
+
/* Struct used for NTLM challenge-response authentication */
struct ntlmdata {
curlntlm state;
+#ifdef USE_WINDOWS_SSPI
+ CredHandle handle;
+ CtxtHandle c_handle;
+ SEC_WINNT_AUTH_IDENTITY identity;
+ SEC_WINNT_AUTH_IDENTITY *p_identity;
+ int has_handles;
+ void *type_2;
+ int n_type_2;
+#else
unsigned char nonce[8];
+#endif
};
#ifdef HAVE_GSSAPI
diff --git a/lib/version.c b/lib/version.c
index ebe0b5ba2..e82eacf59 100644
--- a/lib/version.c
+++ b/lib/version.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -194,6 +194,8 @@ static curl_version_info_data version_info = {
#endif
#ifdef USE_SSLEAY
| CURL_VERSION_SSL
+#endif
+#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI)
| CURL_VERSION_NTLM /* since this requires OpenSSL */
#endif
#ifdef HAVE_LIBZ
diff --git a/src/Makefile.vc6 b/src/Makefile.vc6
index 402b6f8f8..c7dc2c362 100644
--- a/src/Makefile.vc6
+++ b/src/Makefile.vc6
@@ -23,6 +23,24 @@ ZLIB_PATH = ../../zlib-1.2.1
OPENSSL_PATH = ../../openssl-0.9.7e
!ENDIF
+# USE_WINDOWS_SSPI uses windows libraries to allow NTLM authentication
+# without an openssl installation and offers the ability to authenticate
+# using the "current logged in user". It does however require that the
+# Windows SDK be installed.
+#
+# If, for some reason the Windows SDK is installed but not installed
+# in the default location, you can specify WINDOWS_SDK_PATH.
+# It can be downloaded from:
+# http://www.microsoft.com/msdownload/platformsdk/sdkupdate/
+
+# USE_WINDOWS_SSPI = 1
+
+!IFDEF WINDOWS_SSPI
+!IFNDEF WINDOWS_SDK_PATH
+WINDOWS_SDK_PATH = "C:\Program Files\Microsoft SDK"
+!ENDIF
+!ENDIF
+
########################################################
## Nothing more to do below this line!
ZLIB_CFLAGS = /DHAVE_ZLIB_H /DHAVE_ZLIB /DHAVE_LIBZ /I "$(ZLIB_PATH)"
@@ -49,6 +67,12 @@ CFLAGS = /I../lib /I../include /nologo /W3 /GX /DWIN32 /YX /FD /c
LFLAGS = /nologo /out:$(PROGRAM_NAME) /subsystem:console /machine:I386
RESFLAGS = /i../include
+!IFDEF WINDOWS_SSPI
+CFLAGS = $(CFLAGS) /DUSE_WINDOWS_SSPI /I$(WINDOWS_SDK_PATH)\include
+LFLAGS = $(LFLAGS) $(WINDOWS_SDK_PATH)\lib\secur32.lib
+!ENDIF
+
+CFLAGS = $(CFLAGS) /DCURLDEBUG
RELEASE_OBJS= \
hugehelpr.obj \