Atob(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    JSString *str;
    if (!argc)
        return JS_TRUE;

    str = JS_ValueToString(cx, argv[0]);
    if (!str)
        return JS_FALSE;

    size_t base64StrLength = JS_GetStringLength(str);
    char *base64Str = JS_GetStringBytes(str);

    PRUint32 bin_dataLength = (PRUint32)base64StrLength;
    if (base64Str[base64StrLength - 1] == '=') {
        if (base64Str[base64StrLength - 2] == '=')
            bin_dataLength -= 2;
        else  
            --bin_dataLength;
    }
    bin_dataLength = (PRUint32)((PRUint64)bin_dataLength * 3) / 4;

    char *bin_data = PL_Base64Decode(base64Str, base64StrLength, nsnull);
    if (!bin_data)
        return JS_FALSE;

    str = JS_NewStringCopyN(cx, bin_data, bin_dataLength);
    PR_Free(bin_data);
    if (!str)
        return JS_FALSE;

    *rval = STRING_TO_JSVAL(str);
    return JS_TRUE;
}
/**
 * Returns a heap-allocated array of PRUint8s, and stores the length in aLen.
 * Returns nullptr if there's an error of any kind.
 */
static PRUint8* ExtractMessage(const nsACString& aLine, PRUint32* aLen)
{
    // ntlm_auth sends blobs to us as base64-encoded strings after the "xx "
    // preamble on the response line.
    PRInt32 length = aLine.Length();
    // The caller should verify there is a valid "xx " prefix and the line
    // is terminated with a \n
    NS_ASSERTION(length >= 4, "Line too short...");
    const char* line = aLine.BeginReading();
    const char* s = line + 3;
    length -= 4; // lose first 3 chars plus trailing \n
    NS_ASSERTION(s[length] == '\n', "aLine not newline-terminated");
    
    if (length & 3) {
        // The base64 encoded block must be multiple of 4. If not, something
        // screwed up.
        NS_WARNING("Base64 encoded block should be a multiple of 4 chars");
        return nullptr;
    } 

    // Calculate the exact length. I wonder why there isn't a function for this
    // in plbase64.
    PRInt32 numEquals;
    for (numEquals = 0; numEquals < length; ++numEquals) {
        if (s[length - 1 - numEquals] != '=')
            break;
    }
    *aLen = (length/4)*3 - numEquals;
    return reinterpret_cast<PRUint8*>(PL_Base64Decode(s, length, nullptr));
}
Example #3
0
static void
ReadMsg(const char *base64buf, PRUint32 bufLen)
{
    PRUint8 *inBuf = (PRUint8 *) PL_Base64Decode(base64buf, bufLen, NULL);
    if (!inBuf)
    {
        printf("PL_Base64Decode failed\n");
        return;
    }

    const PRUint8 *cursor = inBuf;

    PrintBuf("signature", cursor, 8);

    // verify NTLMSSP signature
    if (memcmp(cursor, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE)) != 0)
    {
        printf("### invalid or corrupt NTLM signature\n");
    }
    cursor += sizeof(NTLM_SIGNATURE);

    PrintBuf("message type", cursor, 4);

    if (memcmp(cursor, NTLM_TYPE1_MARKER, sizeof(NTLM_MARKER_LEN)) == 0)
        ReadType1MsgBody(inBuf, 12);
    else if (memcmp(cursor, NTLM_TYPE2_MARKER, sizeof(NTLM_MARKER_LEN)) == 0)
        ReadType2MsgBody(inBuf, 12);
    else if (memcmp(cursor, NTLM_TYPE3_MARKER, sizeof(NTLM_MARKER_LEN)) == 0)
        ReadType3MsgBody(inBuf, 12);
    else
        printf("### invalid or unknown message type\n");

    PR_Free(inBuf);
}
nsresult nsCMSSecureMessage::
decode(const char *data, unsigned char **result, PRInt32 * _retval)
{
  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::decode\n"));
  nsresult rv = NS_OK;
  PRUint32 len = PL_strlen(data);
  int adjust = 0;

  /* Compute length adjustment */
  if (data[len-1] == '=') {
    adjust++;
    if (data[len-2] == '=') adjust++;
  }

  *result = (unsigned char *)PL_Base64Decode(data, len, NULL);
  if (!*result) {
    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::decode - error decoding base64\n"));
    rv = NS_ERROR_ILLEGAL_VALUE;
    goto loser;
  }

  *_retval = (len*3)/4 - adjust;

loser:
  return rv;
}
/**
 * Decodes the given base64 string.
 *
 * It returns its decoded string in its input.
 *
 * @param pBufInOut   (inout) a buffer of the string
 */
