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