rpms/curl/F-13 0006-curl-7.21.0-f3b77e5.patch, NONE, 1.1 curl.spec, 1.148, 1.149

Kamil Dudka kdudka at fedoraproject.org
Wed Jun 30 13:23:07 UTC 2010


Author: kdudka

Update of /cvs/extras/rpms/curl/F-13
In directory cvs01.phx2.fedoraproject.org:/tmp/cvs-serv17251/F-13

Modified Files:
	curl.spec 
Added Files:
	0006-curl-7.21.0-f3b77e5.patch 
Log Message:
- add support for NTLM authentication (#603783)

0006-curl-7.21.0-f3b77e5.patch:
 CHANGES          |   20 +++
 configure.ac     |    3 
 lib/Makefile.inc |    4 
 lib/curl_md4.h   |   33 ++++++
 lib/http_ntlm.c  |  126 +++++++++++++++++++++++-
 lib/md4.c        |  281 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/nss.c        |  162 ++++++++++++++++++-------------
 lib/nssg.h       |    3 
 lib/setup.h      |    2 
 9 files changed, 556 insertions(+), 78 deletions(-)

--- NEW FILE 0006-curl-7.21.0-f3b77e5.patch ---
 CHANGES          |   20 ++++
 configure.ac     |    3 +-
 lib/Makefile.inc |    4 +-
 lib/curl_md4.h   |   33 +++++++
 lib/http_ntlm.c  |  126 +++++++++++++++++++++++--
 lib/md4.c        |  281 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/nss.c        |  162 ++++++++++++++++++-------------
 lib/nssg.h       |    3 +
 lib/setup.h      |    2 +-
 9 files changed, 556 insertions(+), 78 deletions(-)

diff --git a/CHANGES b/CHANGES
index 92c2753..ccb5e57 100644
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,26 @@
 
                                   Changelog
 
+Kamil Dudka (30 Jun 2010)
+- http_ntlm: add support for NSS
+  
+  When configured with '--without-ssl --with-nss', NTLM authentication
+  now uses NSS crypto library for MD5 and DES.  For MD4 we have a local
+  implementation in that case.  More details are available at
+  https://bugzilla.redhat.com/603783
+  
+  In order to get it working, curl_global_init() must be called with
+  CURL_GLOBAL_SSL or CURL_GLOBAL_ALL.  That's necessary because NSS needs
+  to be initialized globally and we do so only when the NSS library is
+  actually required by protocol.  The mentioned call of curl_global_init()
+  is responsible for creating of the initialization mutex.
+  
+  There was also slightly changed the NSS initialization scenario, in
+  particular, loading of the NSS PEM module.  It used to be loaded always
+  right after the NSS library was initialized.  Now the library is
+  initialized as soon as any SSL or NTLM is required, while the PEM module
+  is prevented from being loaded until the SSL is actually required.
+
 Kamil Dudka (11 May 2010)
 - CRL support in libcurl-NSS has been completely broken. Now it works. Original
   bug report: https://bugzilla.redhat.com/581926
diff --git a/configure.ac b/configure.ac
index 2d394e1..a317ed7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2484,7 +2484,8 @@ fi
 if test "x$USE_WINDOWS_SSPI" = "x1"; then
   SUPPORT_FEATURES="$SUPPORT_FEATURES SSPI"
 fi
-if test "x$USE_SSLEAY" = "x1" -o "x$USE_WINDOWS_SSPI" = "x1" -o "x$GNUTLS_ENABLED" = "x1"; then
+if test "x$USE_SSLEAY" = "x1" -o "x$USE_WINDOWS_SSPI" = "x1" \
+    -o "x$GNUTLS_ENABLED" = "x1" -o "x$NSS_ENABLED" = "x1"; then
   SUPPORT_FEATURES="$SUPPORT_FEATURES NTLM"
 fi
 
diff --git a/lib/Makefile.inc b/lib/Makefile.inc
index 9803c8c..4b33486 100644
--- a/lib/Makefile.inc
+++ b/lib/Makefile.inc
@@ -5,7 +5,7 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c	\
   ldap.c ssluse.c version.c getenv.c escape.c mprintf.c telnet.c	\
   netrc.c getinfo.c transfer.c strequal.c easy.c security.c krb4.c	\
   krb5.c memdebug.c http_chunks.c strtok.c connect.c llist.c hash.c	\
-  multi.c content_encoding.c share.c http_digest.c md5.c curl_rand.c	\
+  multi.c content_encoding.c share.c http_digest.c md4.c md5.c curl_rand.c	\
   http_negotiate.c http_ntlm.c inet_pton.c strtoofft.c strerror.c	\
   hostares.c hostasyn.c hostip4.c hostip6.c hostsyn.c hostthre.c	\
   inet_ntop.c parsedate.c select.c gtls.c sslgen.c tftp.c splay.c	\
@@ -18,7 +18,7 @@ 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	\
   if2ip.h speedcheck.h urldata.h curl_ldap.h ssluse.h escape.h telnet.h	\
   getinfo.h strequal.h krb4.h memdebug.h http_chunks.h curl_rand.h	\
-  strtok.h connect.h llist.h hash.h content_encoding.h share.h		\
+  strtok.h connect.h llist.h hash.h content_encoding.h share.h curl_md4.h	\
   curl_md5.h http_digest.h http_negotiate.h http_ntlm.h inet_pton.h	\
   strtoofft.h strerror.h inet_ntop.h curlx.h curl_memory.h setup.h	\
   transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h gtls.h	\
diff --git a/lib/curl_md4.h b/lib/curl_md4.h
new file mode 100644
index 0000000..6b6c16e
--- /dev/null
+++ b/lib/curl_md4.h
@@ -0,0 +1,33 @@
+#ifndef HEADER_CURL_MD4_H
+#define HEADER_CURL_MD4_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel at 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"
+
+/* NSS crypto library does not provide the MD4 hash algorithm, so that we have
+ * a local implementation of it */
+#ifdef USE_NSS
+void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len);
+#endif /* USE_NSS */
+
+#endif /* HEADER_CURL_MD4_H */
diff --git a/lib/http_ntlm.c b/lib/http_ntlm.c
index 36e538e..0e831ca 100644
--- a/lib/http_ntlm.c
+++ b/lib/http_ntlm.c
@@ -116,6 +116,15 @@
 #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"