void nsMsgBodyHandler::Base64Decode (nsCString &pBufInOut)
{
  char *decodedBody = PL_Base64Decode(pBufInOut.get(), pBufInOut.Length(), nullptr);
  if (decodedBody)
    pBufInOut.Adopt(decodedBody);

  int32_t offset = pBufInOut.FindChar('\n');
  while (offset != -1) {
    pBufInOut.Replace(offset, 1, ' ');
    offset = pBufInOut.FindChar('\n', offset);
  }
  offset = pBufInOut.FindChar('\r');
  while (offset != -1) {
    pBufInOut.Replace(offset, 1, ' ');
    offset = pBufInOut.FindChar('\r', offset);
  } 
}
Example #6
0
nsresult nsSecretDecoderRing::
decode(const char *data, unsigned char **result, PRInt32 * _retval)
{
  nsresult rv = NS_OK;
  PRUint32 len = PL_strlen(data);
  int adjust = 0;

  /* Compute length adjustment */
  if (data[len-1] == '=') {
    adjust++;
    if (data[len-2] == '=') adjust++;
  }

  *result = (unsigned char *)PL_Base64Decode(data, len, NULL);
  if (!*result) { rv = NS_ERROR_ILLEGAL_VALUE; goto loser; }

  *_retval = (len*3)/4 - adjust;

loser:
  return rv;
}
Example #7
0
//----------------------------------------------------------------------------------------
void nsFileSpec::operator = (const nsPersistentFileDescriptor& inDescriptor)
//----------------------------------------------------------------------------------------
{

    nsCAutoString data;
    inDescriptor.GetData(data);

#if defined (XP_MAC) || defined(XP_MACOSX)
    // Decode descriptor into a Handle (which is actually an AliasHandle)
    char* decodedData = PL_Base64Decode(data.get(), data.Length(), nsnull);
    Handle aliasH = nsnull;
    mError = NS_FILE_RESULT(::PtrToHand(decodedData, &aliasH, (data.Length() * 3) / 4));
    PR_Free(decodedData);
    if (NS_FAILED(mError))
        return; // not enough memory?
#endif

#if defined(XP_MAC)
    Boolean changed;
    mError = NS_FILE_RESULT(::ResolveAlias(nsnull, (AliasHandle)aliasH, &mSpec, &changed));
    DisposeHandle((Handle) aliasH);
    mPath.SetToEmpty();
#elif defined(XP_MACOSX)
    Boolean changed;
    FSRef fileRef;
    mError = NS_FILE_RESULT(::FSResolveAlias(nsnull, (AliasHandle)aliasH, &fileRef, &changed));
    ::DisposeHandle(aliasH);

    UInt8 pathBuf[PATH_MAX];
    mError = NS_FILE_RESULT(::FSRefMakePath(&fileRef, pathBuf, PATH_MAX));
    if (NS_FAILED(mError))
      return;
    mPath = (const char*)pathBuf;
#else
    mPath = data.get();
    mError = NS_OK;
#endif
}
nsresult
NS_DeserializeObject(const nsCSubstring& str, nsISupports** obj)
{
  // Base64 maps 3 binary bytes -> 4 ASCII bytes, so this calculation gives us
  // the right size. Compare also the comment in plbase64.h.
  PRUint32 size = (str.Length() * 3) / 4;
  char* buf = PL_Base64Decode(str.BeginReading(), str.Length(), nsnull);
  if (!buf)
    return NS_ERROR_OUT_OF_MEMORY;
  nsCOMPtr<nsIInputStream> stream;
  nsresult rv = NS_NewCStringInputStream(getter_AddRefs(stream),
                                         Substring(buf, buf + size));
  PR_Free(buf);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIObjectInputStream> objstream =
      do_CreateInstance("@mozilla.org/binaryinputstream;1");
  if (!objstream)
    return NS_ERROR_OUT_OF_MEMORY;

  objstream->SetInputStream(stream);
  return objstream->ReadObject(PR_TRUE, obj);
}
nsresult
NS_DeserializeObject(const nsCSubstring& str, nsISupports** obj)
{
  // Base64 maps 3 binary bytes -> 4 ASCII bytes.  If the original byte array
  // does not have length 0 mod 3, the input is padded with zeros and the
  // output is padded with a corresponding number of trailing '=' (which are
  // then sometimes dropped).  To compute the correct length of the original
  // byte array, we have to subtract the number of trailing '=' and then
  // multiply by 3 and then divide by 4 (making sure this is an integer
  // division).

  PRUint32 size = str.Length();
  if (size > 0 && str[size-1] == '=') {
    if (size > 1 && str[size-2] == '=') {
      size -= 2;
    } else {
      size -= 1;
    }
  }
  size = (size * 3) / 4;
  char* buf = PL_Base64Decode(str.BeginReading(), str.Length(), nullptr);
  if (!buf)
    return NS_ERROR_OUT_OF_MEMORY;
  nsCOMPtr<nsIInputStream> stream;
  nsresult rv = NS_NewCStringInputStream(getter_AddRefs(stream),
                                         Substring(buf, size));
  PR_Free(buf);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIObjectInputStream> objstream =
      do_CreateInstance("@mozilla.org/binaryinputstream;1");
  if (!objstream)
    return NS_ERROR_OUT_OF_MEMORY;

  objstream->SetInputStream(stream);
  return objstream->ReadObject(true, obj);
}
//
// GenerateCredentials
//
// This routine is responsible for creating the correct authentication
// blob to pass to the server that requested "Negotiate" authentication.
//
NS_IMETHODIMP
nsHttpNegotiateAuth::GenerateCredentials(nsIHttpAuthenticableChannel *authChannel,
                                         const char *challenge,
                                         bool isProxyAuth,
                                         const PRUnichar *domain,
                                         const PRUnichar *username,
                                         const PRUnichar *password,
                                         nsISupports **sessionState,
                                         nsISupports **continuationState,
                                         PRUint32 *flags,
                                         char **creds)
{
    // ChallengeReceived must have been called previously.
    nsIAuthModule *module = (nsIAuthModule *) *continuationState;
    NS_ENSURE_TRUE(module, NS_ERROR_NOT_INITIALIZED);

    *flags = USING_INTERNAL_IDENTITY;

    LOG(("nsHttpNegotiateAuth::GenerateCredentials() [challenge=%s]\n", challenge));

    NS_ASSERTION(creds, "null param");

#ifdef DEBUG
    bool isGssapiAuth =
        !PL_strncasecmp(challenge, kNegotiate, kNegotiateLen);
    NS_ASSERTION(isGssapiAuth, "Unexpected challenge");
#endif

    //
    // If the "Negotiate:" header had some data associated with it,
    // that data should be used as the input to this call.  This may
    // be a continuation of an earlier call because GSSAPI authentication
    // often takes multiple round-trips to complete depending on the
    // context flags given.  We want to use MUTUAL_AUTHENTICATION which
    // generally *does* require multiple round-trips.  Don't assume
    // auth can be completed in just 1 call.
    //
    unsigned int len = strlen(challenge);

    void *inToken, *outToken;
    PRUint32 inTokenLen, outTokenLen;

    if (len > kNegotiateLen) {
        challenge += kNegotiateLen;
        while (*challenge == ' ')
            challenge++;
        len = strlen(challenge);

        // strip off any padding (see bug 230351)
        while (challenge[len - 1] == '=')
            len--;

        inTokenLen = (len * 3)/4;
        inToken = malloc(inTokenLen);
        if (!inToken)
            return (NS_ERROR_OUT_OF_MEMORY);

        //
        // Decode the response that followed the "Negotiate" token
        //
        if (PL_Base64Decode(challenge, len, (char *) inToken) == NULL) {
            free(inToken);
            return(NS_ERROR_UNEXPECTED);
        }
    }
    else {
        //
        // Initializing, don't use an input token.
        //
        inToken = nullptr;
        inTokenLen = 0;
    }

    nsresult rv = module->GetNextToken(inToken, inTokenLen, &outToken, &outTokenLen);

    free(inToken);

    if (NS_FAILED(rv))
        return rv;

    if (outTokenLen == 0) {
        LOG(("  No output token to send, exiting"));
        return NS_ERROR_FAILURE;
    }

    //
    // base64 encode the output token.
    //
    char *encoded_token = PL_Base64Encode((char *)outToken, outTokenLen, nullptr);

    nsMemory::Free(outToken);

    if (!encoded_token)
        return NS_ERROR_OUT_OF_MEMORY;

    LOG(("  Sending a token of length %d\n", outTokenLen));

    // allocate a buffer sizeof("Negotiate" + " " + b64output_token + "\0")
    *creds = (char *) nsMemory::Alloc(kNegotiateLen + 1 + strlen(encoded_token) + 1);
    if (NS_UNLIKELY(!*creds))
        rv = NS_ERROR_OUT_OF_MEMORY;
    else
        sprintf(*creds, "%s %s", kNegotiate, encoded_token);

    PR_Free(encoded_token);
    return rv;
}
NS_IMETHODIMP
nsHttpNTLMAuth::GenerateCredentials(nsIHttpAuthenticableChannel *authChannel,
                                    const char      *challenge,
                                    bool             isProxyAuth,
                                    const PRUnichar *domain,
                                    const PRUnichar *user,
                                    const PRUnichar *pass,
                                    nsISupports    **sessionState,
                                    nsISupports    **continuationState,
                                    uint32_t       *aFlags,
                                    char           **creds)

