X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=driver%2Fpasswd.c;h=066bc81f9c608d6a0178c5be12605b30556efaaf;hp=c3c2b62ac9f309547db83d887ea1286ab097a60b;hb=6b1c86cf395f59389e4ece4ea8f4bea2c332745b;hpb=e4fa2ac140f7bc56571373a7b7eb585fa4500e38 diff --git a/driver/passwd.c b/driver/passwd.c index c3c2b62a..066bc81f 100644 --- a/driver/passwd.c +++ b/driver/passwd.c @@ -1,5 +1,5 @@ /* passwd.c --- verifying typed passwords with the OS. - * xscreensaver, Copyright (c) 1993-2003 Jamie Zawinski + * xscreensaver, Copyright (c) 1993-2004 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -18,11 +18,27 @@ #include #include +#include #ifdef HAVE_UNISTD_H # include #endif -extern char *blurb(void); +#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); extern void check_for_leaks (const char *where); @@ -42,6 +58,8 @@ struct auth_methods { Bool (*init) (int argc, char **argv, Bool verbose_p); Bool (*priv_init) (int argc, char **argv, Bool verbose_p); Bool (*valid_p) (const char *typed_passwd, Bool verbose_p); + void (*try_unlock) (saver_info *si, Bool verbose_p, + Bool (*valid_p)(const char *typed_passwd, Bool verbose_p)); Bool initted_p; Bool priv_initted_p; }; @@ -53,7 +71,8 @@ extern Bool kerberos_passwd_valid_p (const char *typed_passwd, Bool verbose_p); #endif #ifdef HAVE_PAM extern Bool pam_priv_init (int argc, char **argv, Bool verbose_p); -extern Bool pam_passwd_valid_p (const char *typed_passwd, Bool verbose_p); +extern void pam_try_unlock (saver_info *si, Bool verbose_p, + Bool (*valid_p)(const char *typed_passwd, Bool verbose_p)); #endif #ifdef PASSWD_HELPER_PROGRAM extern Bool ext_priv_init (int argc, char **argv, Bool verbose_p); @@ -63,6 +82,9 @@ extern Bool pwent_lock_init (int argc, char **argv, Bool verbose_p); extern Bool pwent_priv_init (int argc, char **argv, Bool verbose_p); extern Bool pwent_passwd_valid_p (const char *typed_passwd, Bool verbose_p); +Bool lock_priv_init (int argc, char **argv, Bool verbose_p); +Bool lock_init (int argc, char **argv, Bool verbose_p); +Bool passwd_valid_p (const char *typed_passwd, Bool verbose_p); /* The authorization methods to try, in order. Note that the last one (the pwent version) is actually two auth methods, @@ -70,19 +92,19 @@ extern Bool pwent_passwd_valid_p (const char *typed_passwd, Bool verbose_p); (It's all in the same file since the APIs are randomly nearly-identical.) */ struct auth_methods methods[] = { -# ifdef HAVE_KERBEROS - { "Kerberos", kerberos_lock_init, 0, kerberos_passwd_valid_p, +# ifdef HAVE_PAM + { "PAM", 0, pam_priv_init, 0, pam_try_unlock, False, False }, # endif -# ifdef HAVE_PAM - { "PAM", 0, pam_priv_init, pam_passwd_valid_p, +# ifdef HAVE_KERBEROS + { "Kerberos", kerberos_lock_init, 0, kerberos_passwd_valid_p, 0, False, False }, # endif # ifdef PASSWD_HELPER_PROGRAM - { "external", 0, ext_priv_init, ext_passwd_valid_p, + { "external", 0, ext_priv_init, ext_passwd_valid_p, 0, False, False }, -#endif - { "normal", pwent_lock_init, pwent_priv_init, pwent_passwd_valid_p, +# endif + { "normal", pwent_lock_init, pwent_priv_init, pwent_passwd_valid_p, 0, False, False } }; @@ -135,18 +157,117 @@ lock_init (int argc, char **argv, Bool verbose_p) } -Bool -passwd_valid_p (const char *typed_passwd, Bool verbose_p) +/* A basic auth driver that simply prompts for a password then runs it through + * valid_p to determine whether the password is correct. + */ +static void +try_unlock_password(saver_info *si, + Bool verbose_p, + Bool (*valid_p)(const char *typed_passwd, Bool verbose_p)) +{ + struct auth_message message; + struct auth_response *response = NULL; + + 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() + */ + message.type = AUTH_MSGTYPE_PROMPT_NOECHO; + message.msg = "Password:"; + + si->unlock_cb(1, &message, &response, si); + + if (!response) + return; + + 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); + free(response); +} + + +/* 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(). + */ +void +xss_authenticate(saver_info *si, Bool verbose_p) { int i, j; + for (i = 0; i < countof(methods); i++) { - int ok_p = (methods[i].initted_p && - methods[i].valid_p (typed_passwd, verbose_p)); + if (!methods[i].initted_p) + continue; + + if (si->cached_passwd != NULL && methods[i].valid_p) + si->unlock_state = (methods[i].valid_p(si->cached_passwd, verbose_p) == True) + ? ul_success : ul_fail; + else if (methods[i].try_unlock != NULL) + methods[i].try_unlock(si, verbose_p, methods[i].valid_p); + else if (methods[i].valid_p) + try_unlock_password(si, verbose_p, methods[i].valid_p); + else /* Ze goggles, zey do nozing! */ + fprintf(stderr, "%s: authentication method %s does nothing.\n", + blurb(), methods[i].name); check_for_leaks (methods[i].name); - if (ok_p) + if (si->unlock_state == ul_success) { /* If we successfully authenticated by method N, but attempting to authenticate by method N-1 failed, mention that (since if @@ -157,19 +278,29 @@ passwd_valid_p (const char *typed_passwd, Bool verbose_p) { for (j = 0; j < i; j++) if (methods[j].initted_p) - fprintf (stderr, - "%s: authentication via %s passwords failed.\n", - blurb(), methods[j].name); + fprintf (stderr, + "%s: authentication via %s failed.\n", + blurb(), methods[j].name); fprintf (stderr, - "%s: authentication via %s passwords succeeded.\n", + "%s: authentication via %s succeeded.\n", blurb(), methods[i].name); } - - return True; /* Successfully authenticated! */ + goto DONE; /* Successfully authenticated! */ } } - return False; /* Authentication failure. */ + 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); } #endif /* NO_LOCKING -- whole file */