diff options
Diffstat (limited to 'swaylock/main.c')
-rw-r--r-- | swaylock/main.c | 55 |
1 files changed, 25 insertions, 30 deletions
diff --git a/swaylock/main.c b/swaylock/main.c index c2615951..f1c75e22 100644 --- a/swaylock/main.c +++ b/swaylock/main.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <stdio.h> | 7 | #include <stdio.h> |
8 | #include <stdlib.h> | 8 | #include <stdlib.h> |
9 | #include <string.h> | 9 | #include <string.h> |
10 | #include <sys/mman.h> | ||
10 | #include <sys/types.h> | 11 | #include <sys/types.h> |
11 | #include <pwd.h> | 12 | #include <pwd.h> |
12 | #include <getopt.h> | 13 | #include <getopt.h> |
@@ -56,8 +57,7 @@ void sway_terminate(int exit_code) { | |||
56 | exit(exit_code); | 57 | exit(exit_code); |
57 | } | 58 | } |
58 | 59 | ||
59 | char *password; | 60 | char password[1024]; |
60 | int password_size; | ||
61 | enum line_source line_source = LINE_SOURCE_DEFAULT; | 61 | enum line_source line_source = LINE_SOURCE_DEFAULT; |
62 | 62 | ||
63 | struct lock_config *init_config() { | 63 | struct lock_config *init_config() { |
@@ -115,7 +115,7 @@ int function_conversation(int num_msg, const struct pam_message **msg, | |||
115 | switch (msg[i]->msg_style) { | 115 | switch (msg[i]->msg_style) { |
116 | case PAM_PROMPT_ECHO_OFF: | 116 | case PAM_PROMPT_ECHO_OFF: |
117 | case PAM_PROMPT_ECHO_ON: | 117 | case PAM_PROMPT_ECHO_ON: |
118 | pam_reply[i].resp = password; | 118 | pam_reply[i].resp = strdup(password); // PAM clears and frees this |
119 | break; | 119 | break; |
120 | 120 | ||
121 | case PAM_ERROR_MSG: | 121 | case PAM_ERROR_MSG: |
@@ -127,9 +127,15 @@ int function_conversation(int num_msg, const struct pam_message **msg, | |||
127 | return PAM_SUCCESS; | 127 | return PAM_SUCCESS; |
128 | } | 128 | } |
129 | 129 | ||
130 | /** | 130 | void clear_password_buffer() { |
131 | * Note: PAM will free() 'password' during the process | 131 | // Use volatile keyword so so compiler can't optimize this out. |
132 | */ | 132 | volatile char *pw = password; |
133 | volatile char zero = '\0'; | ||
134 | for (size_t i = 0; i < sizeof(password); ++i) { | ||
135 | pw[i] = zero; | ||
136 | } | ||
137 | } | ||
138 | |||
133 | bool verify_password() { | 139 | bool verify_password() { |
134 | struct passwd *passwd = getpwuid(getuid()); | 140 | struct passwd *passwd = getpwuid(getuid()); |
135 | char *username = passwd->pw_name; | 141 | char *username = passwd->pw_name; |
@@ -151,8 +157,7 @@ bool verify_password() { | |||
151 | 157 | ||
152 | void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t code, uint32_t codepoint) { | 158 | void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t code, uint32_t codepoint) { |
153 | int redraw_screen = 0; | 159 | int redraw_screen = 0; |
154 | char *password_realloc; | 160 | size_t i; |
155 | int i; | ||
156 | 161 | ||
157 | if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { | 162 | if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { |
158 | switch (sym) { | 163 | switch (sym) { |
@@ -165,14 +170,14 @@ void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t cod | |||
165 | wl_dispatch_events(); | 170 | wl_dispatch_events(); |
166 | 171 | ||
167 | if (verify_password()) { | 172 | if (verify_password()) { |
173 | clear_password_buffer(); | ||
168 | exit(0); | 174 | exit(0); |
169 | } | 175 | } |
170 | 176 | ||
171 | render_data.auth_state = AUTH_STATE_INVALID; | 177 | render_data.auth_state = AUTH_STATE_INVALID; |
172 | redraw_screen = 1; | 178 | redraw_screen = 1; |
173 | 179 | ||
174 | password_size = 1024; | 180 | clear_password_buffer(); |
175 | password = malloc(password_size); | ||
176 | password[0] = '\0'; | 181 | password[0] = '\0'; |
177 | break; | 182 | break; |
178 | case XKB_KEY_BackSpace: | 183 | case XKB_KEY_BackSpace: |
@@ -207,9 +212,7 @@ void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t cod | |||
207 | render_data.auth_state = AUTH_STATE_BACKSPACE; | 212 | render_data.auth_state = AUTH_STATE_BACKSPACE; |
208 | redraw_screen = 1; | 213 | redraw_screen = 1; |
209 | 214 | ||
210 | password_size = 1024; | 215 | clear_password_buffer(); |
211 | free(password); | ||
212 | password = malloc(password_size); | ||
213 | password[0] = '\0'; | 216 | password[0] = '\0'; |
214 | break; | 217 | break; |
215 | } | 218 | } |
@@ -218,22 +221,10 @@ void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t cod | |||
218 | render_data.auth_state = AUTH_STATE_INPUT; | 221 | render_data.auth_state = AUTH_STATE_INPUT; |
219 | redraw_screen = 1; | 222 | redraw_screen = 1; |
220 | i = strlen(password); | 223 | i = strlen(password); |
221 | if (i + 1 == password_size) { | 224 | if (i + 1 < sizeof(password)) { |
222 | password_size += 1024; | 225 | password[i] = (char)codepoint; |
223 | password_realloc = realloc(password, password_size); | 226 | password[i + 1] = '\0'; |
224 | // reset password if realloc fails. | ||
225 | if (password_realloc == NULL) { | ||
226 | password_size = 1024; | ||
227 | free(password); | ||
228 | password = malloc(password_size); | ||
229 | password[0] = '\0'; | ||
230 | break; | ||
231 | } else { | ||
232 | password = password_realloc; | ||
233 | } | ||
234 | } | 227 | } |
235 | password[i] = (char)codepoint; | ||
236 | password[i + 1] = '\0'; | ||
237 | break; | 228 | break; |
238 | } | 229 | } |
239 | if (redraw_screen) { | 230 | if (redraw_screen) { |
@@ -535,8 +526,12 @@ int main(int argc, char **argv) { | |||
535 | sway_abort("Unsupported scaling mode: %s", scaling_mode_str); | 526 | sway_abort("Unsupported scaling mode: %s", scaling_mode_str); |
536 | } | 527 | } |
537 | 528 | ||
538 | password_size = 1024; | 529 | #ifdef __linux__ |
539 | password = malloc(password_size); | 530 | // Most non-linux platforms require root to mlock() |
531 | if (mlock(password, sizeof(password)) != 0) { | ||
532 | sway_abort("Unable to mlock() password memory."); | ||
533 | } | ||
534 | #endif | ||
540 | password[0] = '\0'; | 535 | password[0] = '\0'; |
541 | render_data.surfaces = create_list(); | 536 | render_data.surfaces = create_list(); |
542 | if (!socket_path) { | 537 | if (!socket_path) { |