extensions/auth/nsAuthSASL.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* vim:set ts=4 sw=4 et cindent: */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "nsComponentManagerUtils.h"
michael@0 7 #include "nsNativeCharsetUtils.h"
michael@0 8 #include "nsIServiceManager.h"
michael@0 9 #include "nsIPrefService.h"
michael@0 10
michael@0 11 #include "nsAuthSASL.h"
michael@0 12
michael@0 13 static const char kNegotiateAuthSSPI[] = "network.auth.use-sspi";
michael@0 14
michael@0 15 nsAuthSASL::nsAuthSASL()
michael@0 16 {
michael@0 17 mSASLReady = false;
michael@0 18 }
michael@0 19
michael@0 20 void nsAuthSASL::Reset()
michael@0 21 {
michael@0 22 mSASLReady = false;
michael@0 23 }
michael@0 24
michael@0 25 /* Limitations apply to this class's thread safety. See the header file */
michael@0 26 NS_IMPL_ISUPPORTS(nsAuthSASL, nsIAuthModule)
michael@0 27
michael@0 28 NS_IMETHODIMP
michael@0 29 nsAuthSASL::Init(const char *serviceName,
michael@0 30 uint32_t serviceFlags,
michael@0 31 const char16_t *domain,
michael@0 32 const char16_t *username,
michael@0 33 const char16_t *password)
michael@0 34 {
michael@0 35 nsresult rv;
michael@0 36
michael@0 37 NS_ASSERTION(username, "SASL requires a username");
michael@0 38 NS_ASSERTION(!domain && !password, "unexpected credentials");
michael@0 39
michael@0 40 mUsername = username;
michael@0 41
michael@0 42 // If we're doing SASL, we should do mutual auth
michael@0 43 serviceFlags |= REQ_MUTUAL_AUTH;
michael@0 44
michael@0 45 // Find out whether we should be trying SSPI or not
michael@0 46 const char *contractID = NS_AUTH_MODULE_CONTRACTID_PREFIX "kerb-gss";
michael@0 47
michael@0 48 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
michael@0 49 if (prefs) {
michael@0 50 bool val;
michael@0 51 rv = prefs->GetBoolPref(kNegotiateAuthSSPI, &val);
michael@0 52 if (NS_SUCCEEDED(rv) && val)
michael@0 53 contractID = NS_AUTH_MODULE_CONTRACTID_PREFIX "kerb-sspi";
michael@0 54 }
michael@0 55
michael@0 56 mInnerModule = do_CreateInstance(contractID, &rv);
michael@0 57 // if we can't create the GSSAPI module, then bail
michael@0 58 NS_ENSURE_SUCCESS(rv, rv);
michael@0 59
michael@0 60 mInnerModule->Init(serviceName, serviceFlags, nullptr, nullptr, nullptr);
michael@0 61
michael@0 62 return NS_OK;
michael@0 63 }
michael@0 64
michael@0 65 NS_IMETHODIMP
michael@0 66 nsAuthSASL::GetNextToken(const void *inToken,
michael@0 67 uint32_t inTokenLen,
michael@0 68 void **outToken,
michael@0 69 uint32_t *outTokenLen)
michael@0 70 {
michael@0 71 nsresult rv;
michael@0 72 void *unwrappedToken;
michael@0 73 char *message;
michael@0 74 uint32_t unwrappedTokenLen, messageLen;
michael@0 75 nsAutoCString userbuf;
michael@0 76
michael@0 77 if (!mInnerModule)
michael@0 78 return NS_ERROR_NOT_INITIALIZED;
michael@0 79
michael@0 80 if (mSASLReady) {
michael@0 81 // If the server COMPLETEs with an empty token, Cyrus sends us that token.
michael@0 82 // I don't think this is correct, but we need to handle that behaviour.
michael@0 83 // Cyrus ignores the contents of our reply token.
michael@0 84 if (inTokenLen == 0) {
michael@0 85 *outToken = nullptr;
michael@0 86 *outTokenLen = 0;
michael@0 87 return NS_OK;
michael@0 88 }
michael@0 89 // We've completed the GSSAPI portion of the handshake, and are
michael@0 90 // now ready to do the SASL security layer and authzid negotiation
michael@0 91
michael@0 92 // Input packet from the server needs to be unwrapped.
michael@0 93 rv = mInnerModule->Unwrap(inToken, inTokenLen, &unwrappedToken,
michael@0 94 &unwrappedTokenLen);
michael@0 95 if (NS_FAILED(rv)) {
michael@0 96 Reset();
michael@0 97 return rv;
michael@0 98 }
michael@0 99
michael@0 100 // If we were doing security layers then we'd care what the
michael@0 101 // server had sent us. We're not, so all we had to do was make
michael@0 102 // sure that the signature was correct with the above unwrap()
michael@0 103 nsMemory::Free(unwrappedToken);
michael@0 104
michael@0 105 NS_CopyUnicodeToNative(mUsername, userbuf);
michael@0 106 messageLen = userbuf.Length() + 4 + 1;
michael@0 107 message = (char *)nsMemory::Alloc(messageLen);
michael@0 108 if (!message) {
michael@0 109 Reset();
michael@0 110 return NS_ERROR_OUT_OF_MEMORY;
michael@0 111 }
michael@0 112 message[0] = 0x01; // No security layer
michael@0 113 message[1] = 0x00;
michael@0 114 message[2] = 0x00;
michael@0 115 message[3] = 0x00; // Maxbuf must be zero if we've got no sec layer
michael@0 116 strcpy(message+4, userbuf.get());
michael@0 117 // Userbuf should not be nullptr terminated, so trim the trailing nullptr
michael@0 118 // when wrapping the message
michael@0 119 rv = mInnerModule->Wrap((void *) message, messageLen-1, false,
michael@0 120 outToken, outTokenLen);
michael@0 121 nsMemory::Free(message);
michael@0 122 Reset(); // All done
michael@0 123 return NS_SUCCEEDED(rv) ? NS_SUCCESS_AUTH_FINISHED : rv;
michael@0 124 }
michael@0 125 rv = mInnerModule->GetNextToken(inToken, inTokenLen, outToken,
michael@0 126 outTokenLen);
michael@0 127 if (rv == NS_SUCCESS_AUTH_FINISHED) {
michael@0 128 mSASLReady = true;
michael@0 129 rv = NS_OK;
michael@0 130 }
michael@0 131 return rv;
michael@0 132 }
michael@0 133
michael@0 134 NS_IMETHODIMP
michael@0 135 nsAuthSASL::Unwrap(const void *inToken,
michael@0 136 uint32_t inTokenLen,
michael@0 137 void **outToken,
michael@0 138 uint32_t *outTokenLen)
michael@0 139 {
michael@0 140 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 141 }
michael@0 142
michael@0 143 NS_IMETHODIMP
michael@0 144 nsAuthSASL::Wrap(const void *inToken,
michael@0 145 uint32_t inTokenLen,
michael@0 146 bool confidential,
michael@0 147 void **outToken,
michael@0 148 uint32_t *outTokenLen)
michael@0 149 {
michael@0 150 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 151 }

mercurial