File firefox-ntlm.patch of Package kompozer
diff --git a/mozilla/extensions/auth/Makefile.in b/mozilla/extensions/auth/Makefile.in
index f0aff40..46e5f5e 100644
--- a/mozilla/extensions/auth/Makefile.in
+++ b/mozilla/extensions/auth/Makefile.in
@@ -78,6 +78,8 @@ CPPSRCS += \
ifeq ($(OS_ARCH),WINNT)
LOCAL_INCLUDES += -DUSE_SSPI
CPPSRCS += nsAuthSSPI.cpp
+else
+CPPSRCS += nsAuthSambaNTLM.cpp
endif
include $(topsrcdir)/config/rules.mk
diff --git a/mozilla/extensions/auth/nsAuthFactory.cpp b/mozilla/extensions/auth/nsAuthFactory.cpp
index b3d515c..71705e5 100644
--- a/mozilla/extensions/auth/nsAuthFactory.cpp
+++ b/mozilla/extensions/auth/nsAuthFactory.cpp
@@ -127,6 +127,36 @@ nsKerbSSPIAuthConstructor(nsISupports *outer, REFNSIID iid, void **result)
{0x8c, 0xd6, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66} \
}
+#else
+
+#define NS_SAMBANTLMAUTH_CID \
+{ /* bc54f001-6eb0-4e32-9f49-7e064d8e70ef */ \
+ 0xbc54f001, \
+ 0x6eb0, \
+ 0x4e32, \
+ {0x9f, 0x49, 0x7e, 0x06, 0x4d, 0x8e, 0x70, 0xef} \
+}
+
+#include "nsAuthSambaNTLM.h"
+static NS_METHOD
+nsSambaNTLMAuthConstructor(nsISupports *outer, REFNSIID iid, void **result)
+{
+ if (outer)
+ return NS_ERROR_NO_AGGREGATION;
+
+ nsCOMPtr<nsAuthSambaNTLM> auth = new nsAuthSambaNTLM();
+ if (!auth)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = auth->SpawnNTLMAuthHelper();
+ if (NS_FAILED(rv)) {
+ // Failure here probably means that cached credentials were not available
+ return rv;
+ }
+
+ return auth->QueryInterface(iid, result);
+}
+
#endif
static NS_METHOD
@@ -206,6 +236,12 @@ static nsModuleComponentInfo components[] = {
NS_AUTH_MODULE_CONTRACTID_PREFIX "sys-ntlm",
nsSysNTLMAuthConstructor
},
+#else
+ { "nsAuthSambaNTLM",
+ NS_SAMBANTLMAUTH_CID,
+ NS_AUTH_MODULE_CONTRACTID_PREFIX "sys-ntlm",
+ nsSambaNTLMAuthConstructor
+ },
#endif
{ "nsHttpNegotiateAuth",
NS_HTTPNEGOTIATEAUTH_CID,
diff --git a/mozilla/extensions/auth/nsAuthSambaNTLM.cpp b/mozilla/extensions/auth/nsAuthSambaNTLM.cpp
new file mode 100644
index 0000000..05d00f2
--- /dev/null
+++ b/mozilla/extensions/auth/nsAuthSambaNTLM.cpp
@@ -0,0 +1,323 @@
+/* vim:set ts=4 sw=4 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Samba NTLM Authentication.
+ *
+ * The Initial Developer of the Original Code is Novell.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Robert O'Callahan (rocallahan@novell.com)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsAuth.h"
+#include "nsAuthSambaNTLM.h"
+#include "prenv.h"
+#include "plbase64.h"
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <errno.h>
+
+nsAuthSambaNTLM::nsAuthSambaNTLM()
+ : mInitialMessage(nsnull), mChildPID(0), mFromChildFD(-1), mToChildFD(-1)
+{
+}
+
+nsAuthSambaNTLM::~nsAuthSambaNTLM()
+{
+ // ntlm_auth reads from stdin regularly so closing our file handles
+ // should cause it to exit. Trying to kill it with a signal would be
+ // problematic because another process could have spawned with that pid
+ // if it has unexpectedly quit.
+ Shutdown();
+ free(mInitialMessage);
+}
+
+void
+nsAuthSambaNTLM::Shutdown()
+{
+ if (mFromChildFD >= 0) {
+ close(mFromChildFD);
+ mFromChildFD = -1;
+ }
+ if (mToChildFD >= 0) {
+ close(mToChildFD);
+ mToChildFD = -1;
+ }
+ if (mChildPID) {
+ waitpid(mChildPID, nsnull, 0);
+ mChildPID = 0;
+ }
+}
+
+NS_IMPL_ISUPPORTS1(nsAuthSambaNTLM, nsIAuthModule)
+
+static PRBool
+SpawnIOChild(char** aArgs, pid_t* aPID, int* aFromChildFD, int* aToChildFD)
+{
+ int toChildPipe[2];
+ if (pipe(toChildPipe) < 0)
+ return PR_FALSE;
+ int fromChildPipe[2];
+ if (pipe(fromChildPipe) < 0) {
+ close(toChildPipe[0]);
+ close(toChildPipe[1]);
+ return PR_FALSE;
+ }
+
+ pid_t pid = fork();
+ if (pid < 0) {
+ PRInt32 i;
+ for (i = 0; i < 2; ++i) {
+ close(fromChildPipe[i]);
+ close(toChildPipe[i]);
+ }
+ NS_WARNING("fork() failed");
+ return PR_FALSE;
+ }
+
+ if (pid > 0) {
+ // We are the parent
+ close(toChildPipe[0]);
+ close(fromChildPipe[1]);
+ *aPID = pid;
+ *aFromChildFD = fromChildPipe[0];
+ *aToChildFD = toChildPipe[1];
+ return PR_TRUE;
+ }
+
+ // We are the child
+ close(toChildPipe[1]);
+ close(fromChildPipe[0]);
+ // Make stdin read from toChildPipe
+ int result0 = dup2(toChildPipe[0], 0);
+ // Make stdout write to fromChildPipe
+ int result1 = dup2(fromChildPipe[1], 1);
+ if (result0 >= 0 && result1 >= 0) {
+ execvp(aArgs[0], aArgs);
+ }
+
+ // Guess an error occurred! Just exit, the parent will notice
+ // that we're not responding correctly.
+ LOG(("ntlm_auth exec failure, errno=%d", errno));
+ exit(0);
+ // ... satisfy the compiler
+ return PR_FALSE;
+}
+
+static PRBool WriteString(int aFD, const nsACString& aString)
+{
+ PRInt32 length = aString.Length();
+ nsPromiseFlatCString flat(aString);
+ const char* s = flat.get();
+ LOG(("Writing to ntlm_auth: %s", s));
+
+ while (length > 0) {
+ int result = write(aFD, s, length);
+ if (result <= 0)
+ return PR_FALSE;
+ s += result;
+ length -= result;
+ }
+ return PR_TRUE;
+}
+
+static PRBool ReadLine(int aFD, nsACString& aString)
+{
+ // ntlm_auth is defined to only send one line in response to each of our
+ // input lines. So this simple unbuffered strategy works as long as we
+ // read the response immediately after sending one request.
+ aString.Truncate();
+ for (;;) {
+ char buf[1024];
+ int result = read(aFD, buf, sizeof(buf));
+ if (result <= 0)
+ return PR_FALSE;
+ aString.Append(buf, result);
+ if (buf[result - 1] == '\n') {
+ LOG(("Read from ntlm_auth: %s", nsPromiseFlatCString(aString).get()));
+ return PR_TRUE;
+ }
+ }
+}
+
+/**
+ * Returns a heap-allocated array of PRUint8s, and stores the length in aLen.
+ * Returns nsnull if there's an error of any kind.
+ */
+static PRUint8* ExtractMessage(const nsACString& aLine, PRUint32* aLen)
+{
+ // ntlm_auth sends blobs to us as base64-encoded strings after the "xx "
+ // preamble on the response line.
+ PRInt32 length = aLine.Length();
+ // The caller should verify there is a valid "xx " prefix and the line
+ // is terminated with a \n
+ NS_ASSERTION(length >= 4, "Line too short...");
+ nsPromiseFlatCString flat(aLine);
+ const char* s = flat.get() + 3;
+ length -= 4; // lose first 3 chars plus trailing \n
+ NS_ASSERTION(s[length] == '\n', "aLine not newline-terminated");
+
+ if (length & 3) {
+ // The base64 encoded block must be multiple of 4. If not, something
+ // screwed up.
+ NS_WARNING("Base64 encoded block should be a multiple of 4 chars");
+ return nsnull;
+ }
+
+ // Calculate the exact length. I wonder why there isn't a function for this
+ // in plbase64.
+ PRInt32 numEquals;
+ for (numEquals = 0; numEquals < length; ++numEquals) {
+ if (flat.get()[length - 1 - numEquals] != '=')
+ break;
+ }
+ *aLen = (length/4)*3 - numEquals;
+ return NS_REINTERPRET_CAST(PRUint8*, PL_Base64Decode(flat.get() + 3, length - 4, nsnull));
+}
+
+nsresult
+nsAuthSambaNTLM::SpawnNTLMAuthHelper()
+{
+ const char* username = PR_GetEnv("USER");
+ if (!username)
+ return NS_ERROR_FAILURE;
+
+ char* args[] = {
+ "ntlm_auth",
+ "--helper-protocol", "ntlmssp-client-1",
+ "--use-cached-creds",
+ "--username", NS_CONST_CAST(char*, username),
+ nsnull
+ };
+
+ PRBool isOK = SpawnIOChild(args, &mChildPID, &mFromChildFD, &mToChildFD);
+ if (!isOK)
+ return NS_ERROR_FAILURE;
+
+ if (!WriteString(mToChildFD, NS_LITERAL_CSTRING("YR\n")))
+ return NS_ERROR_FAILURE;
+ nsCString line;
+ if (!ReadLine(mFromChildFD, line))
+ return NS_ERROR_FAILURE;
+ if (!StringBeginsWith(line, NS_LITERAL_CSTRING("YR "))) {
+ // Something went wrong. Perhaps no credentials are accessible.
+ return NS_ERROR_FAILURE;
+ }
+
+ // It gave us an initial client-to-server request packet. Save that
+ // because we'll need it later.
+ mInitialMessage = ExtractMessage(line, &mInitialMessageLen);
+ if (!mInitialMessage)
+ return NS_ERROR_FAILURE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsAuthSambaNTLM::Init(const char *serviceName,
+ PRUint32 serviceFlags,
+ const PRUnichar *domain,
+ const PRUnichar *username,
+ const PRUnichar *password)
+{
+ NS_ASSERTION(!username && !domain && !password, "unexpected credentials");
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsAuthSambaNTLM::GetNextToken(const void *inToken,
+ PRUint32 inTokenLen,
+ void **outToken,
+ PRUint32 *outTokenLen)
+{
+ if (!inToken) {
+ /* someone wants our initial message */
+ *outToken = nsMemory::Clone(mInitialMessage, mInitialMessageLen);
+ if (!*outToken)
+ return NS_ERROR_OUT_OF_MEMORY;
+ *outTokenLen = mInitialMessageLen;
+ return NS_OK;
+ }
+
+ /* inToken must be a type 2 message. Get ntlm_auth to generate our response */
+ char* encoded = PL_Base64Encode(NS_STATIC_CAST(const char*, inToken), inTokenLen, nsnull);
+ if (!encoded)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsCString request;
+ request.AssignLiteral("TT ");
+ request.Append(encoded);
+ free(encoded);
+ request.Append('\n');
+
+ if (!WriteString(mToChildFD, request))
+ return NS_ERROR_FAILURE;
+ nsCString line;
+ if (!ReadLine(mFromChildFD, line))
+ return NS_ERROR_FAILURE;
+ if (!StringBeginsWith(line, NS_LITERAL_CSTRING("KK "))) {
+ // Something went wrong. Perhaps no credentials are accessible.
+ return NS_ERROR_FAILURE;
+ }
+ PRUint8* buf = ExtractMessage(line, outTokenLen);
+ if (!buf)
+ return NS_ERROR_FAILURE;
+ // *outToken has to be freed by nsMemory::Free, which may not be free()
+ *outToken = nsMemory::Clone(buf, *outTokenLen);
+ if (!*outToken) {
+ free(buf);
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ // We're done. Close our file descriptors now and reap the helper
+ // process.
+ Shutdown();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsAuthSambaNTLM::Unwrap(const void *inToken,
+ PRUint32 inTokenLen,
+ void **outToken,
+ PRUint32 *outTokenLen)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsAuthSambaNTLM::Wrap(const void *inToken,
+ PRUint32 inTokenLen,
+ PRBool confidential,
+ void **outToken,
+ PRUint32 *outTokenLen)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
diff --git a/mozilla/extensions/auth/nsAuthSambaNTLM.h b/mozilla/extensions/auth/nsAuthSambaNTLM.h
new file mode 100644
index 0000000..6034f03
--- /dev/null
+++ b/mozilla/extensions/auth/nsAuthSambaNTLM.h
@@ -0,0 +1,78 @@
+/* vim:set ts=4 sw=4 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Samba NTLM Authentication.
+ *
+ * The Initial Developer of the Original Code is Novell.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Robert O'Callahan (rocallahan@novell.com)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsAuthSambaNTLM_h__
+#define nsAuthSambaNTLM_h__
+
+#include "nsIAuthModule.h"
+#include "nsString.h"
+#include "nsCOMPtr.h"
+
+/**
+ * This is an implementation of NTLM authentication that does single-signon
+ * by obtaining the user's Unix username and then asking Samba's
+ * ntlm_auth tool to do the authentication for us
+ * using the user's password cached in winbindd, if available. If the
+ * password is not available then this component fails to instantiate so
+ * nsHttpNTLMAuth will fall back to a different NTLM implementation.
+ */
+class nsAuthSambaNTLM : public nsIAuthModule
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIAUTHMODULE
+
+ nsAuthSambaNTLM();
+
+ // We spawn the ntlm_auth helper from the module constructor, because
+ // that lets us fail to instantiate the module if ntlm_auth isn't
+ // available, triggering fallback to the built-in NTLM support (which
+ // doesn't support single signon, of course)
+ nsresult SpawnNTLMAuthHelper();
+
+private:
+ ~nsAuthSambaNTLM();
+
+ void Shutdown();
+
+ PRUint8* mInitialMessage; /* free with free() */
+ PRUint32 mInitialMessageLen;
+ PRInt32 mChildPID;
+ PRInt32 mFromChildFD, mToChildFD;
+};
+
+#endif /* nsAuthSambaNTLM_h__ */
diff --git a/mozilla/netwerk/protocol/http/src/nsHttpNTLMAuth.cpp b/mozilla/netwerk/protocol/http/src/nsHttpNTLMAuth.cpp
index 9c25334..cde2695 100644
--- a/mozilla/netwerk/protocol/http/src/nsHttpNTLMAuth.cpp
+++ b/mozilla/netwerk/protocol/http/src/nsHttpNTLMAuth.cpp
@@ -46,8 +46,6 @@
//-----------------------------------------------------------------------------
-#ifdef XP_WIN
-
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
#include "nsIServiceManager.h"
@@ -208,8 +206,6 @@ public:
};
NS_IMPL_ISUPPORTS0(nsNTLMSessionState)
-#endif
-
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS1(nsHttpNTLMAuth, nsIHttpAuthenticator)
@@ -231,7 +227,6 @@ nsHttpNTLMAuth::ChallengeReceived(nsIHttpChannel *channel,
// start new auth sequence if challenge is exactly "NTLM"
if (PL_strcasecmp(challenge, "NTLM") == 0) {
nsCOMPtr<nsISupports> module;
-#ifdef XP_WIN
//
// our session state is non-null to indicate that we've flagged
// this auth domain as not accepting the system's default login.
@@ -239,7 +234,7 @@ nsHttpNTLMAuth::ChallengeReceived(nsIHttpChannel *channel,
PRBool trySysNTLM = (*sessionState == nsnull);
//
- // on windows, we may have access to the built-in SSPI library,
+ // we may have access to a built-in SSPI library,
// which could be used to authenticate the user without prompting.
//
// if the continuationState is null, then we may want to try using
@@ -266,9 +261,7 @@ nsHttpNTLMAuth::ChallengeReceived(nsIHttpChannel *channel,
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*sessionState);
}
-#else
- {
-#endif
+
module = do_CreateInstance(NS_AUTH_MODULE_CONTRACTID_PREFIX "ntlm");
// prompt user for domain, username, and password...