|
Lines 48-53
from The Open Group.
Link Here
|
| 48 |
#ifdef HAVE_LIBBSD |
48 |
#ifdef HAVE_LIBBSD |
| 49 |
#include <bsd/stdlib.h> /* for arc4random_buf() */ |
49 |
#include <bsd/stdlib.h> /* for arc4random_buf() */ |
| 50 |
#endif |
50 |
#endif |
|
|
51 |
#include <errno.h> |
| 52 |
#ifdef HAVE_SYS_SYSCALL_H |
| 53 |
#include <syscall.h> |
| 54 |
#endif |
| 51 |
|
55 |
|
| 52 |
struct protocol { |
56 |
struct protocol { |
| 53 |
unsigned short name_length; |
57 |
unsigned short name_length; |
|
Lines 302-319
GenerateAuthorization(unsigned name_leng
Link Here
|
| 302 |
return -1; |
306 |
return -1; |
| 303 |
} |
307 |
} |
| 304 |
|
308 |
|
|
|
309 |
#if ! defined(HAVE_ARC4RANDOM_BUF) |
| 310 |
|
| 311 |
// fallback function to get random data directly from /dev/urandom |
| 312 |
|
| 313 |
static int |
| 314 |
GetUrandom ( char *buffer, size_t length ) |
| 315 |
{ |
| 316 |
int random_fd = -1; |
| 317 |
int res = -1; |
| 318 |
size_t filled = 0; |
| 319 |
|
| 320 |
// larger requests are typically rejected by getentropy() / getrandom() |
| 321 |
// because they could block or return partially filled buffers |
| 322 |
if( length > 256 ) { |
| 323 |
errno = EIO; |
| 324 |
return -1; |
| 325 |
} |
| 326 |
|
| 327 |
random_fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); |
| 328 |
|
| 329 |
if( random_fd == -1 ) { |
| 330 |
return -1; |
| 331 |
} |
| 332 |
|
| 333 |
while( filled < length ) { |
| 334 |
res = read(random_fd, (char*)buffer + filled, length - filled); |
| 335 |
|
| 336 |
if( res == -1 ) { |
| 337 |
// shouldn't actually happen acc. to man(4) random, |
| 338 |
// but you never know |
| 339 |
if( errno == EINTR ) { |
| 340 |
continue; |
| 341 |
} |
| 342 |
|
| 343 |
return -1; |
| 344 |
} |
| 345 |
else if( res == 0 ) { |
| 346 |
// no more bytes available? should not happen |
| 347 |
errno = EIO; |
| 348 |
return -1; |
| 349 |
} |
| 350 |
|
| 351 |
filled += res; |
| 352 |
} |
| 353 |
|
| 354 |
return 0; |
| 355 |
} |
| 356 |
|
| 357 |
#endif // ! defined(HAVE_ARC4RANDOM_BUF) |
| 358 |
|
| 359 |
#if !defined(HAVE_GETENTROPY) && defined(HAVE_SYS_SYSCALL_H) && defined(SYS_getrandom) |
| 360 |
# define TRY_GETRANDOM |
| 361 |
#endif |
| 362 |
|
| 363 |
#ifdef TRY_GETRANDOM |
| 364 |
|
| 365 |
/* |
| 366 |
* wrapper for the getrandom() syscall which was for a long time implemented |
| 367 |
* in the Linux kernel, but not wrapped in glibc |
| 368 |
*/ |
| 369 |
static int |
| 370 |
GetRandom ( char *buffer, size_t length ) |
| 371 |
{ |
| 372 |
int res; |
| 373 |
size_t filled = 0; |
| 374 |
|
| 375 |
// larger requests are typically rejected by getentropy() / getrandom() |
| 376 |
// because they could block or return partially filled buffers |
| 377 |
if( length > 256 ) |
| 378 |
{ |
| 379 |
errno = EIO; |
| 380 |
return -1; |
| 381 |
} |
| 382 |
|
| 383 |
while( filled < length ) |
| 384 |
{ |
| 385 |
/* |
| 386 |
* glibc does not contain a syscall wrapper for this in older |
| 387 |
* versions |
| 388 |
*/ |
| 389 |
res = syscall(SYS_getrandom, (char*)buffer + filled, length - filled, 0); |
| 390 |
|
| 391 |
if( res == -1 ) |
| 392 |
{ |
| 393 |
if( errno == EINTR ) { |
| 394 |
continue; |
| 395 |
} |
| 396 |
|
| 397 |
return -1; |
| 398 |
} |
| 399 |
else if( res == 0 ) |
| 400 |
{ |
| 401 |
// no more bytes available? should not happen |
| 402 |
errno = EIO; |
| 403 |
return -1; |
| 404 |
} |
| 405 |
|
| 406 |
filled += res; |
| 407 |
} |
| 408 |
|
| 409 |
return 0; |
| 410 |
} |
| 411 |
|
| 412 |
#endif /* TRY_GETRANDOM */ |
| 413 |
|
| 305 |
void |
414 |
void |
| 306 |
GenerateRandomData(int len, char *buf) |
415 |
GenerateRandomData(int len, char *buf) |
| 307 |
{ |
416 |
{ |
| 308 |
#ifdef HAVE_ARC4RANDOM_BUF |
417 |
#ifdef HAVE_ARC4RANDOM_BUF |
| 309 |
arc4random_buf(buf, len); |
418 |
arc4random_buf(buf, len); |
| 310 |
#else |
419 |
#else |
| 311 |
int fd; |
420 |
int ret = -1; |
|
|
421 |
# ifdef HAVE_GETENTROPY |
| 422 |
/* use getentropy instead */ |
| 423 |
ret = getentropy (auth, len); |
| 424 |
# elif defined(TRY_GETRANDOM) |
| 425 |
/* try getrandom() wrapper */ |
| 426 |
ret = GetRandom(buf, len); |
| 427 |
# endif |
| 428 |
|
| 429 |
if( ret == -1 ) { |
| 430 |
// fallback to manual reading of /dev/urandom |
| 431 |
ret = GetUrandom(buf, len); |
| 432 |
} |
| 312 |
|
433 |
|
| 313 |
fd = open("/dev/urandom", O_RDONLY); |
434 |
if( ret == -1 ) { |
| 314 |
read(fd, buf, len); |
435 |
// no error return possible, rather abort than have security problems |
| 315 |
close(fd); |
436 |
OsAbort(); |
| 316 |
#endif |
437 |
} |
|
|
438 |
#endif // HAVE_ARC4RANDOM_BUF |
| 317 |
} |
439 |
} |
| 318 |
|
440 |
|
| 319 |
#endif /* XCSECURITY */ |
441 |
#endif /* XCSECURITY */ |