Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 104099
Collapse All | Expand All

(-)kcheckpass.c (-29 / +67 lines)
Lines 14-20 Link Here
14
 *
14
 *
15
 * You should have received a copy of the GNU General Public
15
 * You should have received a copy of the GNU General Public
16
 * License along with this program; if not, write to the Free
16
 * License along with this program; if not, write to the Free
17
 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17
 * Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA  02110-1301, USA.
18
 *
18
 *
19
 *
19
 *
20
 *	kcheckpass is a simple password checker. Just invoke and
20
 *	kcheckpass is a simple password checker. Just invoke and
Lines 264-271 Link Here
264
264
265
  va_start(ap, fmt);
265
  va_start(ap, fmt);
266
  vfprintf(stderr, fmt, ap);
266
  vfprintf(stderr, fmt, ap);
267
  va_end(ap);
267
}
268
}
268
269
270
#ifndef O_NOFOLLOW
271
# define O_NOFOLLOW 0
272
#endif
273
269
static void ATTR_NORETURN
274
static void ATTR_NORETURN
270
usage(int exitval)
275
usage(int exitval)
271
{
276
{
Lines 286-291 Link Here
286
  exit(exitval);
291
  exit(exitval);
287
}
292
}
288
293
294
static int exclusive_lock(int fd)
295
{
296
  struct flock lk;
297
  lk.l_type = F_WRLCK;
298
  lk.l_whence = SEEK_SET;
299
  lk.l_start = lk.l_len = 0;
300
  return fcntl(fd, F_SETLKW, &lk);
301
}
289
302
290
int
303
int
291
main(int argc, char **argv)
304
main(int argc, char **argv)
Lines 299-308 Link Here
299
  char		*p;
312
  char		*p;
300
#endif
313
#endif
301
  struct passwd	*pw;
314
  struct passwd	*pw;
302
  int		c, nfd, lfd, numtries;
315
  int		c, nfd, tfd, lfd;
303
  uid_t		uid;
316
  uid_t		uid;
304
  long		lasttime;
317
  time_t	lasttime;
305
  AuthReturn	ret;
318
  AuthReturn	ret;
319
  char tmpname[64], fname[64], fcont[64];
320
  time_t left = 3;
321
  lfd = tfd = 0;
306
322
307
#ifdef HAVE_OSF_C2_PASSWD
323
#ifdef HAVE_OSF_C2_PASSWD
308
  initialize_osf_security(argc, argv);
324
  initialize_osf_security(argc, argv);
Lines 371-376 Link Here
371
      return AuthError;
387
      return AuthError;
372
    }
388
    }
373
  }
389
  }
390
391
  /* see if we had already a failed attempt */
392
  if ( uid != geteuid() ) {
393
    strcpy(tmpname, "/var/lock/kcheckpass.tmp.XXXXXX");
394
    if ((tfd=mkstemp(tmpname)) < 0)
395
      return AuthError;
396
397
    /* try locking out concurrent kcheckpass processes */
398
    exclusive_lock(tfd);
399
    
400
    write(tfd, fcont, sprintf(fcont, "%lu\n", time(0)+left));
401
    (void) lseek(tfd, 0, SEEK_SET);
402
403
    sprintf(fname, "/var/lock/kcheckpass.%d", uid );
404
405
    if ((lfd = open(fname, O_RDWR | O_NOFOLLOW)) >= 0) {
406
      if (exclusive_lock(lfd) == 0) {
407
        if ((c = read(lfd, fcont, sizeof(fcont)-1)) > 0 &&
408
	    (fcont[c] = '\0', sscanf(fcont, "%ld", &lasttime) == 1))
409
	  {
410
            time_t ct = time(0);
411
412
	    /* in case we were killed early, sleep the remaining time
413
	     * to properly enforce invocation throttling and make sure
414
	     * that users can't use kcheckpass for bruteforcing password
415
             */
416
            if(lasttime > ct && lasttime < ct + left)
417
              sleep (lasttime - ct);
418
          }
419
      }
420
      close(lfd);
421
    }
422
    rename(tmpname, fname);
423
  }
424
374
  /* Now do the fandango */
425
  /* Now do the fandango */
375
  ret = Authenticate(
426
  ret = Authenticate(
376
#ifdef HAVE_PAM
427
#ifdef HAVE_PAM
Lines 379-413 Link Here
379
                     method,
430
                     method,
380
                     username, 
431
                     username, 
381
                     sfd < 0 ? conv_legacy : conv_server);
432
                     sfd < 0 ? conv_legacy : conv_server);
433
382
  if (ret == AuthOk || ret == AuthBad) {
434
  if (ret == AuthOk || ret == AuthBad) {
383
    /* Security: Don't undermine the shadow system. */
435
    /* Security: Don't undermine the shadow system. */
384
    if (uid != geteuid()) {
436
    if (uid != geteuid()) {
385
      char fname[32], fcont[32];
437
      if (ret == AuthBad) {
386
      sprintf(fname, "/var/lock/kcheckpass.%d", uid);
438
        write(tfd, fcont, sprintf(fcont, "%lu\n", time(0)+left));
387
      if ((lfd = open(fname, O_RDWR | O_CREAT)) >= 0) {
439
      } else
388
        struct flock lk;
440
        unlink(fname);
389
        lk.l_type = F_WRLCK;
441
	
390
        lk.l_whence = SEEK_SET;
442
      unlink(tmpname);
391
        lk.l_start = lk.l_len = 0;
443
392
	if (fcntl(lfd, F_SETLKW, &lk))
444
      if (ret == AuthBad)
393
          return AuthError;
445
        sleep(left);  
394
        if ((c = read(lfd, fcont, sizeof(fcont))) > 0 &&
446
395
            (fcont[c] = 0, sscanf(fcont, "%ld %d\n", &lasttime, &numtries) == 2))
447
      close(tfd);
396
        {
397
          time_t left = lasttime - time(0);
398
          if (numtries < 20)
399
            numtries++;
400
          left += 2 << (numtries > 10 ? numtries - 10 : 0);
401
          if (left > 0)
402
            sleep(left);
403
        } else
404
          numtries = 0;
405
        if (ret == AuthBad) {
406
          lseek(lfd, 0, SEEK_SET);
407
          write(lfd, fcont, sprintf(fcont, "%ld %d\n", time(0), numtries));
408
        } else
409
          unlink(fname);
410
      }
411
    }
448
    }
412
    if (ret == AuthBad) {
449
    if (ret == AuthBad) {
413
      message("Authentication failure\n");
450
      message("Authentication failure\n");
Lines 417-422 Link Here
417
      }
454
      }
418
    }
455
    }
419
  }
456
  }
457
420
  return ret;
458
  return ret;
421
}
459
}
422
460

Return to bug 104099