tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }