]> granicus.if.org Git - curl/commitdiff
NTLM: move NTLM core specifics into curl_ntlm_core.[ch]
authorYang Tse <yangsita@gmail.com>
Sat, 27 Aug 2011 23:19:08 +0000 (01:19 +0200)
committerYang Tse <yangsita@gmail.com>
Sat, 27 Aug 2011 23:19:08 +0000 (01:19 +0200)
lib/Makefile.inc
lib/Makefile.vc6
lib/curl_ntlm.c
lib/curl_ntlm_core.c [new file with mode: 0644]
lib/curl_ntlm_core.h [new file with mode: 0644]
lib/curl_ntlm_wb.c
packages/Symbian/group/libcurl.mmp

index a724f605bf32043a8f181e9b39968662d79fcfb6..3778fbcf02da2301bec85c7730538e1ab323c041 100644 (file)
@@ -22,7 +22,8 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c   \
   pingpong.c rtsp.c curl_threads.c warnless.c hmac.c polarssl.c                \
   curl_rtmp.c openldap.c curl_gethostname.c gopher.c axtls.c           \
   idn_win32.c http_negotiate_sspi.c cyassl.c http_proxy.c non-ascii.c  \
-  asyn-ares.c asyn-thread.c curl_gssapi.c curl_ntlm.c curl_ntlm_wb.c
+  asyn-ares.c asyn-thread.c curl_gssapi.c curl_ntlm.c curl_ntlm_wb.c   \
+  curl_ntlm_core.c
 
 HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h      \
   progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h     \
@@ -38,4 +39,4 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h     \
   curl_memrchr.h imap.h pop3.h smtp.h pingpong.h rtsp.h curl_threads.h \
   warnless.h curl_hmac.h polarssl.h curl_rtmp.h curl_gethostname.h     \
   gopher.h axtls.h cyassl.h http_proxy.h non-ascii.h asyn.h curl_ntlm.h \
-  curl_gssapi.h curl_ntlm_wb.h
+  curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h
index cbf4b8a03d0358b5ee6d800c835562f5186c145e..d3b11d993e095affe1d6d6b823ba8d8caafe34b1 100644 (file)
@@ -507,6 +507,7 @@ X_OBJS= \
        $(DIROBJ)\curl_gethostname.obj \\r
        $(DIROBJ)\curl_memrchr.obj \\r
        $(DIROBJ)\curl_ntlm.obj \\r
+       $(DIROBJ)\curl_ntlm_core.obj \\r
        $(DIROBJ)\curl_ntlm_wb.obj \\r
        $(DIROBJ)\curl_rand.obj \\r
        $(DIROBJ)\curl_rtmp.obj \\r
index d4f2cc20b217796a476d7f84890354a48b440395..4398d146c157ef12c2b6455cb5475eeb1314cea4 100644 (file)
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
 
 #if (defined(NETWARE) && !defined(__NOVELL_LIBC__))
 #include <netdb.h>
@@ -49,7 +43,7 @@
 #define BUILDING_CURL_NTLM_C
 
 #include "urldata.h"
-#include "non-ascii.h"  /* for Curl_convert_... prototypes */
+#include "non-ascii.h"
 #include "sendf.h"
 #include "select.h"
 #include "rawstr.h"
 #error "OPENSSL_VERSION_NUMBER not defined"
 #endif
 
-#if OPENSSL_VERSION_NUMBER < 0x00907001L
-#define DES_key_schedule des_key_schedule
-#define DES_cblock des_cblock
-#define DES_set_odd_parity des_set_odd_parity
-#define DES_set_key des_set_key
-#define DES_ecb_encrypt des_ecb_encrypt
-
-/* This is how things were done in the old days */
-#define DESKEY(x) x
-#define DESKEYARG(x) x
-#else
-/* Modern version */
-#define DESKEYARG(x) *x
-#define DESKEY(x) &x
-#endif
-
 #ifdef OPENSSL_NO_MD4
 /* This requires MD4, but OpenSSL was compiled without it */
 #define USE_NTRESPONSES 0
 #    error "Can't compile NTLM support without a crypto library."
 #endif
 