{
    LOG(("nsHttpNTLMAuth::GenerateCredentials\n"));

    *creds = nullptr;
    *aFlags = 0;

    // if user or password is empty, ChallengeReceived returned
    // identityInvalid = false, that means we are using default user
    // credentials; see  nsAuthSSPI::Init method for explanation of this
    // condition
    if (!user || !pass)
        *aFlags = USING_INTERNAL_IDENTITY;

    nsresult rv;
    nsCOMPtr<nsIAuthModule> module = do_QueryInterface(*continuationState, &rv);
    NS_ENSURE_SUCCESS(rv, rv);

    void *inBuf, *outBuf;
    uint32_t inBufLen, outBufLen;

    // initial challenge
    if (PL_strcasecmp(challenge, "NTLM") == 0) {
        // NTLM service name format is 'HTTP@host' for both http and https
        nsCOMPtr<nsIURI> uri;
        rv = authChannel->GetURI(getter_AddRefs(uri));
        if (NS_FAILED(rv))
            return rv;
        nsAutoCString serviceName, host;
        rv = uri->GetAsciiHost(host);
        if (NS_FAILED(rv))
            return rv;
        serviceName.AppendLiteral("HTTP@");
        serviceName.Append(host);
        // initialize auth module
        uint32_t reqFlags = nsIAuthModule::REQ_DEFAULT;
        if (isProxyAuth)
            reqFlags |= nsIAuthModule::REQ_PROXY_AUTH;

        rv = module->Init(serviceName.get(), reqFlags, domain, user, pass);
        if (NS_FAILED(rv))
            return rv;

// This update enables updated Windows machines (Win7 or patched previous
// versions) and Linux machines running Samba (updated for Channel
// Binding), to perform Channel Binding when authenticating using NTLMv2
// and an outer secure channel.
//
// Currently only implemented for Windows, linux support will be landing in
// a separate patch, update this #ifdef accordingly then.
#if defined (XP_WIN) /* || defined (LINUX) */
        // We should retrieve the server certificate and compute the CBT,
        // but only when we are using the native NTLM implementation and
        // not the internal one.
        // It is a valid case not having the security info object.  This
        // occures when we connect an https site through an ntlm proxy.
        // After the ssl tunnel has been created, we get here the second
        // time and now generate the CBT from now valid security info.
        nsCOMPtr<nsIChannel> channel = do_QueryInterface(authChannel, &rv);
        if (NS_FAILED(rv))
            return rv;

        nsCOMPtr<nsISupports> security;
        rv = channel->GetSecurityInfo(getter_AddRefs(security));
        if (NS_FAILED(rv))
            return rv;

        nsCOMPtr<nsISSLStatusProvider> statusProvider =
            do_QueryInterface(security);

        if (mUseNative && statusProvider) {
            nsCOMPtr<nsISSLStatus> status;
            rv = statusProvider->GetSSLStatus(getter_AddRefs(status));
            if (NS_FAILED(rv))
                return rv;

            nsCOMPtr<nsIX509Cert> cert;
            rv = status->GetServerCert(getter_AddRefs(cert));
            if (NS_FAILED(rv))
                return rv;

            uint32_t length;
            uint8_t* certArray;
            cert->GetRawDER(&length, &certArray);						
			
            // If there is a server certificate, we pass it along the
            // first time we call GetNextToken().
            inBufLen = length;
            inBuf = certArray;
        } else {
            // If there is no server certificate, we don't pass anything.
            inBufLen = 0;
            inBuf = nullptr;
        }
#else // Extended protection update is just for Linux and Windows machines.
        inBufLen = 0;
        inBuf = nullptr;
#endif
    }
    else {
        // decode challenge; skip past "NTLM " to the start of the base64
        // encoded data.
        int len = strlen(challenge);
        if (len < 6)
            return NS_ERROR_UNEXPECTED; // bogus challenge
        challenge += 5;
        len -= 5;

        // strip off any padding (see bug 230351)
        while (challenge[len - 1] == '=')
          len--;

        // decode into the input secbuffer
        inBufLen = (len * 3)/4;      // sufficient size (see plbase64.h)
        inBuf = nsMemory::Alloc(inBufLen);
        if (!inBuf)
            return NS_ERROR_OUT_OF_MEMORY;

        if (PL_Base64Decode(challenge, len, (char *) inBuf) == nullptr) {
            nsMemory::Free(inBuf);
            return NS_ERROR_UNEXPECTED; // improper base64 encoding
        }
    }

    rv = module->GetNextToken(inBuf, inBufLen, &outBuf, &outBufLen);
    if (NS_SUCCEEDED(rv)) {
        // base64 encode data in output buffer and prepend "NTLM "
        int credsLen = 5 + ((outBufLen + 2)/3)*4;
        *creds = (char *) nsMemory::Alloc(credsLen + 1);
        if (!*creds)
            rv = NS_ERROR_OUT_OF_MEMORY;
        else {
            memcpy(*creds, "NTLM ", 5);
            PL_Base64Encode((char *) outBuf, outBufLen, *creds + 5);
            (*creds)[credsLen] = '\0'; // null terminate
        }
        // OK, we are done with |outBuf|
        nsMemory::Free(outBuf);
    }

    if (inBuf)
        nsMemory::Free(inBuf);

    return rv;
}
nsresult
nsDataChannel::OpenContentStream(PRBool async, nsIInputStream **result,
                                 nsIChannel** channel)
{
    NS_ENSURE_TRUE(URI(), NS_ERROR_NOT_INITIALIZED);

    nsresult rv;

    nsCAutoString spec;
    rv = URI()->GetAsciiSpec(spec);
    if (NS_FAILED(rv)) return rv;

    nsCString contentType, contentCharset, dataBuffer;
    PRBool lBase64;
    rv = nsDataHandler::ParseURI(spec, contentType, contentCharset,
                                 lBase64, dataBuffer);

    NS_UnescapeURL(dataBuffer);

    if (lBase64) {
        // Don't allow spaces in base64-encoded content. This is only
        // relevant for escaped spaces; other spaces are stripped in
        // NewURI.
        dataBuffer.StripWhitespace();
    }
    
    nsCOMPtr<nsIInputStream> bufInStream;
    nsCOMPtr<nsIOutputStream> bufOutStream;
    
    // create an unbounded pipe.
    rv = NS_NewPipe(getter_AddRefs(bufInStream),
                    getter_AddRefs(bufOutStream),
                    nsIOService::gDefaultSegmentSize,
                    PR_UINT32_MAX,
                    async, PR_TRUE);
    if (NS_FAILED(rv))
        return rv;

    PRUint32 contentLen;
    if (lBase64) {
        const PRUint32 dataLen = dataBuffer.Length();
        PRInt32 resultLen = 0;
        if (dataLen >= 1 && dataBuffer[dataLen-1] == '=') {
            if (dataLen >= 2 && dataBuffer[dataLen-2] == '=')
                resultLen = dataLen-2;
            else
                resultLen = dataLen-1;
        } else {
            resultLen = dataLen;
        }
        resultLen = ((resultLen * 3) / 4);

        // XXX PL_Base64Decode will return a null pointer for decoding
        // errors.  Since those are more likely than out-of-memory,
        // should we return NS_ERROR_MALFORMED_URI instead?
        char * decodedData = PL_Base64Decode(dataBuffer.get(), dataLen, nsnull);
        if (!decodedData) {
            return NS_ERROR_OUT_OF_MEMORY;
        }

        rv = bufOutStream->Write(decodedData, resultLen, &contentLen);

        PR_Free(decodedData);
    } else {
        rv = bufOutStream->Write(dataBuffer.get(), dataBuffer.Length(), &contentLen);
    }
    if (NS_FAILED(rv))
        return rv;

    SetContentType(contentType);
    SetContentCharset(contentCharset);
    SetContentLength64(contentLen);

    NS_ADDREF(*result = bufInStream);

    return NS_OK;
}
// |decode_mime_part2_str| taken from comi18n.c
// Decode RFC2047-encoded words in the input and convert the result to UTF-8.
// If aOverrideCharset is true, charset in RFC2047-encoded words is 
// ignored and aDefaultCharset is assumed, instead. aDefaultCharset
// is also used to convert raw octets (without RFC 2047 encoding) to UTF-8.
//static
nsresult DecodeRFC2047Str(const char *aHeader, const char *aDefaultCharset, 
                          PRBool aOverrideCharset, nsACString &aResult)
{
  const char *p, *q, *r;
  char *decodedText;
  const char *begin; // tracking pointer for where we are in the input buffer
  PRInt32 isLastEncodedWord = 0;
  const char *charsetStart, *charsetEnd;
  char charset[80];

  // initialize charset name to an empty string
  charset[0] = '\0';

  begin = aHeader;

  // To avoid buffer realloc, if possible, set capacity in advance. No 
  // matter what,  more than 3x expansion can never happen for all charsets
  // supported by Mozilla. SCSU/BCSU with the sliding window set to a
  // non-BMP block may be exceptions, but Mozilla does not support them. 
  // Neither any known mail/news program use them. Even if there's, we're
  // safe because we don't use a raw *char any more.
  aResult.SetCapacity(3 * strlen(aHeader));

  while ((p = PL_strstr(begin, "=?")) != 0) {
    if (isLastEncodedWord) {
      // See if it's all whitespace.
      for (q = begin; q < p; ++q) {
        if (!PL_strchr(" \t\r\n", *q)) break;
      }
    }

    if (!isLastEncodedWord || q < p) {
      // copy the part before the encoded-word
      CopyRawHeader(begin, p - begin, aDefaultCharset, aResult);
      begin = p;
    }

    p += 2;

    // Get charset info
    charsetStart = p;
    charsetEnd = 0;
    for (q = p; *q != '?'; q++) {
      if (*q <= ' ' || PL_strchr(especials, *q)) {
        goto badsyntax;
      }

      // RFC 2231 section 5
      if (!charsetEnd && *q == '*') {
        charsetEnd = q; 
      }
    }
    if (!charsetEnd) {
      charsetEnd = q;
    }

    // Check for too-long charset name
    if (PRUint32(charsetEnd - charsetStart) >= sizeof(charset)) 
      goto badsyntax;
    
    memcpy(charset, charsetStart, charsetEnd - charsetStart);
    charset[charsetEnd - charsetStart] = 0;

    q++;
    if (*q != 'Q' && *q != 'q' && *q != 'B' && *q != 'b')
      goto badsyntax;

    if (q[1] != '?')
      goto badsyntax;

    r = q;
    for (r = q + 2; *r != '?'; r++) {
      if (*r < ' ') goto badsyntax;
    }
    if (r[1] != '=')
        goto badsyntax;
    else if (r == q + 2) {
        // it's empty, skip
        begin = r + 2;
        isLastEncodedWord = 1;
        continue;
    }

    if(*q == 'Q' || *q == 'q')
      decodedText = DecodeQ(q + 2, r - (q + 2));
    else {
      // bug 227290. ignore an extraneous '=' at the end.
      // (# of characters in B-encoded part has to be a multiple of 4)
      PRInt32 n = r - (q + 2);
      n -= (n % 4 == 1 && !PL_strncmp(r - 3, "===", 3)) ? 1 : 0;
      decodedText = PL_Base64Decode(q + 2, n, nsnull);
    }

    if (decodedText == nsnull)
      goto badsyntax;

    // Override charset if requested.  Never override labeled UTF-8.
    // Use default charset instead of UNKNOWN-8BIT
    if ((aOverrideCharset && 0 != nsCRT::strcasecmp(charset, "UTF-8")) ||
        (aDefaultCharset && 0 == nsCRT::strcasecmp(charset, "UNKNOWN-8BIT"))) {
      PL_strncpy(charset, aDefaultCharset, sizeof(charset) - 1);
      charset[sizeof(charset) - 1] = '\0';
    }

    {
      nsCOMPtr<nsIUTF8ConverterService> 
        cvtUTF8(do_GetService(NS_UTF8CONVERTERSERVICE_CONTRACTID));
      nsCAutoString utf8Text;
      // skip ASCIIness/UTF8ness test if aCharset is 7bit non-ascii charset.
      if (cvtUTF8 &&
          NS_SUCCEEDED(
            cvtUTF8->ConvertStringToUTF8(nsDependentCString(decodedText),
            charset, IS_7BIT_NON_ASCII_CHARSET(charset), utf8Text))) {
        aResult.Append(utf8Text);
      } else {
        aResult.Append(REPLACEMENT_CHAR);
      }
    }
    PR_Free(decodedText);
    begin = r + 2;
    isLastEncodedWord = 1;
    continue;

  badsyntax:
    // copy the part before the encoded-word
    aResult.Append(begin, p - begin);
    begin = p;
    isLastEncodedWord = 0;
  }

  // put the tail back
  CopyRawHeader(begin, strlen(begin), aDefaultCharset, aResult);

  nsCAutoString tempStr(aResult);
  tempStr.ReplaceChar('\t', ' ');
  aResult = tempStr;

  return NS_OK;
}
NS_IMETHODIMP
MailEwsLoadCalendarItemsCallback::LocalOperation(void * response) {
    load_item_response * r = (load_item_response *)response;
    if (!r) return NS_OK;

    ews_item ** item = r->item;
    nsresult rv;

    mailews_logger << "create calIEvent on main threads:"
                   << r->item_count
                   << std::endl;

    nsCOMPtr<nsIMutableArray> calendarItems =
		    do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
    NS_ENSURE_SUCCESS(rv, rv);

    nsCString ownerEmail;
	rv = GetOwnerEmail(m_pIncomingServer, ownerEmail);
	NS_ENSURE_SUCCESS(rv, rv);

    for(int i=0;i < r->item_count;i++) {
        if (item[i]->item_type == EWS_Item_Calendar) {
            ews_calendar_item * cal_item = (ews_calendar_item*)item[i];

	        nsCOMPtr<calIEvent> e =
			        do_CreateInstance(CAL_EVENT_CONTRACTID, &rv);
	        NS_ENSURE_SUCCESS(rv, rv);

            if (item[i]->mime_content) {
                char *decodedContent =
                        PL_Base64Decode(item[i]->mime_content,
                                        strlen(item[i]->mime_content),
                                        nullptr);
                nsCString data;
                data.Adopt(decodedContent);

                CleanUpIcalString(data);

                rv = e->SetIcalString(data);
                NS_ENSURE_SUCCESS(rv, rv);

                nsCString uid(((ews_calendar_item*)item[i])->uid);
                
                if (uid.IsEmpty()) {
                    GenerateUid(uid);
                    mailews_logger << "generate uid for event:"
                                   << item[i]->item_id
                                   << ","
                                   << item[i]->change_key
                                   << ","
                                   << uid.get()
                                   << std::endl
                                   << data.get()
                                   << std::endl;
                }
                e->SetId(uid);

                nsCOMPtr<calIDateTime> dtStart;
                e->GetStartDate(getter_AddRefs(dtStart));

                if (!dtStart) {
                    mailews_logger << "skip no start date event:"
                                   << item[i]->item_id
                                   << ","
                                   << item[i]->change_key
                                   << ","
                                   << uid.get()
                                   << std::endl
                                   << data.get()
                                   << std::endl;
                    continue;
                }

                rv = e->RemoveAllAttendees();
                NS_ENSURE_SUCCESS(rv, rv);
	
                rv = UpdateAttendee(e,
                                    (ews_calendar_item*)item[i],
                                    ownerEmail,
                                    true);
                NS_ENSURE_SUCCESS(rv, rv);
                rv = UpdateAttendee(e,
                                    (ews_calendar_item*)item[i],
                                    ownerEmail,
                                    false);
                NS_ENSURE_SUCCESS(rv, rv);
                rv = UpdateOccurrence(e,
                                      (ews_calendar_item*)item[i]);
                NS_ENSURE_SUCCESS(rv, rv);

                rv = UpdateStatus(e,
                                  ownerEmail);
                NS_ENSURE_SUCCESS(rv, rv);
            } else {
                rv = From(m_pIncomingServer,
                          (ews_calendar_item *)item[i], e);
                NS_ENSURE_SUCCESS(rv, rv);
            }

	        //Save item id
            rv = SetPropertyString(e,
                                   NS_LITERAL_STRING("X-ITEM-ID"),
                                   nsCString(item[i]->item_id));
	        NS_ENSURE_SUCCESS(rv, rv);

	        //Save change key
            rv = SetPropertyString(e,
                                   NS_LITERAL_STRING("X-CHANGE-KEY"),
                                   nsCString(item[i]->change_key));
	        NS_ENSURE_SUCCESS(rv, rv);

            //Save Master id
            if (cal_item->recurring_master_id) {
                rv = SetPropertyString(e,
                                       NS_LITERAL_STRING("X-MASTER_ID"),
                                       nsCString(cal_item->recurring_master_id));
                NS_ENSURE_SUCCESS(rv, rv);

                rv = SetPropertyString(e,
                                       NS_LITERAL_STRING("X-MASTER_UID"),
                                       nsCString(cal_item->recurring_master_uid));
                NS_ENSURE_SUCCESS(rv, rv);
            } else if (cal_item->calendar_item_type ==
                       EWS_CalendarItemType_Single) {
                e->SetRecurrenceId(nullptr);
            }

	        calendarItems->AppendElement(e, false);
        }
    }

    nsCOMPtr<nsIArray> resultArray(do_QueryInterface(calendarItems));
    
    mailews_logger << "create calIEvent on main threads done:"
                   << r->item_count
                   << std::endl;
    return m_pCalCallback->OnResult(resultArray);
}
Example #15
0
/* nsIX509Cert constructX509FromBase64 (in string base64); */
NS_IMETHODIMP
nsNSSCertificateDB::ConstructX509FromBase64(const char * base64, nsIX509Cert **_retval)
{
  if (!_retval) {
    return NS_ERROR_FAILURE;
  }

  nsNSSShutDownPreventionLock locker;
  PRUint32 len = PL_strlen(base64);
  int adjust = 0;

  /* Compute length adjustment */
  if (base64[len-1] == '=') {
    adjust++;
    if (base64[len-2] == '=') adjust++;
  }

  nsresult rv = NS_OK;
  char *certDER = 0;
  PRInt32 lengthDER = 0;

  certDER = PL_Base64Decode(base64, len, NULL);
  if (!certDER || !*certDER) {
    rv = NS_ERROR_ILLEGAL_VALUE;
  }
  else {
    lengthDER = (len*3)/4 - adjust;

    SECItem secitem_cert;
    secitem_cert.type = siDERCertBuffer;
    secitem_cert.data = (unsigned char*)certDER;
    secitem_cert.len = lengthDER;

    CERTCertificate *cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &secitem_cert, nsnull, PR_FALSE, PR_TRUE);

    if (!cert) {
      rv = NS_ERROR_FAILURE;
    }
    else {
      nsNSSCertificate *nsNSS = new nsNSSCertificate(cert);
      if (!nsNSS) {
        rv = NS_ERROR_OUT_OF_MEMORY;
      }
      else {
        nsresult rv = nsNSS->QueryInterface(NS_GET_IID(nsIX509Cert), (void**)_retval);

        if (NS_SUCCEEDED(rv) && *_retval) {
          NS_ADDREF(*_retval);
        }
        
        NS_RELEASE(nsNSS);
      }
      CERT_DestroyCertificate(cert);
    }
  }
  
  if (certDER) {
    nsCRT::free(certDER);
  }
  return rv;
}
NS_IMETHODIMP
nsHttpNTLMAuth::GenerateCredentials(nsIHttpChannel  *httpChannel,
                                    const char      *challenge,
                                    PRBool           isProxyAuth,
                                    const PRUnichar *domain,
                                    const PRUnichar *user,
                                    const PRUnichar *pass,
                                    nsISupports    **sessionState,
                                    nsISupports    **continuationState,
                                    PRUint32       *aFlags,
                                    char           **creds)