@@ -250,6 +259,11 @@ CURLntlm Curl_input_ntlm(struct connectdata *conn,
   static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
 #endif
 
+#ifdef USE_NSS
+  if(CURLE_OK != Curl_nss_force_init(conn->data))
+    return CURLNTLM_BAD;
+#endif
+
   ntlm = proxy?&conn->proxyntlm:&conn->ntlm;
 
   /* skip initial whitespaces */
@@ -351,16 +365,14 @@ static void setup_des_key(const unsigned char *key_56,
   DES_set_odd_parity(&key);
   DES_set_key(&key, ks);
 }
-#elif defined(USE_GNUTLS)
+
+#else /* defined(USE_SSLEAY) */
 
 /*
- * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.
+ * Turns a 56 bit key into the 64 bit, odd parity key.  Used by GnuTLS and NSS.
  */
-static void setup_des_key(const unsigned char *key_56,
-                          gcry_cipher_hd_t *des)
+static void extend_key_56_to_64(const unsigned char *key_56, char *key)
 {
-  char key[8];
-
   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));
@@ -369,10 +381,84 @@ static void setup_des_key(const unsigned char *key_56,
   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);
 }
-#endif
+
+#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
@@ -414,6 +500,10 @@ static void lm_resp(const unsigned char *keys,
   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
 }
 