-/* The last #include file should be: */
-#include "memdebug.h"
-
-/* Hostname buffer size */
-#define HOSTNAME_MAX 1024
-
-/* "NTLMSSP" signature is always in ASCII regardless of the platform */
-#define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
-
 #ifndef USE_NTRESPONSES
 /* Define this to make the type-3 message include the NT response message */
 #define USE_NTRESPONSES 1
 #define USE_NTLM2SESSION 1
 #endif
 
+#include "curl_ntlm_core.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* Hostname buffer size */
+#define HOSTNAME_MAX 1024
+
+/* "NTLMSSP" signature is always in ASCII regardless of the platform */
+#define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
+
 #define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
 #define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8) & 0xff), \
   (((x) >> 16) & 0xff), (((x) >> 24) & 0xff)
@@ -229,6 +209,7 @@ static void ntlm_print_flags(FILE *handle, unsigned long flags)
 static void ntlm_print_hex(FILE *handle, const char *buf, size_t len)
 {
   const char *p = buf;
+  (void)handle;
   fprintf(stderr, "0x");
   while(len-- > 0)
     fprintf(stderr, "%02.2x", (unsigned int)*p++);
@@ -360,293 +341,6 @@ CURLcode Curl_ntlm_decode_type2_message(struct SessionHandle *data,
   return CURLE_OK;
 }
 
-#ifndef USE_WINDOWS_SSPI
-
-#ifdef USE_SSLEAY
-/*
- * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.  The
- * key schedule ks is also set.
- */
-static void setup_des_key(const unsigned char *key_56,
-                          DES_key_schedule DESKEYARG(ks))
-{
-  DES_cblock key;
-
-  key[0] = key_56[0];
-  key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
-  key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
-  key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
-  key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
-  key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
-  key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
-  key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
-
-  DES_set_odd_parity(&key);
-  DES_set_key(&key, ks);
-}
-
-#else /* defined(USE_SSLEAY) */
-
-/*
- * Turns a 56 bit key into the 64 bit, odd parity key.  Used by GnuTLS and NSS.
- */
-static void extend_key_56_to_64(const unsigned char *key_56, char *key)
-{
-  key[0] = key_56[0];
-  key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
-  key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
-  key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
-  key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
-  key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
-  key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
-  key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
-}
-
-#if defined(USE_GNUTLS)
-
-/*
- * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.
- */
-static void setup_des_key(const unsigned char *key_56,
-                          gcry_cipher_hd_t *des)
-{
-  char key[8];
-  extend_key_56_to_64(key_56, key);
-  gcry_cipher_setkey(*des, key, 8);
-}
-
-#elif defined(USE_NSS)
-
-/*
- * Expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of data, using
- * the expanded key.  The caller is responsible for giving 64 bit of valid
- * data is IN and (at least) 64 bit large buffer as OUT.
- */
-static bool encrypt_des(const unsigned char *in, unsigned char *out,
-                        const unsigned char *key_56)
-{
-  const CK_MECHANISM_TYPE mech = CKM_DES_ECB; /* DES cipher in ECB mode */
-  PK11SlotInfo *slot = NULL;
-  char key[8];                                /* expanded 64 bit key */
-  SECItem key_item;
-  PK11SymKey *symkey = NULL;
-  SECItem *param = NULL;
-  PK11Context *ctx = NULL;
-  int out_len;                                /* not used, required by NSS */
-  bool rv = FALSE;
-
-  /* use internal slot for DES encryption (requires NSS to be initialized) */
-  slot = PK11_GetInternalKeySlot();
-  if(!slot)
-    return FALSE;
-
-  /* expand the 56 bit key to 64 bit and wrap by NSS */
-  extend_key_56_to_64(key_56, key);
-  key_item.data = (unsigned char *)key;
-  key_item.len = /* hard-wired */ 8;
-  symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, CKA_ENCRYPT,
-                             &key_item, NULL);
-  if(!symkey)
-    goto fail;
-
-  /* create DES encryption context */
-  param = PK11_ParamFromIV(mech, /* no IV in ECB mode */ NULL);
-  if(!param)
-    goto fail;
-  ctx = PK11_CreateContextBySymKey(mech, CKA_ENCRYPT, symkey, param);
-  if(!ctx)
-    goto fail;
-
-  /* perform the encryption */
-  if(SECSuccess == PK11_CipherOp(ctx, out, &out_len, /* outbuflen */ 8,
-                                 (unsigned char *)in, /* inbuflen */ 8)
-      && SECSuccess == PK11_Finalize(ctx))
-    rv = /* all OK */ TRUE;
-
-fail:
-  /* cleanup */
-  if(ctx)
-    PK11_DestroyContext(ctx, PR_TRUE);
-  if(symkey)
-    PK11_FreeSymKey(symkey);
-  if(param)
-    SECITEM_FreeItem(param, PR_TRUE);
-  PK11_FreeSlot(slot);
-  return rv;
-}
-
-#endif /* defined(USE_NSS) */
-
-#endif /* defined(USE_SSLEAY) */
-
- /*
-  * takes a 21 byte array and treats it as 3 56-bit DES keys. The
-  * 8 byte plaintext is encrypted with each key and the resulting 24
-  * bytes are stored in the results array.
-  */
-static void lm_resp(const unsigned char *keys,
-                    const unsigned char *plaintext,
-                    unsigned char *results)
-{
-#ifdef USE_SSLEAY
-  DES_key_schedule ks;
-
-  setup_des_key(keys, DESKEY(ks));
-  DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results,
-                  DESKEY(ks), DES_ENCRYPT);
-
-  setup_des_key(keys + 7, DESKEY(ks));
-  DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 8),
-                  DESKEY(ks), DES_ENCRYPT);
-
-  setup_des_key(keys + 14, DESKEY(ks));
-  DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 16),
-                  DESKEY(ks), DES_ENCRYPT);
-#elif defined(USE_GNUTLS)
-  gcry_cipher_hd_t des;
-
-  gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
-  setup_des_key(keys, &des);
-  gcry_cipher_encrypt(des, results, 8, plaintext, 8);
-  gcry_cipher_close(des);
-
-  gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
-  setup_des_key(keys + 7, &des);
-  gcry_cipher_encrypt(des, results + 8, 8, plaintext, 8);
-  gcry_cipher_close(des);
-
-  gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
-  setup_des_key(keys + 14, &des);
-  gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8);
-  gcry_cipher_close(des);
-#elif defined(USE_NSS)
-  encrypt_des(plaintext, results, keys);
-  encrypt_des(plaintext, results + 8, keys + 7);
-  encrypt_des(plaintext, results + 16, keys + 14);
-#endif
-}
-
-/*
- * Set up lanmanager hashed password
- */
-static void mk_lm_hash(struct SessionHandle *data,
-                       const char *password,
-                       unsigned char *lmbuffer /* 21 bytes */)
-{
-  CURLcode res;
-  unsigned char pw[14];
-  static const unsigned char magic[] = {
-    0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */
-  };
-  size_t len = CURLMIN(strlen(password), 14);
-
-  Curl_strntoupper((char *)pw, password, len);
-  memset(&pw[len], 0, 14 - len);
-
-  /*
-   * The LanManager hashed password needs to be created using the
-   * password in the network encoding not the host encoding.
-   */
-  res = Curl_convert_to_network(data, (char *)pw, 14);
-  if(res)
-    return;
-
-  {
-    /* Create LanManager hashed password. */
-
-#ifdef USE_SSLEAY
-    DES_key_schedule ks;
-
-    setup_des_key(pw, DESKEY(ks));
-    DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
-                    DESKEY(ks), DES_ENCRYPT);
-
-    setup_des_key(pw + 7, DESKEY(ks));
-    DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer + 8),
-                    DESKEY(ks), DES_ENCRYPT);
-#elif defined(USE_GNUTLS)
-    gcry_cipher_hd_t des;
-
-    gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
-    setup_des_key(pw, &des);
-    gcry_cipher_encrypt(des, lmbuffer, 8, magic, 8);
-    gcry_cipher_close(des);
-
-    gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
-    setup_des_key(pw + 7, &des);
-    gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8);
-    gcry_cipher_close(des);
-#elif defined(USE_NSS)
-    encrypt_des(magic, lmbuffer, pw);
-    encrypt_des(magic, lmbuffer + 8, pw + 7);
-#endif
-
-    memset(lmbuffer + 16, 0, 21 - 16);
-  }
-}
-
-#if USE_NTRESPONSES
-static void ascii_to_unicode_le(unsigned char *dest, const char *src,
-                                size_t srclen)
-{
-  size_t i;
-  for(i = 0; i < srclen; i++) {
-    dest[2 * i] = (unsigned char)src[i];
-    dest[2 * i + 1] = '\0';
-  }
-}
-
-/*
- * Set up nt hashed passwords
- */
-static CURLcode mk_nt_hash(struct SessionHandle *data,
-                           const char *password,
-                           unsigned char *ntbuffer /* 21 bytes */)
-{
-  size_t len = strlen(password);
-  unsigned char *pw = malloc(len * 2);
-  CURLcode result;
-  if(!pw)
-    return CURLE_OUT_OF_MEMORY;
-
-  ascii_to_unicode_le(pw, password, len);
-
-  /*
-   * The NT hashed password needs to be created using the password in the
-   * network encoding not the host encoding.
-   */
-  result = Curl_convert_to_network(data, (char *)pw, len * 2);
-  if(result)
-    return result;
-
-  {
-    /* Create NT hashed password. */
-#ifdef USE_SSLEAY
-    MD4_CTX MD4pw;
-    MD4_Init(&MD4pw);
-    MD4_Update(&MD4pw, pw, 2 * len);
-    MD4_Final(ntbuffer, &MD4pw);
-#elif defined(USE_GNUTLS)
-    gcry_md_hd_t MD4pw;
-    gcry_md_open(&MD4pw, GCRY_MD_MD4, 0);
-    gcry_md_write(MD4pw, pw, 2 * len);
-    memcpy (ntbuffer, gcry_md_read (MD4pw, 0), MD4_DIGEST_LENGTH);
-    gcry_md_close(MD4pw);
-#elif defined(USE_NSS)
-    Curl_md4it(ntbuffer, pw, 2 * len);
-#endif
-
-    memset(ntbuffer + 16, 0, 21 - 16);
-  }
-
-  free(pw);
-
-  return CURLE_OK;
-}
-#endif
-
-#endif
-
 #ifdef USE_WINDOWS_SSPI
 void Curl_ntlm_sspi_cleanup(struct ntlmdata *ntlm)
 {
@@ -1096,11 +790,12 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data,
     PK11_DestroyContext(MD5pw, PR_TRUE);
 #endif
 
-    /* We shall only use the first 8 bytes of md5sum,
-       but the des code in lm_resp only encrypt the first 8 bytes */
-    if(mk_nt_hash(data, passwdp, ntbuffer) == CURLE_OUT_OF_MEMORY)
+    /* We shall only use the first 8 bytes of md5sum, but the des
+       code in Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */
+    if(CURLE_OUT_OF_MEMORY ==
+       Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer))
       return CURLE_OUT_OF_MEMORY;
