diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Makefile.inc | 5 | ||||
| -rw-r--r-- | lib/Makefile.vc6 | 1 | ||||
| -rw-r--r-- | lib/curl_ntlm.c | 352 | ||||
| -rw-r--r-- | lib/curl_ntlm_core.c | 412 | ||||
| -rw-r--r-- | lib/curl_ntlm_core.h | 43 | ||||
| -rw-r--r-- | lib/curl_ntlm_wb.c | 8 | 
6 files changed, 483 insertions, 338 deletions
| diff --git a/lib/Makefile.inc b/lib/Makefile.inc index a724f605b..3778fbcf0 100644 --- a/lib/Makefile.inc +++ b/lib/Makefile.inc @@ -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 diff --git a/lib/Makefile.vc6 b/lib/Makefile.vc6 index cbf4b8a03..d3b11d993 100644 --- a/lib/Makefile.vc6 +++ b/lib/Makefile.vc6 @@ -507,6 +507,7 @@ X_OBJS= \  	$(DIROBJ)\curl_gethostname.obj \
  	$(DIROBJ)\curl_memrchr.obj \
  	$(DIROBJ)\curl_ntlm.obj \
 +	$(DIROBJ)\curl_ntlm_core.obj \
  	$(DIROBJ)\curl_ntlm_wb.obj \
  	$(DIROBJ)\curl_rand.obj \
  	$(DIROBJ)\curl_rtmp.obj \
 diff --git a/lib/curl_ntlm.c b/lib/curl_ntlm.c index d4f2cc20b..4398d146c 100644 --- a/lib/curl_ntlm.c +++ b/lib/curl_ntlm.c @@ -35,12 +35,6 @@  #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" @@ -87,22 +81,6 @@  #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 @@ -134,15 +112,6 @@  #    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 @@ -152,6 +121,17 @@  #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 index 000000000..b8cc4c691 --- /dev/null +++ b/lib/curl_ntlm_core.c @@ -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 index 000000000..ea855905f --- /dev/null +++ b/lib/curl_ntlm_core.h @@ -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 */ diff --git a/lib/curl_ntlm_wb.c b/lib/curl_ntlm_wb.c index fc7e09a57..2b400e8a6 100644 --- a/lib/curl_ntlm_wb.c +++ b/lib/curl_ntlm_wb.c @@ -36,20 +36,12 @@  #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 */ | 
