X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Fpasswd.c;h=fd42c5521351da99fa65a2584e8debe429bd7789;hb=ffcd2e7e3da122dbba5c4188e05d3a63d0ede26e;hp=99fdee08c62744b45d5df7a307dee208fa071613;hpb=c494fd2e6b3b25582375d62e40f4f5cc984ca424;p=xscreensaver diff --git a/driver/passwd.c b/driver/passwd.c index 99fdee08..fd42c552 100644 --- a/driver/passwd.c +++ b/driver/passwd.c @@ -23,8 +23,19 @@ # include #endif +#ifndef VMS +# include /* for getpwuid() */ +#else /* VMS */ +# include "vms-pwd.h" +#endif /* VMS */ + +#ifdef HAVE_SYSLOG +# include +#endif /* HAVE_SYSLOG */ + #include +#include "xscreensaver.h" #include "auth.h" extern const char *blurb(void); @@ -159,6 +170,9 @@ try_unlock_password(saver_info *si, memset(&message, 0, sizeof(message)); + if (verbose_p) + fprintf(stderr, "%s: non-PAM password auth.\n", blurb()); + /* Call the auth_conv function with "Password:", then feed * the result into valid_p() */ @@ -170,7 +184,13 @@ try_unlock_password(saver_info *si, if (!response) return; - si->unlock_state = valid_p(response->response, verbose_p) ? ul_success : ul_fail; + if (valid_p (response->response, verbose_p)) + si->unlock_state = ul_success; /* yay */ + else if (si->unlock_state == ul_cancel || + si->unlock_state == ul_time) + ; /* more specific failures ok */ + else + si->unlock_state = ul_fail; /* generic failure */ if (response->response) free(response->response); @@ -178,6 +198,48 @@ try_unlock_password(saver_info *si, } +/* Write a password failure to the system log. + */ +static void +do_syslog (saver_info *si, Bool verbose_p) +{ +# ifdef HAVE_SYSLOG + struct passwd *pw = getpwuid (getuid ()); + char *d = DisplayString (si->dpy); + char *u = (pw && pw->pw_name ? pw->pw_name : "???"); + int opt = 0; + int fac = 0; + +# ifdef LOG_PID + opt = LOG_PID; +# endif + +# if defined(LOG_AUTHPRIV) + fac = LOG_AUTHPRIV; +# elif defined(LOG_AUTH) + fac = LOG_AUTH; +# else + fac = LOG_DAEMON; +# endif + + if (!d) d = ""; + +# undef FMT +# define FMT "FAILED LOGIN %d ON DISPLAY \"%s\", FOR \"%s\"" + + if (verbose_p) + fprintf (stderr, "%s: syslog: " FMT "\n", blurb(), + si->unlock_failures, d, u); + + openlog (progname, opt, fac); + syslog (LOG_NOTICE, FMT, si->unlock_failures, d, u); + closelog (); + +# endif /* HAVE_SYSLOG */ +} + + + /** * Runs through each authentication driver calling its try_unlock function. * Called xss_authenticate() because AIX beat us to the name authenticate(). @@ -187,6 +249,8 @@ xss_authenticate(saver_info *si, Bool verbose_p) { int i, j; + si->unlock_state = ul_read; + for (i = 0; i < countof(methods); i++) { if (!methods[i].initted_p) @@ -205,6 +269,20 @@ xss_authenticate(saver_info *si, Bool verbose_p) check_for_leaks (methods[i].name); + /* If password authentication failed, but the password was NULL + (meaning the user just hit RET) then treat that as "cancel". + This means that if the password is literally NULL, it will + work; but if not, then NULL passwords are treated as cancel. + */ + if (si->unlock_state == ul_fail && + si->cached_passwd && + !*si->cached_passwd) + { + fprintf (stderr, "%s: assuming null password means cancel.\n", + blurb()); + si->unlock_state = ul_cancel; + } + if (si->unlock_state == ul_success) { /* If we successfully authenticated by method N, but attempting @@ -225,11 +303,29 @@ xss_authenticate(saver_info *si, Bool verbose_p) } goto DONE; /* Successfully authenticated! */ } + else if (si->unlock_state == ul_cancel || + si->unlock_state == ul_time) + { + /* If any auth method gets a cancel or timeout, don't try the + next auth method! We're done! */ + fprintf (stderr, + "%s: authentication via %s %s.\n", + blurb(), methods[i].name, + (si->unlock_state == ul_cancel + ? "cancelled" : "timed out")); + goto DONE; + } } if (verbose_p) fprintf(stderr, "%s: All authentication mechanisms failed.\n", blurb()); + if (si->unlock_state == ul_fail) + { + si->unlock_failures++; + do_syslog (si, verbose_p); + } + DONE: if (si->auth_finished_cb) si->auth_finished_cb (si);