@@ -470,11 +560,14 @@ static void mk_lm_hash(struct SessionHandle *data,
     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,
@@ -525,6 +618,8 @@ static CURLcode mk_nt_hash(struct SessionHandle *data,
     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);
@@ -599,6 +694,11 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
   DEBUGASSERT(conn);
   DEBUGASSERT(conn->data);
 
+#ifdef USE_NSS
+  if(CURLE_OK != Curl_nss_force_init(conn->data))
+    return CURLE_OUT_OF_MEMORY;
+#endif
+
   if(proxy) {
     allocuserpwd = &conn->allocptr.proxyuserpwd;
     userp = conn->proxyuser;
@@ -926,6 +1026,11 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
       gcry_md_hd_t MD5pw;
       Curl_gtls_seed(conn->data); /* Initiate the seed if not already done */
       gcry_randomize(entropy, 8, GCRY_STRONG_RANDOM);
+#elif defined(USE_NSS)
+      PK11Context *MD5pw;
+      unsigned int outlen;
+      Curl_nss_seed(conn->data);  /* Initiate the seed if not already done */
+      PK11_GenerateRandom(entropy, 8);
 #endif
 
       /* 8 bytes random data as challenge in lmresp */
@@ -946,6 +1051,11 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
       gcry_md_write(MD5pw, tmp, MD5_DIGEST_LENGTH);
       memcpy(md5sum, gcry_md_read (MD5pw, 0), MD5_DIGEST_LENGTH);
       gcry_md_close(MD5pw);
+#elif defined(USE_NSS)
+      MD5pw = PK11_CreateDigestContext(SEC_OID_MD5);
+      PK11_DigestOp(MD5pw, tmp, 16);
+      PK11_DigestFinal(MD5pw, md5sum, &outlen, MD5_DIGEST_LENGTH);
+      PK11_DestroyContext(MD5pw, PR_TRUE);
 #endif
 
       /* We shall only use the first 8 bytes of md5sum,
diff --git a/lib/md4.c b/lib/md4.c
new file mode 100644
index 0000000..7000083
--- /dev/null
+++ b/lib/md4.c
@@ -0,0 +1,281 @@
+/*-
+   Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
+
+   License to copy and use this software is granted provided that it
+   is identified as the "RSA Data Security, Inc. MD4 Message-Digest
+   Algorithm" in all material mentioning or referencing this software
+   or this function.
+
+   License is also granted to make and use derivative works provided
+   that such works are identified as "derived from the RSA Data
+   Security, Inc. MD4 Message-Digest Algorithm" in all material
+   mentioning or referencing the derived work.
+
+   RSA Data Security, Inc. makes no representations concerning either
+   the merchantability of this software or the suitability of this
+   software for any particular purpose. It is provided "as is"
+   without express or implied warranty of any kind.
+
+   These notices must be retained in any copies of any part of this
+   documentation and/or software.
+ */
+
+#include "setup.h"
+
+/* NSS crypto library does not provide the MD4 hash algorithm, so that we have
+ * a local implementation of it */
+#ifdef USE_NSS
+
+#include "curl_md4.h"
+#include <string.h>
+
+typedef unsigned int UINT4;
+
+typedef struct MD4Context {
+  UINT4 state[4];               /* state (ABCD) */
+  UINT4 count[2];               /* number of bits, modulo 2^64 (lsb first) */
+  unsigned char buffer[64];     /* input buffer */
+} MD4_CTX;
+
+/* Constants for MD4Transform routine.
+ */
+#define S11 3
+#define S12 7
+#define S13 11
+#define S14 19
+#define S21 3
+#define S22 5
+#define S23 9
+#define S24 13
+#define S31 3
+#define S32 9
+#define S33 11
+#define S34 15
+
+static void MD4Transform(UINT4 [4], const unsigned char [64]);
+static void Encode(unsigned char *, UINT4 *, unsigned int);
+static void Decode(UINT4 *, const unsigned char *, unsigned int);
+
+static unsigned char PADDING[64] = {
+  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G and H are basic MD4 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
+/* Rotation is separate from addition to prevent recomputation */
+#define FF(a, b, c, d, x, s) { \
+    (a) += F ((b), (c), (d)) + (x); \
+    (a) = ROTATE_LEFT ((a), (s)); \
+  }
+#define GG(a, b, c, d, x, s) { \
+    (a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \
+    (a) = ROTATE_LEFT ((a), (s)); \
+  }
+#define HH(a, b, c, d, x, s) { \
+    (a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \
+    (a) = ROTATE_LEFT ((a), (s)); \
+  }
+
+/* MD4 initialization. Begins an MD4 operation, writing a new context.
+ */
+static void MD4Init(MD4_CTX *context)
+{
+  context->count[0] = context->count[1] = 0;
+
+  /* Load magic initialization constants.
+   */
+  context->state[0] = 0x67452301;
+  context->state[1] = 0xefcdab89;
+  context->state[2] = 0x98badcfe;
+  context->state[3] = 0x10325476;
+}
+
+/* MD4 block update operation. Continues an MD4 message-digest
+     operation, processing another message block, and updating the
+     context.
+ */
+static void MD4Update(MD4_CTX *context, const unsigned char *input,
+                      unsigned int inputLen)
+{
+  unsigned int i, bufindex, partLen;
+
+  /* Compute number of bytes mod 64 */
+  bufindex = (unsigned int)((context->count[0] >> 3) & 0x3F);
+  /* Update number of bits */
+  if ((context->count[0] += ((UINT4)inputLen << 3))
+      < ((UINT4)inputLen << 3))
+    context->count[1]++;
+  context->count[1] += ((UINT4)inputLen >> 29);
+
+  partLen = 64 - bufindex;
+  /* Transform as many times as possible.
+   */
+  if (inputLen >= partLen) {
+    bcopy(input, &context->buffer[bufindex], partLen);
+    MD4Transform (context->state, context->buffer);
+
+    for (i = partLen; i + 63 < inputLen; i += 64)
+      MD4Transform (context->state, &input[i]);
+
+    bufindex = 0;
+  }
+  else
+    i = 0;
+
+  /* Buffer remaining input */
+  bcopy(&input[i], &context->buffer[bufindex], inputLen-i);
+}
+
+/* MD4 padding. */
+static void MD4Pad(MD4_CTX *context)
+{
+  unsigned char bits[8];
+  unsigned int bufindex, padLen;
+
+  /* Save number of bits */
+  Encode (bits, context->count, 8);
+
+  /* Pad out to 56 mod 64.
+   */
+  bufindex = (unsigned int)((context->count[0] >> 3) & 0x3f);
+  padLen = (bufindex < 56) ? (56 - bufindex) : (120 - bufindex);
+  MD4Update (context, PADDING, padLen);
+
+  /* Append length (before padding) */
+  MD4Update (context, bits, 8);
+}
+
+/* MD4 finalization. Ends an MD4 message-digest operation, writing the
+     the message digest and zeroizing the context.
+ */
+static void MD4Final (unsigned char digest[16], MD4_CTX *context)
+{
+  /* Do padding */
+  MD4Pad (context);
+
+  /* Store state in digest */
+  Encode (digest, context->state, 16);
+
+  /* Zeroize sensitive information.
+   */
+  memset(context, 0, sizeof(*context));
+}
+
+/* MD4 basic transformation. Transforms state based on block.
+ */
+static void MD4Transform (UINT4 state[4], const unsigned char block[64])
+{
+  UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+  Decode (x, block, 64);
+
+  /* Round 1 */
+  FF (a, b, c, d, x[ 0], S11); /* 1 */
+  FF (d, a, b, c, x[ 1], S12); /* 2 */
+  FF (c, d, a, b, x[ 2], S13); /* 3 */
+  FF (b, c, d, a, x[ 3], S14); /* 4 */
+  FF (a, b, c, d, x[ 4], S11); /* 5 */
+  FF (d, a, b, c, x[ 5], S12); /* 6 */
+  FF (c, d, a, b, x[ 6], S13); /* 7 */
+  FF (b, c, d, a, x[ 7], S14); /* 8 */
+  FF (a, b, c, d, x[ 8], S11); /* 9 */
+  FF (d, a, b, c, x[ 9], S12); /* 10 */
+  FF (c, d, a, b, x[10], S13); /* 11 */
+  FF (b, c, d, a, x[11], S14); /* 12 */
+  FF (a, b, c, d, x[12], S11); /* 13 */
+  FF (d, a, b, c, x[13], S12); /* 14 */
+  FF (c, d, a, b, x[14], S13); /* 15 */
+  FF (b, c, d, a, x[15], S14); /* 16 */
+
+  /* Round 2 */
+  GG (a, b, c, d, x[ 0], S21); /* 17 */
+  GG (d, a, b, c, x[ 4], S22); /* 18 */
+  GG (c, d, a, b, x[ 8], S23); /* 19 */
+  GG (b, c, d, a, x[12], S24); /* 20 */
+  GG (a, b, c, d, x[ 1], S21); /* 21 */
+  GG (d, a, b, c, x[ 5], S22); /* 22 */
+  GG (c, d, a, b, x[ 9], S23); /* 23 */
+  GG (b, c, d, a, x[13], S24); /* 24 */
+  GG (a, b, c, d, x[ 2], S21); /* 25 */
+  GG (d, a, b, c, x[ 6], S22); /* 26 */
+  GG (c, d, a, b, x[10], S23); /* 27 */
+  GG (b, c, d, a, x[14], S24); /* 28 */
+  GG (a, b, c, d, x[ 3], S21); /* 29 */
+  GG (d, a, b, c, x[ 7], S22); /* 30 */
+  GG (c, d, a, b, x[11], S23); /* 31 */
+  GG (b, c, d, a, x[15], S24); /* 32 */
+
+  /* Round 3 */
+  HH (a, b, c, d, x[ 0], S31); /* 33 */
+  HH (d, a, b, c, x[ 8], S32); /* 34 */
+  HH (c, d, a, b, x[ 4], S33); /* 35 */
+  HH (b, c, d, a, x[12], S34); /* 36 */
+  HH (a, b, c, d, x[ 2], S31); /* 37 */
+  HH (d, a, b, c, x[10], S32); /* 38 */
+  HH (c, d, a, b, x[ 6], S33); /* 39 */
+  HH (b, c, d, a, x[14], S34); /* 40 */
+  HH (a, b, c, d, x[ 1], S31); /* 41 */
+  HH (d, a, b, c, x[ 9], S32); /* 42 */
+  HH (c, d, a, b, x[ 5], S33); /* 43 */
+  HH (b, c, d, a, x[13], S34); /* 44 */
+  HH (a, b, c, d, x[ 3], S31); /* 45 */
+  HH (d, a, b, c, x[11], S32); /* 46 */
+  HH (c, d, a, b, x[ 7], S33); /* 47 */
+  HH (b, c, d, a, x[15], S34); /* 48 */
+
+  state[0] += a;
+  state[1] += b;
+  state[2] += c;
+  state[3] += d;
+
+  /* Zeroize sensitive information.
+   */
+  memset(x, 0, sizeof(x));
+}
+
+/* Encodes input (UINT4) into output (unsigned char). Assumes len is
+     a multiple of 4.
+ */
+static void Encode(unsigned char *output, UINT4 *input, unsigned int len)
+{
+  unsigned int i, j;
+
+  for (i = 0, j = 0; j < len; i++, j += 4) {
+    output[j] = (unsigned char)(input[i] & 0xff);
+    output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+    output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+    output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+  }
+}
+
+/* Decodes input (unsigned char) into output (UINT4). Assumes len is
+     a multiple of 4.
+ */
+static void Decode (UINT4 *output, const unsigned char *input, unsigned int len)
+{
+  unsigned int i, j;
+
+  for (i = 0, j = 0; j < len; i++, j += 4)
+    output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
+      (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
+}
+
+void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len)
+{
+  MD4_CTX ctx;
+  MD4Init(&ctx);
+  MD4Update(&ctx, input, (unsigned int)len);
+  MD4Final(output, &ctx);
+}
+#endif /* USE_NSS */
diff --git a/lib/nss.c b/lib/nss.c
index 5e94d31..752f3c5 100644
--- a/lib/nss.c
+++ b/lib/nss.c
@@ -891,6 +891,57 @@ isTLSIntoleranceError(PRInt32 err)
   }
 }
 
