@@ -23,7 +23,9 @@ limitations under the License.
2323#include <sys/select.h> // for timeval, select, fd_set, FD_SET
2424#include <sys/time.h> // for gettimeofday, timeval
2525#include <time.h> // for time, nanosleep, localtime_r
26- #include <unistd.h> // for close, _exit, dup2, pipe, dup
26+ #include <signal.h> // for SIGTERM
27+ #include <unistd.h> // for close, _exit, dup2, pipe, dup,
28+ // STDIN_FILENO, STDOUT_FILENO
2729
2830#if __STDC_VERSION__ >= 199901L
2931#include <inttypes.h>
@@ -75,6 +77,9 @@ const char *authproto_executable;
7577//! The maximum time to wait at a prompt for user input in seconds.
7678int prompt_timeout ;
7779
80+ //! Whether to kill the authproto after prompt timeout is reached.
81+ int kill_authproto_after_timeout ;
82+
7883//! Number of dancers in the disco password display
7984#define DISCO_PASSWORD_DANCERS 5
8085
@@ -821,8 +826,10 @@ void BuildTitle(char *output, size_t output_size, const char *input) {
821826 * \param title The title of the message.
822827 * \param str The message itself.
823828 * \param is_warning Whether to use the warning style to display the message.
829+ * \param show_kbd_indicators Whether to show kbd indicators (like Caps Lock).
824830 */
825- void DisplayMessage (const char * title , const char * str , int is_warning ) {
831+ void DisplayMessage (const char * title , const char * str , int is_warning ,
832+ int show_kbd_indicators ) {
826833 char full_title [256 ];
827834 BuildTitle (full_title , sizeof (full_title ), title );
828835
@@ -837,8 +844,8 @@ void DisplayMessage(const char *title, const char *str, int is_warning) {
837844
838845 int indicators_warning = 0 ;
839846 int have_multiple_layouts = 0 ;
840- const char * indicators =
841- GetIndicators (& indicators_warning , & have_multiple_layouts );
847+ const char * indicators = show_kbd_indicators ?
848+ GetIndicators (& indicators_warning , & have_multiple_layouts ) : "" ;
842849 int len_indicators = strlen (indicators );
843850 int tw_indicators = TextWidth (indicators , len_indicators );
844851
@@ -1026,6 +1033,88 @@ void ShowFromArray(const char **array, size_t displaymarker, char *displaybuf,
10261033 * displaylen = strlen (selection );
10271034}
10281035
1036+ /*! \brief Shows the user a static message such as a PAM text info or error
1037+ *
1038+ * \param title The title of the message.
1039+ * \param msg The message itself.
1040+ * \param is_warning Whether to use the warning style to display the message.
1041+ * \param extra_read_fd Pass an extra fd to monitor so in case something is
1042+ * written to it, we can capture and return immediatelly.
1043+ * \return 1 if successful, anything else otherwise.
1044+ */
1045+ int PromptStaticMessage (const char * title , const char * msg , int is_warning , int extra_read_fd ) {
1046+ XEvent x11_ev ;
1047+ char inputbuf ;
1048+ int result = 1 ;
1049+ time_t deadline = time (NULL ) + prompt_timeout ; // global variable
1050+
1051+ PlaySound (is_warning ? SOUND_ERROR : SOUND_INFO );
1052+
1053+ while (1 ) {
1054+ DisplayMessage (title , msg , is_warning , 0 );
1055+
1056+ // Blocks waiting for user input or activity on extra_read_fd
1057+ struct timeval timeout ;
1058+ timeout .tv_sec = 0 ;
1059+ timeout .tv_usec = BLINK_INTERVAL ;
1060+ fd_set set ;
1061+ memset (& set , 0 , sizeof (set )); // For clang-analyzer.
1062+ FD_ZERO (& set );
1063+ FD_SET (STDIN_FILENO , & set );
1064+ int max_nfds = 0 ;
1065+ if (extra_read_fd >= 1 ) {
1066+ FD_SET (extra_read_fd , & set );
1067+ max_nfds = extra_read_fd ;
1068+ }
1069+ int nfds = select (max_nfds + 1 , & set , NULL , NULL , & timeout );
1070+
1071+ if (nfds < 0 ) {
1072+ LogErrno ("select" );
1073+ break ;
1074+ }
1075+
1076+ time_t now = time (NULL );
1077+ if (now > deadline ) {
1078+ Log ("AUTH_TIMEOUT hit" );
1079+ result = 0 ;
1080+ break ;
1081+ }
1082+
1083+ // Select timeout reached, means we just re-render and continue the loop
1084+ if (nfds == 0 ) {
1085+ continue ;
1086+ }
1087+
1088+ // Reset the prompt timeout, so we keep the screen on if a key is pressed
1089+ deadline = now + prompt_timeout ;
1090+
1091+ // If extra_read_fd is available for reading, then we return immediatelly
1092+ if (FD_ISSET (extra_read_fd , & set )) {
1093+ break ;
1094+ }
1095+
1096+ // Reads user input, but stops on EOF
1097+ if (read (STDIN_FILENO , & inputbuf , 1 ) <= 0 ) {
1098+ break ;
1099+ }
1100+
1101+ // And if the user types Esc, then we quit
1102+ if (inputbuf == '\033' ) {
1103+ result = 0 ;
1104+ break ;
1105+ }
1106+ }
1107+
1108+ // Handle X11 events that queued up.
1109+ while (XPending (display ) && (XNextEvent (display , & x11_ev ), 1 )) {
1110+ if (IsMonitorChangeEvent (display , x11_ev .type )) {
1111+ per_monitor_windows_dirty = 1 ; // global variable
1112+ }
1113+ }
1114+
1115+ return result ;
1116+ }
1117+
10291118/*! \brief Ask a question to the user.
10301119 *
10311120 * \param msg The message.
@@ -1074,7 +1163,7 @@ int Prompt(const char *msg, char **response, int echo) {
10741163 LogErrno ("mlock" );
10751164 // We continue anyway, as the user being unable to unlock the screen is
10761165 // worse. But let's alert the user.
1077- DisplayMessage ("Error" , "Password will not be stored securely." , 1 );
1166+ DisplayMessage ("Error" , "Password will not be stored securely." , 1 , 1 );
10781167 WaitForKeypress (1 );
10791168 }
10801169
@@ -1204,7 +1293,7 @@ int Prompt(const char *msg, char **response, int echo) {
12041293 }
12051294 }
12061295 }
1207- DisplayMessage (msg , priv .displaybuf , 0 );
1296+ DisplayMessage (msg , priv .displaybuf , 0 , 1 );
12081297
12091298 if (!played_sound ) {
12101299 PlaySound (SOUND_PROMPT );
@@ -1314,7 +1403,7 @@ int Prompt(const char *msg, char **response, int echo) {
13141403 // We continue anyway, as the user being unable to unlock the screen
13151404 // is worse. But let's alert the user of this.
13161405 DisplayMessage ("Error" , "Password has not been stored securely." ,
1317- 1 );
1406+ 1 , 1 );
13181407 WaitForKeypress (1 );
13191408 }
13201409 if (priv .pwlen != 0 ) {
@@ -1446,18 +1535,20 @@ int Authenticate() {
14461535 char type = ReadPacket (requestfd [0 ], & message , 1 );
14471536 switch (type ) {
14481537 case PTYPE_INFO_MESSAGE :
1449- DisplayMessage ("PAM says" , message , 0 );
1538+ if (!PromptStaticMessage ("PAM message" , message , 0 , requestfd [0 ])) {
1539+ DisplayMessage ("Processing..." , "" , 0 , 0 );
1540+ if (kill_authproto_after_timeout ) {
1541+ kill (childpid , SIGTERM );
1542+ }
1543+ goto done ;
1544+ }
14501545 explicit_bzero (message , strlen (message ));
14511546 free (message );
1452- PlaySound (SOUND_INFO );
1453- WaitForKeypress (1 );
14541547 break ;
14551548 case PTYPE_ERROR_MESSAGE :
1456- DisplayMessage ("Error" , message , 1 );
1549+ PromptStaticMessage ("Error" , message , 1 , requestfd [ 0 ] );
14571550 explicit_bzero (message , strlen (message ));
14581551 free (message );
1459- PlaySound (SOUND_ERROR );
1460- WaitForKeypress (1 );
14611552 break ;
14621553 case PTYPE_PROMPT_LIKE_USERNAME :
14631554 if (Prompt (message , & response , 1 )) {
@@ -1469,7 +1560,7 @@ int Authenticate() {
14691560 }
14701561 explicit_bzero (message , strlen (message ));
14711562 free (message );
1472- DisplayMessage ("Processing..." , "" , 0 );
1563+ DisplayMessage ("Processing..." , "" , 0 , 1 );
14731564 break ;
14741565 case PTYPE_PROMPT_LIKE_PASSWORD :
14751566 if (Prompt (message , & response , 0 )) {
@@ -1481,7 +1572,7 @@ int Authenticate() {
14811572 }
14821573 explicit_bzero (message , strlen (message ));
14831574 free (message );
1484- DisplayMessage ("Processing..." , "" , 0 );
1575+ DisplayMessage ("Processing..." , "" , 0 , 1 );
14851576 break ;
14861577 case 0 :
14871578 goto done ;
@@ -1598,6 +1689,8 @@ int main(int argc_local, char **argv_local) {
15981689 GetIntSetting ("XSECURELOCK_BURNIN_MITIGATION_DYNAMIC" , 0 );
15991690
16001691 prompt_timeout = GetIntSetting ("XSECURELOCK_AUTH_TIMEOUT" , 5 * 60 );
1692+ kill_authproto_after_timeout =
1693+ GetIntSetting ("XSECURELOCK_AUTHPROTO_KILL_ON_TIMEOUT" , 0 );
16011694 show_username = GetIntSetting ("XSECURELOCK_SHOW_USERNAME" , 1 );
16021695 show_hostname = GetIntSetting ("XSECURELOCK_SHOW_HOSTNAME" , 1 );
16031696 paranoid_password_flag = GetIntSetting (
0 commit comments