diff --git a/Makefile b/Makefile index 0302e2f..eb5e9d2 100644 --- a/Makefile +++ b/Makefile @@ -13,23 +13,47 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -LDLIBS=-lX11 -lcrypt -CDEFS=-DSHADOW_PWD +LDLIBS=-lX11 -lcrypt $(shell pkg-config --libs libnotify) +CDEFS=-DSHADOW_PWD $(RESPATH) CC=gcc -CFLAGS=-Wall ${CDEFS} +CFLAGS=-Wall ${CDEFS} $(shell pkg-config --cflags libnotify) INSTALL=install RM=rm +CONFIGPATH=/usr/share/xtrlock/ +RESPATH=-D'LOCK_IMG_PATH="$(CONFIGPATH)lock.png"' -D'UNLOCK_IMG_PATH="$(CONFIGPATH)unlock.png"' +#RESPATH=-D'LOCK_IMG_PATH="$(shell readlink -f lock.png)"' -D'UNLOCK_IMG_PATH="$(shell readlink -f unlock.png)"' +LID_CMD:=xtrlock -l xtrlock: xtrlock.o xtrlock.o: xtrlock.c +debug: + $(CC) xtrlock.c $(LDLIBS) $(CFLAGS) -DDEBUG -g -o xtrlock + +clean: + -rm -f xtrlock.o xtrlock + install: xtrlock - $(INSTALL) -c -m 2755 -o root -g shadow xtrlock /usr/bin + $(INSTALL) -c -m 2755 -o root -g shadow xtrlock /usr/bin + if [ ! -d "$(CONFIGPATH)" ]; then mkdir $(CONFIGPATH); fi + $(INSTALL) -c -m 644 resources/lock.png $(CONFIGPATH) + $(INSTALL) -c -m 644 resources/unlock.png $(CONFIGPATH) install.man: - $(INSTALL) -c -m 644 xtrlock.man /usr/man/man1/xtrlock.1x + $(INSTALL) -c -m 644 xtrlock.man /usr/share/man/man1/xtrlock.1x -remove: - $(RM) /usr/bin/xtrlock +install.bash_completion: + $(INSTALL) -c -m 754 xtrlock-completion.sh /usr/share/bash-completion/completions/xtrlock +install.on_lid: + cp ./on-lid-close.sh on-lid-close.sh.tmp + sed 's/xtrlock -l/$(LID_CMD)/g' on-lid-close.sh.tmp > tmp && mv tmp on-lid-close.sh.tmp + $(INSTALL) -c -m 744 -o root xtrlock-lid-down /etc/acpi/events/xtrlock-lid-down + $(INSTALL) -c -m 744 -o root ./on-lid-close.sh.tmp /etc/acpi/on-lid-close.sh + rm -f on-lid-close.sh.tmp +remove: + $(RM) /usr/bin/xtrlock + $(RM) -rf $(CONFIGPATH) + $(RM) -f /usr/share/bash-completion/completions/xtrlock + $(RM) -f /etc/acpi/on-lid-close.sh /etc/acpi/events/xtrlock-lid-down diff --git a/README.md b/README.md index 40cc1da..a5cf18b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ -DO NOT USE! +USE OR NOT? DEPENDS ON YOU! =========== +#### From last author: + Since working on this project, I have come to the conclusion that using anything but xscreensaver is a very unwise decision ([details](http://www.jwz.org/xscreensaver/toolkits.html)). I am no longer updating this project and strongly advise against its use (or the use of the upstream branch). Since this program puts you in peril of disclosing sensitive information, I do think its general concept is a Bad Idea™. Imagine your friend bob writes an OTR-encrypted message to you via Jabber, which causes Pidgin to open a new window display the decrypted message. If you just want to confuse/annoy people, I would suggest having xscreensaver take a screenshot when the screen is locked, which is then displayed by feh, xv or any other program capable of displaying images on X root windows. Another IMHO very nice (though seriously hacky) method is the one I described [in this gist](https://gist.github.com/jaseg/3487142): Have xscreensaver spawn an actual Windows XP VM that curious people can interact with, including automatic reset on screen unlocking. @@ -8,3 +10,32 @@ If you just want to confuse/annoy people, I would suggest having xscreensaver ta Thanks for checking out anyway! jaseg + + +#### From this author: + +I am modifing this project into a simple screen lock that have more of the conviniency rather than security. It will be modified to deal with laptop lids that always touch the keyboard or someone trying to mess around with your screen when your are in the toliet. However, please carefully read the note from the last author and deside if a professional screen lock like Xscreensaver is necessary for you! Nevertheless, IMHO this program should be able to deal with routine cases secure enough. + +Please check out the releases to grab a finished version! Any contribution would be appreciated! +2017/7/13 + +d0048 + +#### Installation Guide: +##### On linux: +1. Install required libiary and tools to build the project: +Debian series: `sudo apt-get install bash-completion libnotify-dev libx11-dev build-essential cmake cmake-data pkg-config` +Redhat series: `sudo dnf install bash-completion libnotify-dev libx11-dev build-essential cmake cmake-data pkg-config` +2. Download the correct version of source code you want and unzip it.(Probably from releases if stability is required) +3. `cd Better-XTrLock` +4. `make && sudo make install` to install the main binaries. +5. To install the manual for xtrlock, `sudo make install.man`. Then use `man xtrlock` to read the manual. +6. To install the auto completion support for bash 'sudo make install.bash_completion` +7. To trigger xtrlock on lid close, `sudo make install.on_lid LID_CMD='lock_command_with_args'`.(e.g: `LID_CMD='xtrlock -l -n'`). If no command specified, `xtrlock -l` will be used. +8. `xtrlock -h` to view usage + +#### Removal Guide: +##### On linux: +1. Download the correct version of source code you want and unzip it.(Probably from releases if stability is required) +2. `cd Better-XTrLock` +3. `sudo make remove` diff --git a/on-lid-close.sh b/on-lid-close.sh new file mode 100644 index 0000000..1cab7e2 --- /dev/null +++ b/on-lid-close.sh @@ -0,0 +1,11 @@ +#!/bin/bash +target='xtrlock -l'; +who | awk '{print $1, $NF}' | tr -d "()" | +while read u d; do + id=$(id -u $u) + . /run/user/$id/dbus-session + export DBUS_SESSION_BUS_ADDRESS + export DISPLAY=$d + sudo su $u -c "$target" + +done diff --git a/resources/Lock_Unlock.png b/resources/Lock_Unlock.png new file mode 100644 index 0000000..93fe537 Binary files /dev/null and b/resources/Lock_Unlock.png differ diff --git a/resources/lock.png b/resources/lock.png new file mode 100644 index 0000000..e81d350 Binary files /dev/null and b/resources/lock.png differ diff --git a/resources/unlock.png b/resources/unlock.png new file mode 100644 index 0000000..588a353 Binary files /dev/null and b/resources/unlock.png differ diff --git a/xtrlock-completion.sh b/xtrlock-completion.sh new file mode 100755 index 0000000..011cb94 --- /dev/null +++ b/xtrlock-completion.sh @@ -0,0 +1,15 @@ +# xtrlock(1) completion -*- shell-script -*- + +_xtrlock(){ + local cur="${COMP_WORDS[COMP_CWORD]}"; + local xtr_opts="-h --help -l --lock-user-password -p --password -e --encrypted-password -c --calculate -b --block-screen -d --delay-of-blink -n --notify" + #local prevcur="${COMP_WORDS[COMP_CWORD]}"; + #local prev="${COMP_WORDS[COMP_CWORD-1]}"; + + COMPREPLY=(); + if [[ ${cur} == -* ]] ; then + COMPREPLY=($(compgen -W "${xtr_opts}" \'"$cur"\')) + return 0; + fi +} +complete -F _xtrlock xtrlock; diff --git a/xtrlock-lid-down b/xtrlock-lid-down new file mode 100644 index 0000000..e4c5f95 --- /dev/null +++ b/xtrlock-lid-down @@ -0,0 +1,2 @@ +event=button/lid LID close +action=/etc/acpi/on-lid-close.sh diff --git a/xtrlock.c b/xtrlock.c index e0228bc..91e034f 100644 --- a/xtrlock.c +++ b/xtrlock.c @@ -18,196 +18,450 @@ #include #include +#include #include #include -#include -#include -#include -#include -#include +#include +#include #include -#include #include #include +#include +#include +#include +#include +#include #include -#include +#include +#include +#include #include -#include -#include +#include #include +#include +#include #ifdef SHADOW_PWD #include #endif -Display *display; -Window window, root; +#ifdef DEBUG +#define debug_print(...) \ + do { \ + printf(__VA_ARGS__); \ + } while (0) +#else +#define debug_print(...) \ + do { \ + } while (0) +#endif + +#define msleep(x) usleep(x * 1000) + +Display* display; +Window window, blank_window, trans_window; #define TIMEOUTPERATTEMPT 30000 -#define MAXGOODWILL (TIMEOUTPERATTEMPT*5) +#define MAXGOODWILL (TIMEOUTPERATTEMPT * 5) #define INITIALGOODWILL MAXGOODWILL #define GOODWILLPORTION 0.3 +bool blank_screen = false; +bool send_notification = false; +int blink_delay = 100; -struct passwd *pw; -int passwordok(const char *s) { -#if 0 - char key[3]; - char *encr; - - key[0] = *(pw->pw_passwd); - key[1] = (pw->pw_passwd)[1]; - key[2] = 0; - encr = crypt(s, key); - return !strcmp(encr, pw->pw_passwd); -#else - /* simpler, and should work with crypt() algorithms using longer - salt strings (like the md5-based one on freebsd). --marekm */ - return !strcmp(crypt(s, pw->pw_passwd), pw->pw_passwd); +struct { /*Setting correspond to the custom passwd setting. --d0048*/ + bool enable; + char* pwd; +} cust_pw_setting; + +struct passwd* pw; +int passwordok(const char* s) +{ + /* simpler, and should work with crypt() algorithms using longer + salt strings (like the md5-based one on freebsd). --marekm */ + debug_print("%s, %i\n", s, (int)strlen(s)); + + if (cust_pw_setting.enable) { + debug_print("Entered_de: %s\n", s); + debug_print("Original_de: %s\n", cust_pw_setting.pwd); + char* enter = crypt(s, cust_pw_setting.pwd); + char* original = cust_pw_setting.pwd; + if (NULL == enter) { + fprintf(stderr, "\"strdup\" or \"crypt\":%s\n", strerror(errno)); + return false; + } + debug_print("Entered: %s\n", enter); + debug_print("Original: %s\n", original); + return !strcmp(enter, original); + } else { /*salt in the second argument seems to be automatically used by crypt*/ + char* result = crypt(s, pw->pw_passwd); + if (NULL == result) { + fprintf(stderr, "\"strdup\" or \"crypt\":%s\n", strerror(errno)); + return false; + } + debug_print("Entered_de: %s\n", result); + debug_print("Original_de: %s\n", pw->pw_passwd); + return !strcmp(result, pw->pw_passwd); + } +} + +void print_help() +{ + printf("Xtrlock:\n" + " -h --help show this help\n" + " -l --lock-user-password lock immediately with the user's default password\n" + " -p --password [password_string] use custom non-encrypted password\n" + " -e --encrypted-password [password_hash] use encrypted custom password with salt of itself\n" + " -c --calculate [password_string] calculate the password string that can be used with the \"-c\" option\n" + " -b --block-screen lock with a blank screen\n" + " -d --delay of blink [delay_usec] milliseconds the screen blinks on successful locks(0 for no-delay & 100000 for 0.1 s)\n" + " -n --notify send message notification on lock and unlock\n" + "Thanks for using!\n"); +} + +char rand_ch() +{ /*range of characters in int: [A-Z]|[a-z][0-9](rand % max-min+1+min)*/ + /*time based rand refreshes too slow thus not the best choice*/ + /*use a-z in this case only*/ + return (char)((rand() % (90 - 65 + 1)) + 65); +} + +int notify_lock(bool lock){/*0 for unlock, 1 for lock. Function relies on notify-osd*/ + notify_init("Xtrlock"); + + if(lock){ + NotifyNotification* nlock = notify_notification_new ("Successfully Locked", + "The screen has been locked", + 0); + notify_notification_set_timeout(nlock, 1000); /* 1 second. Seems to be ignored by some severs*/ +#ifdef LOCK_IMG_PATH + GError* err = NULL; + GdkPixbuf* pixlock = gdk_pixbuf_new_from_file(LOCK_IMG_PATH, &err); + if(!err && pixlock){ + notify_notification_set_image_from_pixbuf(nlock, pixlock); + debug_print("Successfully load image\n"); + } + else{ + fprintf(stderr,"Failed to read notification icon: "); + *err->message? fprintf(stderr,"%s\n",err->message) : fprintf(stderr,"Nothing to show\n"); + g_error_free(err); + } +#endif + if (!notify_notification_show(nlock, 0)){ + fprintf(stderr, "Fail to notify\n"); + return -1; + } + } + else{ + NotifyNotification* nunlock = notify_notification_new ("Successfully Unlocked", + "The screen has been unlocked", + 0); + notify_notification_set_timeout(nunlock, 1000); +#ifdef UNLOCK_IMG_PATH + GError* err = NULL; + GdkPixbuf* pixunlock = gdk_pixbuf_new_from_file(UNLOCK_IMG_PATH, &err); + if(!err && pixunlock){ + notify_notification_set_image_from_pixbuf(nunlock, pixunlock); + debug_print("Successfully load image\n"); + } + else{ + fprintf(stderr,"Failed to read notification icon: "); + *err->message? fprintf(stderr,"%s\n",err->message) : fprintf(stderr,"Nothing to show\n"); + g_error_free(err); + } #endif + if (!notify_notification_show(nunlock, 0)){ + fprintf(stderr, "Fail to notify\n"); + return -1; + } + } + return 0; } -int main(int argc, char **argv){ - XEvent ev; - KeySym ks; - char cbuf[10], rbuf[128]; /* shadow appears to suggest 127 a good value here */ - int clen, rlen=0; - long goodwill= INITIALGOODWILL, timeout= 0; - XSetWindowAttributes attrib; - Cursor cursor; - Pixmap csr; - XColor xcolor; - int ret; - static char csr_bits[] = {0x00}; +int lock() +{ + XEvent ev; + KeySym ks; + char cbuf[10], rbuf[128]; /* shadow appears to suggest 127 a good value here */ + int clen, rlen = 0; + long goodwill = INITIALGOODWILL, timeout = 0; + XSetWindowAttributes attrib; + Cursor cursor; + Pixmap csr; + XColor xcolor; + int ret; + static char csr_bits[] = { 0x00 }; + struct timeval tv; + int tvt, gs; + + if (!cust_pw_setting.enable) { + debug_print("Sensing user pwd\n"); #ifdef SHADOW_PWD - struct spwd *sp; + struct spwd* sp; #endif - struct timeval tv; - int tvt, gs; - - if (argc != 1) { - fprintf(stderr,"xtrlock: no arguments allowed\n"); - exit(1); - } - - errno=0; pw= getpwuid(getuid()); - if (!pw) { perror("password entry for uid not found"); exit(1); } + errno = 0; + pw = getpwuid(getuid()); + if (!pw) { + perror("password entry for uid not found"); + exit(1); + } #ifdef SHADOW_PWD - sp = getspnam(pw->pw_name); - if (sp) - pw->pw_passwd = sp->sp_pwdp; - endspent(); + sp = getspnam(pw->pw_name); + if (sp) + pw->pw_passwd = sp->sp_pwdp; + endspent(); #endif - /* logically, if we need to do the following then the same - applies to being installed setgid shadow. - we do this first, because of a bug in linux. --jdamery */ - setgid(getgid()); - /* we can be installed setuid root to support shadow passwords, - and we don't need root privileges any longer. --marekm */ - setuid(getuid()); - - if (strlen(pw->pw_passwd) < 13) { - fputs("password entry has no pwd\n",stderr); exit(1); - } - - display= XOpenDisplay(0); - - if (display==NULL) { - fprintf(stderr,"xtrlock: cannot open display\n"); - exit(1); - } - - attrib.override_redirect= True; - window= XCreateWindow(display,DefaultRootWindow(display), - 0,0,1,1,0,CopyFromParent,InputOnly,CopyFromParent, - CWOverrideRedirect,&attrib); - - XSelectInput(display,window,KeyPressMask|KeyReleaseMask); - - - - csr= XCreateBitmapFromData(display,window,csr_bits,1,1); - - cursor= XCreatePixmapCursor(display,csr,csr,&xcolor,&xcolor,1,1); - - XMapWindow(display,window); - - /*Sometimes the WM doesn't ungrab the keyboard quickly enough if - *launching xtrlock from a keystroke shortcut, meaning xtrlock fails - *to start We deal with this by waiting (up to 100 times) for 10,000 - *microsecs and trying to grab each time. If we still fail - *(i.e. after 1s in total), then give up, and emit an error - */ - - gs=0; /*gs==grab successful*/ - for (tvt=0 ; tvt<100; tvt++) { - ret = XGrabKeyboard(display,window,False,GrabModeAsync,GrabModeAsync, - CurrentTime); - if (ret == GrabSuccess) { - gs=1; - break; - } - /*grab failed; wait .01s*/ - tv.tv_sec=0; - tv.tv_usec=10000; - select(1,NULL,NULL,NULL,&tv); - } - if (gs==0){ - fprintf(stderr,"xtrlock: cannot grab keyboard\n"); - exit(1); - } - - if (XGrabPointer(display,window,False,(KeyPressMask|KeyReleaseMask)&0, - GrabModeAsync,GrabModeAsync,None, - cursor,CurrentTime)!=GrabSuccess) { - XUngrabKeyboard(display,CurrentTime); - fprintf(stderr,"xtrlock: cannot grab pointer\n"); - exit(1); - } - - for (;;) { - XNextEvent(display,&ev); - switch (ev.type) { - case KeyPress: - if (ev.xkey.time < timeout) { XBell(display,0); break; } - clen= XLookupString(&ev.xkey,cbuf,9,&ks,0); - switch (ks) { - case XK_Escape: case XK_Clear: - rlen=0; break; - case XK_Delete: case XK_BackSpace: - if (rlen>0) rlen--; - break; - case XK_Linefeed: case XK_Return: - if (rlen==0) break; - rbuf[rlen]=0; - if (passwordok(rbuf)) goto loop_x; - XBell(display,0); - rlen= 0; - if (timeout) { - goodwill+= ev.xkey.time - timeout; - if (goodwill > MAXGOODWILL) { - goodwill= MAXGOODWILL; - } + /* logically, if we need to do the following then the same + applies to being installed setgid shadow. + we do this first, because of a bug in linux. --jdamery */ + setgid(getgid()); + /* we can be installed setuid root to support shadow passwords, + and we don't need root privileges any longer. --marekm */ + setuid(getuid()); + + if (strlen(pw->pw_passwd) <= 1) { /*mark as 'x', which means shadow password is enabled.*/ + fputs("password entry has no pwd\n", stderr); + exit(1); + } + debug_print("Passwd sensed:%s\n", pw->pw_passwd); + } + display = XOpenDisplay(0); + + if (display == NULL) { + fprintf(stderr, "xtrlock: cannot open display\n"); + exit(1); + } + + attrib.override_redirect = True; + attrib.background_pixel = BlackPixel(display, DefaultScreen(display)); + + blank_window = XCreateWindow(display, DefaultRootWindow(display), /*init blank window*/ + 0, 0, DisplayWidth(display, DefaultScreen(display)), + DisplayHeight(display, DefaultScreen(display)), + 0, DefaultDepth(display, DefaultScreen(display)), CopyFromParent, DefaultVisual(display, DefaultScreen(display)), + CWOverrideRedirect | CWBackPixel, &attrib); + + trans_window = XCreateWindow(display, DefaultRootWindow(display), /*init window identical to Background*/ + 0, 0, 1, 1, 0, CopyFromParent, InputOnly, CopyFromParent, + CWOverrideRedirect, &attrib); + + window = trans_window; + + XSelectInput(display, window, KeyPressMask | KeyReleaseMask); + + csr = XCreateBitmapFromData(display, window, csr_bits, 1, 1); + + cursor = XCreatePixmapCursor(display, csr, csr, &xcolor, &xcolor, 1, 1); + + XMapWindow(display, window); + + /*Sometimes the WM doesn't ungrab the keyboard quickly enough if + *launching xtrlock from a keystroke shortcut, meaning xtrlock fails + *to start We deal with this by waiting (up to 100 times) for 10,000 + *microsecs and trying to grab each time. If we still fail + *(i.e. after 1s in total), then give up, and emit an error. + *Also, only blank the screen to indicate a success lock. + */ + + gs = 0; /*gs==grab successful*/ + for (tvt = 0; tvt < 100; tvt++) { + ret = XGrabKeyboard(display, window, False, GrabModeAsync, GrabModeAsync, + CurrentTime); + if (ret == GrabSuccess) { + gs = 1; + break; + } + /*grab failed; wait .01s*/ + tv.tv_sec = 0; + tv.tv_usec = 10000; + select(1, NULL, NULL, NULL, &tv); + } + if (gs == 0) { + fprintf(stderr, "xtrlock: cannot grab keyboard\n"); + exit(1); + } + + if (XGrabPointer(display, window, False, (KeyPressMask | KeyReleaseMask) & 0, + GrabModeAsync, GrabModeAsync, None, + cursor, CurrentTime) + != GrabSuccess) { + XUngrabKeyboard(display, CurrentTime); + fprintf(stderr, "xtrlock: cannot grab pointer\n"); + exit(1); + } + + if (!blank_screen && blink_delay != 0) { /*blink to indicate a successful lock*/ + XMapWindow(display, blank_window); + XFlush(display); + msleep(blink_delay); /*0.1s as default, or custom value*/ + XUnmapWindow(display, blank_window); + debug_print("Unmapped after %i u seconds\n", blink_delay); + XMapWindow(display, trans_window); + XFlush(display); + debug_print("locked and blinked\n"); + } + + if(blank_screen){ + XMapWindow(display, blank_window); + } + + if(send_notification){ + notify_lock(true); + } + printf("Successfully locked\n"); + + for (;;) { /*start checker loop*/ + XNextEvent(display, &ev); + switch (ev.type) { + case KeyPress: + if (ev.xkey.time < timeout) { + XBell(display, 0); + break; + } + clen = XLookupString(&ev.xkey, cbuf, 9, &ks, 0); + switch (ks) { + case XK_Escape: + case XK_Clear: + rlen = 0; + break; + case XK_Delete: + case XK_BackSpace: + if (rlen > 0) + rlen--; + break; + case XK_Linefeed: + case XK_Return: + if (rlen == 0) + break; + else + rbuf[rlen] = 0; + if (passwordok(rbuf)) + goto loop_x; + XBell(display, 0); + rlen = 0; + if (timeout) { + goodwill += ev.xkey.time - timeout; + if (goodwill > MAXGOODWILL) { + goodwill = MAXGOODWILL; + } + } + timeout = -goodwill * GOODWILLPORTION; + goodwill += timeout; + timeout += ev.xkey.time + TIMEOUTPERATTEMPT; + break; + default: + if (clen != 1) + break; + /* allow space for the trailing \0 */ + if (rlen < (sizeof(rbuf) - 1)) { + rbuf[rlen] = cbuf[0]; + rlen++; + } + break; + } + break; + + default: + break; + } + } /*end checker loop*/ +loop_x: /*loop exit*/ + if(send_notification){ + notify_lock(false); + } + notify_uninit(); + exit(0); +} + +int main(int argc, char** argv) +{ /*TODO: Add keeper process*/ + /*TODO: On lid close*/ + /*TODO: Record failed trails*/ + errno = 0; + bool need_lock = false; + cust_pw_setting.enable = false; + + FILE* fp_dev_rand = NULL; + fp_dev_rand = fopen("/dev/urandom", "r"); + if (!fp_dev_rand) { + fprintf(stderr, "failed to open /dev/random: %s\n", strerror(errno)); + exit(1); + } + unsigned int seed; + fread(&seed, sizeof(int), 1, fp_dev_rand); + debug_print("Read seed from /dev/rand: %u\n", seed); + srand(seed); + fclose(fp_dev_rand); + + static struct option long_options[] = + { + {"help", no_argument, NULL, 'h'}, + {"password", required_argument, NULL, 'p'}, + {"encrypted-password", required_argument, NULL, 'e'}, + {"calculate", required_argument, NULL, 'c'}, + {"lock-user-password", no_argument, NULL, 'l'}, + {"block-screen", no_argument, NULL, 'b'}, + {"delay-of-blink", required_argument, NULL, 'd'}, + {"notify", no_argument, NULL, 'n'}, + {NULL, 0, NULL, 0} + }; + char opt = 0; + //while ((opt = getopt(argc, argv, "hp:e:c:lbd:n")) != -1) { + while ((opt = getopt_long(argc, argv, "hp:e:c:lbd:n", long_options, NULL)) != -1) { + debug_print("Processing args: \"%c|%c\"\n", opt, optopt); + + if ('h' == opt) { /*help(no arg)*/ + print_help(); + exit(0); + } + if ('p' == opt) { /*custom pwd without encryption*/ + char f_salt[3] = { rand_ch(), rand_ch(), '\0' }; + debug_print("salt_generated: %s\n", f_salt); + cust_pw_setting.enable = true; + cust_pw_setting.pwd = strdup(crypt(optarg, f_salt)); /*never freed, fine in this case*/ + need_lock = true; + if (NULL == cust_pw_setting.pwd) { + fprintf(stderr, "strdup:%s\n", strerror(errno)); + exit(-1); + } + } + if ('e' == opt) { /*custom pwd encrypted already*/ + cust_pw_setting.enable = true; + cust_pw_setting.pwd = optarg; + need_lock = true; + } + if ('c' == opt) { /*encryption of pwd*/ + char f_salt[2] = { rand_ch(), rand_ch() }; + printf("%s\n", crypt(optarg, f_salt)); + exit(0); + } + if ('l' == opt) { /*lock with user default password after delay(no arg)*/ + debug_print("locked immidiently\n"); + need_lock = true; + } + if ('b' == opt) { /*lock with a blank screen(no arg)*/ + blank_screen = true; + debug_print("blank_screen mode \n"); + } + if ('d' == opt) { /*delay of screen blinks*/ + blink_delay = atoi(optarg); + if (blink_delay < 0) { + fprintf(stderr, "Delay value not valid\n"); + exit(1); + } + } + if('n' == opt){/*send notification*/ + send_notification = true; + } + if('?' == opt){ + print_help(); + exit(1); + } } - timeout= -goodwill*GOODWILLPORTION; - goodwill+= timeout; - timeout+= ev.xkey.time + TIMEOUTPERATTEMPT; - break; - default: - if (clen != 1) break; - /* allow space for the trailing \0 */ - if (rlen < (sizeof(rbuf) - 1)){ - rbuf[rlen]=cbuf[0]; - rlen++; - } - break; - } - break; - default: - break; - } - } - loop_x: - exit(0); + if (need_lock) + lock(); + print_help(); + exit(1); } diff --git a/xtrlock.man b/xtrlock.man index 72122b3..2814cc0 100644 --- a/xtrlock.man +++ b/xtrlock.man @@ -2,7 +2,7 @@ .SH NAME xtrlock \- Lock X display until password supplied, leaving windows visible .SH SYNOPSIS -.B xtrlock +.B A modified version of xtrlock with more functions implemented. .SH DESCRIPTION .B xtrlock locks the X server till the user enters their password at the keyboard. @@ -25,7 +25,61 @@ generate bells and are otherwise ignored until a timeout has expired. The X server screen saver continues to operate normally; if it comes into operation the display may be restored by the usual means of touching a key (Shift, for example) or the mouse. -.SH OPTIONS, X RESOURCES, CONFIGURATION + +This program now allows user to use their own password instead of +the default user password, which often is also used for other things +such as root access via sudo(for many desktop users, I know that!) +that one may not want to reveal. Using another password and share it +with your friend could solved this. + +To use this program with keyboard shortcuts, try tools like xbindkeys. +However, to encrypt the password in the config files of the binding +tools, one may want to use the -c flag to encrypt the password string +and pass the encrypted string with the -e flag. + +To lock and cover the screen completely as what a normal screen lock +does instead of exposing the screen, pass the -b flag. + +To receive a desktop notification on lock and unlock. The notification +usually appears at the right up corner of the screen and last one +second as default, this may vary according to the notification server +used. The image displayed on the notification is located at the /usr/share/xtrlock +by default. Feel free to change the image by replacing the lock.png or +unlock.png with the replacement. + +Also, in order to notify the user that the screen has been successfully +locked, the screen will be blinked (which can be configured with -d +option) on successful locks under normal mode. While the -b flag is passed, +the screen will only be covered on successful locks. +[If the worse comes to the worst, use ++ and login to kill +this program...] + +.SH OPTIONS: + -h --help show this help + + -l --lock-user-password lock immediately with + the user's default password + + -p --password [password_string] use custom non-encrypted + password + + -e --encrypted-password [password_hash] use encrypted custom password + with salt of itself + + -c --calculate [password_string] calculate the password string + that can be used with the "-c" + option + + -b --block-screen lock with a blank screen + + -d --delay of blink [delay_usec] milliseconds the screen blinks + on successful locks + (0 for no-delay & 100000 for 0.1 s) + + -n --notify send message notification on + lock and unlock + +.SH X RESOURCES, CONFIGURATION: None. .SH BUGS Additional input devices other than the keyboard and mouse are not