| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 | #include "rar.hpp"/*	// OPENMPT ADDITION#if defined(_WIN_ALL)typedef BOOL (WINAPI *CRYPTPROTECTMEMORY)(LPVOID pData,DWORD cbData,DWORD dwFlags);typedef BOOL (WINAPI *CRYPTUNPROTECTMEMORY)(LPVOID pData,DWORD cbData,DWORD dwFlags);#ifndef CRYPTPROTECTMEMORY_BLOCK_SIZE#define CRYPTPROTECTMEMORY_BLOCK_SIZE           16#define CRYPTPROTECTMEMORY_SAME_PROCESS         0x00#define CRYPTPROTECTMEMORY_CROSS_PROCESS        0x01#endifclass CryptLoader{  private:    HMODULE hCrypt;    bool LoadCalled;  public:    CryptLoader()     {      hCrypt=NULL;      pCryptProtectMemory=NULL;      pCryptUnprotectMemory=NULL;      LoadCalled=false;    }    ~CryptLoader()    {      if (hCrypt!=NULL)        FreeLibrary(hCrypt);      hCrypt=NULL;      pCryptProtectMemory=NULL;      pCryptUnprotectMemory=NULL;    };    void Load()    {      if (!LoadCalled)      {        hCrypt = LoadSysLibrary(L"Crypt32.dll");        if (hCrypt != NULL)        {          // Available since Vista.          pCryptProtectMemory = (CRYPTPROTECTMEMORY)GetProcAddress(hCrypt, "CryptProtectMemory");          pCryptUnprotectMemory = (CRYPTUNPROTECTMEMORY)GetProcAddress(hCrypt, "CryptUnprotectMemory");        }        LoadCalled=true;      }    }    CRYPTPROTECTMEMORY pCryptProtectMemory;    CRYPTUNPROTECTMEMORY pCryptUnprotectMemory;};// We need to call FreeLibrary when RAR is exiting.static CryptLoader GlobalCryptLoader;#endif*/	// OPENMPT ADDITIONSecPassword::SecPassword(){  return;	// OPENMPT ADDITION  CrossProcess=false;  Set(L"");}SecPassword::~SecPassword(){  return;	// OPENMPT ADDITION  Clean();}void SecPassword::Clean(){  return;	// OPENMPT ADDITION  PasswordSet=false;  cleandata(Password,sizeof(Password));} // When we call memset in end of function to clean local variables// for security reason, compiler optimizer can remove such call.// So we use our own function for this purpose.void cleandata(void *data,size_t size){  return;	// OPENMPT ADDITION  if (data==NULL || size==0)    return;#if defined(_WIN_ALL) && defined(_MSC_VER)  SecureZeroMemory(data,size);#else  // 'volatile' is required. Otherwise optimizers can remove this function  // if cleaning local variables, which are not used after that.  volatile byte *d = (volatile byte *)data;  for (size_t i=0;i<size;i++)    d[i]=0;#endif}// We got a complain from user that it is possible to create WinRAR dump// with "Create dump file" command in Windows Task Manager and then easily// locate Unicode password string in the dump. It is unsecure if several// people share the same computer and somebody left WinRAR copy with entered// password. So we decided to obfuscate the password to make it more difficult// to find it in dump.void SecPassword::Process(const wchar *Src,size_t SrcSize,wchar *Dst,size_t DstSize,bool Encode){  return;	// OPENMPT ADDITION  // Source string can be shorter than destination as in case when we process  // -p<pwd> parameter, so we need to take into account both sizes.  memcpy(Dst,Src,Min(SrcSize,DstSize)*sizeof(*Dst));  SecHideData(Dst,DstSize*sizeof(*Dst),Encode,CrossProcess);}void SecPassword::Get(wchar *Psw,size_t MaxSize){  return;	// OPENMPT ADDITION  if (PasswordSet)  {    Process(Password,ASIZE(Password),Psw,MaxSize,false);    Psw[MaxSize-1]=0;  }  else    *Psw=0;}void SecPassword::Set(const wchar *Psw){  return;	// OPENMPT ADDITION  if (*Psw==0)  {    PasswordSet=false;    memset(Password,0,sizeof(Password));  }  else  {    PasswordSet=true;    Process(Psw,wcslen(Psw)+1,Password,ASIZE(Password),true);  }}size_t SecPassword::Length(){  return 0;	// OPENMPT ADDITION  wchar Plain[MAXPASSWORD];  Get(Plain,ASIZE(Plain));  size_t Length=wcslen(Plain);  cleandata(Plain,ASIZE(Plain));  return Length;}bool SecPassword::operator == (SecPassword &psw){  return false;	// OPENMPT ADDITION  // We cannot compare encoded data directly, because there is no guarantee  // than encryption function will always produce the same result for same  // data (salt?) and because we do not clean the rest of password buffer  // after trailing zero before encoding password. So we decode first.  wchar Plain1[MAXPASSWORD],Plain2[MAXPASSWORD];  Get(Plain1,ASIZE(Plain1));  psw.Get(Plain2,ASIZE(Plain2));  bool Result=wcscmp(Plain1,Plain2)==0;  cleandata(Plain1,ASIZE(Plain1));  cleandata(Plain2,ASIZE(Plain2));  return Result;}void SecHideData(void *Data,size_t DataSize,bool Encode,bool CrossProcess){  /*	// OPENMPT ADDITION  // CryptProtectMemory is not available in UWP and CryptProtectData  // increases data size not allowing in place conversion.#if defined(_WIN_ALL)  // Try to utilize the secure Crypt[Un]ProtectMemory if possible.  if (GlobalCryptLoader.pCryptProtectMemory==NULL)    GlobalCryptLoader.Load();  size_t Aligned=DataSize-DataSize%CRYPTPROTECTMEMORY_BLOCK_SIZE;  DWORD Flags=CrossProcess ? CRYPTPROTECTMEMORY_CROSS_PROCESS : CRYPTPROTECTMEMORY_SAME_PROCESS;  if (Encode)  {    if (GlobalCryptLoader.pCryptProtectMemory!=NULL)    {      if (!GlobalCryptLoader.pCryptProtectMemory(Data,DWORD(Aligned),Flags))      {        ErrHandler.GeneralErrMsg(L"CryptProtectMemory failed");        ErrHandler.SysErrMsg();        ErrHandler.Exit(RARX_FATAL);      }      return;    }  }  else  {    if (GlobalCryptLoader.pCryptUnprotectMemory!=NULL)    {      if (!GlobalCryptLoader.pCryptUnprotectMemory(Data,DWORD(Aligned),Flags))      {        ErrHandler.GeneralErrMsg(L"CryptUnprotectMemory failed");        ErrHandler.SysErrMsg();        ErrHandler.Exit(RARX_FATAL);      }      return;    }  }#endif    // CryptProtectMemory is not available, so only slightly obfuscate data.  uint Key;#ifdef _WIN_ALL  Key=GetCurrentProcessId();#elif defined(_UNIX)  Key=getpid();#else  Key=0; // Just an arbitrary value.#endif  for (size_t I=0;I<DataSize;I++)    *((byte *)Data+I)^=Key+I+75;  */	// OPENMPT ADDITION}
 |