33// Distributed under the MIT software license, see the accompanying
44// file COPYING or http://www.opensource.org/licenses/mit-license.php.
55
6+ #if defined(HAVE_CONFIG_H)
7+ #include " config/pivx-config.h"
8+ #endif
9+
610#include " randomenv.h"
711
12+ #include " clientversion.h"
813#include " crypto/sha512.h"
914#include " support/cleanse.h"
1015#include " utiltime.h" // for GetTime()
1419
1520#include < algorithm>
1621#include < chrono>
22+ #include < climits>
1723#include < thread>
1824#include < vector>
1925
2026#include < stdint.h>
2127#include < string.h>
2228#ifndef WIN32
29+ #include < sys/types.h> // must go before a number of other headers
30+ #include < fcntl.h>
31+ #include < netinet/in.h>
32+ #include < sys/resource.h>
33+ #include < sys/socket.h>
34+ #include < sys/stat.h>
2335#include < sys/time.h>
24- #include < sys/types .h>
36+ #include < sys/utsname .h>
2537#include < unistd.h>
2638#endif
2739#ifdef __MACH__
2840#include < mach/clock.h>
2941#include < mach/mach.h>
3042#include < mach/mach_time.h>
3143#endif
44+ #if HAVE_DECL_GETIFADDRS
45+ #include < ifaddrs.h>
46+ #endif
47+
48+ // ! Necessary on some platforms
49+ extern char ** environ;
3250
3351namespace {
3452
@@ -85,6 +103,53 @@ CSHA512& operator<<(CSHA512& hasher, const T& data) {
85103 return hasher;
86104}
87105
106+ #ifndef WIN32
107+ void AddSockaddr (CSHA512& hasher, const struct sockaddr *addr)
108+ {
109+ if (addr == nullptr ) return ;
110+ switch (addr->sa_family ) {
111+ case AF_INET:
112+ hasher.Write ((const unsigned char *)addr, sizeof (sockaddr_in));
113+ break ;
114+ case AF_INET6:
115+ hasher.Write ((const unsigned char *)addr, sizeof (sockaddr_in6));
116+ break ;
117+ default :
118+ hasher.Write ((const unsigned char *)&addr->sa_family , sizeof (addr->sa_family ));
119+ }
120+ }
121+
122+ void AddFile (CSHA512& hasher, const char *path)
123+ {
124+ struct stat sb = {};
125+ int f = open (path, O_RDONLY);
126+ size_t total = 0 ;
127+ if (f != -1 ) {
128+ unsigned char fbuf[4096 ];
129+ int n;
130+ hasher.Write ((const unsigned char *)&f, sizeof (f));
131+ if (fstat (f, &sb) == 0 ) hasher << sb;
132+ do {
133+ n = read (f, fbuf, sizeof (fbuf));
134+ if (n > 0 ) hasher.Write (fbuf, n);
135+ total += n;
136+ /* not bothering with EINTR handling. */
137+ } while (n == sizeof (fbuf) && total < 1048576 ); // Read only the first 1 Mbyte
138+ close (f);
139+ }
140+ }
141+
142+ void AddPath (CSHA512& hasher, const char *path)
143+ {
144+ struct stat sb = {};
145+ if (stat (path, &sb) == 0 ) {
146+ hasher.Write ((const unsigned char *)path, strlen (path) + 1 );
147+ hasher << sb;
148+ }
149+ }
150+ #endif
151+
152+
88153} // namespace
89154
90155void RandAddDynamicEnv (CSHA512& hasher)
@@ -99,48 +164,157 @@ void RandAddDynamicEnv(CSHA512& hasher)
99164#else
100165# ifndef __MACH__
101166 // On non-MacOS systems, use various clock_gettime() calls.
102- struct timespec ts;
167+ struct timespec ts = {} ;
103168# ifdef CLOCK_MONOTONIC
104169 clock_gettime (CLOCK_MONOTONIC, &ts);
105- hasher << ts. tv_sec << ts. tv_nsec ;
170+ hasher << ts;
106171# endif
107172# ifdef CLOCK_REALTIME
108173 clock_gettime (CLOCK_REALTIME, &ts);
109- hasher << ts. tv_sec << ts. tv_nsec ;
174+ hasher << ts;
110175# endif
111176# ifdef CLOCK_BOOTTIME
112177 clock_gettime (CLOCK_BOOTTIME, &ts);
113- hasher << ts. tv_sec << ts. tv_nsec ;
178+ hasher << ts;
114179# endif
115180# else
116181 // On MacOS use mach_absolute_time (number of CPU ticks since boot) as a replacement for CLOCK_MONOTONIC,
117182 // and clock_get_time for CALENDAR_CLOCK as a replacement for CLOCK_REALTIME.
118183 hasher << mach_absolute_time ();
119184 // From https://gist.github.com/jbenet/1087739
120185 clock_serv_t cclock;
121- mach_timespec_t mts;
186+ mach_timespec_t mts = {} ;
122187 if (host_get_clock_service (mach_host_self (), CALENDAR_CLOCK, &cclock) == KERN_SUCCESS && clock_get_time (cclock, &mts) == KERN_SUCCESS) {
123- hasher << mts. tv_sec << mts. tv_nsec ;
188+ hasher << mts;
124189 mach_port_deallocate (mach_task_self (), cclock);
125190 }
126191# endif
127192 // gettimeofday is available on all UNIX systems, but only has microsecond precision.
128- struct timeval tv;
193+ struct timeval tv = {} ;
129194 gettimeofday (&tv, nullptr );
130- hasher << tv. tv_sec << tv. tv_usec ;
195+ hasher << tv;
131196#endif
132197 // Probably redundant, but also use all the clocks C++11 provides:
133198 hasher << std::chrono::system_clock::now ().time_since_epoch ().count ();
134199 hasher << std::chrono::steady_clock::now ().time_since_epoch ().count ();
135200 hasher << std::chrono::high_resolution_clock::now ().time_since_epoch ().count ();
201+
202+ #ifndef WIN32
203+ // Current resource usage.
204+ struct rusage usage = {};
205+ if (getrusage (RUSAGE_SELF, &usage) == 0 ) hasher << usage;
206+ #endif
207+
208+ #ifdef __linux__
209+ AddFile (hasher, " /proc/diskstats" );
210+ AddFile (hasher, " /proc/vmstat" );
211+ AddFile (hasher, " /proc/schedstat" );
212+ AddFile (hasher, " /proc/zoneinfo" );
213+ AddFile (hasher, " /proc/meminfo" );
214+ AddFile (hasher, " /proc/softirqs" );
215+ AddFile (hasher, " /proc/stat" );
216+ AddFile (hasher, " /proc/self/schedstat" );
217+ AddFile (hasher, " /proc/self/status" );
218+ #endif
219+
220+ // Stack and heap location
221+ void * addr = malloc (4097 );
222+ hasher << &addr << addr;
223+ free (addr);
136224}
137225
138226void RandAddStaticEnv (CSHA512& hasher)
139227{
228+ // Some compile-time static properties
229+ hasher << (CHAR_MIN < 0 ) << sizeof (void *) << sizeof (long ) << sizeof (int );
230+ #if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
231+ hasher << __GNUC__ << __GNUC_MINOR__ << __GNUC_PATCHLEVEL__;
232+ #endif
233+ #ifdef _MSC_VER
234+ hasher << _MSC_VER;
235+ #endif
236+ hasher << __cplusplus;
237+ #ifdef _XOPEN_VERSION
238+ hasher << _XOPEN_VERSION;
239+ #endif
240+ #ifdef __VERSION__
241+ const char * COMPILER_VERSION = __VERSION__;
242+ hasher.Write ((const unsigned char *)COMPILER_VERSION, strlen (COMPILER_VERSION) + 1 );
243+ #endif
244+
245+ // Bitcoin client version
246+ hasher << CLIENT_VERSION;
247+
248+ // Memory locations
249+ hasher << &hasher << &RandAddStaticEnv << &malloc << &errno << &environ;
250+
251+ // Hostname
252+ char hname[256 ];
253+ if (gethostname (hname, 256 ) == 0 ) {
254+ hasher.Write ((const unsigned char *)hname, strnlen (hname, 256 ));
255+ }
256+
257+ #if HAVE_DECL_GETIFADDRS
258+ // Network interfaces
259+ struct ifaddrs *ifad = NULL ;
260+ getifaddrs (&ifad);
261+ struct ifaddrs *ifit = ifad;
262+ while (ifit != NULL ) {
263+ hasher.Write ((const unsigned char *)&ifit, sizeof (ifit));
264+ hasher.Write ((const unsigned char *)ifit->ifa_name , strlen (ifit->ifa_name ) + 1 );
265+ hasher.Write ((const unsigned char *)&ifit->ifa_flags , sizeof (ifit->ifa_flags ));
266+ AddSockaddr (hasher, ifit->ifa_addr );
267+ AddSockaddr (hasher, ifit->ifa_netmask );
268+ AddSockaddr (hasher, ifit->ifa_dstaddr );
269+ ifit = ifit->ifa_next ;
270+ }
271+ freeifaddrs (ifad);
272+ #endif
273+
274+ #ifndef WIN32
275+ // UNIX kernel information
276+ struct utsname name;
277+ if (uname (&name) != -1 ) {
278+ hasher.Write ((const unsigned char *)&name.sysname , strlen (name.sysname ) + 1 );
279+ hasher.Write ((const unsigned char *)&name.nodename , strlen (name.nodename ) + 1 );
280+ hasher.Write ((const unsigned char *)&name.release , strlen (name.release ) + 1 );
281+ hasher.Write ((const unsigned char *)&name.version , strlen (name.version ) + 1 );
282+ hasher.Write ((const unsigned char *)&name.machine , strlen (name.machine ) + 1 );
283+ }
284+
285+ /* Path and filesystem provided data */
286+ AddPath (hasher, " /" );
287+ AddPath (hasher, " ." );
288+ AddPath (hasher, " /tmp" );
289+ AddPath (hasher, " /home" );
290+ AddPath (hasher, " /proc" );
291+ #ifdef __linux__
292+ AddFile (hasher, " /proc/cmdline" );
293+ AddFile (hasher, " /proc/cpuinfo" );
294+ AddFile (hasher, " /proc/version" );
295+ #endif
296+ AddFile (hasher, " /etc/passwd" );
297+ AddFile (hasher, " /etc/group" );
298+ AddFile (hasher, " /etc/hosts" );
299+ AddFile (hasher, " /etc/resolv.conf" );
300+ AddFile (hasher, " /etc/timezone" );
301+ AddFile (hasher, " /etc/localtime" );
302+
303+ /* TODO: sysctl's for OSX to fetch information not available from /proc */
304+ #endif
305+
306+ // Env variables
307+ if (environ) {
308+ for (size_t i = 0 ; environ[i]; ++i) {
309+ hasher.Write ((const unsigned char *)environ[i], strlen (environ[i]));
310+ }
311+ }
312+
313+ // Process, thread, user, session, group, ... ids.
140314#ifdef WIN32
141315 hasher << GetCurrentProcessId () << GetCurrentThreadId ();
142316#else
143- hasher << getpid ();
317+ hasher << getpid () << getppid () << getsid ( 0 ) << getpgid ( 0 ) << getuid () << geteuid () << getgid () << getegid () ;
144318#endif
145319 hasher << std::this_thread::get_id ();
146320}
0 commit comments