GCC Code Coverage Report


Directory: ./
File: panels/system/users/run-passwd.c
Date: 2024-05-04 07:58:27
Exec Total Coverage
Lines: 0 247 0.0%
Functions: 0 15 0.0%
Branches: 0 143 0.0%

Line Branch Exec Source
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* run-passwd.c: this file is part of users-admin, a gnome-system-tools frontend
3 * for user administration.
4 *
5 * Copyright (C) 2002 Diego Gonzalez
6 * Copyright (C) 2006 Johannes H. Jensen
7 * Copyright (C) 2010 Milan Bouchet-Valat
8 *
9 * Written by: Diego Gonzalez <diego@pemas.net>
10 * Modified by: Johannes H. Jensen <joh@deworks.net>,
11 * Milan Bouchet-Valat <nalimilan@club.fr>.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2, or (at your option)
16 * any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <http://www.gnu.org/licenses/>.
25 *
26 * Most of this code originally comes from gnome-about-me-password.c,
27 * from gnome-control-center.
28 */
29
30 #include <config.h>
31 #include <glib/gi18n.h>
32
33 #include <unistd.h>
34 #include <errno.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <sys/wait.h>
38
39 #if __sun
40 #include <sys/types.h>
41 #include <signal.h>
42 #endif
43
44 #include "run-passwd.h"
45
46 /* Passwd states */
47 typedef enum {
48 PASSWD_STATE_NONE, /* Passwd is not asking for anything */
49 PASSWD_STATE_AUTH, /* Passwd is asking for our current password */
50 PASSWD_STATE_NEW, /* Passwd is asking for our new password */
51 PASSWD_STATE_RETYPE, /* Passwd is asking for our retyped new password */
52 PASSWD_STATE_DONE, /* Passwd succeeded but has not yet exited */
53 PASSWD_STATE_ERR /* Passwd reported an error but has not yet exited */
54 } PasswdState;
55
56 struct PasswdHandler {
57 const char *current_password;
58 const char *new_password;
59
60 /* Communication with the passwd program */
61 GPid backend_pid;
62
63 GIOChannel *backend_stdin;
64 GIOChannel *backend_stdout;
65
66 GQueue *backend_stdin_queue; /* Write queue to backend_stdin */
67
68 /* GMainLoop IDs */
69 guint backend_child_watch_id; /* g_child_watch_add (PID) */
70 guint backend_stdout_watch_id; /* g_io_add_watch (stdout) */
71
72 /* State of the passwd program */
73 PasswdState backend_state;
74 gboolean changing_password;
75
76 PasswdCallback auth_cb;
77 gpointer auth_cb_data;
78
79 PasswdCallback chpasswd_cb;
80 gpointer chpasswd_cb_data;
81 };
82
83 /* Buffer size for backend output */
84 #define BUFSIZE 64
85
86
87 static GQuark
88 passwd_error_quark (void)
89 {
90 static GQuark q = 0;
91
92 if (q == 0) {
93 q = g_quark_from_static_string("passwd_error");
94 }
95
96 return q;
97 }
98
99 /* Error handling */
100 #define PASSWD_ERROR (passwd_error_quark ())
101
102
103 static void
104 stop_passwd (PasswdHandler *passwd_handler);
105
106 static void
107 free_passwd_resources (PasswdHandler *passwd_handler);
108
109 static gboolean
110 io_watch_stdout (GIOChannel *source, GIOCondition condition, PasswdHandler *passwd_handler);
111
112
113 /*
114 * Spawning and closing of backend {{
115 */
116
117 /* Child watcher */
118 static void
119 child_watch_cb (GPid pid, gint status, PasswdHandler *passwd_handler)
120 {
121 if (WIFEXITED (status)) {
122 if (WEXITSTATUS (status) >= 255) {
123 g_warning ("Child exited unexpectedly");
124 }
125 if (WEXITSTATUS (status) == 0) {
126 if (passwd_handler->backend_state == PASSWD_STATE_RETYPE) {
127 passwd_handler->backend_state = PASSWD_STATE_DONE;
128 if (passwd_handler->chpasswd_cb)
129 passwd_handler->chpasswd_cb (passwd_handler,
130 NULL,
131 passwd_handler->chpasswd_cb_data);
132 }
133 }
134 }
135
136 free_passwd_resources (passwd_handler);
137 }
138
139 static void
140 child_setup_cb (gpointer data)
141 {
142 signal (SIGPIPE, SIG_IGN);
143 dup2 (fileno (stdout), fileno (stderr));
144 }
145
146 /* Spawn passwd backend
147 * Returns: TRUE on success, FALSE otherwise and sets error appropriately */
148 static gboolean
149 spawn_passwd (PasswdHandler *passwd_handler, GError **error)
150 {
151 gchar *argv[2];
152 gchar **envp;
153 gint my_stdin, my_stdout;
154
155 argv[0] = "/usr/bin/passwd"; /* Is it safe to rely on a hard-coded path? */
156 argv[1] = NULL;
157
158 envp = g_get_environ ();
159 envp = g_environ_setenv (envp, "LC_ALL", "C", TRUE);
160
161 if (!g_spawn_async_with_pipes (NULL, /* Working directory */
162 argv, /* Argument vector */
163 envp, /* Environment */
164 G_SPAWN_DO_NOT_REAP_CHILD, /* Flags */
165 child_setup_cb, /* Child setup */
166 NULL, /* Data to child setup */
167 &passwd_handler->backend_pid, /* PID */
168 &my_stdin, /* Stdin */
169 &my_stdout, /* Stdout */
170 NULL, /* Stderr */
171 error)) { /* GError */
172
173 /* An error occurred */
174 free_passwd_resources (passwd_handler);
175
176 g_strfreev (envp);
177
178 return FALSE;
179 }
180
181 g_strfreev (envp);
182
183 /* Open IO Channels */
184 passwd_handler->backend_stdin = g_io_channel_unix_new (my_stdin);
185 passwd_handler->backend_stdout = g_io_channel_unix_new (my_stdout);
186
187 /* Set raw encoding */
188 /* Set nonblocking mode */
189 if (g_io_channel_set_encoding (passwd_handler->backend_stdin, NULL, error) != G_IO_STATUS_NORMAL ||
190 g_io_channel_set_encoding (passwd_handler->backend_stdout, NULL, error) != G_IO_STATUS_NORMAL ||
191 g_io_channel_set_flags (passwd_handler->backend_stdin, G_IO_FLAG_NONBLOCK, error) != G_IO_STATUS_NORMAL ||
192 g_io_channel_set_flags (passwd_handler->backend_stdout, G_IO_FLAG_NONBLOCK, error) != G_IO_STATUS_NORMAL ) {
193
194 /* Clean up */
195 stop_passwd (passwd_handler);
196 return FALSE;
197 }
198
199 /* Turn off buffering */
200 g_io_channel_set_buffered (passwd_handler->backend_stdin, FALSE);
201 g_io_channel_set_buffered (passwd_handler->backend_stdout, FALSE);
202
203 /* Add IO Channel watcher */
204 passwd_handler->backend_stdout_watch_id = g_io_add_watch (passwd_handler->backend_stdout,
205 G_IO_IN | G_IO_PRI,
206 (GIOFunc) io_watch_stdout, passwd_handler);
207
208 /* Add child watcher */
209 passwd_handler->backend_child_watch_id = g_child_watch_add (passwd_handler->backend_pid, (GChildWatchFunc) child_watch_cb, passwd_handler);
210
211 /* Success! */
212
213 return TRUE;
214 }
215
216 /* Stop passwd backend */
217 static void
218 stop_passwd (PasswdHandler *passwd_handler)
219 {
220 /* This is the standard way of returning from the dialog with passwd.
221 * If we return this way we can safely kill passwd as it has completed
222 * its task.
223 */
224
225 if (passwd_handler->backend_pid != -1) {
226 kill (passwd_handler->backend_pid, 9);
227 }
228
229 /* We must run free_passwd_resources here and not let our child
230 * watcher do it, since it will access invalid memory after the
231 * dialog has been closed and cleaned up.
232 *
233 * If we had more than a single thread we'd need to remove
234 * the child watch before trying to kill the child.
235 */
236 free_passwd_resources (passwd_handler);
237 }
238
239 /* Clean up passwd resources */
240 static void
241 free_passwd_resources (PasswdHandler *passwd_handler)
242 {
243 /* Remove the child watcher */
244 g_clear_handle_id (&passwd_handler->backend_child_watch_id, g_source_remove);
245
246 /* Close IO channels (internal file descriptors are automatically closed) */
247 if (passwd_handler->backend_stdin != NULL) {
248 g_autoptr(GError) error = NULL;
249
250 if (g_io_channel_shutdown (passwd_handler->backend_stdin, TRUE, &error) != G_IO_STATUS_NORMAL) {
251 g_warning ("Could not shutdown backend_stdin IO channel: %s", error->message);
252 }
253
254 g_clear_pointer (&passwd_handler->backend_stdin, g_io_channel_unref);
255 }
256
257 if (passwd_handler->backend_stdout != NULL) {
258 g_autoptr(GError) error = NULL;
259
260 if (g_io_channel_shutdown (passwd_handler->backend_stdout, TRUE, &error) != G_IO_STATUS_NORMAL) {
261 g_warning ("Could not shutdown backend_stdout IO channel: %s", error->message);
262 }
263
264 g_clear_pointer (&passwd_handler->backend_stdout, g_io_channel_unref);
265 }
266
267 /* Remove IO watcher */
268 g_clear_handle_id (&passwd_handler->backend_stdout_watch_id, g_source_remove);
269
270 /* Close PID */
271 if (passwd_handler->backend_pid != -1) {
272
273 g_spawn_close_pid (passwd_handler->backend_pid);
274
275 passwd_handler->backend_pid = -1;
276 }
277
278 /* Clear backend state */
279 passwd_handler->backend_state = PASSWD_STATE_NONE;
280 }
281
282 /*
283 * }} Spawning and closing of backend
284 */
285
286 /*
287 * Backend communication code {{
288 */
289
290 /* Write the first element of queue through channel */
291 static void
292 io_queue_pop (GQueue *queue, GIOChannel *channel)
293 {
294 g_autofree gchar *buf = NULL;
295 gsize bytes_written;
296 g_autoptr(GError) error = NULL;
297
298 buf = g_queue_pop_head (queue);
299
300 if (buf != NULL) {
301
302 if (g_io_channel_write_chars (channel, buf, -1, &bytes_written, &error) != G_IO_STATUS_NORMAL) {
303 g_warning ("Could not write queue element \"%s\" to channel: %s", buf, error->message);
304 }
305
306 /* Ensure passwords are cleared from memory */
307 memset (buf, 0, strlen (buf));
308 }
309 }
310
311 /* Goes through the argument list, checking if one of them occurs in str
312 * Returns: TRUE as soon as an element is found to match, FALSE otherwise */
313 static gboolean
314 is_string_complete (gchar *str, ...)
315 {
316 va_list ap;
317 gchar *arg;
318
319 if (strlen (str) == 0) {
320 return FALSE;
321 }
322
323 va_start (ap, str);
324
325 while ((arg = va_arg (ap, char *)) != NULL) {
326 if (strstr (str, arg) != NULL) {
327 va_end (ap);
328 return TRUE;
329 }
330 }
331
332 va_end (ap);
333
334 return FALSE;
335 }
336
337 /*
338 * IO watcher for stdout, called whenever there is data to read from the backend.
339 * This is where most of the actual IO handling happens.
340 */
341 static gboolean
342 io_watch_stdout (GIOChannel *source, GIOCondition condition, PasswdHandler *passwd_handler)
343 {
344 static GString *str = NULL; /* Persistent buffer */
345
346 gchar buf[BUFSIZE]; /* Temporary buffer */
347 gsize bytes_read;
348 g_autoptr(GError) gio_error = NULL;
349
350 gboolean reinit = FALSE;
351
352 /* Initialize buffer */
353 if (str == NULL) {
354 str = g_string_new ("");
355 }
356
357 if (g_io_channel_read_chars (source, buf, BUFSIZE, &bytes_read, &gio_error)
358 != G_IO_STATUS_NORMAL) {
359 g_warning ("IO Channel read error: %s", gio_error->message);
360 return TRUE;
361 }
362
363 str = g_string_append_len (str, buf, bytes_read);
364
365 /* In which state is the backend? */
366 switch (passwd_handler->backend_state) {
367 case PASSWD_STATE_AUTH:
368 /* Passwd is asking for our current password */
369
370 if (is_string_complete (str->str, "assword: ", "failure", "wrong", "error", NULL)) {
371
372 if (strstr (str->str, "assword: ") != NULL &&
373 strstr (str->str, "incorrect") == NULL &&
374 strstr (str->str, "urrent") == NULL) {
375 /* Authentication successful */
376
377 passwd_handler->backend_state = PASSWD_STATE_NEW;
378
379 /* Trigger callback to update authentication status */
380 if (passwd_handler->auth_cb)
381 passwd_handler->auth_cb (passwd_handler,
382 NULL,
383 passwd_handler->auth_cb_data);
384
385 } else {
386 /* Authentication failed */
387 g_autoptr(GError) error = NULL;
388
389 error = g_error_new_literal (PASSWD_ERROR, PASSWD_ERROR_AUTH_FAILED,
390 _("Authentication failed"));
391
392 passwd_handler->changing_password = FALSE;
393
394 /* This error can happen both while authenticating or while changing password:
395 * if chpasswd_cb is set, this means we're already changing password */
396 if (passwd_handler->chpasswd_cb)
397 passwd_handler->chpasswd_cb (passwd_handler,
398 error,
399 passwd_handler->chpasswd_cb_data);
400 else if (passwd_handler->auth_cb)
401 passwd_handler->auth_cb (passwd_handler,
402 error,
403 passwd_handler->auth_cb_data);
404 }
405
406 reinit = TRUE;
407 }
408 break;
409 case PASSWD_STATE_NEW:
410 /* Passwd is asking for our new password */
411
412 if (is_string_complete (str->str, "assword: ", NULL)) {
413 /* Advance to next state */
414 passwd_handler->backend_state = PASSWD_STATE_RETYPE;
415
416 /* Pop retyped password from queue and into IO channel */
417 io_queue_pop (passwd_handler->backend_stdin_queue, passwd_handler->backend_stdin);
418
419 reinit = TRUE;
420 }
421 break;
422 case PASSWD_STATE_RETYPE:
423 /* Passwd is asking for our retyped new password */
424
425 if (is_string_complete (str->str,
426 "successfully",
427 "short",
428 "longer",
429 "palindrome",
430 "dictionary",
431 "simple",
432 "simplistic",
433 "similar",
434 "case",
435 "different",
436 "wrapped",
437 "recovered",
438 "recent",
439 "unchanged",
440 "match",
441 "1 numeric or special",
442 "failure",
443 "DIFFERENT",
444 "BAD PASSWORD",
445 NULL)) {
446
447 if (strstr (str->str, "successfully") != NULL) {
448 /* Hooray! */
449
450 passwd_handler->backend_state = PASSWD_STATE_DONE;
451 /* Trigger callback to update status */
452 if (passwd_handler->chpasswd_cb)
453 passwd_handler->chpasswd_cb (passwd_handler,
454 NULL,
455 passwd_handler->chpasswd_cb_data);
456 }
457 else {
458 /* Ohnoes! */
459 g_autoptr(GError) error = NULL;
460
461 if (strstr (str->str, "recovered") != NULL) {
462 /* What does this indicate?
463 * "Authentication information cannot be recovered?" from libpam? */
464 error = g_error_new_literal (PASSWD_ERROR, PASSWD_ERROR_UNKNOWN,
465 str->str);
466 } else if (strstr (str->str, "short") != NULL ||
467 strstr (str->str, "longer") != NULL) {
468 error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_REJECTED,
469 _("The new password is too short"));
470 } else if (strstr (str->str, "palindrome") != NULL ||
471 strstr (str->str, "simple") != NULL ||
472 strstr (str->str, "simplistic") != NULL ||
473 strstr (str->str, "dictionary") != NULL) {
474 error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_REJECTED,
475 _("The new password is too simple"));
476 } else if (strstr (str->str, "similar") != NULL ||
477 strstr (str->str, "different") != NULL ||
478 strstr (str->str, "case") != NULL ||
479 strstr (str->str, "wrapped") != NULL) {
480 error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_REJECTED,
481 _("The old and new passwords are too similar"));
482 } else if (strstr (str->str, "recent") != NULL) {
483 error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_REJECTED,
484 _("The new password has already been used recently."));
485 } else if (strstr (str->str, "1 numeric or special") != NULL) {
486 error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_REJECTED,
487 _("The new password must contain numeric or special characters"));
488 } else if (strstr (str->str, "unchanged") != NULL ||
489 strstr (str->str, "match") != NULL) {
490 error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_REJECTED,
491 _("The old and new passwords are the same"));
492 } else if (strstr (str->str, "failure") != NULL) {
493 /* Authentication failure */
494 error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_AUTH_FAILED,
495 _("Your password has been changed since you initially authenticated!"));
496 }
497 else if (strstr (str->str, "DIFFERENT")) {
498 error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_REJECTED,
499 _("The new password does not contain enough different characters"));
500 }
501 else {
502 error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_UNKNOWN,
503 _("Unknown error"));
504 }
505
506 /* At this point, passwd might have exited, in which case
507 * child_watch_cb should clean up for us and remove this watcher.
508 * On some error conditions though, passwd just re-prompts us
509 * for our new password. */
510 passwd_handler->backend_state = PASSWD_STATE_ERR;
511
512 passwd_handler->changing_password = FALSE;
513
514 /* Trigger callback to update status */
515 if (passwd_handler->chpasswd_cb)
516 passwd_handler->chpasswd_cb (passwd_handler,
517 error,
518 passwd_handler->chpasswd_cb_data);
519 }
520
521 reinit = TRUE;
522
523 /* child_watch_cb should clean up for us now */
524 }
525 break;
526 case PASSWD_STATE_NONE:
527 /* Passwd is not asking for anything yet */
528 if (is_string_complete (str->str, "assword: ", NULL)) {
529
530 /* If the user does not have a password set,
531 * passwd will immediately ask for the new password,
532 * so skip the AUTH phase */
533 if (is_string_complete (str->str, "new", "New", NULL)) {
534 g_autofree gchar *pw = NULL;
535
536 passwd_handler->backend_state = PASSWD_STATE_NEW;
537
538 /* since passwd didn't ask for our old password
539 * in this case, simply remove it from the queue */
540 pw = g_queue_pop_head (passwd_handler->backend_stdin_queue);
541
542 /* Pop the IO queue, i.e. send new password */
543 io_queue_pop (passwd_handler->backend_stdin_queue, passwd_handler->backend_stdin);
544
545 } else {
546
547 passwd_handler->backend_state = PASSWD_STATE_AUTH;
548
549 /* Pop the IO queue, i.e. send current password */
550 io_queue_pop (passwd_handler->backend_stdin_queue, passwd_handler->backend_stdin);
551 }
552
553 reinit = TRUE;
554 }
555 break;
556 default:
557 /* Passwd has returned an error */
558 reinit = TRUE;
559 break;
560 }
561
562 if (reinit) {
563 g_string_free (str, TRUE);
564 str = NULL;
565 }
566
567 /* Continue calling us */
568 return TRUE;
569 }
570
571 /*
572 * }} Backend communication code
573 */
574
575 /* Adds the current password to the IO queue */
576 static void
577 authenticate (PasswdHandler *passwd_handler)
578 {
579 gchar *s;
580
581 s = g_strdup_printf ("%s\n", passwd_handler->current_password);
582
583 g_queue_push_tail (passwd_handler->backend_stdin_queue, s);
584 }
585
586 /* Adds the new password twice to the IO queue */
587 static void
588 update_password (PasswdHandler *passwd_handler)
589 {
590 gchar *s;
591
592 s = g_strdup_printf ("%s\n", passwd_handler->new_password);
593
594 g_queue_push_tail (passwd_handler->backend_stdin_queue, s);
595 /* We need to allocate new space because io_queue_pop() g_free()s
596 * every element of the queue after it's done */
597 g_queue_push_tail (passwd_handler->backend_stdin_queue, g_strdup (s));
598 }
599
600
601 PasswdHandler *
602 passwd_init (void)
603 {
604 PasswdHandler *passwd_handler;
605
606 passwd_handler = g_new0 (PasswdHandler, 1);
607
608 /* Initialize backend_pid. -1 means the backend is not running */
609 passwd_handler->backend_pid = -1;
610
611 /* Initialize IO Channels */
612 passwd_handler->backend_stdin = NULL;
613 passwd_handler->backend_stdout = NULL;
614
615 /* Initialize write queue */
616 passwd_handler->backend_stdin_queue = g_queue_new ();
617
618 /* Initialize watchers */
619 passwd_handler->backend_child_watch_id = 0;
620 passwd_handler->backend_stdout_watch_id = 0;
621
622 /* Initialize backend state */
623 passwd_handler->backend_state = PASSWD_STATE_NONE;
624 passwd_handler->changing_password = FALSE;
625
626 return passwd_handler;
627 }
628
629 void
630 passwd_destroy (PasswdHandler *passwd_handler)
631 {
632 g_queue_free (passwd_handler->backend_stdin_queue);
633 stop_passwd (passwd_handler);
634 g_free (passwd_handler);
635 }
636
637 void
638 passwd_authenticate (PasswdHandler *passwd_handler,
639 const char *current_password,
640 PasswdCallback cb,
641 const gpointer user_data)
642 {
643 g_autoptr(GError) error = NULL;
644
645 /* Don't stop if we've already started changing password */
646 if (passwd_handler->changing_password)
647 return;
648
649 /* Clear data from possible previous attempts to change password */
650 passwd_handler->new_password = NULL;
651 passwd_handler->chpasswd_cb = NULL;
652 passwd_handler->chpasswd_cb_data = NULL;
653 g_queue_foreach (passwd_handler->backend_stdin_queue, (GFunc) g_free, NULL);
654 g_queue_clear (passwd_handler->backend_stdin_queue);
655
656 passwd_handler->current_password = current_password;
657 passwd_handler->auth_cb = cb;
658 passwd_handler->auth_cb_data = user_data;
659
660 /* Spawn backend */
661 stop_passwd (passwd_handler);
662
663 if (!spawn_passwd (passwd_handler, &error)) {
664 g_warning ("%s", error->message);
665 return;
666 }
667
668 authenticate (passwd_handler);
669
670 /* Our IO watcher should now handle the rest */
671 }
672
673 gboolean
674 passwd_change_password (PasswdHandler *passwd_handler,
675 const char *new_password,
676 PasswdCallback cb,
677 const gpointer user_data)
678 {
679 passwd_handler->changing_password = TRUE;
680
681 passwd_handler->new_password = new_password;
682 passwd_handler->chpasswd_cb = cb;
683 passwd_handler->chpasswd_cb_data = user_data;
684
685 /* Stop passwd if an error occurred and it is still running */
686 if (passwd_handler->backend_state == PASSWD_STATE_ERR) {
687
688 /* Stop passwd, free resources */
689 stop_passwd (passwd_handler);
690 }
691
692 /* Check that the backend is still running, or that an error
693 * has occurred but it has not yet exited */
694 if (passwd_handler->backend_pid == -1) {
695 /* If it is not, re-run authentication */
696 g_autoptr(GError) error = NULL;
697
698 /* Spawn backend */
699 stop_passwd (passwd_handler);
700
701 if (!spawn_passwd (passwd_handler, &error)) {
702 g_warning ("%s", error->message);
703 return FALSE;
704 }
705
706 /* Add current and new passwords to queue */
707 authenticate (passwd_handler);
708 update_password (passwd_handler);
709 } else {
710 /* Only add new passwords to queue */
711 update_password (passwd_handler);
712 }
713
714 /* Pop new password through the backend.
715 * If user has no password, popping the queue would output current
716 * password, while 'passwd' is waiting for the new one. So wait for
717 * io_watch_stdout() to remove current password from the queue,
718 * and output the new one for us.
719 */
720 if (passwd_handler->current_password)
721 io_queue_pop (passwd_handler->backend_stdin_queue, passwd_handler->backend_stdin);
722
723 /* Our IO watcher should now handle the rest */
724
725 return TRUE;
726 }
727