summaryrefslogtreecommitdiff
path: root/Linux-PAM/modules/pam_unix/unix_chkpwd.c
diff options
context:
space:
mode:
Diffstat (limited to 'Linux-PAM/modules/pam_unix/unix_chkpwd.c')
-rw-r--r--Linux-PAM/modules/pam_unix/unix_chkpwd.c184
1 files changed, 184 insertions, 0 deletions
diff --git a/Linux-PAM/modules/pam_unix/unix_chkpwd.c b/Linux-PAM/modules/pam_unix/unix_chkpwd.c
new file mode 100644
index 00000000..11ac3aac
--- /dev/null
+++ b/Linux-PAM/modules/pam_unix/unix_chkpwd.c
@@ -0,0 +1,184 @@
+/*
+ * This program is designed to run setuid(root) or with sufficient
+ * privilege to read all of the unix password databases. It is designed
+ * to provide a mechanism for the current user (defined by this
+ * process' uid) to verify their own password.
+ *
+ * The password is read from the standard input. The exit status of
+ * this program indicates whether the user is authenticated or not.
+ *
+ * Copyright information is located at the end of the file.
+ *
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <shadow.h>
+#include <signal.h>
+#include <time.h>
+
+#include <security/_pam_types.h>
+#include <security/_pam_macros.h>
+
+#include "passverify.h"
+
+static int _check_expiry(const char *uname)
+{
+ struct spwd *spent;
+ struct passwd *pwent;
+ int retval;
+ int daysleft;
+
+ retval = get_account_info(uname, &pwent, &spent);
+ if (retval != PAM_SUCCESS) {
+ helper_log_err(LOG_ALERT, "could not obtain user info (%s)", uname);
+ printf("-1\n");
+ return retval;
+ }
+
+ if (spent == NULL) {
+ printf("-1\n");
+ return retval;
+ }
+
+ retval = check_shadow_expiry(spent, &daysleft);
+ printf("%d\n", daysleft);
+ return retval;
+}
+
+int main(int argc, char *argv[])
+{
+ char pass[MAXPASS + 1];
+ char *option;
+ int npass, nullok;
+ int blankpass = 0;
+ int retval = PAM_AUTH_ERR;
+ char *user;
+ char *passwords[] = { pass };
+
+ /*
+ * Catch or ignore as many signal as possible.
+ */
+ setup_signals();
+
+ /*
+ * we establish that this program is running with non-tty stdin.
+ * this is to discourage casual use. It does *NOT* prevent an
+ * intruder from repeatadly running this program to determine the
+ * password of the current user (brute force attack, but one for
+ * which the attacker must already have gained access to the user's
+ * account).
+ */
+
+ if (isatty(STDIN_FILENO) || argc != 3 ) {
+ helper_log_err(LOG_NOTICE
+ ,"inappropriate use of Unix helper binary [UID=%d]"
+ ,getuid());
+ fprintf(stderr
+ ,"This binary is not designed for running in this way\n"
+ "-- the system administrator has been informed\n");
+ sleep(10); /* this should discourage/annoy the user */
+ return PAM_SYSTEM_ERR;
+ }
+
+ /*
+ * Determine what the current user's name is.
+ * We must thus skip the check if the real uid is 0.
+ */
+ if (getuid() == 0) {
+ user=argv[1];
+ }
+ else {
+ user = getuidname(getuid());
+ /* if the caller specifies the username, verify that user
+ matches it */
+ if (strcmp(user, argv[1])) {
+ return PAM_AUTH_ERR;
+ }
+ }
+
+ option=argv[2];
+
+ if (strcmp(option, "chkexpiry") == 0)
+ /* Check account information from the shadow file */
+ return _check_expiry(argv[1]);
+ /* read the nullok/nonull option */
+ else if (strcmp(option, "nullok") == 0)
+ nullok = 1;
+ else if (strcmp(option, "nonull") == 0)
+ nullok = 0;
+ else
+ return PAM_SYSTEM_ERR;
+
+ /* read the password from stdin (a pipe from the pam_unix module) */
+
+ npass = read_passwords(STDIN_FILENO, 1, passwords);
+
+ if (npass != 1) { /* is it a valid password? */
+ helper_log_err(LOG_DEBUG, "no password supplied");
+ *pass = '\0';
+ }
+
+ if (*pass == '\0') {
+ blankpass = 1;
+ }
+
+ retval = helper_verify_password(user, pass, nullok);
+
+ memset(pass, '\0', MAXPASS); /* clear memory of the password */
+
+ /* return pass or fail */
+
+ if (retval != PAM_SUCCESS) {
+ if (!nullok || !blankpass)
+ /* no need to log blank pass test */
+ helper_log_err(LOG_NOTICE, "password check failed for user (%s)", user);
+ return PAM_AUTH_ERR;
+ } else {
+ return PAM_SUCCESS;
+ }
+}
+
+/*
+ * Copyright (c) Andrew G. Morgan, 1996. All rights reserved
+ * Copyright (c) Red Hat, Inc., 2007,2008. All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */