- add support for NTLM authentication (#603783)
This commit is contained in:
parent
887f1deb36
commit
d616d7a60a
855
0001-curl-7.21.0-ntlm.patch
Normal file
855
0001-curl-7.21.0-ntlm.patch
Normal file
@ -0,0 +1,855 @@
|
||||
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 f561aad..30bb18b 100644
|
||||
--- a/CHANGES
|
||||
+++ b/CHANGES
|
||||
@@ -6,6 +6,26 @@
|
||||
|
||||
Changelog
|
||||
|
||||
+Kamil Dudka (28 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.
|
||||
+
|
||||
Version 7.21.0 (16 June 2010)
|
||||
|
||||
Daniel Stenberg (5 June 2010)
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index af30b8a..18a3642 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -2659,7 +2659,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 6311780..a502e8f 100644
|
||||
--- a/lib/Makefile.inc
|
||||
+++ b/lib/Makefile.inc
|
||||
@@ -6,7 +6,7 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
|
||||
netrc.c getinfo.c transfer.c strequal.c easy.c security.c krb4.c \
|
||||
curl_fnmatch.c fileinfo.c ftplistparser.c wildcard.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 \
|
||||
@@ -20,7 +20,7 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.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 \
|
||||
curl_fnmatch.h wildcard.h fileinfo.h ftplistparser.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@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 4058d78..6d3f12c 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)
|
||||
{
|
||||
@@ -1039,16 +1105,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;
|
||||
|
||||
@@ -1062,76 +1124,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();
|
||||
@@ -1448,4 +1470,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 6eaa178..f9cc46a 100644
|
||||
--- a/lib/nssg.h
|
||||
+++ b/lib/nssg.h
|
||||
@@ -46,6 +46,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 43f98a8..90bb898 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
|
11
curl.spec
11
curl.spec
@ -1,13 +1,16 @@
|
||||
Summary: A utility for getting files from remote servers (FTP, HTTP, and others)
|
||||
Name: curl
|
||||
Version: 7.21.0
|
||||
Release: 1%{?dist}
|
||||
Release: 2%{?dist}
|
||||
License: MIT
|
||||
Group: Applications/Internet
|
||||
Source: http://curl.haxx.se/download/%{name}-%{version}.tar.lzma
|
||||
Source2: curlbuild.h
|
||||
Source3: hide_selinux.c
|
||||
|
||||
# patch adding support for NTLM authentication (#603783)
|
||||
Patch1: 0001-curl-7.21.0-ntlm.patch
|
||||
|
||||
# patch making libcurl multilib ready
|
||||
Patch101: 0101-curl-7.20.0-multilib.patch
|
||||
|
||||
@ -94,6 +97,9 @@ for f in CHANGES README; do
|
||||
mv -f ${f}.utf8 ${f}
|
||||
done
|
||||
|
||||
# upstream patches (not yet applied)
|
||||
%patch1 -p1
|
||||
|
||||
# Fedora patches
|
||||
%patch101 -p1
|
||||
%patch102 -p1
|
||||
@ -207,6 +213,9 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%{_datadir}/aclocal/libcurl.m4
|
||||
|
||||
%changelog
|
||||
* Mon Jun 28 2010 Kamil Dudka <kdudka@redhat.com> 7.21.0-2
|
||||
- add support for NTLM authentication (#603783)
|
||||
|
||||
* Wed Jun 16 2010 Kamil Dudka <kdudka@redhat.com> 7.21.0-1
|
||||
- new upstream release, drop applied patches
|
||||
- update of %%description
|
||||
|
Loading…
Reference in New Issue
Block a user