-    lm_resp(ntbuffer, md5sum, ntresp);
+    Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp);
 
     /* End of NTLM2 Session code */
   }
@@ -1114,15 +809,16 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data,
     unsigned char lmbuffer[0x18];
 
 #if USE_NTRESPONSES
-    if(mk_nt_hash(data, passwdp, ntbuffer) == CURLE_OUT_OF_MEMORY)
+    if(CURLE_OUT_OF_MEMORY ==
+       Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer))
       return CURLE_OUT_OF_MEMORY;
-    lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
+    Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
 #endif
 
-    mk_lm_hash(data, passwdp, lmbuffer);
-    lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
+    Curl_ntlm_core_mk_lm_hash(data, passwdp, lmbuffer);
+    Curl_ntlm_core_lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
     /* A safer but less compatible alternative is:
-     *   lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
+     *   Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
      * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
   }
 
diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c
new file mode 100644 (file)
index 0000000..b8cc4c6
--- /dev/null
@@ -0,0 +1,412 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "setup.h"
+
+/* NTLM details:
+
+   http://davenport.sourceforge.net/ntlm.html
+   http://www.innovation.ch/java/ntlm.html
+*/
+
+#ifdef USE_NTLM
+
+#include "non-ascii.h"
+#include "rawstr.h"
+#include "curl_memory.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#ifdef USE_SSLEAY
+#include "ssluse.h"
+#    ifdef USE_OPENSSL
+#      include <openssl/des.h>
+#      ifndef OPENSSL_NO_MD4
+#        include <openssl/md4.h>
+#      endif
+#      include <openssl/md5.h>
+#      include <openssl/ssl.h>
+#      include <openssl/rand.h>
+#    else
+#      include <des.h>
+#      ifndef OPENSSL_NO_MD4
+#        include <md4.h>
+#      endif
+#      include <md5.h>
+#      include <ssl.h>
+#      include <rand.h>
+#    endif
+
+#ifndef OPENSSL_VERSION_NUMBER
+#error "OPENSSL_VERSION_NUMBER not defined"
+#endif
+
+#if OPENSSL_VERSION_NUMBER < 0x00907001L
+#define DES_key_schedule des_key_schedule
+#define DES_cblock des_cblock
+#define DES_set_odd_parity des_set_odd_parity
+#define DES_set_key des_set_key
+#define DES_ecb_encrypt des_ecb_encrypt
+
+/* This is how things were done in the old days */
+#define DESKEY(x) x
+#define DESKEYARG(x) x
+#else
+/* Modern version */
+#define DESKEYARG(x) *x
+#define DESKEY(x) &x
+#endif
+
+#ifdef OPENSSL_NO_MD4
+/* This requires MD4, but OpenSSL was compiled without it */
+#define USE_NTRESPONSES 0
+#define USE_NTLM2SESSION 0
+#endif
+
+#elif defined(USE_GNUTLS)
+
+#include "gtls.h"
+#include <gcrypt.h>
+
+#define MD5_DIGEST_LENGTH 16
+#define MD4_DIGEST_LENGTH 16
+
+#elif defined(USE_NSS)
+
+#include "curl_md4.h"
+#include "nssg.h"
+#include <nss.h>
+#include <pk11pub.h>
+#include <hasht.h>
+#define MD5_DIGEST_LENGTH MD5_LENGTH
+
+#elif defined(USE_WINDOWS_SSPI)
+
+#include "curl_sspi.h"
+
+#else
+#    error "Can't compile NTLM support without a crypto library."
+#endif
+
+#ifndef USE_NTRESPONSES
+/* Define this to make the type-3 message include the NT response message */
+#define USE_NTRESPONSES 1
+
+/* Define this to make the type-3 message include the NTLM2Session response
+   message, requires USE_NTRESPONSES. */
+#define USE_NTLM2SESSION 1
+#endif
+
+#include "curl_ntlm_core.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifndef USE_WINDOWS_SSPI
+
+#ifdef USE_SSLEAY
+/*
+ * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.  The
+ * key schedule ks is also set.
+ */
+static void setup_des_key(const unsigned char *key_56,
+                          DES_key_schedule DESKEYARG(ks))
+{
+  DES_cblock key;
+
+  key[0] = key_56[0];
+  key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
+  key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
+  key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
+  key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
+  key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
+  key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
+  key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
+
+  DES_set_odd_parity(&key);
+  DES_set_key(&key, ks);
+}
+
+#else /* defined(USE_SSLEAY) */
+
+/*
+ * Turns a 56 bit key into the 64 bit, odd parity key.  Used by GnuTLS and NSS.
+ */
+static void extend_key_56_to_64(const unsigned char *key_56, char *key)
+{
+  key[0] = key_56[0];
+  key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
+  key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
+  key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
+  key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
+  key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
+  key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
+  key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
+}
+
+#if defined(USE_GNUTLS)
+
+/*
+ * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.
+ */
+static void setup_des_key(const unsigned char *key_56,
+                          gcry_cipher_hd_t *des)
+{
+  char key[8];
+  extend_key_56_to_64(key_56, key);
+  gcry_cipher_setkey(*des, key, 8);
+}
+
+#elif defined(USE_NSS)
+
+/*
+ * Expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of data, using
+ * the expanded key.  The caller is responsible for giving 64 bit of valid
+ * data is IN and (at least) 64 bit large buffer as OUT.
+ */
+static bool encrypt_des(const unsigned char *in, unsigned char *out,
+                        const unsigned char *key_56)
+{
+  const CK_MECHANISM_TYPE mech = CKM_DES_ECB; /* DES cipher in ECB mode */
+  PK11SlotInfo *slot = NULL;
+  char key[8];                                /* expanded 64 bit key */
+  SECItem key_item;
+  PK11SymKey *symkey = NULL;
+  SECItem *param = NULL;
+  PK11Context *ctx = NULL;
+  int out_len;                                /* not used, required by NSS */
+  bool rv = FALSE;
+
+  /* use internal slot for DES encryption (requires NSS to be initialized) */
+  slot = PK11_GetInternalKeySlot();
+  if(!slot)
+    return FALSE;
+
+  /* expand the 56 bit key to 64 bit and wrap by NSS */
+  extend_key_56_to_64(key_56, key);
+  key_item.data = (unsigned char *)key;
+  key_item.len = /* hard-wired */ 8;
+  symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, CKA_ENCRYPT,
+                             &key_item, NULL);
+  if(!symkey)
+    goto fail;
+
+  /* create DES encryption context */
+  param = PK11_ParamFromIV(mech, /* no IV in ECB mode */ NULL);
+  if(!param)
+    goto fail;
+  ctx = PK11_CreateContextBySymKey(mech, CKA_ENCRYPT, symkey, param);
+  if(!ctx)
+    goto fail;
+
+  /* perform the encryption */
+  if(SECSuccess == PK11_CipherOp(ctx, out, &out_len, /* outbuflen */ 8,
+                                 (unsigned char *)in, /* inbuflen */ 8)
+      && SECSuccess == PK11_Finalize(ctx))
+    rv = /* all OK */ TRUE;
+
+fail:
+  /* cleanup */
+  if(ctx)
+    PK11_DestroyContext(ctx, PR_TRUE);
+  if(symkey)
+    PK11_FreeSymKey(symkey);
+  if(param)
+    SECITEM_FreeItem(param, PR_TRUE);
+  PK11_FreeSlot(slot);
+  return rv;
+}
+
+#endif /* defined(USE_NSS) */
+
+#endif /* defined(USE_SSLEAY) */
+
+ /*
+  * takes a 21 byte array and treats it as 3 56-bit DES keys. The
+  * 8 byte plaintext is encrypted with each key and the resulting 24
+  * bytes are stored in the results array.
+  */
+void Curl_ntlm_core_lm_resp(const unsigned char *keys,
+                            const unsigned char *plaintext,
+                            unsigned char *results)
+{
+#ifdef USE_SSLEAY
+  DES_key_schedule ks;
+
+  setup_des_key(keys, DESKEY(ks));
+  DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results,
+                  DESKEY(ks), DES_ENCRYPT);
+
+  setup_des_key(keys + 7, DESKEY(ks));
+  DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 8),
+                  DESKEY(ks), DES_ENCRYPT);
+
+  setup_des_key(keys + 14, DESKEY(ks));
+  DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 16),
+                  DESKEY(ks), DES_ENCRYPT);
+#elif defined(USE_GNUTLS)
+  gcry_cipher_hd_t des;
+
+  gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+  setup_des_key(keys, &des);
+  gcry_cipher_encrypt(des, results, 8, plaintext, 8);
+  gcry_cipher_close(des);
+
+  gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+  setup_des_key(keys + 7, &des);
+  gcry_cipher_encrypt(des, results + 8, 8, plaintext, 8);
+  gcry_cipher_close(des);
+
+  gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+  setup_des_key(keys + 14, &des);
+  gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8);
+  gcry_cipher_close(des);
+#elif defined(USE_NSS)
+  encrypt_des(plaintext, results, keys);
+  encrypt_des(plaintext, results + 8, keys + 7);
+  encrypt_des(plaintext, results + 16, keys + 14);
+#endif
+}
+
+/*
+ * Set up lanmanager hashed password
+ */
+void Curl_ntlm_core_mk_lm_hash(struct SessionHandle *data,
+                               const char *password,
+                               unsigned char *lmbuffer /* 21 bytes */)
+{
+  CURLcode res;
+  unsigned char pw[14];
+  static const unsigned char magic[] = {
+    0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */
+  };
+  size_t len = CURLMIN(strlen(password), 14);
+
+  Curl_strntoupper((char *)pw, password, len);
+  memset(&pw[len], 0, 14 - len);
+
+  /*
+   * The LanManager hashed password needs to be created using the
+   * password in the network encoding not the host encoding.
+   */
+  res = Curl_convert_to_network(data, (char *)pw, 14);
+  if(res)
+    return;
+
+  {
+    /* Create LanManager hashed password. */
+
+#ifdef USE_SSLEAY
+    DES_key_schedule ks;
+
+    setup_des_key(pw, DESKEY(ks));
+    DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
+                    DESKEY(ks), DES_ENCRYPT);
+
+    setup_des_key(pw + 7, DESKEY(ks));
+    DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer + 8),
+                    DESKEY(ks), DES_ENCRYPT);
+#elif defined(USE_GNUTLS)
+    gcry_cipher_hd_t des;
+
+    gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+    setup_des_key(pw, &des);
+    gcry_cipher_encrypt(des, lmbuffer, 8, magic, 8);
+    gcry_cipher_close(des);
+
+    gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+    setup_des_key(pw + 7, &des);
+    gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8);
+    gcry_cipher_close(des);
+#elif defined(USE_NSS)
+    encrypt_des(magic, lmbuffer, pw);
+    encrypt_des(magic, lmbuffer + 8, pw + 7);
+#endif
+
+    memset(lmbuffer + 16, 0, 21 - 16);
+  }
+}
+
+#if USE_NTRESPONSES
+static void ascii_to_unicode_le(unsigned char *dest, const char *src,
+                                size_t srclen)
+{
+  size_t i;
+  for(i = 0; i < srclen; i++) {
+    dest[2 * i] = (unsigned char)src[i];
+    dest[2 * i + 1] = '\0';
+  }
+}
+
+/*
+ * Set up nt hashed passwords
+ */
+CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data,
+                                   const char *password,
+                                   unsigned char *ntbuffer /* 21 bytes */)
+{
+  size_t len = strlen(password);
+  unsigned char *pw = malloc(len * 2);
+  CURLcode result;
+  if(!pw)
+    return CURLE_OUT_OF_MEMORY;
+
+  ascii_to_unicode_le(pw, password, len);
+
+  /*
+   * The NT hashed password needs to be created using the password in the
+   * network encoding not the host encoding.
+   */
+  result = Curl_convert_to_network(data, (char *)pw, len * 2);
+  if(result)
+    return result;
+
+  {
+    /* Create NT hashed password. */
+#ifdef USE_SSLEAY
+    MD4_CTX MD4pw;
+    MD4_Init(&MD4pw);
+    MD4_Update(&MD4pw, pw, 2 * len);
+    MD4_Final(ntbuffer, &MD4pw);
+#elif defined(USE_GNUTLS)
+    gcry_md_hd_t MD4pw;
+    gcry_md_open(&MD4pw, GCRY_MD_MD4, 0);
+    gcry_md_write(MD4pw, pw, 2 * len);
+    memcpy (ntbuffer, gcry_md_read (MD4pw, 0), MD4_DIGEST_LENGTH);
+    gcry_md_close(MD4pw);
+#elif defined(USE_NSS)
+    Curl_md4it(ntbuffer, pw, 2 * len);
+#endif
+
+    memset(ntbuffer + 16, 0, 21 - 16);
+  }
+
+  free(pw);
+
+  return CURLE_OK;
+}
+#endif /* USE_NTRESPONSES */
+
+#endif /* !USE_WINDOWS_SSPI */
+
+#endif /* USE_NTLM */
diff --git a/lib/curl_ntlm_core.h b/lib/curl_ntlm_core.h
new file mode 100644 (file)
index 0000000..ea85590
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef HEADER_CURL_NTLM_CORE_H
+#define HEADER_CURL_NTLM_CORE_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#ifdef USE_NTLM
+
+void Curl_ntlm_core_lm_resp(const unsigned char *keys,
+                            const unsigned char *plaintext,
+                            unsigned char *results);
+
+void Curl_ntlm_core_mk_lm_hash(struct SessionHandle *data,
+                               const char *password,
+                               unsigned char *lmbuffer /* 21 bytes */);
+
+#if !defined(USE_WINDOWS_SSPI) && (USE_NTRESPONSES != 0)
+CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data,
+                                   const char *password,
+                                   unsigned char *ntbuffer /* 21 bytes */);
+#endif
+
+#endif /* USE_NTLM */
+
+#endif /* HEADER_CURL_NTLM_CORE_H */
index fc7e09a57653083e0234d392ae3408940bee8b7b..2b400e8a6bf05923953fb348450de89227f567ac 100644 (file)
 #include <signal.h>
 #endif
 