+static CURLcode init_nss(struct SessionHandle *data)
+{
+  char *cert_dir;
+  struct_stat st;
+  if(initialized)
+    return CURLE_OK;
+
+  /* First we check if $SSL_DIR points to a valid dir */
+  cert_dir = getenv("SSL_DIR");
+  if(cert_dir) {
+    if((stat(cert_dir, &st) != 0) ||
+        (!S_ISDIR(st.st_mode))) {
+      cert_dir = NULL;
+    }
+  }
+
+  /* Now we check if the default location is a valid dir */
+  if(!cert_dir) {
+    if((stat(SSL_DIR, &st) == 0) &&
+        (S_ISDIR(st.st_mode))) {
+      cert_dir = (char *)SSL_DIR;
+    }
+  }
+
+  if(!NSS_IsInitialized()) {
+    SECStatus rv;
+    initialized = 1;
+    infof(data, "Initializing NSS with certpath: %s\n",
+          cert_dir ? cert_dir : "none");
+    if(!cert_dir) {
+      rv = NSS_NoDB_Init(NULL);
+    }
+    else {
+      char *certpath =
+        PR_smprintf("%s%s", NSS_VersionCheck("3.12.0") ? "sql:" : "", cert_dir);
+      rv = NSS_Initialize(certpath, "", "", "", NSS_INIT_READONLY);
+      PR_smprintf_free(certpath);
+    }
+    if(rv != SECSuccess) {
+      infof(data, "Unable to initialize NSS database\n");
+      initialized = 0;
+      return CURLE_SSL_CACERT_BADFILE;
+    }
+  }
+
+  if(num_enabled_ciphers() == 0)
+    NSS_SetDomesticPolicy();
+
+  return CURLE_OK;
+}
+
 /**
  * Global SSL init
  *
@@ -911,6 +962,21 @@ int Curl_nss_init(void)
   return 1;
 }
 
+CURLcode Curl_nss_force_init(struct SessionHandle *data)
+{
+  CURLcode rv;
+  if(!nss_initlock) {
+    failf(data, "unable to initialize NSS, curl_global_init() should have been "
+                "called with CURL_GLOBAL_SSL or CURL_GLOBAL_ALL");
+    return CURLE_OUT_OF_MEMORY;
+  }
+
+  PR_Lock(nss_initlock);
+  rv = init_nss(data);
+  PR_Unlock(nss_initlock);
+  return rv;
+}
+
 /* Global cleanup */
 void Curl_nss_cleanup(void)
 {
@@ -1036,16 +1102,12 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
   struct SessionHandle *data = conn->data;
   curl_socket_t sockfd = conn->sock[sockindex];
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-  SECStatus rv;
-  char *certDir = NULL;
   int curlerr;
   const int *cipher_to_enable;
   PRSocketOptionData sock_opt;
   long time_left;
   PRUint32 timeout;
 
-  curlerr = CURLE_SSL_CONNECT_ERROR;
-
   if (connssl->state == ssl_connection_complete)
     return CURLE_OK;
 
@@ -1059,76 +1121,36 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
 
   /* FIXME. NSS doesn't support multiple databases open at the same time. */
   PR_Lock(nss_initlock);
-  if(!initialized) {
-    struct_stat st;
-
-    /* First we check if $SSL_DIR points to a valid dir */
-    certDir = getenv("SSL_DIR");
-    if(certDir) {
-      if((stat(certDir, &st) != 0) ||
-         (!S_ISDIR(st.st_mode))) {
-        certDir = NULL;
-      }
-    }
-
-    /* Now we check if the default location is a valid dir */
-    if(!certDir) {
-      if((stat(SSL_DIR, &st) == 0) &&
-         (S_ISDIR(st.st_mode))) {
-        certDir = (char *)SSL_DIR;
-      }
-    }
-
-    if (!NSS_IsInitialized()) {
-      initialized = 1;
-      infof(conn->data, "Initializing NSS with certpath: %s\n",
-            certDir ? certDir : "none");
-      if(!certDir) {
-        rv = NSS_NoDB_Init(NULL);
-      }
-      else {
-        char *certpath = PR_smprintf("%s%s",
-                                     NSS_VersionCheck("3.12.0") ? "sql:" : "",
-                                     certDir);
-        rv = NSS_Initialize(certpath, "", "", "", NSS_INIT_READONLY);
-        PR_smprintf_free(certpath);
-      }
-      if(rv != SECSuccess) {
-        infof(conn->data, "Unable to initialize NSS database\n");
-        curlerr = CURLE_SSL_CACERT_BADFILE;
-        initialized = 0;
-        PR_Unlock(nss_initlock);
-        goto error;
-      }
-    }
+  curlerr = init_nss(conn->data);
+  if(CURLE_OK != curlerr) {
+    PR_Unlock(nss_initlock);
+    goto error;
+  }
 
-    if(num_enabled_ciphers() == 0)
-      NSS_SetDomesticPolicy();
+  curlerr = CURLE_SSL_CONNECT_ERROR;
 
 #ifdef HAVE_PK11_CREATEGENERICOBJECT
-    if(!mod) {
-      char *configstring = aprintf("library=%s name=PEM", pem_library);
-      if(!configstring) {
-        PR_Unlock(nss_initlock);
-        goto error;
-      }
-      mod = SECMOD_LoadUserModule(configstring, NULL, PR_FALSE);
-      free(configstring);
+  if(!mod) {
+    char *configstring = aprintf("library=%s name=PEM", pem_library);
+    if(!configstring) {
+      PR_Unlock(nss_initlock);
+      goto error;
+    }
+    mod = SECMOD_LoadUserModule(configstring, NULL, PR_FALSE);
+    free(configstring);
 
-      if(!mod || !mod->loaded) {
-        if(mod) {
-          SECMOD_DestroyModule(mod);
-          mod = NULL;
-        }
-        infof(data, "WARNING: failed to load NSS PEM library %s. Using "
-              "OpenSSL PEM certificates will not work.\n", pem_library);
+    if(!mod || !mod->loaded) {
+      if(mod) {
+        SECMOD_DestroyModule(mod);
+        mod = NULL;
       }
+      infof(data, "WARNING: failed to load NSS PEM library %s. Using "
+            "OpenSSL PEM certificates will not work.\n", pem_library);
     }
+  }
 #endif
 
-    PK11_SetPasswordFunc(nss_get_password);
-
-  }
+  PK11_SetPasswordFunc(nss_get_password);
   PR_Unlock(nss_initlock);
 
   model = PR_NewTCPSocket();
@@ -1445,4 +1467,12 @@ size_t Curl_nss_version(char *buffer, size_t size)
 {
   return snprintf(buffer, size, "NSS/%s", NSS_VERSION);
 }
+
+int Curl_nss_seed(struct SessionHandle *data)
+{
+  /* TODO: implement? */
+  (void) data;
+  return 0;
+}
+
 #endif /* USE_NSS */
diff --git a/lib/nssg.h b/lib/nssg.h
index 309c3d6..68ee8c0 100644
--- a/lib/nssg.h
+++ b/lib/nssg.h
@@ -60,6 +60,9 @@ size_t Curl_nss_version(char *buffer, size_t size);
 int Curl_nss_check_cxn(struct connectdata *cxn);
 int Curl_nss_seed(struct SessionHandle *data);
 
+/* initialize NSS library if not already */
+CURLcode Curl_nss_force_init(struct SessionHandle *data);
+
 /* API setup for NSS */
 #define curlssl_init Curl_nss_init
 #define curlssl_cleanup Curl_nss_cleanup
diff --git a/lib/setup.h b/lib/setup.h
index ca98ad7..9743311 100644
--- a/lib/setup.h
+++ b/lib/setup.h
@@ -530,7 +530,7 @@ int netware_init(void);
 #endif
 
 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_NTLM)
-#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI) || defined(USE_GNUTLS)
+#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI) || defined(USE_GNUTLS) || defined(USE_NSS)
 #define USE_NTLM
 #endif
 #endif


Index: curl.spec
===================================================================
RCS file: /cvs/extras/rpms/curl/F-13/curl.spec,v
retrieving revision 1.148
retrieving revision 1.149
diff -u -p -r1.148 -r1.149
--- curl.spec	4 Jun 2010 10:27:51 -0000	1.148
+++ curl.spec	30 Jun 2010 13:23:07 -0000	1.149
@@ -1,7 +1,7 @@
 Summary: A utility for getting files from remote servers (FTP, HTTP, and others)
 Name: curl
 Version: 7.20.1
-Release: 2%{?dist}
+Release: 3%{?dist}
 License: MIT
 Group: Applications/Internet
 Source: http://curl.haxx.se/download/%{name}-%{version}.tar.lzma
@@ -30,6 +30,9 @@ Patch4: 0004-curl-7.20.1-crl-test.patch
 # upstream commit 47dda4a1d43c9341753388ab3babb0d27cf34840
 Patch5: 0005-curl-7.20.1-47dda4a.patch
 
+# patch adding support for NTLM authentication (#603783)
+Patch6: 0006-curl-7.21.0-f3b77e5.patch
+
 # patch making libcurl multilib ready
 Patch101: 0101-curl-7.20.0-multilib.patch
 
@@ -133,10 +136,9 @@ done
 %patch1 -p1
 %patch2 -p1
 %patch3 -p1
-%patch5 -p1
-
-# upstream patches (not yet applied)
 %patch4 -p1
+%patch5 -p1
+%patch6 -p1
 
 # Fedora patches
 %patch101 -p1
@@ -241,6 +243,9 @@ rm -rf $RPM_BUILD_ROOT
 %{_datadir}/aclocal/libcurl.m4
 
 %changelog
+* Wed Jun 30 2010 Kamil Dudka <kdudka at redhat.com> 7.20.1-3
+- add support for NTLM authentication (#603783)
+
 * Fri Jun 04 2010 Kamil Dudka <kdudka at redhat.com> 7.20.1-2
 - workaround for broken applications using curl multi (#599340)
 



More information about the scm-commits mailing list