/
zOMGdev
/
cppcms
Обзор
Документация
Войти
/
zOMGdev
/
cppcms
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/urandom.cpp
129 строк
3 KB
Artyom Beilis
Attempt to fix #43 failure to read from /dev/urandom
18 июл 2018, 19:59
18 июл 2018, 19:59
3e3cf43
Код
Авторство
О чём код?
/////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com> // // See accompanying file COPYING.TXT file for licensing details. // /////////////////////////////////////////////////////////////////////////////// #define CPPCMS_SOURCE #include <cppcms/urandom.h> #include <cppcms/cppcms_error.h> #ifdef CPPCMS_WIN_NATIVE #include <sstream> #include <booster/thread.h> #ifndef NOMINMAX #define NOMINMAX #endif #include "windows.h" #include "wincrypt.h" namespace cppcms { class urandom_device_impl { public: urandom_device_impl() { if(CryptAcquireContext(&provider_,0,0,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT)) return; if(GetLastError() == (DWORD)(NTE_BAD_KEYSET)) { if(CryptAcquireContext(&provider_,0,0,PROV_RSA_FULL,CRYPT_NEWKEYSET)) return; } std::ostringstream ss; ss<<"CryptAcquireContext failed with code 0x"<<std::hex<<GetLastError(); throw cppcms_error(ss.str()); } ~urandom_device_impl() { CryptReleaseContext(provider_,0); } void generate(void *ptr,unsigned len) { if(CryptGenRandom(provider_,len,static_cast<BYTE *>(ptr))) return; std::ostringstream ss; ss<<"CryptGenRandom failed with code 0x"<<std::hex<<GetLastError(); throw cppcms_error(ss.str()); } private: HCRYPTPROV provider_; }; booster::thread_specific_ptr<urandom_device_impl> urandom_device_impl_ptr; struct urandom_device::_data {}; urandom_device::urandom_device() { } urandom_device::~urandom_device() { } void urandom_device::generate(void *ptr,unsigned len) { if(!urandom_device_impl_ptr.get()) urandom_device_impl_ptr.reset(new urandom_device_impl()); urandom_device_impl_ptr->generate(ptr,len); } } // cppcms #else #ifndef CPPCMS_WIN32 #include "daemonize.h" #endif #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #include <fcntl.h> #include <unistd.h> namespace cppcms { struct urandom_device::_data {}; urandom_device::urandom_device() { } urandom_device::~urandom_device() { } void urandom_device::generate(void *ptr,unsigned len) { if(len == 0) return; int n = 0; #ifndef CPPCMS_WIN32 if(impl::daemonizer::global_urandom_fd!=-1) { n = read(impl::daemonizer::global_urandom_fd,ptr,len); } else #endif { int fd = open("/dev/urandom",O_RDONLY); if(!fd) throw cppcms_error("Failed to open /dev/urandom"); while(len > 0) { n = read(fd,ptr,len); if(n < 0 && errno == EINTR) continue; if(n <= 0) break; ptr = static_cast<char *>(ptr) + n; len -= n; } close(fd); } if(len > 0) { throw cppcms_error("Failed to read /dev/urandom"); } } } #endif