Mercurial > dropbear
comparison svr-auth.c @ 1622:e11ed628708b
- Add adaptive authentication failure delay
- Rework monotonic_now/gettime_wrapper and use clock_gettime on more platforms
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Mon, 05 Nov 2018 23:36:34 +0800 |
parents | 1fbe598a14fb |
children | 592a18dac250 |
comparison
equal
deleted
inserted
replaced
1621:8cdabd7d34aa | 1622:e11ed628708b |
---|---|
77 unsigned int userlen, servicelen, methodlen; | 77 unsigned int userlen, servicelen, methodlen; |
78 int valid_user = 0; | 78 int valid_user = 0; |
79 | 79 |
80 TRACE(("enter recv_msg_userauth_request")) | 80 TRACE(("enter recv_msg_userauth_request")) |
81 | 81 |
82 /* for compensating failure delay */ | |
83 gettime_wrapper(&ses.authstate.auth_starttime); | |
84 | |
82 /* ignore packets if auth is already done */ | 85 /* ignore packets if auth is already done */ |
83 if (ses.authstate.authdone == 1) { | 86 if (ses.authstate.authdone == 1) { |
84 TRACE(("leave recv_msg_userauth_request: authdone already")) | 87 TRACE(("leave recv_msg_userauth_request: authdone already")) |
85 return; | 88 return; |
86 } | 89 } |
380 | 383 |
381 buf_putbyte(ses.writepayload, partial ? 1 : 0); | 384 buf_putbyte(ses.writepayload, partial ? 1 : 0); |
382 encrypt_packet(); | 385 encrypt_packet(); |
383 | 386 |
384 if (incrfail) { | 387 if (incrfail) { |
385 unsigned int delay; | 388 /* The SSH_MSG_AUTH_FAILURE response is delayed to attempt to |
386 genrandom((unsigned char*)&delay, sizeof(delay)); | 389 avoid user enumeration and slow brute force attempts. |
387 /* We delay for 300ms +- 50ms */ | 390 The delay is adjusted by the time already spent in processing |
388 delay = 250000 + (delay % 100000); | 391 authentication (ses.authstate.auth_starttime timestamp). */ |
392 | |
393 /* Desired total delay 300ms +-50ms (in nanoseconds). | |
394 Beware of integer overflow if increasing these values */ | |
395 const unsigned int mindelay = 250000000; | |
396 const unsigned int vardelay = 100000000; | |
397 unsigned int rand_delay; | |
398 struct timespec delay; | |
399 | |
400 gettime_wrapper(&delay); | |
401 delay.tv_sec -= ses.authstate.auth_starttime.tv_sec; | |
402 delay.tv_nsec -= ses.authstate.auth_starttime.tv_nsec; | |
403 | |
404 /* carry */ | |
405 if (delay.tv_nsec < 0) { | |
406 delay.tv_nsec += 1000000000; | |
407 delay.tv_sec -= 1; | |
408 } | |
409 | |
410 genrandom((unsigned char*)&rand_delay, sizeof(rand_delay)); | |
411 rand_delay = mindelay + (rand_delay % vardelay); | |
412 | |
413 if (delay.tv_sec == 0 && delay.tv_nsec <= mindelay) { | |
414 /* Compensate for elapsed time */ | |
415 delay.tv_nsec = rand_delay - delay.tv_nsec; | |
416 } else { | |
417 /* No time left or time went backwards, just delay anyway */ | |
418 delay.tv_sec = 0; | |
419 delay.tv_nsec = rand_delay; | |
420 } | |
421 | |
422 | |
389 #if DROPBEAR_FUZZ | 423 #if DROPBEAR_FUZZ |
390 if (!fuzz.fuzzing) | 424 if (!fuzz.fuzzing) |
391 #endif | 425 #endif |
392 { | 426 { |
393 usleep(delay); | 427 while (nanosleep(&delay, &delay) == -1 && errno == EINTR) { /* Go back to sleep */ } |
394 } | 428 } |
429 | |
395 ses.authstate.failcount++; | 430 ses.authstate.failcount++; |
396 } | 431 } |
397 | 432 |
398 if (ses.authstate.failcount >= svr_opts.maxauthtries) { | 433 if (ses.authstate.failcount >= svr_opts.maxauthtries) { |
399 char * userstr; | 434 char * userstr; |