00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00039 #include "blocxx/BLOCXX_config.h"
00040
00041 #ifdef BLOCXX_HAVE_OPENSSL
00042
00043
00044
00045
00046 #include "blocxx/Array.hpp"
00047 #include "blocxx/Assertion.hpp"
00048 #include "blocxx/Exec.hpp"
00049 #include "blocxx/FileSystem.hpp"
00050 #include "blocxx/Mutex.hpp"
00051 #include "blocxx/MutexLock.hpp"
00052 #include "blocxx/GlobalMutex.hpp"
00053 #include "blocxx/Secure.hpp"
00054 #include "blocxx/SecureRand.hpp"
00055 #include "blocxx/SSLCtxMgr.hpp"
00056 #include "blocxx/String.hpp"
00057 #include "blocxx/Thread.hpp"
00058 #include "blocxx/ThreadOnce.hpp"
00059 #include "blocxx/UnnamedPipe.hpp"
00060 #include "blocxx/UserUtils.hpp"
00061 #include "blocxx/Process.hpp"
00062
00063 #include <cmath>
00064 #include <csignal>
00065 #include <cstring>
00066 #include <limits>
00067 #ifdef BLOCXX_HAVE_UNISTD_H
00068 #include <unistd.h>
00069 #endif
00070
00071 #include <fcntl.h>
00072 #include <openssl/rand.h>
00073 #include <openssl/err.h>
00074 #ifdef BLOCXX_HAVE_SYS_RESOURCE_H
00075 #include <sys/resource.h>
00076 #endif
00077 #ifndef BLOCXX_WIN32
00078 #include <sys/time.h>
00079 #endif
00080
00081 #ifdef BLOCXX_WIN32
00082 #include <wincrypt.h>
00083 #endif
00084
00085 using namespace blocxx;
00086
00087 namespace
00088 {
00089 unsigned const RESEED_BYTES = 16;
00090 unsigned const SEED_BYTES = 16;
00091
00092 template <typename T> struct unsigned_equivalent
00093 {
00094 typedef T type;
00095 };
00096
00097 template <> struct unsigned_equivalent<char>
00098 {
00099 typedef unsigned char type;
00100 };
00101
00102 template <> struct unsigned_equivalent<signed char>
00103 {
00104 typedef unsigned char type;
00105 };
00106
00107 template <> struct unsigned_equivalent<short>
00108 {
00109 typedef unsigned short type;
00110 };
00111
00112 template <> struct unsigned_equivalent<int>
00113 {
00114 typedef unsigned int type;
00115 };
00116
00117 template <> struct unsigned_equivalent<long>
00118 {
00119 typedef unsigned long type;
00120 };
00121
00122 template <> struct unsigned_equivalent<long long>
00123 {
00124 typedef unsigned long long type;
00125 };
00126
00127 blocxx::OnceFlag guard = BLOCXX_ONCE_INIT;
00128
00129 void rand_init_impl();
00130 }
00131
00132 namespace BLOCXX_NAMESPACE
00133 {
00134 BLOCXX_DEFINE_EXCEPTION(SecureRand);
00135
00136 namespace Secure
00137 {
00138 void rand_init()
00139 {
00140 callOnce(guard, &rand_init_impl);
00141 }
00142
00143 unsigned char * rand(unsigned char * buf, std::size_t n)
00144 {
00145 callOnce(guard, &rand_init_impl);
00146 ERR_clear_error();
00147 if (!RAND_bytes(buf, n))
00148 {
00149 BLOCXX_THROW(SecureRandException,
00150 SSLCtxMgr::getOpenSSLErrorDescription().c_str());
00151 }
00152 return buf;
00153 }
00154
00155 ::pid_t fork_reseed()
00156 {
00157 #ifdef BLOCXX_WIN32
00158 #pragma message(Reminder "TODO: implement it for Win!")
00159
00160 return BLOCXX_INVALID_HANDLE;
00161 #else
00162 unsigned char seed[2][RESEED_BYTES];
00163 rand(seed[0], sizeof(seed[0]));
00164 rand(seed[1], sizeof(seed[1]));
00165
00166 ::pid_t rv = ::fork();
00167 if (rv < 0)
00168 {
00169 return rv;
00170 }
00171
00172 std::size_t idx = rv > 0;
00173 RAND_seed(seed[idx], sizeof(seed[idx]));
00174
00175 std::memset(seed[1 - idx], 0, sizeof(seed[1- idx]));
00176
00177 return rv;
00178 #endif
00179 }
00180
00181 namespace Impl
00182 {
00183 template <typename UnsignedInt>
00184 UnsignedInt rand_uint_lt(UnsignedInt n)
00185 {
00186 BLOCXX_ASSERT(n > 0);
00187 if ((n & (n - 1)) == 0)
00188 {
00189 return rand_uint<UnsignedInt>() % n;
00190 }
00191 UnsignedInt const uint_max = static_cast<UnsignedInt>(-1);
00192 UnsignedInt const bound = uint_max - (uint_max % n);
00193 UnsignedInt rn;
00194 do
00195 {
00196 rn = rand_uint<UnsignedInt>();
00197 } while (rn >= bound);
00198 return rn % n;
00199 }
00200
00201
00202 template unsigned char
00203 BLOCXX_COMMON_API rand_uint_lt<unsigned char>(unsigned char);
00204 template unsigned short
00205 BLOCXX_COMMON_API rand_uint_lt<unsigned short>(unsigned short);
00206 template unsigned int
00207 BLOCXX_COMMON_API rand_uint_lt<unsigned int>(unsigned int);
00208 template unsigned long
00209 BLOCXX_COMMON_API rand_uint_lt<unsigned long>(unsigned long);
00210 template unsigned long long
00211 BLOCXX_COMMON_API rand_uint_lt<unsigned long long>(unsigned long long);
00212
00213 template <typename Integer>
00214 Integer rand_range(Integer min_value, Integer max_value)
00215 {
00216 BLOCXX_ASSERT(max_value >= min_value);
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 typedef typename unsigned_equivalent<Integer>::type UnsignedInt;
00227 UnsignedInt const umax = static_cast<UnsignedInt>(max_value);
00228 UnsignedInt const umin = static_cast<UnsignedInt>(min_value);
00229 UnsignedInt const diff = umax - umin;
00230
00231
00232
00233
00234
00235 UnsignedInt const range = diff + static_cast<UnsignedInt>(1);
00236
00237
00238
00239
00240
00241
00242
00243 UnsignedInt rv;
00244 if (range == 0)
00245 {
00246
00247
00248
00249 rv = rand_uint<UnsignedInt>();
00250 }
00251 else
00252 {
00253
00254
00255
00256 rv = umin + rand_uint_lt(range);
00257 }
00258 return static_cast<Integer>(rv);
00259 }
00260
00261
00262 template char
00263 BLOCXX_COMMON_API rand_range(char, char);
00264 template signed char
00265 BLOCXX_COMMON_API rand_range(signed char, signed char);
00266 template unsigned char
00267 BLOCXX_COMMON_API rand_range(unsigned char, unsigned char);
00268 template short
00269 BLOCXX_COMMON_API rand_range(short, short);
00270 template unsigned short
00271 BLOCXX_COMMON_API rand_range(unsigned short, unsigned short);
00272 template int
00273 BLOCXX_COMMON_API rand_range(int, int);
00274 template unsigned int
00275 BLOCXX_COMMON_API rand_range(unsigned int, unsigned int);
00276 template long
00277 BLOCXX_COMMON_API rand_range(long, long);
00278 template unsigned long
00279 BLOCXX_COMMON_API rand_range(unsigned long, unsigned long);
00280 template long long
00281 BLOCXX_COMMON_API rand_range(long long, long long);
00282 template unsigned long long
00283 BLOCXX_COMMON_API rand_range(unsigned long long, unsigned long long);
00284
00285 template <unsigned int N>
00286 struct log2
00287 {
00288 enum { value = 1 + log2<N/2>::value };
00289 };
00290
00291 template <>
00292 struct log2<1>
00293 {
00294 enum { value = 0 };
00295 };
00296
00297
00298 template <typename Number>
00299 struct bits_precision
00300 {
00301 typedef std::numeric_limits<Number> lim_t;
00302 enum { value = lim_t::digits * log2<lim_t::radix>::value };
00303 };
00304
00305 template <typename Real>
00306 Real rand_unit_interval()
00307 {
00308 typedef UInt32 uint_t;
00309 int const UINT_BITS = 32;
00310 int const NUINT =
00311 (bits_precision<Real>::value + UINT_BITS - 1) / UINT_BITS;
00312 Real rv = 0.0;
00313 for (int i = 1; i <= NUINT; ++i)
00314 {
00315 Real r = static_cast<Real>(rand_uint<uint_t>());
00316 rv += std::ldexp(r, -UINT_BITS * i);
00317 }
00318 return rv;
00319 }
00320
00321
00322 template float rand_unit_interval<float>();
00323 template double rand_unit_interval<double>();
00324 template long double rand_unit_interval<long double>();
00325
00326 }
00327
00328 void rand_save_state()
00329 {
00330 char randFile[MAXPATHLEN];
00331 char const * rval = RAND_file_name(randFile, MAXPATHLEN);
00332 if (rval)
00333 {
00334
00335
00336 using namespace FileSystem::Path;
00337 if (security(dirname(randFile)).first == E_SECURE_DIR)
00338 {
00339 if (RAND_write_file(randFile) <= 0)
00340 {
00341
00342
00343
00344 FileSystem::removeFile(randFile);
00345 }
00346 }
00347 }
00348
00349 }
00350
00351 }
00352 }
00353
00354 namespace
00355 {
00356
00357
00358
00359 volatile sig_atomic_t g_counter;
00360 volatile unsigned char* g_data;
00361 volatile sig_atomic_t g_dataIdx;
00362 int g_dataSize;
00363 }
00364
00365 extern "C"
00366 {
00367
00368
00369 #ifdef BLOCXX_NCR
00370 static void randomALRMHandler()
00371 #else
00372 static void randomALRMHandler(int sig)
00373 #endif
00374 {
00375 if (g_dataIdx < g_dataSize)
00376 {
00377 g_data[g_dataIdx++] ^= g_counter & 0xFF;
00378 }
00379 }
00380 }
00381
00382 namespace
00383 {
00384 GlobalMutex g_randomTimerGuard = BLOCXX_GLOBAL_MUTEX_INIT();
00385
00386 #ifndef BLOCXX_WIN32
00387
00388
00389 void generateRandomTimerData(unsigned char* data, int size, int* iterations)
00390 {
00391 BLOCXX_ASSERT(data != 0);
00392 BLOCXX_ASSERT(size > 0);
00393 BLOCXX_ASSERT(iterations != 0);
00394
00395
00396 MutexLock l(g_randomTimerGuard);
00397
00398
00399 g_data = data;
00400 g_dataSize = size;
00401 g_dataIdx = 0;
00402
00403
00404 struct sigaction sa, osa;
00405 sa.sa_handler = randomALRMHandler;
00406 sa.sa_flags = 0;
00407 sigemptyset(&sa.sa_mask);
00408 sigaction(SIGALRM, &sa, &osa);
00409
00410
00411 struct ::itimerval tv, otv;
00412 tv.it_value.tv_sec = 0;
00413 tv.it_value.tv_usec = 10 * 1000;
00414 tv.it_interval = tv.it_value;
00415 setitimer(ITIMER_REAL, &tv, &otv);
00416
00417 while ((*iterations)-- > 0)
00418 {
00419
00420 for (g_dataIdx = 0; g_dataIdx < g_dataSize;)
00421 {
00422 ++g_counter;
00423 }
00424
00425
00426 for (int j = 0; j < g_dataSize; j++)
00427 {
00428 g_data[j] = (g_data[j]>>3) | (g_data[j]<<5);
00429 }
00430 }
00431 setitimer(ITIMER_REAL, &otv, 0);
00432
00433
00434 sigaction(SIGALRM, &osa, 0);
00435
00436 }
00437
00438 void generateRandomDataFromFile(const char* name, int len)
00439 {
00440 int fd = ::open(name, O_RDONLY);
00441 if (fd == -1)
00442 {
00443 return;
00444 }
00445
00446 std::vector<char> buf(len);
00447 int bytesRead = ::read(fd, &buf[0], len);
00448 if (bytesRead == -1)
00449 {
00450 return;
00451 }
00452 buf.resize(bytesRead);
00453 ::RAND_add(&buf[0], buf.size(), 0.0);
00454
00455 }
00456
00457 void generateRandomDataFromTime(double entropy)
00458 {
00459 struct timeval tv;
00460 ::gettimeofday(&tv, 0);
00461 ::RAND_add(&tv, sizeof(tv), entropy);
00462
00463 clock_t c(::clock());
00464 ::RAND_add(&c, sizeof(c), entropy);
00465
00466 struct rusage ru;
00467 ::getrusage(RUSAGE_SELF, &ru);
00468 ::RAND_add(&ru, sizeof(ru), entropy);
00469
00470 ::getrusage(RUSAGE_CHILDREN, &ru);
00471 ::RAND_add(&ru, sizeof(ru), entropy);
00472 }
00473
00474 struct cmd
00475 {
00476 const char* command;
00477
00478
00479 double usefulness;
00480 };
00481
00482
00483 const cmd randomSourceCommands[] =
00484 {
00485 { "advfsstat -b usr_domain", 0.01 },
00486 { "advfsstat -l 2 usr_domain", 0.5 },
00487 { "advfsstat -p usr_domain", 0.01 },
00488 { "arp -a -n", 0.5 },
00489 { "df", 0.5 },
00490 { "df -i", 0.5 },
00491 { "df -a", 0.5 },
00492 { "df -in", 0.5 },
00493 { "dmesg", 0.5 },
00494 { "errpt -a", 0.5 },
00495 { "ifconfig -a", 0.5 },
00496 { "iostat", 0.5 },
00497 { "ipcs -a", 0.5 },
00498 { "last", 0.5 },
00499 { "lastlog", 0.5 },
00500 { "lpstat -t", 0.1 },
00501 { "ls -alniR /var/log", 1.0 },
00502 { "ls -alniR /var/adm", 1.0 },
00503 { "ls -alni /var/spool/mail", 1.0 },
00504 { "ls -alni /proc", 1.0 },
00505 { "ls -alniR /tmp", 1.0 },
00506 { "ls -alniR /var/tmp", 1.0 },
00507 { "ls -alni /var/mail", 1.0 },
00508 { "ls -alniR /var/db", 1.0 },
00509 { "ls -alniR /etc", 1.0 },
00510 { "ls -alniR /private/var/log", 1.0 },
00511 { "ls -alniR /private/var/db", 1.0 },
00512 { "ls -alniR /private/etc", 1.0 },
00513 { "ls -alniR /private/tmp", 1.0 },
00514 { "ls -alniR /private/var/tmp", 1.0 },
00515 { "mpstat", 1.5 },
00516 { "netstat -s", 1.5 },
00517 { "netstat -n", 1.5 },
00518 { "netstat -a -n", 1.5 },
00519 { "netstat -anv", 1.5 },
00520 { "netstat -i -n", 0.5 },
00521 { "netstat -r -n", 0.1 },
00522 { "netstat -m", 0.5 },
00523 { "netstat -ms", 0.5 },
00524 { "nfsstat", 0.5 },
00525 { "ps laxww", 1.5 },
00526 { "ps -laxww", 1.5 },
00527 { "ps -al", 1.5 },
00528 { "ps -el", 1.5 },
00529 { "ps -efl", 1.5 },
00530 { "ps -efly", 1.5 },
00531 { "ps aux", 1.5 },
00532 { "ps -A", 1.5 },
00533 { "pfstat", 0.5 },
00534 { "portstat", 0.5 },
00535 { "pstat -p", 0.5 },
00536 { "pstat -S", 0.5 },
00537 { "pstat -A", 0.5 },
00538 { "pstat -t", 0.5 },
00539 { "pstat -v", 0.5 },
00540 { "pstat -x", 0.5 },
00541 { "pstat -t", 0.5 },
00542 { "ripquery -nw 1 127.0.0.1", 0.5 },
00543 { "sar -A 1 1", 0.5 },
00544 { "snmp_request localhost public get 1.3.6.1.2.1.7.1.0", 0.5 },
00545 { "snmp_request localhost public get 1.3.6.1.2.1.7.4.0", 0.5 },
00546 { "snmp_request localhost public get 1.3.6.1.2.1.4.3.0", 0.5 },
00547 { "snmp_request localhost public get 1.3.6.1.2.1.6.10.0", 0.5 },
00548 { "snmp_request localhost public get 1.3.6.1.2.1.6.11.0", 0.5 },
00549 { "snmp_request localhost public get 1.3.6.1.2.1.6.13.0", 0.5 },
00550 { "snmp_request localhost public get 1.3.6.1.2.1.5.1.0", 0.5 },
00551 { "snmp_request localhost public get 1.3.6.1.2.1.5.3.0", 0.5 },
00552 { "tail -c 1024 /var/log/messages", 1.0 },
00553 { "tail -c 1024 /var/log/syslog", 1.0 },
00554 { "tail -c 1024 /var/log/system.log", 1.0 },
00555 { "tail -c 1024 /var/log/debug", 1.0 },
00556 { "tail -c 1024 /var/adm/messages", 1.0 },
00557 { "tail -c 1024 /var/adm/syslog", 1.0 },
00558 { "tail -c 1024 /var/adm/syslog/mail.log", 1.0 },
00559 { "tail -c 1024 /var/adm/syslog/syslog.log", 1.0 },
00560 { "tail -c 1024 /var/log/maillog", 1.0 },
00561 { "tail -c 1024 /var/adm/maillog", 1.0 },
00562 { "tail -c 1024 /var/adm/SPlogs/SPdaemon.log", 1.0 },
00563 { "tail -c 1024 /usr/es/adm/cluster.log", 1.0 },
00564 { "tail -c 1024 /usr/adm/cluster.log", 1.0 },
00565 { "tail -c 1024 /var/adm/cluster.log", 1.0 },
00566 { "tail -c 1024 /var/adm/ras/conslog", 1.0 },
00567 { "tcpdump -c 100 -efvvx", 1 },
00568 { "uptime", 0.5 },
00569 { "vmstat", 2.0 },
00570 { "vmstat -c", 2.0 },
00571 { "vmstat -s", 2.0 },
00572 { "vmstat -i", 2.0 },
00573 { "vmstat -f", 2.0 },
00574 { "w", 2.5 },
00575 { "who -u", 0.5 },
00576 { "who -i", 0.5 },
00577 { "who -a", 0.5 },
00578
00579 { 0, 0 }
00580 };
00581
00582 class RandomOutputGatherer : public Exec::OutputCallback
00583 {
00584 private:
00585 virtual void doHandleData(
00586 const char* data, size_t dataLen, Exec::EOutputSource outputSource,
00587 const ProcessRef& theProc, size_t streamIndex,
00588 Array<char>& inputBuffer
00589 )
00590 {
00591 if (outputSource == Exec::E_STDERR)
00592 {
00593
00594
00595 ::RAND_add(data, dataLen, 0.0);
00596 }
00597 else
00598 {
00599
00600
00601 ::RAND_add(
00602 data, dataLen,
00603 randomSourceCommands[streamIndex].usefulness *
00604 static_cast<double>(dataLen) / 1024.0
00605 );
00606 }
00607
00608
00609 ::RAND_add(&dataLen, sizeof(dataLen), 0.0);
00610 ::RAND_add(&outputSource, sizeof(outputSource), 0.0);
00611
00612 generateRandomDataFromTime(0.1);
00613 }
00614
00615 };
00616
00617 class RandomInputCallback : public Exec::InputCallback
00618 {
00619 private:
00620 virtual void doGetData(
00621 Array<char>& inputBuffer, const ProcessRef& theProcess,
00622 size_t streamIndex
00623 )
00624 {
00625
00626 if (theProcess->in()->isOpen())
00627 {
00628 theProcess->in()->close();
00629 }
00630 }
00631 };
00632
00633 String locateInPath(const String& cmd, const String& path)
00634 {
00635 StringArray pathElements(path.tokenize(":"));
00636 for (size_t i = 0; i < pathElements.size(); ++i)
00637 {
00638 String testCmd(pathElements[i] + '/' + cmd);
00639 if (FileSystem::exists(testCmd))
00640 {
00641 return testCmd;
00642 }
00643 }
00644 return cmd;
00645 }
00646
00647 class RandomTimerThread : public Thread
00648 {
00649 virtual Int32 run()
00650 {
00651
00652
00653 unsigned char buf[256];
00654 int iterations = 8;
00655 generateRandomTimerData(buf, sizeof(buf), &iterations);
00656 ::RAND_add(buf, sizeof(buf), 32);
00657
00658
00659
00660 generateRandomDataFromTime(0.1);
00661
00662 return 0;
00663 }
00664 };
00665 #endif
00666
00667 void rand_init_impl()
00668 {
00669 #ifdef BLOCXX_WIN32
00670
00671
00672
00673 HCRYPTPROV hProvider = 0;
00674 BYTE buf[64];
00675
00676 if (CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL,
00677 CRYPT_VERIFYCONTEXT))
00678 {
00679 if (CryptGenRandom(hProvider, sizeof(buf), buf))
00680 {
00681 RAND_add(buf, sizeof(buf), sizeof(buf));
00682 }
00683 CryptReleaseContext(hProvider, 0);
00684 }
00685
00686
00687 ::RAND_screen();
00688 #endif
00689
00690
00691 RAND_egd(BLOCXX_DEFAULT_STATE_DIR"/egd-pool");
00692
00693
00694
00695 if (::RAND_status() == 1)
00696 {
00697 return;
00698 }
00699
00700 #ifndef BLOCXX_WIN32
00701
00702
00703 if (::SSLeay() < 0x00907000L)
00704 {
00705
00706 int loadedBytes = RAND_load_file("/dev/random", 1024);
00707 if (loadedBytes == 0)
00708 {
00709
00710 RAND_load_file("/dev/urandom", 1024);
00711 }
00712
00713 if (RAND_status() == 1)
00714 {
00715 return;
00716 }
00717
00718
00719 const char *names[] =
00720 {
00721 "/var/run/egd-pool",
00722 "/dev/egd-pool",
00723 "/etc/egd-pool",
00724 "/etc/entropy",
00725 NULL
00726 };
00727
00728 for (int i = 0; names[i]; i++)
00729 {
00730 if (RAND_egd(names[i]) != -1)
00731 {
00732 break;
00733 }
00734 }
00735
00736 if (RAND_status() == 1)
00737 {
00738 return;
00739 }
00740 }
00741
00742
00743 char randFile[MAXPATHLEN];
00744 const char* rval = ::RAND_file_name(randFile, MAXPATHLEN);
00745 if (rval)
00746 {
00747 using namespace FileSystem::Path;
00748 try
00749 {
00750 if (security(randFile).first == E_SECURE_FILE)
00751 {
00752 ::RAND_load_file(randFile, -1);
00753 }
00754 }
00755 catch (FileSystemException& e)
00756 {
00757
00758 }
00759 }
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779 generateRandomDataFromTime(0.0);
00780
00781 RandomTimerThread randomTimerThread;
00782 randomTimerThread.start();
00783
00784
00785 const char* files[] = { "/dev/mem", 0 };
00786 for (const char** p = files; *p; ++p)
00787 {
00788 generateRandomDataFromFile(*p, 1024*1024*2);
00789 }
00790
00791 generateRandomDataFromTime(0.1);
00792
00793 pid_t myPid(::getpid());
00794 ::RAND_add(&myPid, sizeof(myPid), 0.0);
00795
00796 pid_t parentPid(::getppid());
00797 ::RAND_add(&parentPid, sizeof(parentPid), 0.0);
00798
00799 uid_t myUid(::getuid());
00800 ::RAND_add(&myUid, sizeof(myUid), 0.0);
00801
00802 gid_t myGid(::getgid());
00803 ::RAND_add(&myGid, sizeof(myGid), 0.0);
00804
00805
00806 Array<ProcessRef> procs;
00807 for (size_t i = 0; randomSourceCommands[i].command != 0; ++i)
00808 {
00809 StringArray cmd = String(randomSourceCommands[i].command).tokenize();
00810 if( cmd.empty() )
00811 {
00812
00813 continue;
00814 }
00815
00816 if (cmd[0][0] != '/')
00817 {
00818 const char * RANDOM_COMMAND_PATH =
00819 "/bin:/sbin:/usr/bin:/usr/sbin:/usr/ucb:/usr/etc:/usr/bsd:"
00820 "/etc:/usr/local/bin:/usr/local/sbin";
00821
00822
00823 String locatedCmd = locateInPath(cmd[0], RANDOM_COMMAND_PATH);
00824 if( locatedCmd == cmd[0] )
00825 {
00826
00827 continue;
00828 }
00829
00830 try
00831 {
00832 using namespace FileSystem::Path;
00833 if (security(locatedCmd).first != E_SECURE_FILE)
00834 {
00835
00836 continue;
00837 }
00838 }
00839 catch (FileSystemException& e)
00840 {
00841
00842 continue;
00843 }
00844
00845 cmd[0] = locatedCmd;
00846 }
00847 try
00848 {
00849
00850
00851 procs.push_back(Exec::spawn(cmd));
00852 }
00853 catch(const ExecErrorException& e)
00854 {
00855
00856 }
00857 }
00858
00859 RandomOutputGatherer randomOutputGatherer;
00860 RandomInputCallback randomInputCallback;
00861 const Timeout RANDOM_COMMAND_TIMEOUT = Timeout::relative(10.0);
00862 try
00863 {
00864 Exec::processInputOutput(
00865 randomOutputGatherer, procs,
00866 randomInputCallback, RANDOM_COMMAND_TIMEOUT
00867 );
00868 }
00869 catch (ExecTimeoutException&)
00870 {
00871
00872 }
00873
00874
00875 for (size_t i = 0; i < procs.size(); ++i)
00876 {
00877 procs[i]->waitCloseTerm(Timeout::relative(0.001), Timeout::relative(0.002), Timeout::relative(0.003));
00878 Process::Status status = procs[i]->processStatus();
00879 if (!status.terminatedSuccessfully())
00880 {
00881 int rv = status.exitStatus();
00882 ::RAND_add(&rv, sizeof(rv), 0.0);
00883 }
00884 }
00885
00886 randomTimerThread.join();
00887
00888 generateRandomDataFromTime(0.1);
00889 #endif
00890 }
00891
00892 }
00893 #endif // #ifdef BLOCXX_HAVE_OPENSSL