-#if (defined(NETWARE) && !defined(__NOVELL_LIBC__))
-#include <netdb.h>
-#endif
-
 #include "urldata.h"
-#include "non-ascii.h"  /* for Curl_convert_... prototypes */
 #include "sendf.h"
 #include "select.h"
-#include "rawstr.h"
-#include "curl_base64.h"
 #include "curl_ntlm_wb.h"
 #include "url.h"
 #include "strerror.h"
-#include "curl_gethostname.h"
 #include "curl_memory.h"
 
 #define _MPRINTF_REPLACE /* use our functions only */
index 1420ce886eeb32280cae322a42ee438487f3507a..8092cefaa321839cd664f9b6ff655bfc5373af6c 100644 (file)
@@ -36,7 +36,7 @@ SOURCE \
   pingpong.c rtsp.c curl_threads.c warnless.c hmac.c polarssl.c                \
   curl_rtmp.c openldap.c curl_gethostname.c gopher.c axtls.c           \
   idn_win32.c http_negotiate_sspi.c cyassl.c http_proxy.c non-ascii.c  \
-  asyn-ares.c asyn-thread.c curl_ntlm.c curl_ntlm_wb.c
+  asyn-ares.c asyn-thread.c curl_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c
 
 USERINCLUDE   ../../../lib ../../../include/curl
 #ifdef ENABLE_SSL