unix_update.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*
  2. * This program is designed to run with sufficient privilege
  3. * to read and write all of the unix password databases.
  4. * Its purpose is to allow updating the databases when
  5. * SELinux confinement of the caller domain prevents them to
  6. * do that themselves.
  7. *
  8. * The password is read from the standard input. The exit status of
  9. * this program indicates whether the password was updated or not.
  10. *
  11. * Copyright information is located at the end of the file.
  12. *
  13. */
  14. #include "config.h"
  15. #include <stdarg.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <syslog.h>
  20. #include <unistd.h>
  21. #include <sys/types.h>
  22. #include <sys/stat.h>
  23. #include <pwd.h>
  24. #include <shadow.h>
  25. #include <signal.h>
  26. #include <time.h>
  27. #include <sys/time.h>
  28. #include <security/_pam_types.h>
  29. #include <security/_pam_macros.h>
  30. #include "passverify.h"
  31. #include "pam_inline.h"
  32. static int
  33. set_password(const char *forwho, const char *shadow, const char *remember)
  34. {
  35. struct passwd *pwd = NULL;
  36. int retval;
  37. char pass[PAM_MAX_RESP_SIZE + 1];
  38. char towhat[PAM_MAX_RESP_SIZE + 1];
  39. int npass = 0;
  40. /* we don't care about number format errors because the helper
  41. should be called internally only */
  42. int doshadow = atoi(shadow);
  43. int nremember = atoi(remember);
  44. char *passwords[] = { pass, towhat };
  45. /* read the password from stdin (a pipe from the pam_unix module) */
  46. npass = pam_read_passwords(STDIN_FILENO, 2, passwords);
  47. if (npass != 2) { /* is it a valid password? */
  48. if (npass == 1) {
  49. helper_log_err(LOG_DEBUG, "no new password supplied");
  50. memset(pass, '\0', PAM_MAX_RESP_SIZE);
  51. } else {
  52. helper_log_err(LOG_DEBUG, "no valid passwords supplied");
  53. }
  54. return PAM_AUTHTOK_ERR;
  55. }
  56. if (lock_pwdf() != PAM_SUCCESS)
  57. return PAM_AUTHTOK_LOCK_BUSY;
  58. pwd = getpwnam(forwho);
  59. if (pwd == NULL) {
  60. retval = PAM_USER_UNKNOWN;
  61. goto done;
  62. }
  63. /* If real caller uid is not root we must verify that
  64. received old pass agrees with the current one.
  65. We always allow change from null pass. */
  66. if (getuid()) {
  67. retval = helper_verify_password(forwho, pass, 1);
  68. if (retval != PAM_SUCCESS) {
  69. goto done;
  70. }
  71. }
  72. /* first, save old password */
  73. if (save_old_password(forwho, pass, nremember)) {
  74. retval = PAM_AUTHTOK_ERR;
  75. goto done;
  76. }
  77. if (doshadow || is_pwd_shadowed(pwd)) {
  78. retval = unix_update_shadow(forwho, towhat);
  79. if (retval == PAM_SUCCESS)
  80. if (!is_pwd_shadowed(pwd))
  81. retval = unix_update_passwd(forwho, "x");
  82. } else {
  83. retval = unix_update_passwd(forwho, towhat);
  84. }
  85. done:
  86. memset(pass, '\0', PAM_MAX_RESP_SIZE);
  87. memset(towhat, '\0', PAM_MAX_RESP_SIZE);
  88. unlock_pwdf();
  89. if (retval == PAM_SUCCESS) {
  90. return PAM_SUCCESS;
  91. } else {
  92. return PAM_AUTHTOK_ERR;
  93. }
  94. }
  95. int main(int argc, char *argv[])
  96. {
  97. char *option;
  98. /*
  99. * Catch or ignore as many signal as possible.
  100. */
  101. setup_signals();
  102. /*
  103. * we establish that this program is running with non-tty stdin.
  104. * this is to discourage casual use. It does *NOT* prevent an
  105. * intruder from repeatadly running this program to determine the
  106. * password of the current user (brute force attack, but one for
  107. * which the attacker must already have gained access to the user's
  108. * account).
  109. */
  110. if (isatty(STDIN_FILENO) || argc != 5 ) {
  111. helper_log_err(LOG_NOTICE
  112. ,"inappropriate use of Unix helper binary [UID=%d]"
  113. ,getuid());
  114. fprintf(stderr
  115. ,"This binary is not designed for running in this way\n"
  116. "-- the system administrator has been informed\n");
  117. sleep(10); /* this should discourage/annoy the user */
  118. return PAM_SYSTEM_ERR;
  119. }
  120. /* We must be root to read/update shadow.
  121. */
  122. if (geteuid() != 0) {
  123. return PAM_CRED_INSUFFICIENT;
  124. }
  125. option = argv[2];
  126. if (strcmp(option, "update") == 0) {
  127. /* Attempting to change the password */
  128. return set_password(argv[1], argv[3], argv[4]);
  129. }
  130. return PAM_SYSTEM_ERR;
  131. }
  132. /*
  133. * Copyright (c) Andrew G. Morgan, 1996. All rights reserved
  134. * Copyright (c) Red Hat, Inc., 2007, 2008. All rights reserved
  135. *
  136. * Redistribution and use in source and binary forms, with or without
  137. * modification, are permitted provided that the following conditions
  138. * are met:
  139. * 1. Redistributions of source code must retain the above copyright
  140. * notice, and the entire permission notice in its entirety,
  141. * including the disclaimer of warranties.
  142. * 2. Redistributions in binary form must reproduce the above copyright
  143. * notice, this list of conditions and the following disclaimer in the
  144. * documentation and/or other materials provided with the distribution.
  145. * 3. The name of the author may not be used to endorse or promote
  146. * products derived from this software without specific prior
  147. * written permission.
  148. *
  149. * ALTERNATIVELY, this product may be distributed under the terms of
  150. * the GNU Public License, in which case the provisions of the GPL are
  151. * required INSTEAD OF the above restrictions. (This clause is
  152. * necessary due to a potential bad interaction between the GPL and
  153. * the restrictions contained in a BSD-style copyright.)
  154. *
  155. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  156. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  157. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  158. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  159. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  160. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  161. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  162. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  163. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  164. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  165. * OF THE POSSIBILITY OF SUCH DAMAGE.
  166. */