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 |
|