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
8 * The password is read from the standard input. The exit status of
9 * this program indicates whether the password was updated or not.
11 * Copyright information is located at the end of the file.
23 #include <sys/types.h>
31 #include <security/_pam_types.h>
32 #include <security/_pam_macros.h>
34 #include "passverify.h"
37 set_password(const char *forwho, const char *shadow, const char *remember)
39 struct passwd *pwd = NULL;
41 char pass[MAXPASS + 1];
42 char towhat[MAXPASS + 1];
44 /* we don't care about number format errors because the helper
45 should be called internally only */
46 int doshadow = atoi(shadow);
47 int nremember = atoi(remember);
48 char *passwords[] = { pass, towhat };
50 /* read the password from stdin (a pipe from the pam_unix module) */
52 npass = read_passwords(STDIN_FILENO, 2, passwords);
54 if (npass != 2) { /* is it a valid password? */
56 helper_log_err(LOG_DEBUG, "no new password supplied");
57 memset(pass, '\0', MAXPASS);
59 helper_log_err(LOG_DEBUG, "no valid passwords supplied");
61 return PAM_AUTHTOK_ERR;
64 if (lock_pwdf() != PAM_SUCCESS)
65 return PAM_AUTHTOK_LOCK_BUSY;
67 pwd = getpwnam(forwho);
70 retval = PAM_USER_UNKNOWN;
74 /* If real caller uid is not root we must verify that
75 received old pass agrees with the current one.
76 We always allow change from null pass. */
78 retval = helper_verify_password(forwho, pass, 1);
79 if (retval != PAM_SUCCESS) {
84 /* first, save old password */
85 if (save_old_password(forwho, pass, nremember)) {
86 retval = PAM_AUTHTOK_ERR;
90 if (doshadow || is_pwd_shadowed(pwd)) {
91 retval = unix_update_shadow(forwho, towhat);
92 if (retval == PAM_SUCCESS)
93 if (!is_pwd_shadowed(pwd))
94 retval = unix_update_passwd(forwho, "x");
96 retval = unix_update_passwd(forwho, towhat);
100 memset(pass, '\0', MAXPASS);
101 memset(towhat, '\0', MAXPASS);
105 if (retval == PAM_SUCCESS) {
108 return PAM_AUTHTOK_ERR;
112 int main(int argc, char *argv[])
117 * Catch or ignore as many signal as possible.
122 * we establish that this program is running with non-tty stdin.
123 * this is to discourage casual use. It does *NOT* prevent an
124 * intruder from repeatadly running this program to determine the
125 * password of the current user (brute force attack, but one for
126 * which the attacker must already have gained access to the user's
130 if (isatty(STDIN_FILENO) || argc != 5 ) {
131 helper_log_err(LOG_NOTICE
132 ,"inappropriate use of Unix helper binary [UID=%d]"
135 ,"This binary is not designed for running in this way\n"
136 "-- the system administrator has been informed\n");
137 sleep(10); /* this should discourage/annoy the user */
138 return PAM_SYSTEM_ERR;
141 /* We must be root to read/update shadow.
143 if (geteuid() != 0) {
144 return PAM_CRED_INSUFFICIENT;
149 if (strcmp(option, "update") == 0) {
150 /* Attempting to change the password */
151 return set_password(argv[1], argv[3], argv[4]);
154 return PAM_SYSTEM_ERR;
158 * Copyright (c) Andrew G. Morgan, 1996. All rights reserved
159 * Copyright (c) Red Hat, Inc., 2007, 2008. All rights reserved
161 * Redistribution and use in source and binary forms, with or without
162 * modification, are permitted provided that the following conditions
164 * 1. Redistributions of source code must retain the above copyright
165 * notice, and the entire permission notice in its entirety,
166 * including the disclaimer of warranties.
167 * 2. Redistributions in binary form must reproduce the above copyright
168 * notice, this list of conditions and the following disclaimer in the
169 * documentation and/or other materials provided with the distribution.
170 * 3. The name of the author may not be used to endorse or promote
171 * products derived from this software without specific prior
172 * written permission.
174 * ALTERNATIVELY, this product may be distributed under the terms of
175 * the GNU Public License, in which case the provisions of the GPL are
176 * required INSTEAD OF the above restrictions. (This clause is
177 * necessary due to a potential bad interaction between the GPL and
178 * the restrictions contained in a BSD-style copyright.)
180 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
181 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
182 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
183 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
184 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
185 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
186 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
187 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
188 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
189 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
190 * OF THE POSSIBILITY OF SUCH DAMAGE.