1 /* vim:set ts=4 sw=4 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/. */
6 #include "nsComponentManagerUtils.h"
7 #include "nsNativeCharsetUtils.h"
8 #include "nsIServiceManager.h"
9 #include "nsIPrefService.h"
11 #include "nsAuthSASL.h"
13 static const char kNegotiateAuthSSPI
[] = "network.auth.use-sspi";
15 nsAuthSASL::nsAuthSASL()
20 void nsAuthSASL::Reset()
25 /* Limitations apply to this class's thread safety. See the header file */
26 NS_IMPL_ISUPPORTS(nsAuthSASL
, nsIAuthModule
)
29 nsAuthSASL::Init(const char *serviceName
,
30 uint32_t serviceFlags
,
31 const char16_t
*domain
,
32 const char16_t
*username
,
33 const char16_t
*password
)
37 NS_ASSERTION(username
, "SASL requires a username");
38 NS_ASSERTION(!domain
&& !password
, "unexpected credentials");
42 // If we're doing SASL, we should do mutual auth
43 serviceFlags
|= REQ_MUTUAL_AUTH
;
45 // Find out whether we should be trying SSPI or not
46 const char *contractID
= NS_AUTH_MODULE_CONTRACTID_PREFIX
"kerb-gss";
48 nsCOMPtr
<nsIPrefBranch
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
51 rv
= prefs
->GetBoolPref(kNegotiateAuthSSPI
, &val
);
52 if (NS_SUCCEEDED(rv
) && val
)
53 contractID
= NS_AUTH_MODULE_CONTRACTID_PREFIX
"kerb-sspi";
56 mInnerModule
= do_CreateInstance(contractID
, &rv
);
57 // if we can't create the GSSAPI module, then bail
58 NS_ENSURE_SUCCESS(rv
, rv
);
60 mInnerModule
->Init(serviceName
, serviceFlags
, nullptr, nullptr, nullptr);
66 nsAuthSASL::GetNextToken(const void *inToken
,
69 uint32_t *outTokenLen
)
74 uint32_t unwrappedTokenLen
, messageLen
;
75 nsAutoCString userbuf
;
78 return NS_ERROR_NOT_INITIALIZED
;
81 // If the server COMPLETEs with an empty token, Cyrus sends us that token.
82 // I don't think this is correct, but we need to handle that behaviour.
83 // Cyrus ignores the contents of our reply token.
84 if (inTokenLen
== 0) {
89 // We've completed the GSSAPI portion of the handshake, and are
90 // now ready to do the SASL security layer and authzid negotiation
92 // Input packet from the server needs to be unwrapped.
93 rv
= mInnerModule
->Unwrap(inToken
, inTokenLen
, &unwrappedToken
,
100 // If we were doing security layers then we'd care what the
101 // server had sent us. We're not, so all we had to do was make
102 // sure that the signature was correct with the above unwrap()
103 nsMemory::Free(unwrappedToken
);
105 NS_CopyUnicodeToNative(mUsername
, userbuf
);
106 messageLen
= userbuf
.Length() + 4 + 1;
107 message
= (char *)nsMemory::Alloc(messageLen
);
110 return NS_ERROR_OUT_OF_MEMORY
;
112 message
[0] = 0x01; // No security layer
115 message
[3] = 0x00; // Maxbuf must be zero if we've got no sec layer
116 strcpy(message
+4, userbuf
.get());
117 // Userbuf should not be nullptr terminated, so trim the trailing nullptr
118 // when wrapping the message
119 rv
= mInnerModule
->Wrap((void *) message
, messageLen
-1, false,
120 outToken
, outTokenLen
);
121 nsMemory::Free(message
);
123 return NS_SUCCEEDED(rv
) ? NS_SUCCESS_AUTH_FINISHED
: rv
;
125 rv
= mInnerModule
->GetNextToken(inToken
, inTokenLen
, outToken
,
127 if (rv
== NS_SUCCESS_AUTH_FINISHED
) {
135 nsAuthSASL::Unwrap(const void *inToken
,
138 uint32_t *outTokenLen
)
140 return NS_ERROR_NOT_IMPLEMENTED
;
144 nsAuthSASL::Wrap(const void *inToken
,
148 uint32_t *outTokenLen
)
150 return NS_ERROR_NOT_IMPLEMENTED
;