forked from mirrors/gecko-dev
		
	Adds Win32 networking APIs to the function broker so that we can run SSL communications outside of the sandbox.
		
			
				
	
	
		
			359 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			359 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- */
 | 
						|
/* vim: set sw=2 ts=8 et tw=80 : */
 | 
						|
/* This Source Code Form is subject to the terms of the Mozilla Public
 | 
						|
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
						|
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
						|
 | 
						|
#include "FunctionBrokerIPCUtils.h"
 | 
						|
 | 
						|
#if defined(XP_WIN)
 | 
						|
 | 
						|
#include <schannel.h>
 | 
						|
 | 
						|
/* these defines are missing from mingw headers */
 | 
						|
#ifndef SP_PROT_TLS1_1_CLIENT
 | 
						|
#define SP_PROT_TLS1_1_CLIENT 0x00000200
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef SP_PROT_TLS1_2_CLIENT
 | 
						|
#define SP_PROT_TLS1_2_CLIENT 0x00000800
 | 
						|
#endif
 | 
						|
 | 
						|
namespace mozilla {
 | 
						|
namespace plugins {
 | 
						|
 | 
						|
mozilla::LazyLogModule sPluginHooksLog("PluginHooks");
 | 
						|
 | 
						|
static const DWORD SCHANNEL_SUPPORTED_PROTOCOLS =
 | 
						|
  SP_PROT_TLS1_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT;
 | 
						|
 | 
						|
static const DWORD SCHANNEL_SUPPORTED_FLAGS =
 | 
						|
  SCH_CRED_MANUAL_CRED_VALIDATION | SCH_CRED_NO_DEFAULT_CREDS |
 | 
						|
  SCH_CRED_REVOCATION_CHECK_END_CERT;
 | 
						|
 | 
						|
void
 | 
						|
OpenFileNameIPC::CopyFromOfn(LPOPENFILENAMEW aLpofn)
 | 
						|
{
 | 
						|
  mHwndOwner = nullptr;
 | 
						|
 | 
						|
  // Filter is double-NULL terminated.  mFilter should include the double-NULL.
 | 
						|
  mHasFilter = aLpofn->lpstrFilter != nullptr;
 | 
						|
  if (mHasFilter) {
 | 
						|
    uint32_t dNullIdx = 0;
 | 
						|
    while (aLpofn->lpstrFilter[dNullIdx] != L'\0' ||
 | 
						|
           aLpofn->lpstrFilter[dNullIdx+1] != L'\0') {
 | 
						|
      dNullIdx++;
 | 
						|
    }
 | 
						|
    mFilter.assign(aLpofn->lpstrFilter, dNullIdx+2);
 | 
						|
  }
 | 
						|
  mHasCustomFilter = aLpofn->lpstrCustomFilter != nullptr;
 | 
						|
  if (mHasCustomFilter) {
 | 
						|
    mCustomFilterIn = std::wstring(aLpofn->lpstrCustomFilter);
 | 
						|
    mNMaxCustFilterOut =
 | 
						|
      aLpofn->nMaxCustFilter - (wcslen(aLpofn->lpstrCustomFilter) + 1);
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    mNMaxCustFilterOut = 0;
 | 
						|
  }
 | 
						|
  mFilterIndex = aLpofn->nFilterIndex;
 | 
						|
  mFile = std::wstring(aLpofn->lpstrFile);
 | 
						|
  mNMaxFile = aLpofn->nMaxFile;
 | 
						|
  mNMaxFileTitle =
 | 
						|
    aLpofn->lpstrFileTitle != nullptr ? aLpofn->nMaxFileTitle : 0;
 | 
						|
  mHasInitialDir = aLpofn->lpstrInitialDir != nullptr;
 | 
						|
  if (mHasInitialDir) {
 | 
						|
    mInitialDir = std::wstring(aLpofn->lpstrInitialDir);
 | 
						|
  }
 | 
						|
  mHasTitle = aLpofn->lpstrTitle != nullptr;
 | 
						|
  if (mHasTitle) {
 | 
						|
    mTitle = std::wstring(aLpofn->lpstrTitle);
 | 
						|
  }
 | 
						|
  mHasDefExt = aLpofn->lpstrDefExt != nullptr;
 | 
						|
  if (mHasDefExt) {
 | 
						|
    mDefExt = std::wstring(aLpofn->lpstrDefExt);
 | 
						|
  }
 | 
						|
 | 
						|
  mFlags = aLpofn->Flags;
 | 
						|
  // If the user sets OFN_ALLOWMULTISELECT then we require OFN_EXPLORER
 | 
						|
  // as well.  Without OFN_EXPLORER, the method has ancient legacy
 | 
						|
  // behavior that we don't support.
 | 
						|
  MOZ_ASSERT((mFlags & OFN_EXPLORER) || !(mFlags & OFN_ALLOWMULTISELECT));
 | 
						|
 | 
						|
  // We ignore any visual customization and callbacks that the user set.
 | 
						|
  mFlags &= ~(OFN_ENABLEHOOK | OFN_ENABLETEMPLATEHANDLE | OFN_ENABLETEMPLATE);
 | 
						|
 | 
						|
  mFlagsEx = aLpofn->FlagsEx;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
OpenFileNameIPC::AddToOfn(LPOPENFILENAMEW aLpofn) const
 | 
						|
{
 | 
						|
  aLpofn->lStructSize = sizeof(OPENFILENAMEW);
 | 
						|
  aLpofn->hwndOwner = mHwndOwner;
 | 
						|
  if (mHasFilter) {
 | 
						|
    memcpy(const_cast<LPWSTR>(aLpofn->lpstrFilter),
 | 
						|
           mFilter.data(), mFilter.size() * sizeof(wchar_t));
 | 
						|
  }
 | 
						|
  if (mHasCustomFilter) {
 | 
						|
    aLpofn->nMaxCustFilter = mCustomFilterIn.size() + 1 + mNMaxCustFilterOut;
 | 
						|
    wcscpy(aLpofn->lpstrCustomFilter, mCustomFilterIn.c_str());
 | 
						|
    memset(aLpofn->lpstrCustomFilter + mCustomFilterIn.size() + 1, 0,
 | 
						|
           mNMaxCustFilterOut * sizeof(wchar_t));
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    aLpofn->nMaxCustFilter = 0;
 | 
						|
  }
 | 
						|
  aLpofn->nFilterIndex = mFilterIndex;
 | 
						|
  if (mNMaxFile > 0) {
 | 
						|
    wcsncpy(aLpofn->lpstrFile, mFile.c_str(),
 | 
						|
            std::min(static_cast<uint32_t>(mFile.size()+1), mNMaxFile));
 | 
						|
    aLpofn->lpstrFile[mNMaxFile - 1] = L'\0';
 | 
						|
  }
 | 
						|
  aLpofn->nMaxFile = mNMaxFile;
 | 
						|
  aLpofn->nMaxFileTitle = mNMaxFileTitle;
 | 
						|
  if (mHasInitialDir) {
 | 
						|
    wcscpy(const_cast<LPWSTR>(aLpofn->lpstrInitialDir), mInitialDir.c_str());
 | 
						|
  }
 | 
						|
  if (mHasTitle) {
 | 
						|
    wcscpy(const_cast<LPWSTR>(aLpofn->lpstrTitle), mTitle.c_str());
 | 
						|
  }
 | 
						|
  aLpofn->Flags = mFlags;  /* TODO: Consider adding OFN_NOCHANGEDIR */
 | 
						|
  if (mHasDefExt) {
 | 
						|
    wcscpy(const_cast<LPWSTR>(aLpofn->lpstrDefExt), mDefExt.c_str());
 | 
						|
  }
 | 
						|
  aLpofn->FlagsEx = mFlagsEx;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
OpenFileNameIPC::AllocateOfnStrings(LPOPENFILENAMEW aLpofn) const
 | 
						|
{
 | 
						|
  if (mHasFilter) {
 | 
						|
    // mFilter is double-NULL terminated and it includes the double-NULL in its length.
 | 
						|
    aLpofn->lpstrFilter =
 | 
						|
      static_cast<LPCTSTR>(moz_xmalloc(sizeof(wchar_t) * (mFilter.size())));
 | 
						|
  }
 | 
						|
  if (mHasCustomFilter) {
 | 
						|
    aLpofn->lpstrCustomFilter =
 | 
						|
      static_cast<LPTSTR>(moz_xmalloc(sizeof(wchar_t) * (mCustomFilterIn.size() + 1 + mNMaxCustFilterOut)));
 | 
						|
  }
 | 
						|
  aLpofn->lpstrFile =
 | 
						|
    static_cast<LPTSTR>(moz_xmalloc(sizeof(wchar_t) * mNMaxFile));
 | 
						|
  if (mNMaxFileTitle > 0) {
 | 
						|
    aLpofn->lpstrFileTitle =
 | 
						|
      static_cast<LPTSTR>(moz_xmalloc(sizeof(wchar_t) * mNMaxFileTitle));
 | 
						|
  }
 | 
						|
  if (mHasInitialDir) {
 | 
						|
    aLpofn->lpstrInitialDir =
 | 
						|
      static_cast<LPCTSTR>(moz_xmalloc(sizeof(wchar_t) * (mInitialDir.size() + 1)));
 | 
						|
  }
 | 
						|
  if (mHasTitle) {
 | 
						|
    aLpofn->lpstrTitle =
 | 
						|
      static_cast<LPCTSTR>(moz_xmalloc(sizeof(wchar_t) * (mTitle.size() + 1)));
 | 
						|
  }
 | 
						|
  if (mHasDefExt) {
 | 
						|
    aLpofn->lpstrDefExt =
 | 
						|
      static_cast<LPCTSTR>(moz_xmalloc(sizeof(wchar_t) * (mDefExt.size() + 1)));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// static
 | 
						|
void
 | 
						|
OpenFileNameIPC::FreeOfnStrings(LPOPENFILENAMEW aLpofn)
 | 
						|
{
 | 
						|
  if (aLpofn->lpstrFilter) {
 | 
						|
    free(const_cast<LPWSTR>(aLpofn->lpstrFilter));
 | 
						|
  }
 | 
						|
  if (aLpofn->lpstrCustomFilter) {
 | 
						|
    free(aLpofn->lpstrCustomFilter);
 | 
						|
  }
 | 
						|
  if (aLpofn->lpstrFile) {
 | 
						|
    free(aLpofn->lpstrFile);
 | 
						|
  }
 | 
						|
  if (aLpofn->lpstrFileTitle) {
 | 
						|
    free(aLpofn->lpstrFileTitle);
 | 
						|
  }
 | 
						|
  if (aLpofn->lpstrInitialDir) {
 | 
						|
    free(const_cast<LPWSTR>(aLpofn->lpstrInitialDir));
 | 
						|
  }
 | 
						|
  if (aLpofn->lpstrTitle) {
 | 
						|
    free(const_cast<LPWSTR>(aLpofn->lpstrTitle));
 | 
						|
  }
 | 
						|
  if (aLpofn->lpstrDefExt) {
 | 
						|
    free(const_cast<LPWSTR>(aLpofn->lpstrDefExt));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
OpenFileNameRetIPC::CopyFromOfn(LPOPENFILENAMEW aLpofn)
 | 
						|
{
 | 
						|
  if (aLpofn->lpstrCustomFilter != nullptr) {
 | 
						|
    mCustomFilterOut =
 | 
						|
      std::wstring(aLpofn->lpstrCustomFilter + wcslen(aLpofn->lpstrCustomFilter) + 1);
 | 
						|
  }
 | 
						|
  mFile.assign(aLpofn->lpstrFile, aLpofn->nMaxFile);
 | 
						|
  if (aLpofn->lpstrFileTitle != nullptr) {
 | 
						|
    mFileTitle.assign(aLpofn->lpstrFileTitle, wcslen(aLpofn->lpstrFileTitle) + 1);
 | 
						|
  }
 | 
						|
  mFileOffset = aLpofn->nFileOffset;
 | 
						|
  mFileExtension = aLpofn->nFileExtension;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
OpenFileNameRetIPC::AddToOfn(LPOPENFILENAMEW aLpofn) const
 | 
						|
{
 | 
						|
  if (aLpofn->lpstrCustomFilter) {
 | 
						|
    LPWSTR secondString =
 | 
						|
      aLpofn->lpstrCustomFilter + wcslen(aLpofn->lpstrCustomFilter) + 1;
 | 
						|
    const wchar_t* customFilterOut = mCustomFilterOut.c_str();
 | 
						|
    MOZ_ASSERT(wcslen(aLpofn->lpstrCustomFilter) + 1 +
 | 
						|
               wcslen(customFilterOut) + 1 + 1 <= aLpofn->nMaxCustFilter);
 | 
						|
    wcscpy(secondString, customFilterOut);
 | 
						|
    secondString[wcslen(customFilterOut) + 1] = L'\0';  // terminated with two NULLs
 | 
						|
  }
 | 
						|
  MOZ_ASSERT(mFile.size() <= aLpofn->nMaxFile);
 | 
						|
  memcpy(aLpofn->lpstrFile,
 | 
						|
         mFile.data(), mFile.size() * sizeof(wchar_t));
 | 
						|
  if (aLpofn->lpstrFileTitle != nullptr) {
 | 
						|
    MOZ_ASSERT(mFileTitle.size() + 1 < aLpofn->nMaxFileTitle);
 | 
						|
    wcscpy(aLpofn->lpstrFileTitle, mFileTitle.c_str());
 | 
						|
  }
 | 
						|
  aLpofn->nFileOffset = mFileOffset;
 | 
						|
  aLpofn->nFileExtension = mFileExtension;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
IPCSchannelCred::CopyFrom(const PSCHANNEL_CRED& aSCred)
 | 
						|
{
 | 
						|
  // We assert that the aSCred fields take supported values.
 | 
						|
  // If they do not then we ignore the values we were given.
 | 
						|
  MOZ_ASSERT(aSCred->dwVersion == SCHANNEL_CRED_VERSION);
 | 
						|
  MOZ_ASSERT(aSCred->cCreds == 0);
 | 
						|
  MOZ_ASSERT(aSCred->paCred == nullptr);
 | 
						|
  MOZ_ASSERT(aSCred->hRootStore == nullptr);
 | 
						|
  MOZ_ASSERT(aSCred->cMappers == 0);
 | 
						|
  MOZ_ASSERT(aSCred->aphMappers == nullptr);
 | 
						|
  MOZ_ASSERT(aSCred->cSupportedAlgs == 0);
 | 
						|
  MOZ_ASSERT(aSCred->palgSupportedAlgs == nullptr);
 | 
						|
  MOZ_ASSERT((aSCred->grbitEnabledProtocols & SCHANNEL_SUPPORTED_PROTOCOLS) ==
 | 
						|
             aSCred->grbitEnabledProtocols);
 | 
						|
  mEnabledProtocols =
 | 
						|
    aSCred->grbitEnabledProtocols & SCHANNEL_SUPPORTED_PROTOCOLS;
 | 
						|
  mMinStrength = aSCred->dwMinimumCipherStrength;
 | 
						|
  mMaxStrength = aSCred->dwMaximumCipherStrength;
 | 
						|
  MOZ_ASSERT(aSCred->dwSessionLifespan == 0);
 | 
						|
  MOZ_ASSERT((aSCred->dwFlags & SCHANNEL_SUPPORTED_FLAGS) == aSCred->dwFlags);
 | 
						|
  mFlags = aSCred->dwFlags & SCHANNEL_SUPPORTED_FLAGS;
 | 
						|
  MOZ_ASSERT(aSCred->dwCredFormat == 0);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
IPCSchannelCred::CopyTo(PSCHANNEL_CRED& aSCred) const
 | 
						|
{
 | 
						|
  // Validate values as they come from an untrusted process.
 | 
						|
  memset(aSCred, 0, sizeof(SCHANNEL_CRED));
 | 
						|
  aSCred->dwVersion = SCHANNEL_CRED_VERSION;
 | 
						|
  aSCred->grbitEnabledProtocols =
 | 
						|
    mEnabledProtocols & SCHANNEL_SUPPORTED_PROTOCOLS;
 | 
						|
  aSCred->dwMinimumCipherStrength = mMinStrength;
 | 
						|
  aSCred->dwMaximumCipherStrength = mMaxStrength;
 | 
						|
  aSCred->dwFlags = mFlags & SCHANNEL_SUPPORTED_FLAGS;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
IPCInternetBuffers::CopyFrom(const LPINTERNET_BUFFERSA& aBufs)
 | 
						|
{
 | 
						|
  mBuffers.Clear();
 | 
						|
 | 
						|
  LPINTERNET_BUFFERSA inetBuf = aBufs;
 | 
						|
  while (inetBuf) {
 | 
						|
    MOZ_ASSERT(inetBuf->dwStructSize == sizeof(INTERNET_BUFFERSA));
 | 
						|
    Buffer* ipcBuf = mBuffers.AppendElement();
 | 
						|
 | 
						|
    ipcBuf->mHeader.SetIsVoid(inetBuf->lpcszHeader == nullptr);
 | 
						|
    if (inetBuf->lpcszHeader) {
 | 
						|
      ipcBuf->mHeader.Assign(inetBuf->lpcszHeader, inetBuf->dwHeadersLength);
 | 
						|
    }
 | 
						|
    ipcBuf->mHeaderTotal = inetBuf->dwHeadersTotal;
 | 
						|
 | 
						|
    ipcBuf->mBuffer.SetIsVoid(inetBuf->lpvBuffer == nullptr);
 | 
						|
    if (inetBuf->lpvBuffer) {
 | 
						|
      ipcBuf->mBuffer.Assign(static_cast<char*>(inetBuf->lpvBuffer),
 | 
						|
                             inetBuf->dwBufferLength);
 | 
						|
    }
 | 
						|
    ipcBuf->mBufferTotal = inetBuf->dwBufferTotal;
 | 
						|
    inetBuf = inetBuf->Next;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
IPCInternetBuffers::CopyTo(LPINTERNET_BUFFERSA& aBufs) const
 | 
						|
{
 | 
						|
  MOZ_ASSERT(!aBufs);
 | 
						|
 | 
						|
  LPINTERNET_BUFFERSA lastBuf = nullptr;
 | 
						|
  for (size_t idx = 0; idx < mBuffers.Length(); ++idx) {
 | 
						|
    const Buffer& ipcBuf = mBuffers[idx];
 | 
						|
    LPINTERNET_BUFFERSA newBuf =
 | 
						|
      static_cast<LPINTERNET_BUFFERSA>(moz_xcalloc(1, sizeof(INTERNET_BUFFERSA)));
 | 
						|
    if (idx == 0) {
 | 
						|
      aBufs = newBuf;
 | 
						|
    } else {
 | 
						|
      MOZ_ASSERT(lastBuf);
 | 
						|
      lastBuf->Next = newBuf;
 | 
						|
      lastBuf = newBuf;
 | 
						|
    }
 | 
						|
 | 
						|
    newBuf->dwStructSize = sizeof(INTERNET_BUFFERSA);
 | 
						|
 | 
						|
    newBuf->dwHeadersTotal = ipcBuf.mHeaderTotal;
 | 
						|
    if (!ipcBuf.mHeader.IsVoid()) {
 | 
						|
      newBuf->lpcszHeader =
 | 
						|
        static_cast<LPCSTR>(moz_xmalloc(ipcBuf.mHeader.Length()));
 | 
						|
      memcpy(const_cast<char*>(newBuf->lpcszHeader), ipcBuf.mHeader.Data(),
 | 
						|
             ipcBuf.mHeader.Length());
 | 
						|
      newBuf->dwHeadersLength = ipcBuf.mHeader.Length();
 | 
						|
    }
 | 
						|
 | 
						|
    newBuf->dwBufferTotal = ipcBuf.mBufferTotal;
 | 
						|
    if (!ipcBuf.mBuffer.IsVoid()) {
 | 
						|
      newBuf->lpvBuffer = moz_xmalloc(ipcBuf.mBuffer.Length());
 | 
						|
      memcpy(newBuf->lpvBuffer, ipcBuf.mBuffer.Data(),
 | 
						|
             ipcBuf.mBuffer.Length());
 | 
						|
      newBuf->dwBufferLength = ipcBuf.mBuffer.Length();
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/* static */ void
 | 
						|
IPCInternetBuffers::FreeBuffers(LPINTERNET_BUFFERSA& aBufs)
 | 
						|
{
 | 
						|
  if (!aBufs) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  while (aBufs) {
 | 
						|
    LPINTERNET_BUFFERSA temp = aBufs->Next;
 | 
						|
    free(const_cast<char*>(aBufs->lpcszHeader));
 | 
						|
    free(aBufs->lpvBuffer);
 | 
						|
    free(aBufs);
 | 
						|
    aBufs = temp;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
IPCPrintDlg::CopyFrom(const LPPRINTDLGW& aDlg)
 | 
						|
{
 | 
						|
  // DLP: Trouble -- my prior impl "worked" but didn't return anything
 | 
						|
  // AFAIR.  So... ???  But it printed a page!!!  How?!
 | 
						|
  MOZ_ASSERT_UNREACHABLE("TODO: DLP:");
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
IPCPrintDlg::CopyTo(LPPRINTDLGW& aDlg) const
 | 
						|
{
 | 
						|
  MOZ_ASSERT_UNREACHABLE("TODO: DLP:");
 | 
						|
}
 | 
						|
 | 
						|
} // namespace plugins
 | 
						|
} // namespace mozilla
 | 
						|
 | 
						|
#endif // defined(XP_WIN)
 |