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;