aboutsummaryrefslogtreecommitdiff
path: root/libpam/pam_delay.c
diff options
context:
space:
mode:
Diffstat (limited to 'libpam/pam_delay.c')
-rw-r--r--libpam/pam_delay.c41
1 files changed, 30 insertions, 11 deletions
diff --git a/libpam/pam_delay.c b/libpam/pam_delay.c
index 549da896..9c6716a1 100644
--- a/libpam/pam_delay.c
+++ b/libpam/pam_delay.c
@@ -14,12 +14,17 @@
*/
#include "pam_private.h"
+#include <limits.h>
#include <unistd.h>
#include <time.h>
+#ifdef HAVE_SYS_RANDOM_H
+#include <sys/random.h>
+#endif
+
/* **********************************************************************
* initialize the time as unset, this is set on the return from the
- * authenticating pair of of the libpam pam_XXX calls.
+ * authenticating pair of the libpam pam_XXX calls.
*/
void _pam_reset_timer(pam_handle_t *pamh)
@@ -51,29 +56,40 @@ void _pam_start_timer(pam_handle_t *pamh)
* in C'. It is *not* a cryptographically strong generator, but it is
* probably "good enough" for our purposes here.
*
- * /dev/random might be a better place to look for some numbers...
+ * If getrandom is available, retrieve random number from there.
*/
static unsigned int _pam_rand(unsigned int seed)
{
+#ifdef HAVE_GETRANDOM
+ unsigned int value;
+
+ if (getrandom(&value, sizeof(value), GRND_NONBLOCK) ==
+ (ssize_t) sizeof(value)) {
+ return value;
+ }
+#endif
+
#define N1 1664525
#define N2 1013904223
return N1*seed + N2;
}
-static unsigned int _pam_compute_delay(unsigned int seed, unsigned int base)
+static unsigned long long _pam_compute_delay(unsigned int seed,
+ unsigned int base)
{
int i;
double sum;
- unsigned int ans;
+ unsigned long long ans;
for (sum=i=0; i<3; ++i) {
seed = _pam_rand(seed);
sum += (double) ((seed / 10) % 1000000);
}
sum = (sum/3.)/1e6 - .5; /* rescale */
- ans = (unsigned int) ( base*(1.+sum) );
- D(("random number: base=%u -> ans=%u\n", base, ans));
+ sum = base*(1.+sum);
+ ans = sum > (double) ULLONG_MAX ? ULLONG_MAX : (unsigned long long) sum;
+ D(("random number: base=%u -> ans=%llu\n", base, ans));
return ans;
}
@@ -88,7 +104,7 @@ static unsigned int _pam_compute_delay(unsigned int seed, unsigned int base)
void _pam_await_timer(pam_handle_t *pamh, int status)
{
- unsigned int delay;
+ unsigned long long delay;
D(("waiting?..."));
delay = _pam_compute_delay(pamh->fail_delay.begin,
@@ -99,6 +115,7 @@ void _pam_await_timer(pam_handle_t *pamh, int status)
void (*fn)(int, unsigned, void *);
} hack_fn_u;
void *appdata_ptr;
+ unsigned int delay_uint;
if (pamh->pam_conversation) {
appdata_ptr = pamh->pam_conversation->appdata_ptr;
@@ -106,14 +123,16 @@ void _pam_await_timer(pam_handle_t *pamh, int status)
appdata_ptr = NULL;
}
- /* always call the applications delay function, even if
+ delay_uint = delay > UINT_MAX ? UINT_MAX : (unsigned int) delay;
+
+ /* always call the application's delay function, even if
the delay is zero - indicate status */
hack_fn_u.value = pamh->fail_delay.delay_fn_ptr;
- hack_fn_u.fn(status, delay, appdata_ptr);
+ hack_fn_u.fn(status, delay_uint, appdata_ptr);
} else if (status != PAM_SUCCESS && pamh->fail_delay.set) {
- D(("will wait %u usec", delay));
+ D(("will wait %llu usec", delay));
if (delay > 0) {
struct timeval tval;
@@ -138,7 +157,7 @@ int pam_fail_delay(pam_handle_t *pamh, unsigned int usec)
{
unsigned int largest;
- IF_NO_PAMH("pam_fail_delay", pamh, PAM_SYSTEM_ERR);
+ IF_NO_PAMH(pamh, PAM_SYSTEM_ERR);
D(("setting delay to %u",usec));