{
    LOG(("nsHttpNTLMAuth::GenerateCredentials\n"));

    *creds = nsnull;
    *aFlags = 0;

    // if user or password is empty, ChallengeReceived returned
    // identityInvalid = PR_FALSE, that means we are using default user
    // credentials; see  nsAuthSSPI::Init method for explanation of this 
    // condition
    if (!user || !pass)
        *aFlags = USING_INTERNAL_IDENTITY;

    nsresult rv;
    nsCOMPtr<nsIAuthModule> module = do_QueryInterface(*continuationState, &rv);
    NS_ENSURE_SUCCESS(rv, rv);

    void *inBuf, *outBuf;
    PRUint32 inBufLen, outBufLen;

    // initial challenge
    if (PL_strcasecmp(challenge, "NTLM") == 0) {
        // NTLM service name format is 'HTTP@host' for both http and https
        nsCOMPtr<nsIURI> uri;
        rv = httpChannel->GetURI(getter_AddRefs(uri));
        if (NS_FAILED(rv))
            return rv;
        nsCAutoString serviceName, host;
        rv = uri->GetAsciiHost(host);
        if (NS_FAILED(rv))
            return rv;
        serviceName.AppendLiteral("HTTP@");
        serviceName.Append(host);
        // initialize auth module
        rv = module->Init(serviceName.get(), nsIAuthModule::REQ_DEFAULT, domain, user, pass);
        if (NS_FAILED(rv))
            return rv;

        inBufLen = 0;
        inBuf = nsnull;
    }
    else {
        // decode challenge; skip past "NTLM " to the start of the base64
        // encoded data.
        int len = strlen(challenge);
        if (len < 6)
            return NS_ERROR_UNEXPECTED; // bogus challenge
        challenge += 5;
        len -= 5;

        // strip off any padding (see bug 230351)
        while (challenge[len - 1] == '=')
          len--;

        // decode into the input secbuffer
        inBufLen = (len * 3)/4;      // sufficient size (see plbase64.h)
        inBuf = nsMemory::Alloc(inBufLen);
        if (!inBuf)
            return NS_ERROR_OUT_OF_MEMORY;

        if (PL_Base64Decode(challenge, len, (char *) inBuf) == nsnull) {
            nsMemory::Free(inBuf);
            return NS_ERROR_UNEXPECTED; // improper base64 encoding
        }
    }

    rv = module->GetNextToken(inBuf, inBufLen, &outBuf, &outBufLen);
    if (NS_SUCCEEDED(rv)) {
        // base64 encode data in output buffer and prepend "NTLM "
        int credsLen = 5 + ((outBufLen + 2)/3)*4;
        *creds = (char *) nsMemory::Alloc(credsLen + 1);
        if (!*creds)
            rv = NS_ERROR_OUT_OF_MEMORY;
        else {
            memcpy(*creds, "NTLM ", 5);
            PL_Base64Encode((char *) outBuf, outBufLen, *creds + 5);
            (*creds)[credsLen] = '\0'; // null terminate
        }
        // OK, we are done with |outBuf|
        nsMemory::Free(outBuf);
    }

    if (inBuf)
        nsMemory::Free(inBuf);

    return rv;
}