xsu.diff 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. --- loki_setup/CHANGES 2004-11-20 07:43:42.000000000 -0600
  2. +++ loki_setup.zinx/CHANGES 2005-03-16 16:56:46.400205504 -0600
  3. @@ -1,4 +1,6 @@
  4. Current:
  5. +Christopher Lais (Id Software) - Wed Mar 16 08:09:59 CST 2005
  6. + * Fix handling of invalid password in xsu
  7. Ryan C. Gordon (icculus.org) - Sat Nov 20 08:42:16 EST 2004
  8. * Minor carbon_ui tweaks and corrections to update function.
  9. Ludwig Nussel - Wed Nov 10 14:21:21 PST 2004
  10. --- loki_setup/xsu.c 2003-07-02 14:40:39.000000000 -0500
  11. +++ loki_setup.zinx/xsu.c 2005-03-16 16:36:17.752988272 -0600
  12. @@ -37,6 +37,7 @@
  13. #include "xsu.h"
  14. static int term = -1;
  15. +static int term_status = 0;
  16. static gint
  17. exec_su_failed (gpointer user_data)
  18. @@ -79,22 +80,25 @@
  19. if ( sig == SIGCHLD && term > 0 ) {
  20. int status;
  21. pid_t pid = wait(&status);
  22. +
  23. + close(term); term = -1;
  24. + term_status = status;
  25. +
  26. if ( WIFEXITED(status) ) {
  27. #ifdef DEBUG
  28. fprintf(stderr,"Child %d returned\n", pid);
  29. #endif
  30. - gtk_exit(WEXITSTATUS(status));
  31. + /* This is handled at the end of xsu_process */
  32. + return;
  33. } else if ( WIFSIGNALED(status) ) {
  34. #ifdef DEBUG
  35. fprintf(stderr,"Xsu: subprocess %d has died from signal %d\n", pid, WTERMSIG(status));
  36. #endif
  37. gtk_exit(EXIT_ERROR);
  38. + } else {
  39. + fprintf(stderr, "Xsu: got SIGCHLD from %d for unknown reason (%08x)\n", pid, status);
  40. + gtk_exit(EXIT_ERROR);
  41. }
  42. - close(term); term = -1;
  43. -
  44. - while (gtk_events_pending ())
  45. - gtk_main_iteration ();
  46. - gtk_main_quit ();
  47. }
  48. }
  49. @@ -135,22 +139,27 @@
  50. gchar *buffer;
  51. char *argv[6], c;
  52. fd_set fds;
  53. - struct timeval delay = { 0, 10*1000 }; /* 10 ms wait */
  54. + struct timeval delay;
  55. #ifdef DEBUG
  56. printf("void xsu_perform()\n");
  57. #endif
  58. + gtk_widget_hide (gtk_xsu_window);
  59. +
  60. + if (password == NULL)
  61. + return;
  62. +
  63. /* 0.2.1 *
  64. Minor security fix. Password would remain in memory if we don't
  65. clean the password textbox.
  66. */
  67. - gtk_entry_set_text(GTK_ENTRY(gtk_password_textbox),"");
  68. - gtk_widget_hide (gtk_xsu_window);
  69. -
  70. - if (password == NULL)
  71. - return;
  72. + password_return = g_strdup_printf ("%s\n", password);
  73. + /* Technically, we aren't supposed to modify this, but it should
  74. + usually be OK because we're explicitly clearing it afterwards. */
  75. + memset (password, 0, strlen (password));
  76. + gtk_entry_set_text(GTK_ENTRY(gtk_password_textbox),"");
  77. /* xsu 0.2.1 *
  78. Option to set the DISPLAY environment
  79. @@ -177,6 +186,9 @@
  80. argv[2] = "-c";
  81. argv[3] = buffer;
  82. argv[4] = NULL;
  83. +#ifdef DEBUG
  84. + fprintf(stderr, "%s %s -c %s\n", su_command, username, buffer);
  85. +#endif
  86. term = exec_program(su_command, argv);
  87. /* We are not a gnome-application anymore but under control of su */
  88. @@ -231,33 +243,65 @@
  89. fprintf(stderr, "Got it!\n");
  90. #endif
  91. - /* Discard any remaining characters on stdin */
  92. - for(;;) {
  93. + /* Slurp up any extra characters immediately after the password prompt,
  94. + because su might clear the buffer after we send the password if we
  95. + don't. */
  96. + for (;;) {
  97. FD_ZERO(&fds);
  98. FD_SET(term, &fds);
  99. - if ( select(term+1, &fds, NULL, NULL, &delay) ) {
  100. - if ( read(term, &c, 1) <= 0 )
  101. - break;
  102. +
  103. + delay.tv_sec = 0;
  104. + delay.tv_usec = 10*1000; /* 10 ms wait */
  105. +
  106. + if (select(term+1, &fds, NULL, NULL, &delay) > 0) {
  107. + if (read(term, &c, 1) < 0)
  108. + break;
  109. } else
  110. break;
  111. }
  112. - password_return = g_strdup_printf ("%s\n", password);
  113. #ifdef DEBUG
  114. fprintf(stderr,"Sending password\n");
  115. #endif
  116. /* 0.2.2 *
  117. Minor security fix, clear the password from memory
  118. */
  119. - memset (password, 0, strlen (password));
  120. if ( write(term, password_return, strlen(password_return)) < 0 ) {
  121. perror("write");
  122. }
  123. +
  124. memset (password_return, 0, strlen (password_return));
  125. g_free (password_return); password_return = NULL;
  126. - g_free (password); password = NULL;
  127. - //gtk_main();
  128. + /* Eat up any output, and wait for a SIGCHLD saying su exited */
  129. + while (term >= 0) {
  130. + FD_ZERO(&fds);
  131. + FD_SET(term, &fds);
  132. +
  133. + delay.tv_sec = 0;
  134. + delay.tv_usec = 10*1000; /* 10 ms wait */
  135. +
  136. + if ( select(term+1, &fds, NULL, NULL, &delay) > 0 ) {
  137. + read(term, &c, 1);
  138. +#ifdef DEBUG
  139. + fprintf(stderr, "read from pty: %02x\n", c);
  140. +#endif
  141. + }
  142. +
  143. + while (gtk_events_pending ())
  144. + gtk_main_iteration ();
  145. + }
  146. +
  147. + if (WIFEXITED(term_status) && WEXITSTATUS(term_status)) {
  148. + /* su failed, so ask for the password again */
  149. +#ifdef DEBUG
  150. + fprintf(stderr, "returning control to gtk\n");
  151. +#endif
  152. + gtk_widget_show (gtk_xsu_window);
  153. + } else {
  154. + /* Exit normally */
  155. + gtk_main_quit();
  156. + }
  157. }