Line data Source code
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/. */
5 :
6 : #include "nsComponentManagerUtils.h"
7 : #include "nsNativeCharsetUtils.h"
8 : #include "nsIServiceManager.h"
9 : #include "nsIPrefService.h"
10 :
11 : #include "nsAuthSASL.h"
12 :
13 : static const char kNegotiateAuthSSPI[] = "network.auth.use-sspi";
14 :
15 0 : nsAuthSASL::nsAuthSASL()
16 : {
17 0 : mSASLReady = false;
18 0 : }
19 :
20 0 : void nsAuthSASL::Reset()
21 : {
22 0 : mSASLReady = false;
23 0 : }
24 :
25 : /* Limitations apply to this class's thread safety. See the header file */
26 0 : NS_IMPL_ISUPPORTS(nsAuthSASL, nsIAuthModule)
27 :
28 : NS_IMETHODIMP
29 0 : nsAuthSASL::Init(const char *serviceName,
30 : uint32_t serviceFlags,
31 : const char16_t *domain,
32 : const char16_t *username,
33 : const char16_t *password)
34 : {
35 : nsresult rv;
36 :
37 0 : NS_ASSERTION(username, "SASL requires a username");
38 0 : NS_ASSERTION(!domain && !password, "unexpected credentials");
39 :
40 0 : mUsername = username;
41 :
42 : // If we're doing SASL, we should do mutual auth
43 0 : serviceFlags |= REQ_MUTUAL_AUTH;
44 :
45 : // Find out whether we should be trying SSPI or not
46 0 : const char *contractID = NS_AUTH_MODULE_CONTRACTID_PREFIX "kerb-gss";
47 :
48 0 : nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
49 0 : if (prefs) {
50 : bool val;
51 0 : rv = prefs->GetBoolPref(kNegotiateAuthSSPI, &val);
52 0 : if (NS_SUCCEEDED(rv) && val)
53 0 : contractID = NS_AUTH_MODULE_CONTRACTID_PREFIX "kerb-sspi";
54 : }
55 :
56 0 : mInnerModule = do_CreateInstance(contractID, &rv);
57 : // if we can't create the GSSAPI module, then bail
58 0 : NS_ENSURE_SUCCESS(rv, rv);
59 :
60 0 : mInnerModule->Init(serviceName, serviceFlags, nullptr, nullptr, nullptr);
61 :
62 0 : return NS_OK;
63 : }
64 :
65 : NS_IMETHODIMP
66 0 : nsAuthSASL::GetNextToken(const void *inToken,
67 : uint32_t inTokenLen,
68 : void **outToken,
69 : uint32_t *outTokenLen)
70 : {
71 : nsresult rv;
72 : void *unwrappedToken;
73 : char *message;
74 : uint32_t unwrappedTokenLen, messageLen;
75 0 : nsAutoCString userbuf;
76 :
77 0 : if (!mInnerModule)
78 0 : return NS_ERROR_NOT_INITIALIZED;
79 :
80 0 : if (mSASLReady) {
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 0 : if (inTokenLen == 0) {
85 0 : *outToken = nullptr;
86 0 : *outTokenLen = 0;
87 0 : return NS_OK;
88 : }
89 : // We've completed the GSSAPI portion of the handshake, and are
90 : // now ready to do the SASL security layer and authzid negotiation
91 :
92 : // Input packet from the server needs to be unwrapped.
93 0 : rv = mInnerModule->Unwrap(inToken, inTokenLen, &unwrappedToken,
94 0 : &unwrappedTokenLen);
95 0 : if (NS_FAILED(rv)) {
96 0 : Reset();
97 0 : return rv;
98 : }
99 :
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 0 : free(unwrappedToken);
104 :
105 0 : NS_CopyUnicodeToNative(mUsername, userbuf);
106 0 : messageLen = userbuf.Length() + 4 + 1;
107 0 : message = (char *)moz_xmalloc(messageLen);
108 0 : if (!message) {
109 0 : Reset();
110 0 : return NS_ERROR_OUT_OF_MEMORY;
111 : }
112 0 : message[0] = 0x01; // No security layer
113 0 : message[1] = 0x00;
114 0 : message[2] = 0x00;
115 0 : message[3] = 0x00; // Maxbuf must be zero if we've got no sec layer
116 0 : strcpy(message+4, userbuf.get());
117 : // Userbuf should not be nullptr terminated, so trim the trailing nullptr
118 : // when wrapping the message
119 0 : rv = mInnerModule->Wrap((void *) message, messageLen-1, false,
120 0 : outToken, outTokenLen);
121 0 : free(message);
122 0 : Reset(); // All done
123 0 : return NS_SUCCEEDED(rv) ? NS_SUCCESS_AUTH_FINISHED : rv;
124 : }
125 0 : rv = mInnerModule->GetNextToken(inToken, inTokenLen, outToken,
126 0 : outTokenLen);
127 0 : if (rv == NS_SUCCESS_AUTH_FINISHED) {
128 0 : mSASLReady = true;
129 0 : rv = NS_OK;
130 : }
131 0 : return rv;
132 : }
133 :
134 : NS_IMETHODIMP
135 0 : nsAuthSASL::Unwrap(const void *inToken,
136 : uint32_t inTokenLen,
137 : void **outToken,
138 : uint32_t *outTokenLen)
139 : {
140 0 : return NS_ERROR_NOT_IMPLEMENTED;
141 : }
142 :
143 : NS_IMETHODIMP
144 0 : nsAuthSASL::Wrap(const void *inToken,
145 : uint32_t inTokenLen,
146 : bool confidential,
147 : void **outToken,
148 : uint32_t *outTokenLen)
149 : {
150 0 : return NS_ERROR_NOT_IMPLEMENTED;
151 : }
|