summaryrefslogtreecommitdiffstats
path: root/extensions/auth/nsAuthSASL.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/auth/nsAuthSASL.cpp')
-rw-r--r--extensions/auth/nsAuthSASL.cpp123
1 files changed, 123 insertions, 0 deletions
diff --git a/extensions/auth/nsAuthSASL.cpp b/extensions/auth/nsAuthSASL.cpp
new file mode 100644
index 0000000000..9fcb2859a7
--- /dev/null
+++ b/extensions/auth/nsAuthSASL.cpp
@@ -0,0 +1,123 @@
+/* vim:set ts=4 sw=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsNativeCharsetUtils.h"
+#include "nsIPrefService.h"
+#include "nsServiceManagerUtils.h"
+
+#include "nsAuthSASL.h"
+
+static const char kNegotiateAuthSSPI[] = "network.auth.use-sspi";
+
+nsAuthSASL::nsAuthSASL() { mSASLReady = false; }
+
+void nsAuthSASL::Reset() { mSASLReady = false; }
+
+/* Limitations apply to this class's thread safety. See the header file */
+NS_IMPL_ISUPPORTS(nsAuthSASL, nsIAuthModule)
+
+NS_IMETHODIMP
+nsAuthSASL::Init(const nsACString& serviceName, uint32_t serviceFlags,
+ const nsAString& domain, const nsAString& username,
+ const nsAString& password) {
+ nsresult rv;
+
+ NS_ASSERTION(!username.IsEmpty(), "SASL requires a username");
+ NS_ASSERTION(domain.IsEmpty() && password.IsEmpty(),
+ "unexpected credentials");
+
+ mUsername = username;
+
+ // If we're doing SASL, we should do mutual auth
+ serviceFlags |= REQ_MUTUAL_AUTH;
+
+ // Find out whether we should be trying SSPI or not
+ const char* authType = "kerb-gss";
+
+ nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
+ if (prefs) {
+ bool val;
+ rv = prefs->GetBoolPref(kNegotiateAuthSSPI, &val);
+ if (NS_SUCCEEDED(rv) && val) authType = "kerb-sspi";
+ }
+
+ MOZ_ALWAYS_TRUE(mInnerModule = nsIAuthModule::CreateInstance(authType));
+
+ mInnerModule->Init(serviceName, serviceFlags, u""_ns, u""_ns, u""_ns);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsAuthSASL::GetNextToken(const void* inToken, uint32_t inTokenLen,
+ void** outToken, uint32_t* outTokenLen) {
+ nsresult rv;
+ void* unwrappedToken;
+ char* message;
+ uint32_t unwrappedTokenLen, messageLen;
+ nsAutoCString userbuf;
+
+ if (!mInnerModule) return NS_ERROR_NOT_INITIALIZED;
+
+ if (mSASLReady) {
+ // If the server COMPLETEs with an empty token, Cyrus sends us that token.
+ // I don't think this is correct, but we need to handle that behaviour.
+ // Cyrus ignores the contents of our reply token.
+ if (inTokenLen == 0) {
+ *outToken = nullptr;
+ *outTokenLen = 0;
+ return NS_OK;
+ }
+ // We've completed the GSSAPI portion of the handshake, and are
+ // now ready to do the SASL security layer and authzid negotiation
+
+ // Input packet from the server needs to be unwrapped.
+ rv = mInnerModule->Unwrap(inToken, inTokenLen, &unwrappedToken,
+ &unwrappedTokenLen);
+ if (NS_FAILED(rv)) {
+ Reset();
+ return rv;
+ }
+
+ // If we were doing security layers then we'd care what the
+ // server had sent us. We're not, so all we had to do was make
+ // sure that the signature was correct with the above unwrap()
+ free(unwrappedToken);
+
+ NS_CopyUnicodeToNative(mUsername, userbuf);
+ messageLen = userbuf.Length() + 4 + 1;
+ message = (char*)moz_xmalloc(messageLen);
+ message[0] = 0x01; // No security layer
+ message[1] = 0x00;
+ message[2] = 0x00;
+ message[3] = 0x00; // Maxbuf must be zero if we've got no sec layer
+ strcpy(message + 4, userbuf.get());
+ // Userbuf should not be nullptr terminated, so trim the trailing nullptr
+ // when wrapping the message
+ rv = mInnerModule->Wrap((void*)message, messageLen - 1, false, outToken,
+ outTokenLen);
+ free(message);
+ Reset(); // All done
+ return NS_SUCCEEDED(rv) ? NS_SUCCESS_AUTH_FINISHED : rv;
+ }
+ rv = mInnerModule->GetNextToken(inToken, inTokenLen, outToken, outTokenLen);
+ if (rv == NS_SUCCESS_AUTH_FINISHED) {
+ mSASLReady = true;
+ rv = NS_OK;
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsAuthSASL::Unwrap(const void* inToken, uint32_t inTokenLen, void** outToken,
+ uint32_t* outTokenLen) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsAuthSASL::Wrap(const void* inToken, uint32_t inTokenLen, bool confidential,
+ void** outToken, uint32_t* outTokenLen) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}