@@ -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
@@ -825,8 +830,10 @@ void BuildTitle(char *output, size_t output_size, const char *input) {
825830 * \param title The title of the message.
826831 * \param str The message itself.
827832 * \param is_warning Whether to use the warning style to display the message.
833+ * \param show_kbd_indicators Whether to show kbd indicators (like Caps Lock).
828834 */
829- void DisplayMessage (const char * title , const char * str , int is_warning ) {
835+ void DisplayMessage (const char * title , const char * str , int is_warning ,
836+ int show_kbd_indicators ) {
830837 char full_title [256 ];
831838 BuildTitle (full_title , sizeof (full_title ), title );
832839
@@ -841,8 +848,8 @@ void DisplayMessage(const char *title, const char *str, int is_warning) {
841848
842849 int indicators_warning = 0 ;
843850 int have_multiple_layouts = 0 ;
844- const char * indicators =
845- GetIndicators (& indicators_warning , & have_multiple_layouts );
851+ const char * indicators = show_kbd_indicators ?
852+ GetIndicators (& indicators_warning , & have_multiple_layouts ) : "" ;
846853 int len_indicators = strlen (indicators );
847854 int tw_indicators = TextWidth (indicators , len_indicators );
848855
@@ -1030,6 +1037,88 @@ void ShowFromArray(const char **array, size_t displaymarker, char *displaybuf,
10301037 * displaylen = strlen (selection );
10311038}
10321039
1040+ /*! \brief Shows the user a static message such as a PAM text info or error
1041+ *
1042+ * \param title The title of the message.
1043+ * \param msg The message itself.
1044+ * \param is_warning Whether to use the warning style to display the message.
1045+ * \param extra_read_fd Pass an extra fd to monitor so in case something is
1046+ * written to it, we can capture and return immediatelly.
1047+ * \return 1 if successful, anything else otherwise.
1048+ */
1049+ int PromptStaticMessage (const char * title , const char * msg , int is_warning , int extra_read_fd ) {
1050+ XEvent x11_ev ;
1051+ char inputbuf ;
1052+ int result = 1 ;
1053+ time_t deadline = time (NULL ) + prompt_timeout ; // global variable
1054+
1055+ PlaySound (is_warning ? SOUND_ERROR : SOUND_INFO );
1056+
1057+ while (1 ) {
1058+ DisplayMessage (title , msg , is_warning , 0 );
1059+
1060+ // Blocks waiting for user input or activity on extra_read_fd
1061+ struct timeval timeout ;
1062+ timeout .tv_sec = 0 ;
1063+ timeout .tv_usec = BLINK_INTERVAL ;
1064+ fd_set set ;
1065+ memset (& set , 0 , sizeof (set )); // For clang-analyzer.
1066+ FD_ZERO (& set );
1067+ FD_SET (STDIN_FILENO , & set );
1068+ int max_nfds = 0 ;
1069+ if (extra_read_fd >= 1 ) {
1070+ FD_SET (extra_read_fd , & set );
1071+ max_nfds = extra_read_fd ;
1072+ }
1073+ int nfds = select (max_nfds + 1 , & set , NULL , NULL , & timeout );
1074+
1075+ if (nfds < 0 ) {
1076+ LogErrno ("select" );
1077+ break ;
1078+ }
1079+
1080+ time_t now = time (NULL );
1081+ if (now > deadline ) {
1082+ Log ("AUTH_TIMEOUT hit" );
1083+ result = 0 ;
1084+ break ;
1085+ }
1086+
1087+ // Select timeout reached, means we just re-render and continue the loop
1088+ if (nfds == 0 ) {
1089+ continue ;
1090+ }
1091+
1092+ // Reset the prompt timeout, so we keep the screen on if a key is pressed
1093+ deadline = now + prompt_timeout ;
1094+
1095+ // If extra_read_fd is available for reading, then we return immediatelly
1096+ if (FD_ISSET (extra_read_fd , & set )) {
1097+ break ;
1098+ }
1099+
1100+ // Reads user input, but stops on EOF
1101+ if (read (STDIN_FILENO , & inputbuf , 1 ) <= 0 ) {
1102+ break ;
1103+ }
1104+
1105+ // And if the user types Esc, then we quit
1106+ if (inputbuf == '\033' ) {
1107+ result = 0 ;
1108+ break ;
1109+ }
1110+ }
1111+
1112+ // Handle X11 events that queued up.
1113+ while (XPending (display ) && (XNextEvent (display , & x11_ev ), 1 )) {
1114+ if (IsMonitorChangeEvent (display , x11_ev .type )) {
1115+ per_monitor_windows_dirty = 1 ; // global variable
1116+ }
1117+ }
1118+
1119+ return result ;
1120+ }
1121+
10331122/*! \brief Ask a question to the user.
10341123 *
10351124 * \param msg The message.
@@ -1078,7 +1167,7 @@ int Prompt(const char *msg, char **response, int echo) {
10781167 LogErrno ("mlock" );
10791168 // We continue anyway, as the user being unable to unlock the screen is
10801169 // worse. But let's alert the user.
1081- DisplayMessage ("Error" , "Password will not be stored securely." , 1 );
1170+ DisplayMessage ("Error" , "Password will not be stored securely." , 1 , 1 );
10821171 WaitForKeypress (1 );
10831172 }
10841173
@@ -1208,7 +1297,7 @@ int Prompt(const char *msg, char **response, int echo) {
12081297 }
12091298 }
12101299 }
1211- DisplayMessage (msg , priv .displaybuf , 0 );
1300+ DisplayMessage (msg , priv .displaybuf , 0 , 1 );
12121301
12131302 if (!played_sound ) {
12141303 PlaySound (SOUND_PROMPT );
@@ -1318,7 +1407,7 @@ int Prompt(const char *msg, char **response, int echo) {
13181407 // We continue anyway, as the user being unable to unlock the screen
13191408 // is worse. But let's alert the user of this.
13201409 DisplayMessage ("Error" , "Password has not been stored securely." ,
1321- 1 );
1410+ 1 , 1 );
13221411 WaitForKeypress (1 );
13231412 }
13241413 if (priv .pwlen != 0 ) {
@@ -1450,18 +1539,20 @@ int Authenticate() {
14501539 char type = ReadPacket (requestfd [0 ], & message , 1 );
14511540 switch (type ) {
14521541 case PTYPE_INFO_MESSAGE :
1453- DisplayMessage ("PAM says" , message , 0 );
1542+ if (!PromptStaticMessage ("PAM message" , message , 0 , requestfd [0 ])) {
1543+ DisplayMessage ("Processing..." , "" , 0 , 0 );
1544+ if (kill_authproto_after_timeout ) {
1545+ kill (childpid , SIGTERM );
1546+ }
1547+ goto done ;
1548+ }
14541549 explicit_bzero (message , strlen (message ));
14551550 free (message );
1456- PlaySound (SOUND_INFO );
1457- WaitForKeypress (1 );
14581551 break ;
14591552 case PTYPE_ERROR_MESSAGE :
1460- DisplayMessage ("Error" , message , 1 );
1553+ PromptStaticMessage ("Error" , message , 1 , requestfd [ 0 ] );
14611554 explicit_bzero (message , strlen (message ));
14621555 free (message );
1463- PlaySound (SOUND_ERROR );
1464- WaitForKeypress (1 );
14651556 break ;
14661557 case PTYPE_PROMPT_LIKE_USERNAME :
14671558 if (Prompt (message , & response , 1 )) {
@@ -1473,7 +1564,7 @@ int Authenticate() {
14731564 }
14741565 explicit_bzero (message , strlen (message ));
14751566 free (message );
1476- DisplayMessage ("Processing..." , "" , 0 );
1567+ DisplayMessage ("Processing..." , "" , 0 , 1 );
14771568 break ;
14781569 case PTYPE_PROMPT_LIKE_PASSWORD :
14791570 if (Prompt (message , & response , 0 )) {
@@ -1485,7 +1576,7 @@ int Authenticate() {
14851576 }
14861577 explicit_bzero (message , strlen (message ));
14871578 free (message );
1488- DisplayMessage ("Processing..." , "" , 0 );
1579+ DisplayMessage ("Processing..." , "" , 0 , 1 );
14891580 break ;
14901581 case 0 :
14911582 goto done ;
@@ -1602,6 +1693,8 @@ int main(int argc_local, char **argv_local) {
16021693 GetIntSetting ("XSECURELOCK_BURNIN_MITIGATION_DYNAMIC" , 0 );
16031694
16041695 prompt_timeout = GetIntSetting ("XSECURELOCK_AUTH_TIMEOUT" , 5 * 60 );
1696+ kill_authproto_after_timeout =
1697+ GetIntSetting ("XSECURELOCK_AUTHPROTO_KILL_ON_TIMEOUT" , 0 );
16051698 show_username = GetIntSetting ("XSECURELOCK_SHOW_USERNAME" , 1 );
16061699 show_hostname = GetIntSetting ("XSECURELOCK_SHOW_HOSTNAME" , 1 );
16071700 paranoid_password_flag = GetIntSetting (
0 commit comments