2 * This program is designed to run setuid(root) or with sufficient
3 * privilege to read all of the unix password databases. It is designed
4 * to provide a mechanism for the current user (defined by this
5 * process' uid) to verify their own password.
7 * The password is read from the standard input. The exit status of
8 * this program indicates whether the user is authenticated or not.
10 * Copyright information is located at the end of the file.
21 #include <sys/types.h>
32 #include <security/_pam_types.h>
33 #include <security/_pam_macros.h>
35 #include "passverify.h"
37 static int _check_expiry(const char *uname)
44 retval = get_account_info(uname, &pwent, &spent);
45 if (retval != PAM_SUCCESS) {
46 helper_log_err(LOG_ALERT, "could not obtain user info (%s)", uname);
56 retval = check_shadow_expiry(spent, &daysleft);
57 printf("%d\n", daysleft);
62 static int _audit_log(int type, const char *uname, int rc)
66 audit_fd = audit_open();
68 /* You get these error codes only when the kernel doesn't have
69 * audit compiled in. */
70 if (errno == EINVAL || errno == EPROTONOSUPPORT ||
71 errno == EAFNOSUPPORT)
74 helper_log_err(LOG_CRIT, "audit_open() failed: %m");
78 rc = audit_log_acct_message(audit_fd, type, NULL, "PAM:unix_chkpwd",
79 uname, -1, NULL, NULL, NULL, rc == PAM_SUCCESS);
80 if (rc == -EPERM && geteuid() != 0) {
84 audit_close(audit_fd);
86 return rc < 0 ? PAM_AUTH_ERR : PAM_SUCCESS;
90 int main(int argc, char *argv[])
92 char pass[MAXPASS + 1];
96 int retval = PAM_AUTH_ERR;
98 char *passwords[] = { pass };
101 * Catch or ignore as many signal as possible.
106 * we establish that this program is running with non-tty stdin.
107 * this is to discourage casual use. It does *NOT* prevent an
108 * intruder from repeatadly running this program to determine the
109 * password of the current user (brute force attack, but one for
110 * which the attacker must already have gained access to the user's
114 if (isatty(STDIN_FILENO) || argc != 3 ) {
115 helper_log_err(LOG_NOTICE
116 ,"inappropriate use of Unix helper binary [UID=%d]"
119 _audit_log(AUDIT_ANOM_EXEC, getuidname(getuid()), PAM_SYSTEM_ERR);
122 ,"This binary is not designed for running in this way\n"
123 "-- the system administrator has been informed\n");
124 sleep(10); /* this should discourage/annoy the user */
125 return PAM_SYSTEM_ERR;
129 * Determine what the current user's name is.
130 * We must thus skip the check if the real uid is 0.
136 user = getuidname(getuid());
137 /* if the caller specifies the username, verify that user
139 if (strcmp(user, argv[1])) {
141 /* no match -> permanently change to the real user and proceed */
142 if (setuid(getuid()) != 0)
149 if (strcmp(option, "chkexpiry") == 0)
150 /* Check account information from the shadow file */
151 return _check_expiry(argv[1]);
152 /* read the nullok/nonull option */
153 else if (strcmp(option, "nullok") == 0)
155 else if (strcmp(option, "nonull") == 0)
159 _audit_log(AUDIT_ANOM_EXEC, getuidname(getuid()), PAM_SYSTEM_ERR);
161 return PAM_SYSTEM_ERR;
163 /* read the password from stdin (a pipe from the pam_unix module) */
165 npass = read_passwords(STDIN_FILENO, 1, passwords);
167 if (npass != 1) { /* is it a valid password? */
168 helper_log_err(LOG_DEBUG, "no password supplied");
176 retval = helper_verify_password(user, pass, nullok);
178 memset(pass, '\0', MAXPASS); /* clear memory of the password */
180 /* return pass or fail */
182 if (retval != PAM_SUCCESS) {
183 if (!nullok || !blankpass) {
184 /* no need to log blank pass test */
187 _audit_log(AUDIT_USER_AUTH, user, PAM_AUTH_ERR);
189 helper_log_err(LOG_NOTICE, "password check failed for user (%s)", user);
195 return _audit_log(AUDIT_USER_AUTH, user, PAM_SUCCESS);
205 * Copyright (c) Andrew G. Morgan, 1996. All rights reserved
206 * Copyright (c) Red Hat, Inc., 2007,2008. All rights reserved
208 * Redistribution and use in source and binary forms, with or without
209 * modification, are permitted provided that the following conditions
211 * 1. Redistributions of source code must retain the above copyright
212 * notice, and the entire permission notice in its entirety,
213 * including the disclaimer of warranties.
214 * 2. Redistributions in binary form must reproduce the above copyright
215 * notice, this list of conditions and the following disclaimer in the
216 * documentation and/or other materials provided with the distribution.
217 * 3. The name of the author may not be used to endorse or promote
218 * products derived from this software without specific prior
219 * written permission.
221 * ALTERNATIVELY, this product may be distributed under the terms of
222 * the GNU Public License, in which case the provisions of the GPL are
223 * required INSTEAD OF the above restrictions. (This clause is
224 * necessary due to a potential bad interaction between the GPL and
225 * the restrictions contained in a BSD-style copyright.)
227 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
228 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
229 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
230 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
231 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
232 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
233 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
234 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
235 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
236 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
237 * OF THE POSSIBILITY OF SUCH DAMAGE.