diff options
-rw-r--r-- | CHANGES | 6 | ||||
-rw-r--r-- | lib/Makefile.vc6 | 25 | ||||
-rw-r--r-- | lib/http.c | 6 | ||||
-rw-r--r-- | lib/http_ntlm.c | 182 | ||||
-rw-r--r-- | lib/http_ntlm.h | 14 | ||||
-rw-r--r-- | lib/url.c | 6 | ||||
-rw-r--r-- | lib/urldata.h | 20 | ||||
-rw-r--r-- | lib/version.c | 4 | ||||
-rw-r--r-- | src/Makefile.vc6 | 24 |
9 files changed, 272 insertions, 15 deletions
@@ -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 */ @@ -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 \
|