]> granicus.if.org Git - curl/commitdiff
Christopher R. Palmer made it possible to build libcurl with the
authorDaniel Stenberg <daniel@haxx.se>
Thu, 10 Mar 2005 23:15:29 +0000 (23:15 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 10 Mar 2005 23:15:29 +0000 (23:15 +0000)
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.

CHANGES
lib/Makefile.vc6
lib/http.c
lib/http_ntlm.c
lib/http_ntlm.h
lib/url.c
lib/urldata.h
lib/version.c
src/Makefile.vc6

diff --git a/CHANGES b/CHANGES
index 7a5f4581e4e697c99a1350a3096151af8c74b88a..2d686399b30d5c1e54e9a0d5cedb11f1405a5b59 100644 (file)
--- 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.
 
index 3b65abf742bdcb56230700c9311a8d2a612c9002..a8d4379af5e7a73875b7f3fab9ab47b3e867b854 100644 (file)
@@ -42,7 +42,25 @@ OPENSSL_PATH   = ../../openssl-0.9.7e
 ZLIB_PATH  = ../../zlib-1.2.1\r
 !ENDIF\r
 \r
-# Use the high resolution time by default.  Comment this out to use low\r
+# USE_WINDOWS_SSPI uses windows libraries to allow NTLM authentication\r
+# without an openssl installation and offers the ability to authenticate\r
+# using the "current logged in user".  It does however require that the\r
+# Windows SDK be installed.\r
+#\r
+# If, for some reason the Windows SDK is installed but not installed\r
+# in the default location, you can specify WINDOWS_SDK_PATH.\r
+# It can be downloaded from:\r
+# http://www.microsoft.com/msdownload/platformsdk/sdkupdate/\r
+\r
+# USE_WINDOWS_SSPI = 1\r
+\r
+!IFDEF WINDOWS_SSPI\r
+!IFNDEF WINDOWS_SDK_PATH\r
+WINDOWS_SDK_PATH = "C:\Program Files\Microsoft SDK"\r
+!ENDIF\r
+!ENDIF\r
+\r
+Use the high resolution time by default.  Comment this out to use low\r
 # resolution time and not require winmm.lib\r
 USEMM_LIBS = YES\r
 \r
@@ -69,6 +87,11 @@ CFLAGS     = $(CFLAGS) /DWITHOUT_MM_LIB
 #  RSAglue.lib was formerly needed in the SSLLIBS\r
 CFGSET     = FALSE\r
 \r
+!IFDEF WINDOWS_SSPI\r
+CFLAGS = $(CFLAGS) /DUSE_WINDOWS_SSPI /I$(WINDOWS_SDK_PATH)\include\r
+LFLAGS = $(LFLAGS) $(WINDOWS_SDK_PATH)\lib\secur32.lib\r
+!ENDIF\r
+\r
 ######################\r
 # release\r
 \r
index ae25947373ee00b6c4460d2edb95a8247e6d3b3d..28799a6a44f223256fd3087ede9466cd136ef3b7 100644 (file)
@@ -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;
index 63a1126f9372a556d9468fa88dfcbaf17fbea2e2..fa719774ce2ab37cfdddbcd54522566311aab9a1 100644 (file)
@@ -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>
 #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 */
index 4386a1cbf19684c5d90f8ac549be16fc37a0be44..84feee25f3de42f3376f8523e6d3774f89085864 100644 (file)
@@ -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 */
index a6e60a92a36b51e3fe87f71957602daf86324720..06b33039112ed5c5f7525ce526d3bd78c8aee0cf 100644 (file)
--- 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)
index e270334c0bc4733fa01a0742224b82f78d6df84d..4540f05c8157b818cddbf597f92760c66f3eb598 100644 (file)
@@ -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
index ebe0b5ba21d77367435d1de30b3ea6b7f40a182b..e82eacf59a57f9df8408818e6f5622405a27ec08 100644 (file)
@@ -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
index 402b6f8f8c2047c396181bef86625eefe0cbb852..c7dc2c36232dde06f32f93bb2479ea431e42e81c 100644 (file)
@@ -23,6 +23,24 @@ ZLIB_PATH = ../../zlib-1.2.1
 OPENSSL_PATH = ../../openssl-0.9.7e\r
 !ENDIF\r
 \r
+# USE_WINDOWS_SSPI uses windows libraries to allow NTLM authentication\r
+# without an openssl installation and offers the ability to authenticate\r
+# using the "current logged in user".  It does however require that the\r
+# Windows SDK be installed.\r
+#\r
+# If, for some reason the Windows SDK is installed but not installed\r
+# in the default location, you can specify WINDOWS_SDK_PATH.\r
+# It can be downloaded from:\r
+# http://www.microsoft.com/msdownload/platformsdk/sdkupdate/\r
+\r
+# USE_WINDOWS_SSPI = 1\r
+\r
+!IFDEF WINDOWS_SSPI\r
+!IFNDEF WINDOWS_SDK_PATH\r
+WINDOWS_SDK_PATH = "C:\Program Files\Microsoft SDK"\r
+!ENDIF\r
+!ENDIF\r
+\r
 ########################################################\r
 ## Nothing more to do below this line!\r
 ZLIB_CFLAGS   = /DHAVE_ZLIB_H /DHAVE_ZLIB /DHAVE_LIBZ /I "$(ZLIB_PATH)"\r
@@ -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\r
 RESFLAGS = /i../include\r
 \r
+!IFDEF WINDOWS_SSPI\r
+CFLAGS = $(CFLAGS) /DUSE_WINDOWS_SSPI /I$(WINDOWS_SDK_PATH)\include\r
+LFLAGS = $(LFLAGS) $(WINDOWS_SDK_PATH)\lib\secur32.lib\r
+!ENDIF\r
+\r
+CFLAGS = $(CFLAGS) /DCURLDEBUG\r
 \r
 RELEASE_OBJS= \\r
        hugehelpr.obj \\r