ChipMaster's trial hacks on C++CMS starting with v1.2.1. Not sure I'll follow on with the v2 since it looks to be breaking and mostly frivolous.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

130 lines
2.9 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
  4. //
  5. // See accompanying file COPYING.TXT file for licensing details.
  6. //
  7. ///////////////////////////////////////////////////////////////////////////////
  8. #define CPPCMS_SOURCE
  9. #include <cppcms/urandom.h>
  10. #include <cppcms/cppcms_error.h>
  11. #ifdef CPPCMS_WIN_NATIVE
  12. #include <sstream>
  13. #include <booster/thread.h>
  14. #ifndef NOMINMAX
  15. #define NOMINMAX
  16. #endif
  17. #include "windows.h"
  18. #include "wincrypt.h"
  19. namespace cppcms {
  20. class urandom_device_impl {
  21. public:
  22. urandom_device_impl() {
  23. if(CryptAcquireContext(&provider_,0,0,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT))
  24. return;
  25. if(GetLastError() == (DWORD)(NTE_BAD_KEYSET)) {
  26. if(CryptAcquireContext(&provider_,0,0,PROV_RSA_FULL,CRYPT_NEWKEYSET))
  27. return;
  28. }
  29. std::ostringstream ss;
  30. ss<<"CryptAcquireContext failed with code 0x"<<std::hex<<GetLastError();
  31. throw cppcms_error(ss.str());
  32. }
  33. ~urandom_device_impl()
  34. {
  35. CryptReleaseContext(provider_,0);
  36. }
  37. void generate(void *ptr,unsigned len)
  38. {
  39. if(CryptGenRandom(provider_,len,static_cast<BYTE *>(ptr)))
  40. return;
  41. std::ostringstream ss;
  42. ss<<"CryptGenRandom failed with code 0x"<<std::hex<<GetLastError();
  43. throw cppcms_error(ss.str());
  44. }
  45. private:
  46. HCRYPTPROV provider_;
  47. };
  48. booster::thread_specific_ptr<urandom_device_impl> urandom_device_impl_ptr;
  49. struct urandom_device::_data {};
  50. urandom_device::urandom_device()
  51. {
  52. }
  53. urandom_device::~urandom_device()
  54. {
  55. }
  56. void urandom_device::generate(void *ptr,unsigned len)
  57. {
  58. if(!urandom_device_impl_ptr.get())
  59. urandom_device_impl_ptr.reset(new urandom_device_impl());
  60. urandom_device_impl_ptr->generate(ptr,len);
  61. }
  62. } // cppcms
  63. #else
  64. #ifndef CPPCMS_WIN32
  65. #include "daemonize.h"
  66. #endif
  67. #include <sys/types.h>
  68. #include <sys/stat.h>
  69. #include <errno.h>
  70. #include <fcntl.h>
  71. #include <unistd.h>
  72. namespace cppcms {
  73. struct urandom_device::_data {};
  74. urandom_device::urandom_device()
  75. {
  76. }
  77. urandom_device::~urandom_device()
  78. {
  79. }
  80. void urandom_device::generate(void *ptr,unsigned len)
  81. {
  82. if(len == 0)
  83. return;
  84. int n = 0;
  85. #ifndef CPPCMS_WIN32
  86. if(impl::daemonizer::global_urandom_fd!=-1) {
  87. n = read(impl::daemonizer::global_urandom_fd,ptr,len);
  88. }
  89. else
  90. #endif
  91. {
  92. int fd = open("/dev/urandom",O_RDONLY);
  93. if(!fd)
  94. throw cppcms_error("Failed to open /dev/urandom");
  95. while(len > 0) {
  96. n = read(fd,ptr,len);
  97. if(n < 0 && errno == EINTR)
  98. continue;
  99. if(n <= 0)
  100. break;
  101. ptr = static_cast<char *>(ptr) + n;
  102. len -= n;
  103. }
  104. close(fd);
  105. }
  106. if(len > 0) {
  107. throw cppcms_error("Failed to read /dev/urandom");
  108. }
  109. }
  110. }
  111. #endif