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

     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()
    16 {
    17     mSASLReady = false;
    18 }
    20 void nsAuthSASL::Reset() 
    21 {
    22     mSASLReady = false;
    23 }
    25 /* Limitations apply to this class's thread safety. See the header file */
    26 NS_IMPL_ISUPPORTS(nsAuthSASL, nsIAuthModule)
    28 NS_IMETHODIMP
    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)
    34 {
    35     nsresult rv;
    37     NS_ASSERTION(username, "SASL requires a username");
    38     NS_ASSERTION(!domain && !password, "unexpected credentials");
    40     mUsername = username;
    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);
    49     if (prefs) {
    50         bool val;
    51         rv = prefs->GetBoolPref(kNegotiateAuthSSPI, &val);
    52         if (NS_SUCCEEDED(rv) && val)
    53             contractID = NS_AUTH_MODULE_CONTRACTID_PREFIX "kerb-sspi";
    54     }
    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);
    62     return NS_OK;
    63 }
    65 NS_IMETHODIMP
    66 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     nsAutoCString userbuf;
    77     if (!mInnerModule) 
    78         return NS_ERROR_NOT_INITIALIZED;
    80     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         if (inTokenLen == 0) {
    85             *outToken = nullptr;
    86             *outTokenLen = 0;
    87             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
    92         // Input packet from the server needs to be unwrapped.
    93         rv = mInnerModule->Unwrap(inToken, inTokenLen, &unwrappedToken, 
    94                                   &unwrappedTokenLen);
    95         if (NS_FAILED(rv)) {
    96             Reset();
    97             return rv;
    98         }
   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);
   108         if (!message) {
   109           Reset();
   110           return NS_ERROR_OUT_OF_MEMORY;
   111         }
   112         message[0] = 0x01; // No security layer
   113         message[1] = 0x00;
   114         message[2] = 0x00;
   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);
   122         Reset(); // All done
   123         return NS_SUCCEEDED(rv) ? NS_SUCCESS_AUTH_FINISHED : rv;
   124     }
   125     rv = mInnerModule->GetNextToken(inToken, inTokenLen, outToken, 
   126                                     outTokenLen);
   127     if (rv == NS_SUCCESS_AUTH_FINISHED) {
   128         mSASLReady = true;
   129         rv = NS_OK;
   130     }
   131     return rv;
   132 }
   134 NS_IMETHODIMP
   135 nsAuthSASL::Unwrap(const void *inToken,
   136                    uint32_t    inTokenLen,
   137                    void      **outToken,
   138                    uint32_t   *outTokenLen)
   139 {
   140     return NS_ERROR_NOT_IMPLEMENTED;
   141 }
   143 NS_IMETHODIMP
   144 nsAuthSASL::Wrap(const void *inToken,
   145                  uint32_t    inTokenLen,
   146                  bool        confidential,
   147                  void      **outToken,
   148                  uint32_t   *outTokenLen)
   149 {
   150     return NS_ERROR_NOT_IMPLEMENTED;
   151 }

mercurial