X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Flock.c;h=8a00b3ba154869df0ed8c0a25fb5d513ea0e4f51;hb=3210e7e80ee2b5a7d2049a5aaff9f17b9c93dcc9;hp=7a3ed6a259ffbf3ca1a6a5a6da6fdae625f8c64f;hpb=2a991a811de4c7b22f812682b267b616a809fd9a;p=xscreensaver diff --git a/driver/lock.c b/driver/lock.c index 7a3ed6a2..8a00b3ba 100644 --- a/driver/lock.c +++ b/driver/lock.c @@ -23,6 +23,10 @@ #include "xscreensaver.h" #include "resources.h" +#ifdef HAVE_SYSLOG +# include +#endif /* HAVE_SYSLOG */ + #ifdef _VROOT_H_ ERROR! You must not include vroot.h in this file. #endif @@ -35,7 +39,7 @@ extern char *getenv(const char *name); extern int validate_user(char *name, char *password); static Bool -vms_passwd_valid_p(char *pw) +vms_passwd_valid_p(char *pw, Bool verbose_p) { return (validate_user (getenv("USER"), typed_passwd) == 1); } @@ -48,7 +52,7 @@ vms_passwd_valid_p(char *pw) #undef MAX #define MAX(a,b) ((a)>(b)?(a):(b)) -enum passwd_state { pw_read, pw_ok, pw_fail, pw_cancel, pw_time }; +enum passwd_state { pw_read, pw_ok, pw_null, pw_fail, pw_cancel, pw_time }; struct passwd_dialog_data { @@ -58,8 +62,10 @@ struct passwd_dialog_data { int i_beam; float ratio; + Position x, y; Dimension width; Dimension height; + Dimension border_width; char *heading_label; char *body_label; @@ -93,6 +99,8 @@ struct passwd_dialog_data { Dimension thermo_field_x, thermo_field_y; Dimension thermo_field_height; + + Pixmap save_under; }; @@ -100,7 +108,6 @@ void make_passwd_window (saver_info *si) { struct passwd *p = getpwuid (getuid ()); - int x, y, bw; XSetWindowAttributes attrs; unsigned long attrmask = 0; Screen *screen = si->default_screen->screen; @@ -294,23 +301,49 @@ make_passwd_window (saver_info *si) Dimension w = WidthOfScreen(screen); Dimension h = HeightOfScreen(screen); if (si->prefs.debug_p) w /= 2; - x = ((w + pw->width) / 2) - pw->width; - y = ((h + pw->height) / 2) - pw->height; - if (x < 0) x = 0; - if (y < 0) y = 0; + pw->x = ((w + pw->width) / 2) - pw->width; + pw->y = ((h + pw->height) / 2) - pw->height; + if (pw->x < 0) pw->x = 0; + if (pw->y < 0) pw->y = 0; } - bw = get_integer_resource ("passwd.borderWidth", "Dialog.BorderWidth"); + pw->border_width = get_integer_resource ("passwd.borderWidth", + "Dialog.BorderWidth"); si->passwd_dialog = XCreateWindow (si->dpy, RootWindowOfScreen(screen), - x, y, pw->width, pw->height, bw, + pw->x, pw->y, pw->width, pw->height, pw->border_width, DefaultDepthOfScreen (screen), InputOutput, DefaultVisualOfScreen(screen), attrmask, &attrs); XSetWindowBackground (si->dpy, si->passwd_dialog, pw->background); + + /* Before mapping the window, save the bits that are underneath the + rectangle the window will occlude. When we lower the window, we + restore these bits. This works, because the running screenhack + has already been sent SIGSTOP, so we know nothing else is drawing + right now! */ + { + XGCValues gcv; + GC gc; + pw->save_under = XCreatePixmap (si->dpy, + si->default_screen->screensaver_window, + pw->width + (pw->border_width*2) + 1, + pw->height + (pw->border_width*2) + 1, + si->default_screen->current_depth); + gcv.function = GXcopy; + gc = XCreateGC (si->dpy, pw->save_under, GCFunction, &gcv); + XCopyArea (si->dpy, si->default_screen->screensaver_window, + pw->save_under, gc, + pw->x - pw->border_width, pw->y - pw->border_width, + pw->width + (pw->border_width*2) + 1, + pw->height + (pw->border_width*2) + 1, + 0, 0); + XFreeGC (si->dpy, gc); + } + XMapRaised (si->dpy, si->passwd_dialog); XSync (si->dpy, False); @@ -599,6 +632,24 @@ destroy_passwd_window (saver_info *si) si->passwd_dialog = 0; } + if (pw->save_under) + { + XGCValues gcv; + GC gc; + gcv.function = GXcopy; + gc = XCreateGC (si->dpy, si->default_screen->screensaver_window, + GCFunction, &gcv); + XCopyArea (si->dpy, pw->save_under, + si->default_screen->screensaver_window, gc, + 0, 0, + pw->width + (pw->border_width*2) + 1, + pw->height + (pw->border_width*2) + 1, + pw->x - pw->border_width, pw->y - pw->border_width); + XFreePixmap (si->dpy, pw->save_under); + pw->save_under = 0; + XFreeGC (si->dpy, gc); + } + if (pw->heading_label) free (pw->heading_label); if (pw->body_label) free (pw->body_label); if (pw->user_label) free (pw->user_label); @@ -668,6 +719,7 @@ passwd_animate_timer (XtPointer closure, XtIntervalId *id) static void handle_passwd_key (saver_info *si, XKeyEvent *event) { + saver_preferences *p = &si->prefs; passwd_dialog_data *pw = si->pw_data; int pw_size = sizeof (pw->typed_passwd) - 1; char *typed_passwd = pw->typed_passwd; @@ -696,10 +748,18 @@ handle_passwd_key (saver_info *si, XKeyEvent *event) case '\012': case '\015': /* Enter */ if (pw->state != pw_read) ; /* already done? */ - else if (passwd_valid_p (typed_passwd)) - pw->state = pw_ok; + else if (typed_passwd[0] == 0) + pw->state = pw_null; else - pw->state = pw_fail; + { + update_passwd_window (si, "Checking...", pw->ratio); + XSync (si->dpy, False); + if (passwd_valid_p (typed_passwd, p->verbose_p)) + pw->state = pw_ok; + else + pw->state = pw_fail; + update_passwd_window (si, "", pw->ratio); + } break; default: @@ -726,6 +786,7 @@ handle_passwd_key (saver_info *si, XKeyEvent *event) static void passwd_event_loop (saver_info *si) { + saver_preferences *p = &si->prefs; char *msg = 0; XEvent event; passwd_animate_timer ((XtPointer) si, 0); @@ -744,15 +805,83 @@ passwd_event_loop (saver_info *si) switch (si->pw_data->state) { case pw_ok: msg = 0; break; + case pw_null: msg = ""; break; case pw_time: msg = "Timed out!"; break; default: msg = "Sorry!"; break; } + if (si->pw_data->state == pw_fail) + si->unlock_failures++; + + if (p->verbose_p) + switch (si->pw_data->state) + { + case pw_ok: + fprintf (stderr, "%s: password correct.\n", blurb()); break; + case pw_fail: + fprintf (stderr, "%s: password incorrect!\n", blurb()); break; + case pw_null: + case pw_cancel: + fprintf (stderr, "%s: password entry cancelled.\n", blurb()); break; + case pw_time: + fprintf (stderr, "%s: password entry timed out.\n", blurb()); break; + default: break; + } + +#ifdef HAVE_SYSLOG + if (si->pw_data->state == pw_fail) + { + /* If they typed a password (as opposed to just hitting return) and + the password was invalid, log it. + */ + struct passwd *pw = getpwuid (getuid ()); + char *d = DisplayString (si->dpy); + char *u = (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 = ""; + openlog (progname, opt, fac); + syslog (LOG_NOTICE, "FAILED LOGIN %d ON DISPLAY \"%s\", FOR \"%s\"", + si->unlock_failures, d, u); + closelog (); + } +#endif /* HAVE_SYSLOG */ + + if (si->pw_data->state == pw_fail) + XBell (si->dpy, False); + + if (si->pw_data->state == pw_ok && si->unlock_failures != 0) + { + if (si->unlock_failures == 1) + fprintf (real_stderr, + "%s: WARNING: 1 failed attempt to unlock the screen.\n", + blurb()); + else + fprintf (real_stderr, + "%s: WARNING: %d failed attempts to unlock the screen.\n", + blurb(), si->unlock_failures); + fflush (real_stderr); + + si->unlock_failures = 0; + } + if (msg) { si->pw_data->i_beam = 0; update_passwd_window (si, msg, 0.0); - XBell (si->dpy, False); XSync (si->dpy, False); sleep (1); @@ -765,13 +894,18 @@ passwd_event_loop (saver_info *si) } } + Bool unlock_p (saver_info *si) { + saver_preferences *p = &si->prefs; Screen *screen = si->default_screen->screen; Colormap cmap = DefaultColormapOfScreen (screen); Bool status; + if (p->verbose_p) + fprintf (stderr, "%s: prompting for password.\n", blurb()); + if (si->pw_data || si->passwd_dialog) destroy_passwd_window (si);