diff options
Diffstat (limited to 'modules/pam_unix')
29 files changed, 0 insertions, 5692 deletions
diff --git a/modules/pam_unix/.cvsignore b/modules/pam_unix/.cvsignore deleted file mode 100644 index 01819c28..00000000 --- a/modules/pam_unix/.cvsignore +++ /dev/null @@ -1,14 +0,0 @@ -*.la -*.lo -*.so -.deps -.libs -Makefile -Makefile.in -bigcrypt -unix_chkpwd -unix_update -README -pam_unix.8 -unix_chkpwd.8 -unix_update.8 diff --git a/modules/pam_unix/CHANGELOG b/modules/pam_unix/CHANGELOG deleted file mode 100644 index 1476b579..00000000 --- a/modules/pam_unix/CHANGELOG +++ /dev/null @@ -1,55 +0,0 @@ -$Id$ - -* Mon Aug 16 1999 Jan Rêkorajski <baggins@pld.org.pl> -- fixed reentrancy problems - -* Sun Jul 4 21:03:42 PDT 1999 - -- temporarily removed the crypt16 stuff. I'm really paranoid about - crypto stuff and exporting it, and there are a few too many 's-box' - references in the code for my liking.. - -* Wed Jun 30 1999 Steve Langasek <vorlon@netexpress.net> -- further NIS+ fixes - -* Sun Jun 27 1999 Steve Langasek <vorlon@netexpress.net> -- fix to uid-handling code for NIS+ - -* Sat Jun 26 1999 Jan Rêkorajski <baggins@mimuw.edu.pl> -- merged MD5 fix and early failure syslog - by Andrey Vladimirovich Savochkin <saw@msu.ru> -- minor fixes -- added signal handler to unix_chkpwd - -* Fri Jun 25 1999 Stephen Langasek <vorlon@netexpress.net> -- reorganized the code to let it build as separate C files - -* Sun Jun 20 1999 Jan Rêkorajski <baggins@mimuw.edu.pl> -- fixes in pam_unix_auth, it incorrectly saved and restored return - value when likeauth option was used - -* Tue Jun 15 1999 Jan Rêkorajski <baggins@mimuw.edu.pl> -- added NIS+ support - -* Mon Jun 14 1999 Jan Rêkorajski <baggins@mimuw.edu.pl> -- total rewrite based on pam_pwdb module, now there is ONE pam_unix.so - module, it accepts the same options as pam_pwdb - all of them correctly ;) - (pam_pwdb dosn't understand what DISALLOW_NULL_AUTHTOK means) - -* Tue Apr 20 1999 Jan Rêkorajski <baggins@mimuw.edu.pl> -- Arghhh, pam_unix_passwd was not updating /etc/shadow when used with - pam_cracklib. - -* Mon Apr 19 1999 Jan Rêkorajski <baggins@mimuw.edu.pl> -- added "remember=XXX" option that means 'remember XXX old passwords' - Old passwords are stored in /etc/security/opasswd, there can be - maximum of 400 passwords per user. - -* Sat Mar 27 1999 Jan Rêkorajski <baggins@mimuw.edu.pl> -- added crypt16 to pam_unix_auth and pam_unix_passwd (check only, this algorithm - is too lame to use it in real life) - -* Sun Mar 21 1999 Jan Rêkorajski <baggins@mimuw.edu.pl> -- pam_unix_auth now correctly behave when user has NULL AUTHTOK -- pam_unix_auth returns PAM_PERM_DENIED when seteuid fails - diff --git a/modules/pam_unix/Makefile.am b/modules/pam_unix/Makefile.am deleted file mode 100644 index 4d2c58b8..00000000 --- a/modules/pam_unix/Makefile.am +++ /dev/null @@ -1,69 +0,0 @@ -# -# Copyright (c) 2005, 2006 Thorsten Kukuk <kukuk@suse.de> -# - -CLEANFILES = *~ - -EXTRA_DIST = README md5.c md5_crypt.c lckpwdf.-c $(MANS) CHANGELOG \ - tst-pam_unix $(XMLS) - -man_MANS = pam_unix.8 unix_chkpwd.8 unix_update.8 -XMLS = README.xml pam_unix.8.xml unix_chkpwd.8.xml unix_update.8.xml - -TESTS = tst-pam_unix - -securelibdir = $(SECUREDIR) -secureconfdir = $(SCONFIGDIR) - -AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \ - -DCHKPWD_HELPER=\"$(sbindir)/unix_chkpwd\" \ - -DUPDATE_HELPER=\"$(sbindir)/unix_update\" - -if HAVE_LIBSELINUX - AM_CFLAGS += -D"WITH_SELINUX" -endif -if HAVE_LIBCRACK - AM_CFLAGS += -D"USE_CRACKLIB" -endif - -pam_unix_la_LDFLAGS = -no-undefined -avoid-version -module -if HAVE_VERSIONING - pam_unix_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map -endif -pam_unix_la_LIBADD = @LIBCRACK@ @LIBNSL@ -L$(top_builddir)/libpam -lpam \ - @LIBCRYPT@ @LIBSELINUX@ - -securelib_LTLIBRARIES = pam_unix.la - -noinst_HEADERS = md5.h support.h yppasswd.h bigcrypt.h passverify.h - -sbin_PROGRAMS = unix_chkpwd unix_update - -noinst_PROGRAMS = bigcrypt - -pam_unix_la_SOURCES = bigcrypt.c pam_unix_acct.c \ - pam_unix_auth.c pam_unix_passwd.c pam_unix_sess.c support.c \ - passverify.c yppasswd_xdr.c md5_good.c md5_broken.c - -bigcrypt_SOURCES = bigcrypt.c bigcrypt_main.c -bigcrypt_CFLAGS = $(AM_CFLAGS) -bigcrypt_LDADD = @LIBCRYPT@ - -unix_chkpwd_SOURCES = unix_chkpwd.c md5_good.c md5_broken.c bigcrypt.c \ - passverify.c -unix_chkpwd_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ -DHELPER_COMPILE=\"unix_chkpwd\" -unix_chkpwd_LDFLAGS = @PIE_LDFLAGS@ -unix_chkpwd_LDADD = @LIBCRYPT@ @LIBSELINUX@ - -unix_update_SOURCES = unix_update.c md5_good.c md5_broken.c bigcrypt.c \ - passverify.c -unix_update_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ -DHELPER_COMPILE=\"unix_update\" -unix_update_LDFLAGS = @PIE_LDFLAGS@ -unix_update_LDADD = @LIBCRYPT@ @LIBSELINUX@ - -if ENABLE_REGENERATE_MAN -noinst_DATA = README -README: pam_unix.8.xml --include $(top_srcdir)/Make.xml.rules -endif - diff --git a/modules/pam_unix/README.xml b/modules/pam_unix/README.xml deleted file mode 100644 index 7fd340b3..00000000 --- a/modules/pam_unix/README.xml +++ /dev/null @@ -1,41 +0,0 @@ -<?xml version="1.0" encoding='UTF-8'?> -<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" -"http://www.docbook.org/xml/4.3/docbookx.dtd" -[ -<!-- -<!ENTITY pamaccess SYSTEM "pam_unix.8.xml"> ---> -]> - -<article> - - <articleinfo> - - <title> - <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" - href="pam_unix.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_unix-name"]/*)'/> - </title> - - </articleinfo> - - <section> - <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" - href="pam_unix.8.xml" xpointer='xpointer(//refsect1[@id = "pam_unix-description"]/*)'/> - </section> - - <section> - <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" - href="pam_unix.8.xml" xpointer='xpointer(//refsect1[@id = "pam_unix-options"]/*)'/> - </section> - - <section> - <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" - href="pam_unix.8.xml" xpointer='xpointer(//refsect1[@id = "pam_unix-examples"]/*)'/> - </section> - - <section> - <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" - href="pam_unix.8.xml" xpointer='xpointer(//refsect1[@id = "pam_unix-author"]/*)'/> - </section> - -</article> diff --git a/modules/pam_unix/bigcrypt.c b/modules/pam_unix/bigcrypt.c deleted file mode 100644 index 9cd55384..00000000 --- a/modules/pam_unix/bigcrypt.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * This function implements the "bigcrypt" algorithm specifically for - * Linux-PAM. - * - * This algorithm is algorithm 0 (default) shipped with the C2 secure - * implementation of Digital UNIX. - * - * Disclaimer: This work is not based on the source code to Digital - * UNIX, nor am I connected to Digital Equipment Corp, in any way - * other than as a customer. This code is based on published - * interfaces and reasonable guesswork. - * - * Description: The cleartext is divided into blocks of SEGMENT_SIZE=8 - * characters or less. Each block is encrypted using the standard UNIX - * libc crypt function. The result of the encryption for one block - * provides the salt for the suceeding block. - * - * Restrictions: The buffer used to hold the encrypted result is - * statically allocated. (see MAX_PASS_LEN below). This is necessary, - * as the returned pointer points to "static data that are overwritten - * by each call", (XPG3: XSI System Interface + Headers pg 109), and - * this is a drop in replacement for crypt(); - * - * Andy Phillips <atp@mssl.ucl.ac.uk> - */ - -#include "config.h" - -#include <string.h> -#include <stdlib.h> -#include <security/_pam_macros.h> -#ifdef HAVE_CRYPT_H -#include <crypt.h> -#endif - -#include "bigcrypt.h" - -/* - * Max cleartext password length in segments of 8 characters this - * function can deal with (16 segments of 8 chars= max 128 character - * password). - */ - -#define MAX_PASS_LEN 16 -#define SEGMENT_SIZE 8 -#define SALT_SIZE 2 -#define KEYBUF_SIZE ((MAX_PASS_LEN*SEGMENT_SIZE)+SALT_SIZE) -#define ESEGMENT_SIZE 11 -#define CBUF_SIZE ((MAX_PASS_LEN*ESEGMENT_SIZE)+SALT_SIZE+1) - -char *bigcrypt(const char *key, const char *salt) -{ - char *dec_c2_cryptbuf; -#ifdef HAVE_CRYPT_R - struct crypt_data *cdata; -#endif - unsigned long int keylen, n_seg, j; - char *cipher_ptr, *plaintext_ptr, *tmp_ptr, *salt_ptr; - char keybuf[KEYBUF_SIZE + 1]; - - D(("called with key='%s', salt='%s'.", key, salt)); - - /* reset arrays */ - dec_c2_cryptbuf = malloc(CBUF_SIZE); - if (!dec_c2_cryptbuf) { - return NULL; - } -#ifdef HAVE_CRYPT_R - cdata = malloc(sizeof(*cdata)); - if(!cdata) { - free(dec_c2_cryptbuf); - return NULL; - } - cdata->initialized = 0; -#endif - memset(keybuf, 0, KEYBUF_SIZE + 1); - memset(dec_c2_cryptbuf, 0, CBUF_SIZE); - - /* fill KEYBUF_SIZE with key */ - strncpy(keybuf, key, KEYBUF_SIZE); - - /* deal with case that we are doing a password check for a - conventially encrypted password: the salt will be - SALT_SIZE+ESEGMENT_SIZE long. */ - if (strlen(salt) == (SALT_SIZE + ESEGMENT_SIZE)) - keybuf[SEGMENT_SIZE] = '\0'; /* terminate password early(?) */ - - keylen = strlen(keybuf); - - if (!keylen) { - n_seg = 1; - } else { - /* work out how many segments */ - n_seg = 1 + ((keylen - 1) / SEGMENT_SIZE); - } - - if (n_seg > MAX_PASS_LEN) - n_seg = MAX_PASS_LEN; /* truncate at max length */ - - /* set up some pointers */ - cipher_ptr = dec_c2_cryptbuf; - plaintext_ptr = keybuf; - - /* do the first block with supplied salt */ -#ifdef HAVE_CRYPT_R - tmp_ptr = crypt_r(plaintext_ptr, salt, cdata); /* libc crypt_r() */ -#else - tmp_ptr = crypt(plaintext_ptr, salt); /* libc crypt() */ -#endif - /* and place in the static area */ - strncpy(cipher_ptr, tmp_ptr, 13); - cipher_ptr += ESEGMENT_SIZE + SALT_SIZE; - plaintext_ptr += SEGMENT_SIZE; /* first block of SEGMENT_SIZE */ - - /* change the salt (1st 2 chars of previous block) - this was found - by dowsing */ - - salt_ptr = cipher_ptr - ESEGMENT_SIZE; - - /* so far this is identical to "return crypt(key, salt);", if - there is more than one block encrypt them... */ - - if (n_seg > 1) { - for (j = 2; j <= n_seg; j++) { - -#ifdef HAVE_CRYPT_R - tmp_ptr = crypt_r(plaintext_ptr, salt_ptr, cdata); -#else - tmp_ptr = crypt(plaintext_ptr, salt_ptr); -#endif - - /* skip the salt for seg!=0 */ - strncpy(cipher_ptr, (tmp_ptr + SALT_SIZE), ESEGMENT_SIZE); - - cipher_ptr += ESEGMENT_SIZE; - plaintext_ptr += SEGMENT_SIZE; - salt_ptr = cipher_ptr - ESEGMENT_SIZE; - } - } - D(("key=|%s|, salt=|%s|\nbuf=|%s|\n", key, salt, dec_c2_cryptbuf)); - -#ifdef HAVE_CRYPT_R - free(cdata); -#endif - - /* this is the <NUL> terminated encrypted password */ - return dec_c2_cryptbuf; -} diff --git a/modules/pam_unix/bigcrypt.h b/modules/pam_unix/bigcrypt.h deleted file mode 100644 index a66a96e6..00000000 --- a/modules/pam_unix/bigcrypt.h +++ /dev/null @@ -1 +0,0 @@ -extern char *bigcrypt(const char *key, const char *salt); diff --git a/modules/pam_unix/bigcrypt_main.c b/modules/pam_unix/bigcrypt_main.c deleted file mode 100644 index fab212d9..00000000 --- a/modules/pam_unix/bigcrypt_main.c +++ /dev/null @@ -1,18 +0,0 @@ -#include <stdio.h> -#include <string.h> - -#include "bigcrypt.h" - -int -main(int argc, char **argv) -{ - if (argc < 3) { - fprintf(stderr, "Usage: %s password salt\n", - strchr(argv[0], '/') ? - (strchr(argv[0], '/') + 1) : - argv[0]); - return 0; - } - fprintf(stdout, "%s\n", bigcrypt(argv[1], argv[2])); - return 0; -} diff --git a/modules/pam_unix/lckpwdf.-c b/modules/pam_unix/lckpwdf.-c deleted file mode 100644 index 7145617e..00000000 --- a/modules/pam_unix/lckpwdf.-c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * This is a hack, but until libc and glibc both include this function - * by default (libc only includes it if nys is not being used, at the - * moment, and glibc doesn't appear to have it at all) we need to have - * it here, too. :-( - * - * This should not become an official part of PAM. - * - * BEGIN_HACK - */ - -/* - * lckpwdf.c -- prevent simultaneous updates of password files - * - * Before modifying any of the password files, call lckpwdf(). It may block - * for up to 15 seconds trying to get the lock. Return value is 0 on success - * or -1 on failure. When you are done, call ulckpwdf() to release the lock. - * The lock is also released automatically when the process exits. Only one - * process at a time may hold the lock. - * - * These functions are supposed to be conformant with AT&T SVID Issue 3. - * - * Written by Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>, - * public domain. - */ - -#include <fcntl.h> -#include <signal.h> -#ifdef WITH_SELINUX -#include <selinux/selinux.h> -#endif - -#define LOCKFILE "/etc/.pwd.lock" -#define TIMEOUT 15 - -static int lockfd = -1; - -static int set_close_on_exec(int fd) -{ - int flags = fcntl(fd, F_GETFD, 0); - if (flags == -1) - return -1; - flags |= FD_CLOEXEC; - return fcntl(fd, F_SETFD, flags); -} - -static int do_lock(int fd) -{ - struct flock fl; - - memset(&fl, 0, sizeof fl); - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - return fcntl(fd, F_SETLKW, &fl); -} - -static void alarm_catch(int sig) -{ -/* does nothing, but fcntl F_SETLKW will fail with EINTR */ -} - -static int lckpwdf(void) -{ - struct sigaction act, oldact; - sigset_t set, oldset; - - if (lockfd != -1) - return -1; - -#ifdef WITH_SELINUX - if(is_selinux_enabled()>0) - { - lockfd = open(LOCKFILE, O_WRONLY); - if(lockfd == -1 && errno == ENOENT) - { - security_context_t create_context; - int rc; - - if(getfilecon("/etc/passwd", &create_context)) - return -1; - rc = setfscreatecon(create_context); - freecon(create_context); - if(rc) - return -1; - lockfd = open(LOCKFILE, O_CREAT | O_WRONLY, 0600); - if(setfscreatecon(NULL)) - return -1; - } - } - else -#endif - lockfd = open(LOCKFILE, O_CREAT | O_WRONLY, 0600); - if (lockfd == -1) - return -1; - if (set_close_on_exec(lockfd) == -1) - goto cleanup_fd; - - memset(&act, 0, sizeof act); - act.sa_handler = alarm_catch; - act.sa_flags = 0; - sigfillset(&act.sa_mask); - if (sigaction(SIGALRM, &act, &oldact) == -1) - goto cleanup_fd; - - sigemptyset(&set); - sigaddset(&set, SIGALRM); - if (sigprocmask(SIG_UNBLOCK, &set, &oldset) == -1) - goto cleanup_sig; - - alarm(TIMEOUT); - if (do_lock(lockfd) == -1) - goto cleanup_alarm; - alarm(0); - sigprocmask(SIG_SETMASK, &oldset, NULL); - sigaction(SIGALRM, &oldact, NULL); - return 0; - - cleanup_alarm: - alarm(0); - sigprocmask(SIG_SETMASK, &oldset, NULL); - cleanup_sig: - sigaction(SIGALRM, &oldact, NULL); - cleanup_fd: - close(lockfd); - lockfd = -1; - return -1; -} - -static int ulckpwdf(void) -{ - unlink(LOCKFILE); - if (lockfd == -1) - return -1; - - if (close(lockfd) == -1) { - lockfd = -1; - return -1; - } - lockfd = -1; - return 0; -} -/* END_HACK */ diff --git a/modules/pam_unix/md5.c b/modules/pam_unix/md5.c deleted file mode 100644 index d88d6810..00000000 --- a/modules/pam_unix/md5.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * $Id$ - * - * This code implements the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5Context structure, pass it to MD5Init, call MD5Update as - * needed on buffers full of bytes, and then call MD5Final, which - * will fill a supplied 16-byte array with the digest. - * - */ - -#include <string.h> -#include "md5.h" - -#ifndef HIGHFIRST -#define byteReverse(buf, len) /* Nothing */ -#else -static void byteReverse(unsigned char *buf, unsigned longs); - -#ifndef ASM_MD5 -/* - * Note: this code is harmless on little-endian machines. - */ -static void byteReverse(unsigned char *buf, unsigned longs) -{ - uint32 t; - do { - t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | - ((unsigned) buf[1] << 8 | buf[0]); - *(uint32 *) buf = t; - buf += 4; - } while (--longs); -} -#endif -#endif - -/* - * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious - * initialization constants. - */ -void MD5Name(MD5Init)(struct MD5Context *ctx) -{ - ctx->buf[0] = 0x67452301U; - ctx->buf[1] = 0xefcdab89U; - ctx->buf[2] = 0x98badcfeU; - ctx->buf[3] = 0x10325476U; - - ctx->bits[0] = 0; - ctx->bits[1] = 0; -} - -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ -void MD5Name(MD5Update)(struct MD5Context *ctx, unsigned const char *buf, unsigned len) -{ - uint32 t; - - /* Update bitcount */ - - t = ctx->bits[0]; - if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) - ctx->bits[1]++; /* Carry from low to high */ - ctx->bits[1] += len >> 29; - - t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ - - /* Handle any leading odd-sized chunks */ - - if (t) { - unsigned char *p = (unsigned char *) ctx->in + t; - - t = 64 - t; - if (len < t) { - memcpy(p, buf, len); - return; - } - memcpy(p, buf, t); - byteReverse(ctx->in, 16); - MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); - buf += t; - len -= t; - } - /* Process data in 64-byte chunks */ - - while (len >= 64) { - memcpy(ctx->in, buf, 64); - byteReverse(ctx->in, 16); - MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); - buf += 64; - len -= 64; - } - - /* Handle any remaining bytes of data. */ - - memcpy(ctx->in, buf, len); -} - -/* - * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -void MD5Name(MD5Final)(unsigned char digest[16], struct MD5Context *ctx) -{ - unsigned count; - unsigned char *p; - - /* Compute number of bytes mod 64 */ - count = (ctx->bits[0] >> 3) & 0x3F; - - /* Set the first char of padding to 0x80. This is safe since there is - always at least one byte free */ - p = ctx->in + count; - *p++ = 0x80; - - /* Bytes of padding needed to make 64 bytes */ - count = 64 - 1 - count; - - /* Pad out to 56 mod 64 */ - if (count < 8) { - /* Two lots of padding: Pad the first block to 64 bytes */ - memset(p, 0, count); - byteReverse(ctx->in, 16); - MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); - - /* Now fill the next block with 56 bytes */ - memset(ctx->in, 0, 56); - } else { - /* Pad block to 56 bytes */ - memset(p, 0, count - 8); - } - byteReverse(ctx->in, 14); - - /* Append length in bits and transform */ - ((uint32 *) ctx->in)[14] = ctx->bits[0]; - ((uint32 *) ctx->in)[15] = ctx->bits[1]; - - MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); - byteReverse((unsigned char *) ctx->buf, 4); - memcpy(digest, ctx->buf, 16); - memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ -} - -#ifndef ASM_MD5 - -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f, w, x, y, z, data, s) \ - ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) - -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. MD5Update blocks - * the data and converts bytes into longwords for this routine. - */ -void MD5Name(MD5Transform)(uint32 buf[4], uint32 const in[16]) -{ - register uint32 a, b, c, d; - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478U, 7); - MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756U, 12); - MD5STEP(F1, c, d, a, b, in[2] + 0x242070dbU, 17); - MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceeeU, 22); - MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0fafU, 7); - MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62aU, 12); - MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613U, 17); - MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501U, 22); - MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8U, 7); - MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7afU, 12); - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1U, 17); - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7beU, 22); - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122U, 7); - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193U, 12); - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438eU, 17); - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821U, 22); - - MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562U, 5); - MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340U, 9); - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51U, 14); - MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aaU, 20); - MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105dU, 5); - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453U, 9); - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681U, 14); - MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8U, 20); - MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6U, 5); - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6U, 9); - MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87U, 14); - MD5STEP(F2, b, c, d, a, in[8] + 0x455a14edU, 20); - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905U, 5); - MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8U, 9); - MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9U, 14); - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8aU, 20); - - MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942U, 4); - MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681U, 11); - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122U, 16); - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380cU, 23); - MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44U, 4); - MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9U, 11); - MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60U, 16); - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70U, 23); - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6U, 4); - MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127faU, 11); - MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085U, 16); - MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05U, 23); - MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039U, 4); - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5U, 11); - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8U, 16); - MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665U, 23); - - MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244U, 6); - MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97U, 10); - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7U, 15); - MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039U, 21); - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3U, 6); - MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92U, 10); - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47dU, 15); - MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1U, 21); - MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4fU, 6); - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0U, 10); - MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314U, 15); - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1U, 21); - MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82U, 6); - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235U, 10); - MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bbU, 15); - MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391U, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - -#endif diff --git a/modules/pam_unix/md5.h b/modules/pam_unix/md5.h deleted file mode 100644 index 103f168a..00000000 --- a/modules/pam_unix/md5.h +++ /dev/null @@ -1,31 +0,0 @@ - -#ifndef MD5_H -#define MD5_H - -typedef unsigned int uint32; - -struct MD5Context { - uint32 buf[4]; - uint32 bits[2]; - unsigned char in[64]; -}; - -void GoodMD5Init(struct MD5Context *); -void GoodMD5Update(struct MD5Context *, unsigned const char *, unsigned); -void GoodMD5Final(unsigned char digest[16], struct MD5Context *); -void GoodMD5Transform(uint32 buf[4], uint32 const in[16]); -void BrokenMD5Init(struct MD5Context *); -void BrokenMD5Update(struct MD5Context *, unsigned const char *, unsigned); -void BrokenMD5Final(unsigned char digest[16], struct MD5Context *); -void BrokenMD5Transform(uint32 buf[4], uint32 const in[16]); - -char *Goodcrypt_md5(const char *pw, const char *salt); -char *Brokencrypt_md5(const char *pw, const char *salt); - -/* - * This is needed to make RSAREF happy on some MS-DOS compilers. - */ - -typedef struct MD5Context MD5_CTX; - -#endif /* MD5_H */ diff --git a/modules/pam_unix/md5_broken.c b/modules/pam_unix/md5_broken.c deleted file mode 100644 index 193daebb..00000000 --- a/modules/pam_unix/md5_broken.c +++ /dev/null @@ -1,4 +0,0 @@ -#define MD5Name(x) Broken##x - -#include "md5.c" -#include "md5_crypt.c" diff --git a/modules/pam_unix/md5_crypt.c b/modules/pam_unix/md5_crypt.c deleted file mode 100644 index 53972fcc..00000000 --- a/modules/pam_unix/md5_crypt.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * $Id$ - * - * ---------------------------------------------------------------------------- - * "THE BEER-WARE LICENSE" (Revision 42): - * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you - * can do whatever you want with this stuff. If we meet some day, and you think - * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp - * ---------------------------------------------------------------------------- - * - * Origin: Id: crypt.c,v 1.3 1995/05/30 05:42:22 rgrimes Exp - * - */ - -#include <string.h> -#include <stdlib.h> -#include "md5.h" - -static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ -"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - -static void to64(char *s, unsigned long v, int n) -{ - while (--n >= 0) { - *s++ = itoa64[v & 0x3f]; - v >>= 6; - } -} - -/* - * UNIX password - * - * Use MD5 for what it is best at... - */ - -char *MD5Name(crypt_md5)(const char *pw, const char *salt) -{ - const char *magic = "$1$"; - /* This string is magic for this algorithm. Having - * it this way, we can get get better later on */ - char *passwd, *p; - const char *sp, *ep; - unsigned char final[16]; - int sl, pl, i, j; - MD5_CTX ctx, ctx1; - unsigned long l; - - /* Refine the Salt first */ - sp = salt; - - /* TODO: now that we're using malloc'ed memory, get rid of the - strange constant buffer size. */ - passwd = malloc(120); - - /* If it starts with the magic string, then skip that */ - if (!strncmp(sp, magic, strlen(magic))) - sp += strlen(magic); - - /* It stops at the first '$', max 8 chars */ - for (ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++) - continue; - - /* get the length of the true salt */ - sl = ep - sp; - - MD5Name(MD5Init)(&ctx); - - /* The password first, since that is what is most unknown */ - MD5Name(MD5Update)(&ctx,(unsigned const char *)pw,strlen(pw)); - - /* Then our magic string */ - MD5Name(MD5Update)(&ctx,(unsigned const char *)magic,strlen(magic)); - - /* Then the raw salt */ - MD5Name(MD5Update)(&ctx,(unsigned const char *)sp,sl); - - /* Then just as many characters of the MD5(pw,salt,pw) */ - MD5Name(MD5Init)(&ctx1); - MD5Name(MD5Update)(&ctx1,(unsigned const char *)pw,strlen(pw)); - MD5Name(MD5Update)(&ctx1,(unsigned const char *)sp,sl); - MD5Name(MD5Update)(&ctx1,(unsigned const char *)pw,strlen(pw)); - MD5Name(MD5Final)(final,&ctx1); - for (pl = strlen(pw); pl > 0; pl -= 16) - MD5Name(MD5Update)(&ctx,(unsigned const char *)final,pl>16 ? 16 : pl); - - /* Don't leave anything around in vm they could use. */ - memset(final, 0, sizeof final); - - /* Then something really weird... */ - for (j = 0, i = strlen(pw); i; i >>= 1) - if (i & 1) - MD5Name(MD5Update)(&ctx, (unsigned const char *)final+j, 1); - else - MD5Name(MD5Update)(&ctx, (unsigned const char *)pw+j, 1); - - /* Now make the output string */ - strcpy(passwd, magic); - strncat(passwd, sp, sl); - strcat(passwd, "$"); - - MD5Name(MD5Final)(final,&ctx); - - /* - * and now, just to make sure things don't run too fast - * On a 60 Mhz Pentium this takes 34 msec, so you would - * need 30 seconds to build a 1000 entry dictionary... - */ - for (i = 0; i < 1000; i++) { - MD5Name(MD5Init)(&ctx1); - if (i & 1) - MD5Name(MD5Update)(&ctx1,(unsigned const char *)pw,strlen(pw)); - else - MD5Name(MD5Update)(&ctx1,(unsigned const char *)final,16); - - if (i % 3) - MD5Name(MD5Update)(&ctx1,(unsigned const char *)sp,sl); - - if (i % 7) - MD5Name(MD5Update)(&ctx1,(unsigned const char *)pw,strlen(pw)); - - if (i & 1) - MD5Name(MD5Update)(&ctx1,(unsigned const char *)final,16); - else - MD5Name(MD5Update)(&ctx1,(unsigned const char *)pw,strlen(pw)); - MD5Name(MD5Final)(final,&ctx1); - } - - p = passwd + strlen(passwd); - - l = (final[0] << 16) | (final[6] << 8) | final[12]; - to64(p, l, 4); - p += 4; - l = (final[1] << 16) | (final[7] << 8) | final[13]; - to64(p, l, 4); - p += 4; - l = (final[2] << 16) | (final[8] << 8) | final[14]; - to64(p, l, 4); - p += 4; - l = (final[3] << 16) | (final[9] << 8) | final[15]; - to64(p, l, 4); - p += 4; - l = (final[4] << 16) | (final[10] << 8) | final[5]; - to64(p, l, 4); - p += 4; - l = final[11]; - to64(p, l, 2); - p += 2; - *p = '\0'; - - /* Don't leave anything around in vm they could use. */ - memset(final, 0, sizeof final); - - return passwd; -} diff --git a/modules/pam_unix/md5_good.c b/modules/pam_unix/md5_good.c deleted file mode 100644 index 131e4516..00000000 --- a/modules/pam_unix/md5_good.c +++ /dev/null @@ -1,5 +0,0 @@ -#define HIGHFIRST -#define MD5Name(x) Good##x - -#include "md5.c" -#include "md5_crypt.c" diff --git a/modules/pam_unix/pam_unix.8.xml b/modules/pam_unix/pam_unix.8.xml deleted file mode 100644 index 290cb2b9..00000000 --- a/modules/pam_unix/pam_unix.8.xml +++ /dev/null @@ -1,379 +0,0 @@ -<?xml version="1.0" encoding='UTF-8'?> -<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" - "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"> - -<refentry id="pam_unix"> - - <refmeta> - <refentrytitle>pam_unix</refentrytitle> - <manvolnum>8</manvolnum> - <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo> - </refmeta> - - <refnamediv id="pam_unix-name"> - <refname>pam_unix</refname> - <refpurpose>Module for traditional password authentication</refpurpose> - </refnamediv> - - <refsynopsisdiv> - <cmdsynopsis id="pam_unix-cmdsynopsis"> - <command>pam_unix.so</command> - <arg choice="opt"> - ... - </arg> - </cmdsynopsis> - </refsynopsisdiv> - - <refsect1 id="pam_unix-description"> - - <title>DESCRIPTION</title> - - <para> - This is the standard Unix authentication module. It uses standard - calls from the system's libraries to retrieve and set account - information as well as authentication. Usually this is obtained - from the /etc/passwd and the /etc/shadow file as well if shadow is - enabled. - </para> - - <para> - The account component performs the task of establishing the status - of the user's account and password based on the following - <emphasis>shadow</emphasis> elements: expire, last_change, max_change, - min_change, warn_change. In the case of the latter, it may offer advice - to the user on changing their password or, through the - <emphasis remap='B'>PAM_AUTHTOKEN_REQD</emphasis> return, delay - giving service to the user until they have established a new password. - The entries listed above are documented in the <citerefentry> - <refentrytitle>shadow</refentrytitle><manvolnum>5</manvolnum> - </citerefentry> manual page. Should the user's record not contain - one or more of these entries, the corresponding - <emphasis>shadow</emphasis> check is not performed. - </para> - - <para> - The authentication component performs the task of checking the - users credentials (password). The default action of this module - is to not permit the user access to a service if their official - password is blank. - </para> - - <para> - A helper binary, <citerefentry> - <refentrytitle>unix_chkpwd</refentrytitle><manvolnum>8</manvolnum> - </citerefentry>, is provided - to check the user's password when it is stored in a read - protected database. This binary is very simple and will only - check the password of the user invoking it. It is called - transparently on behalf of the user by the authenticating - component of this module. In this way it is possible - for applications like <citerefentry> - <refentrytitle>xlock</refentrytitle><manvolnum>1</manvolnum> - </citerefentry> to work without - being setuid-root. The module, by default, will temporarily turn - off SIGCHLD handling for the duration of execution of the helper - binary. This is generally the right thing to do, as many applications - are not prepared to handle this signal from a child they didn't know - was <function>fork()</function>d. The <option>noreap</option> module - argument can be used to suppress this temporary shielding and may be - needed for use with certain applications. - </para> - - <para> - The password component of this module performs the task of updating - the user's password. - </para> - - <para> - The session component of this module logs when a user logins - or leave the system. - </para> - - <para> - Remaining arguments, supported by others functions of this - module, are silently ignored. Other arguments are logged as - errors through <citerefentry> - <refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum> - </citerefentry>. - </para> - </refsect1> - - <refsect1 id="pam_unix-options"> - - <title>OPTIONS</title> - <variablelist> - <varlistentry> - <term> - <option>debug</option> - </term> - <listitem> - <para> - Turns on debugging via - <citerefentry> - <refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum> - </citerefentry>. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term> - <option>audit</option> - </term> - <listitem> - <para> - A little more extreme than debug. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term> - <option>nullok</option> - </term> - <listitem> - <para> - The default action of this module is to not permit the - user access to a service if their official password is blank. - The <option>nullok</option> argument overrides this default. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <option>try_first_pass</option> - </term> - <listitem> - <para> - Before prompting the user for their password, the module first - tries the previous stacked module's password in case that - satisfies this module as well. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <option>use_first_pass</option> - </term> - <listitem> - <para> - The argument <option>use_first_pass</option> forces the module - to use a previous stacked modules password and will never prompt - the user - if no password is available or the password is not - appropriate, the user will be denied access. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <option>nodelay</option> - </term> - <listitem> - <para> - This argument can be used to discourage the authentication - component from requesting a delay should the authentication - as a whole fail. The default action is for the module to - request a delay-on-failure of the order of two second. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <option>use_authtok</option> - </term> - <listitem> - <para> - When password changing enforce the module to set the new - password to the one provided by a previously stacked - <option>password</option> module (this is used in the - example of the stacking of the <command>pam_cracklib</command> - module documented above). - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <option>not_set_pass</option> - </term> - <listitem> - <para> - This argument is used to inform the module that it is not to - pay attention to/make available the old or new passwords from/to - other (stacked) password modules. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <option>nis</option> - </term> - <listitem> - <para> - NIS RPC is used for setting new passwords. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <option>remember=<replaceable>n</replaceable></option> - </term> - <listitem> - <para> - The last <replaceable>n</replaceable> passwords for each - user are saved in <filename>/etc/security/opasswd</filename> - in order to force password change history and keep the user - from alternating between the same password too frequently. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <option>shadow</option> - </term> - <listitem> - <para> - Try to maintain a shadow based system. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <option>md5</option> - </term> - <listitem> - <para> - When a user changes their password next, encrypt - it with the MD5 algorithm. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <option>bigcrypt</option> - </term> - <listitem> - <para> - When a user changes their password next, - encrypt it with the DEC C2 algorithm. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <option>sha256</option> - </term> - <listitem> - <para> - When a user changes their password next, - encrypt it with the SHA256 algorithm. If the - SHA256 algorithm is not known to the libcrypt, - fall back to MD5. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <option>sha512</option> - </term> - <listitem> - <para> - When a user changes their password next, - encrypt it with the SHA512 algorithm. If the - SHA512 algorithm is not known to the libcrypt, - fall back to MD5. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <option>rounds=<replaceable>n</replaceable></option> - </term> - <listitem> - <para> - Set the optional number of rounds of the SHA256 and SHA512 - password hashing algorithms to <replaceable>n</replaceable>. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <option>broken_shadow</option> - </term> - <listitem> - <para> - Ignore errors reading shadow inforation for - users in the account management module. - </para> - </listitem> - </varlistentry> - </variablelist> - <para> - Invalid arguments are logged with <citerefentry> - <refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum> - </citerefentry>. - </para> - </refsect1> - - <refsect1 id="pam_unix-services"> - <title>MODULE SERVICES PROVIDED</title> - <para> - All service are supported. - </para> - </refsect1> - - <refsect1 id='pam_unix-return_values'> - <title>RETURN VALUES</title> - <variablelist> - <varlistentry> - <term>PAM_IGNORE</term> - <listitem> - <para> - Ignore this module. - </para> - </listitem> - </varlistentry> - </variablelist> - </refsect1> - - <refsect1 id='pam_unix-examples'> - <title>EXAMPLES</title> - <para> - An example usage for <filename>/etc/pam.d/login</filename> - would be: - <programlisting> -# Authenticate the user -auth required pam_unix.so -# Ensure users account and password are still active -account required pam_unix.so -# Change the users password, but at first check the strength -# with pam_cracklib(8) -password required pam_cracklib.so retry=3 minlen=6 difok=3 -password required pam_unix.so use_authtok nullok md5 -session required pam_unix.so - </programlisting> - </para> - </refsect1> - - <refsect1 id='pam_unix-see_also'> - <title>SEE ALSO</title> - <para> - <citerefentry> - <refentrytitle>pam.conf</refentrytitle><manvolnum>5</manvolnum> - </citerefentry>, - <citerefentry> - <refentrytitle>pam.d</refentrytitle><manvolnum>8</manvolnum> - </citerefentry>, - <citerefentry> - <refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum> - </citerefentry> - </para> - </refsect1> - - <refsect1 id='pam_unix-author'> - <title>AUTHOR</title> - <para> - pam_unix was written by various people. - </para> - </refsect1> - -</refentry> diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c deleted file mode 100644 index c09bc175..00000000 --- a/modules/pam_unix/pam_unix_acct.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright Elliot Lee, 1996. All rights reserved. - * Copyright Jan Rêkorajski, 1999. 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. - */ - -#include "config.h" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <sys/types.h> -#include <syslog.h> -#include <pwd.h> -#include <shadow.h> -#include <time.h> /* for time() */ -#include <errno.h> -#include <sys/wait.h> - -#include <security/_pam_macros.h> - -/* indicate that the following groups are defined */ - -#define PAM_SM_ACCOUNT - -#include <security/pam_modules.h> -#include <security/pam_ext.h> -#include <security/pam_modutil.h> - -#include "support.h" -#include "passverify.h" - -int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl, - const char *user, int *daysleft) -{ - int retval=0, child, fds[2]; - void (*sighandler)(int) = NULL; - D(("running verify_binary")); - - /* create a pipe for the messages */ - if (pipe(fds) != 0) { - D(("could not make pipe")); - pam_syslog(pamh, LOG_ERR, "Could not make pipe: %m"); - return PAM_AUTH_ERR; - } - D(("called.")); - - if (off(UNIX_NOREAP, ctrl)) { - /* - * This code arranges that the demise of the child does not cause - * the application to receive a signal it is not expecting - which - * may kill the application or worse. - * - * The "noreap" module argument is provided so that the admin can - * override this behavior. - */ - sighandler = signal(SIGCHLD, SIG_DFL); - } - - /* fork */ - child = fork(); - if (child == 0) { - size_t i=0; - struct rlimit rlim; - static char *envp[] = { NULL }; - char *args[] = { NULL, NULL, NULL, NULL }; - - close(0); close(1); - /* reopen stdin as pipe */ - close(fds[0]); - dup2(fds[1], STDOUT_FILENO); - - /* XXX - should really tidy up PAM here too */ - - if (getrlimit(RLIMIT_NOFILE,&rlim)==0) { - for (i=2; i < rlim.rlim_max; i++) { - if ((unsigned int)fds[1] != i) { - close(i); - } - } - } - - if (geteuid() == 0) { - /* must set the real uid to 0 so the helper will not error - out if pam is called from setuid binary (su, sudo...) */ - setuid(0); - } - - /* exec binary helper */ - args[0] = x_strdup(CHKPWD_HELPER); - args[1] = x_strdup(user); - args[2] = x_strdup("chkexpiry"); - - execve(CHKPWD_HELPER, args, envp); - - pam_syslog(pamh, LOG_ERR, "helper binary execve failed: %m"); - /* should not get here: exit with error */ - close (fds[1]); - D(("helper binary is not available")); - printf("-1\n"); - exit(PAM_AUTHINFO_UNAVAIL); - } else { - close(fds[1]); - if (child > 0) { - char buf[32]; - int rc=0; - rc=waitpid(child, &retval, 0); /* wait for helper to complete */ - if (rc<0) { - pam_syslog(pamh, LOG_ERR, "unix_chkpwd waitpid returned %d: %m", rc); - retval = PAM_AUTH_ERR; - } else { - retval = WEXITSTATUS(retval); - rc = pam_modutil_read(fds[0], buf, sizeof(buf) - 1); - if(rc > 0) { - buf[rc] = '\0'; - if (sscanf(buf,"%d", daysleft) != 1 ) - retval = PAM_AUTH_ERR; - } - else { - pam_syslog(pamh, LOG_ERR, "read unix_chkpwd output error %d: %m", rc); - retval = PAM_AUTH_ERR; - } - } - } else { - pam_syslog(pamh, LOG_ERR, "Fork failed: %m"); - D(("fork failed")); - retval = PAM_AUTH_ERR; - } - close(fds[0]); - } - if (sighandler != SIG_ERR) { - (void) signal(SIGCHLD, sighandler); /* restore old signal handler */ - } - D(("Returning %d",retval)); - return retval; -} - -/* - * PAM framework looks for this entry-point to pass control to the - * account management module. - */ - -PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t * pamh, int flags, - int argc, const char **argv) -{ - unsigned int ctrl; - const void *void_uname; - const char *uname; - int retval, daysleft; - struct spwd *spent; - struct passwd *pwent; - char buf[256]; - - D(("called.")); - - ctrl = _set_ctrl(pamh, flags, NULL, NULL, argc, argv); - - retval = pam_get_item(pamh, PAM_USER, &void_uname); - uname = void_uname; - D(("user = `%s'", uname)); - if (retval != PAM_SUCCESS || uname == NULL) { - pam_syslog(pamh, LOG_ALERT, - "could not identify user (from uid=%lu)", - (unsigned long int)getuid()); - return PAM_USER_UNKNOWN; - } - - retval = get_account_info(pamh, uname, &pwent, &spent); - if (retval == PAM_USER_UNKNOWN) { - pam_syslog(pamh, LOG_ALERT, - "could not identify user (from getpwnam(%s))", - uname); - return retval; - } - - if (retval == PAM_SUCCESS && spent == NULL) - return PAM_SUCCESS; - - if (retval == PAM_UNIX_RUN_HELPER) { - retval = _unix_run_verify_binary(pamh, ctrl, uname, &daysleft); - if (retval == PAM_AUTHINFO_UNAVAIL && - on(UNIX_BROKEN_SHADOW, ctrl)) - return PAM_SUCCESS; - } else if (retval != PAM_SUCCESS) { - if (on(UNIX_BROKEN_SHADOW,ctrl)) - return PAM_SUCCESS; - else - return retval; - } else - retval = check_shadow_expiry(pamh, spent, &daysleft); - - switch (retval) { - case PAM_ACCT_EXPIRED: - pam_syslog(pamh, LOG_NOTICE, - "account %s has expired (account expired)", - uname); - _make_remark(pamh, ctrl, PAM_ERROR_MSG, - _("Your account has expired; please contact your system administrator")); - break; - case PAM_NEW_AUTHTOK_REQD: - if (daysleft == 0) { - pam_syslog(pamh, LOG_NOTICE, - "expired password for user %s (root enforced)", - uname); - _make_remark(pamh, ctrl, PAM_ERROR_MSG, - _("You are required to change your password immediately (root enforced)")); - } else { - pam_syslog(pamh, LOG_DEBUG, - "expired password for user %s (password aged)", - uname); - _make_remark(pamh, ctrl, PAM_ERROR_MSG, - _("You are required to change your password immediately (password aged)")); - } - break; - case PAM_AUTHTOK_EXPIRED: - pam_syslog(pamh, LOG_NOTICE, - "account %s has expired (failed to change password)", - uname); - _make_remark(pamh, ctrl, PAM_ERROR_MSG, - _("Your account has expired; please contact your system administrator")); - break; - case PAM_SUCCESS: - if (daysleft >= 0) { - pam_syslog(pamh, LOG_DEBUG, - "password for user %s will expire in %d days", - uname, daysleft); -#if defined HAVE_DNGETTEXT && defined ENABLE_NLS - snprintf (buf, sizeof (buf), - dngettext(PACKAGE, - "Warning: your password will expire in %d day", - "Warning: your password will expire in %d days", - daysleft), - daysleft); -#else - if (daysleft == 1) - snprintf(buf, sizeof (buf), - _("Warning: your password will expire in %d day"), - daysleft); - else - snprintf(buf, sizeof (buf), - /* TRANSLATORS: only used if dngettext is not supported */ - _("Warning: your password will expire in %d days"), - daysleft); -#endif - _make_remark(pamh, ctrl, PAM_TEXT_INFO, buf); - } - } - - D(("all done")); - - return retval; -} - - -/* static module data */ -#ifdef PAM_STATIC -struct pam_module _pam_unix_acct_modstruct = { - "pam_unix_acct", - NULL, - NULL, - pam_sm_acct_mgmt, - NULL, - NULL, - NULL, -}; -#endif diff --git a/modules/pam_unix/pam_unix_auth.c b/modules/pam_unix/pam_unix_auth.c deleted file mode 100644 index dfedd608..00000000 --- a/modules/pam_unix/pam_unix_auth.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright Alexander O. Yuriev, 1996. All rights reserved. - * NIS+ support by Thorsten Kukuk <kukuk@weber.uni-paderborn.de> - * Copyright Jan Rêkorajski, 1999. 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. - */ - -/* #define DEBUG */ - -#include "config.h" - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <ctype.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <syslog.h> - -/* indicate the following groups are defined */ - -#define PAM_SM_AUTH - -#define _PAM_EXTERN_FUNCTIONS -#include <security/_pam_macros.h> -#include <security/pam_modules.h> -#include <security/pam_ext.h> - -#include "support.h" - -/* - * PAM framework looks for these entry-points to pass control to the - * authentication module. - */ - -/* Fun starts here :) - - * pam_sm_authenticate() performs UNIX/shadow authentication - * - * First, if shadow support is available, attempt to perform - * authentication using shadow passwords. If shadow is not - * available, or user does not have a shadow password, fallback - * onto a normal UNIX authentication - */ - -#define _UNIX_AUTHTOK "-UN*X-PASS" - -#define AUTH_RETURN \ -do { \ - if (on(UNIX_LIKE_AUTH, ctrl) && ret_data) { \ - D(("recording return code for next time [%d]", \ - retval)); \ - *ret_data = retval; \ - pam_set_data(pamh, "unix_setcred_return", \ - (void *) ret_data, setcred_free); \ - } else if (ret_data) \ - free (ret_data); \ - D(("done. [%s]", pam_strerror(pamh, retval))); \ - return retval; \ -} while (0) - - -static void -setcred_free (pam_handle_t *pamh UNUSED, void *ptr, int err UNUSED) -{ - if (ptr) - free (ptr); -} - - -PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags - ,int argc, const char **argv) -{ - unsigned int ctrl; - int retval, *ret_data = NULL; - const char *name; - const void *p; - - D(("called.")); - - ctrl = _set_ctrl(pamh, flags, NULL, NULL, argc, argv); - - /* Get a few bytes so we can pass our return value to - pam_sm_setcred(). */ - if (on(UNIX_LIKE_AUTH, ctrl)) - ret_data = malloc(sizeof(int)); - - /* get the user'name' */ - - retval = pam_get_user(pamh, &name, NULL); - if (retval == PAM_SUCCESS) { - /* - * Various libraries at various times have had bugs related to - * '+' or '-' as the first character of a user name. Don't - * allow this characters here. - */ - if (name == NULL || name[0] == '-' || name[0] == '+') { - pam_syslog(pamh, LOG_ERR, "bad username [%s]", name); - retval = PAM_USER_UNKNOWN; - AUTH_RETURN; - } - if (retval == PAM_SUCCESS && on(UNIX_DEBUG, ctrl)) - D(("username [%s] obtained", name)); - } else { - D(("trouble reading username")); - if (retval == PAM_CONV_AGAIN) { - D(("pam_get_user/conv() function is not ready yet")); - /* it is safe to resume this function so we translate this - * retval to the value that indicates we're happy to resume. - */ - retval = PAM_INCOMPLETE; - } - AUTH_RETURN; - } - - /* if this user does not have a password... */ - - if (_unix_blankpasswd(pamh, ctrl, name)) { - D(("user '%s' has blank passwd", name)); - name = NULL; - retval = PAM_SUCCESS; - AUTH_RETURN; - } - /* get this user's authentication token */ - - retval = _unix_read_password(pamh, ctrl, NULL, _("Password: "), NULL - ,_UNIX_AUTHTOK, &p); - if (retval != PAM_SUCCESS) { - if (retval != PAM_CONV_AGAIN) { - pam_syslog(pamh, LOG_CRIT, - "auth could not identify password for [%s]", name); - } else { - D(("conversation function is not ready yet")); - /* - * it is safe to resume this function so we translate this - * retval to the value that indicates we're happy to resume. - */ - retval = PAM_INCOMPLETE; - } - name = NULL; - AUTH_RETURN; - } - D(("user=%s, password=[%s]", name, p)); - - /* verify the password of this user */ - retval = _unix_verify_password(pamh, name, p, ctrl); - name = p = NULL; - - AUTH_RETURN; -} - - -/* - * The only thing _pam_set_credentials_unix() does is initialization of - * UNIX group IDs. - * - * Well, everybody but me on linux-pam is convinced that it should not - * initialize group IDs, so I am not doing it but don't say that I haven't - * warned you. -- AOY - */ - -PAM_EXTERN int -pam_sm_setcred (pam_handle_t *pamh, int flags UNUSED, - int argc UNUSED, const char **argv UNUSED) -{ - int retval; - const void *pretval = NULL; - - D(("called.")); - - retval = PAM_SUCCESS; - - D(("recovering return code from auth call")); - /* We will only find something here if UNIX_LIKE_AUTH is set -- - don't worry about an explicit check of argv. */ - if (pam_get_data(pamh, "unix_setcred_return", &pretval) == PAM_SUCCESS - && pretval) { - retval = *(const int *)pretval; - pam_set_data(pamh, "unix_setcred_return", NULL, NULL); - D(("recovered data indicates that old retval was %d", retval)); - } - - return retval; -} - -#ifdef PAM_STATIC -struct pam_module _pam_unix_auth_modstruct = { - "pam_unix_auth", - pam_sm_authenticate, - pam_sm_setcred, - NULL, - NULL, - NULL, - NULL, -}; -#endif diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c deleted file mode 100644 index 432f687f..00000000 --- a/modules/pam_unix/pam_unix_passwd.c +++ /dev/null @@ -1,802 +0,0 @@ -/* - * Main coding by Elliot Lee <sopwith@redhat.com>, Red Hat Software. - * Copyright (C) 1996. - * Copyright (c) Jan Rêkorajski, 1999. - * Copyright (c) Red Hat, Inc., 2007, 2008. - * - * 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. - */ - -#include "config.h" - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <malloc.h> -#include <unistd.h> -#include <errno.h> -#include <sys/types.h> -#include <pwd.h> -#include <syslog.h> -#include <shadow.h> -#include <time.h> /* for time() */ -#include <fcntl.h> -#include <ctype.h> -#include <sys/time.h> -#include <sys/stat.h> -#include <rpc/rpc.h> -#include <rpcsvc/yp_prot.h> -#include <rpcsvc/ypclnt.h> - -#include <signal.h> -#include <errno.h> -#include <sys/wait.h> -#ifdef WITH_SELINUX -static int selinux_enabled=-1; -#include <selinux/selinux.h> -#define SELINUX_ENABLED (selinux_enabled!=-1 ? selinux_enabled : (selinux_enabled=is_selinux_enabled()>0)) -#endif - -#ifdef USE_CRACKLIB -#include <crack.h> -#endif - -#include <security/_pam_macros.h> - -/* indicate the following groups are defined */ - -#define PAM_SM_PASSWORD - -#include <security/pam_modules.h> -#include <security/pam_ext.h> -#include <security/pam_modutil.h> - -#include "yppasswd.h" -#include "md5.h" -#include "support.h" -#include "passverify.h" -#include "bigcrypt.h" - -#if !((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1)) -extern int getrpcport(const char *host, unsigned long prognum, - unsigned long versnum, unsigned int proto); -#endif /* GNU libc 2.1 */ - -/* - How it works: - Gets in username (has to be done) from the calling program - Does authentication of user (only if we are not running as root) - Gets new password/checks for sanity - Sets it. - */ - -/* data tokens */ - -#define _UNIX_OLD_AUTHTOK "-UN*X-OLD-PASS" -#define _UNIX_NEW_AUTHTOK "-UN*X-NEW-PASS" - -#define MAX_PASSWD_TRIES 3 -#ifndef CRACKLIB_DICTS -#define CRACKLIB_DICTS NULL -#endif - -static char *getNISserver(pam_handle_t *pamh) -{ - char *master; - char *domainname; - int port, err; - - if ((err = yp_get_default_domain(&domainname)) != 0) { - pam_syslog(pamh, LOG_WARNING, "can't get local yp domain: %s", - yperr_string(err)); - return NULL; - } - if ((err = yp_master(domainname, "passwd.byname", &master)) != 0) { - pam_syslog(pamh, LOG_WARNING, "can't find the master ypserver: %s", - yperr_string(err)); - return NULL; - } - port = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, IPPROTO_UDP); - if (port == 0) { - pam_syslog(pamh, LOG_WARNING, - "yppasswdd not running on NIS master host"); - return NULL; - } - if (port >= IPPORT_RESERVED) { - pam_syslog(pamh, LOG_WARNING, - "yppasswd daemon running on illegal port"); - return NULL; - } - return master; -} - -#ifdef WITH_SELINUX - -static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const char *user, - const char *fromwhat, const char *towhat, int remember) -{ - int retval, child, fds[2]; - void (*sighandler)(int) = NULL; - - D(("called.")); - /* create a pipe for the password */ - if (pipe(fds) != 0) { - D(("could not make pipe")); - return PAM_AUTH_ERR; - } - - if (off(UNIX_NOREAP, ctrl)) { - /* - * This code arranges that the demise of the child does not cause - * the application to receive a signal it is not expecting - which - * may kill the application or worse. - * - * The "noreap" module argument is provided so that the admin can - * override this behavior. - */ - sighandler = signal(SIGCHLD, SIG_DFL); - } - - /* fork */ - child = fork(); - if (child == 0) { - size_t i=0; - struct rlimit rlim; - static char *envp[] = { NULL }; - char *args[] = { NULL, NULL, NULL, NULL, NULL, NULL }; - char buffer[16]; - - /* XXX - should really tidy up PAM here too */ - - close(0); close(1); - /* reopen stdin as pipe */ - close(fds[1]); - dup2(fds[0], STDIN_FILENO); - - if (getrlimit(RLIMIT_NOFILE,&rlim)==0) { - for (i=2; i < rlim.rlim_max; i++) { - if ((unsigned int)fds[0] != i) - close(i); - } - } - - if (SELINUX_ENABLED && geteuid() == 0) { - /* must set the real uid to 0 so the helper will not error - out if pam is called from setuid binary (su, sudo...) */ - setuid(0); - } - - /* exec binary helper */ - args[0] = x_strdup(UPDATE_HELPER); - args[1] = x_strdup(user); - args[2] = x_strdup("update"); - if (on(UNIX_SHADOW, ctrl)) - args[3] = x_strdup("1"); - else - args[3] = x_strdup("0"); - - snprintf(buffer, sizeof(buffer), "%d", remember); - args[4] = x_strdup(buffer); - - execve(UPDATE_HELPER, args, envp); - - /* should not get here: exit with error */ - D(("helper binary is not available")); - exit(PAM_AUTHINFO_UNAVAIL); - } else if (child > 0) { - /* wait for child */ - /* if the stored password is NULL */ - int rc=0; - if (fromwhat) - pam_modutil_write(fds[1], fromwhat, strlen(fromwhat)+1); - else - pam_modutil_write(fds[1], "", 1); - if (towhat) { - pam_modutil_write(fds[1], towhat, strlen(towhat)+1); - } - else - pam_modutil_write(fds[1], "", 1); - - close(fds[0]); /* close here to avoid possible SIGPIPE above */ - close(fds[1]); - rc=waitpid(child, &retval, 0); /* wait for helper to complete */ - if (rc<0) { - pam_syslog(pamh, LOG_ERR, "unix_update waitpid failed: %m"); - retval = PAM_AUTH_ERR; - } else { - retval = WEXITSTATUS(retval); - } - } else { - D(("fork failed")); - close(fds[0]); - close(fds[1]); - retval = PAM_AUTH_ERR; - } - - if (sighandler != SIG_ERR) { - (void) signal(SIGCHLD, sighandler); /* restore old signal handler */ - } - - return retval; -} -#endif - -static int check_old_password(const char *forwho, const char *newpass) -{ - static char buf[16384]; - char *s_luser, *s_uid, *s_npas, *s_pas; - int retval = PAM_SUCCESS; - FILE *opwfile; - - opwfile = fopen(OLD_PASSWORDS_FILE, "r"); - if (opwfile == NULL) - return PAM_ABORT; - - while (fgets(buf, 16380, opwfile)) { - if (!strncmp(buf, forwho, strlen(forwho))) { - char *sptr; - buf[strlen(buf) - 1] = '\0'; - s_luser = strtok_r(buf, ":,", &sptr); - s_uid = strtok_r(NULL, ":,", &sptr); - s_npas = strtok_r(NULL, ":,", &sptr); - s_pas = strtok_r(NULL, ":,", &sptr); - while (s_pas != NULL) { - char *md5pass = Goodcrypt_md5(newpass, s_pas); - if (!strcmp(md5pass, s_pas)) { - _pam_delete(md5pass); - retval = PAM_AUTHTOK_ERR; - break; - } - s_pas = strtok_r(NULL, ":,", &sptr); - _pam_delete(md5pass); - } - break; - } - } - fclose(opwfile); - - return retval; -} - -static int _do_setpass(pam_handle_t* pamh, const char *forwho, - const char *fromwhat, - char *towhat, unsigned int ctrl, int remember) -{ - struct passwd *pwd = NULL; - int retval = 0; - int unlocked = 0; - char *master = NULL; - - D(("called")); - - pwd = getpwnam(forwho); - - if (pwd == NULL) { - retval = PAM_AUTHTOK_ERR; - goto done; - } - - if (on(UNIX_NIS, ctrl) && _unix_comesfromsource(pamh, forwho, 0, 1)) { - if ((master=getNISserver(pamh)) != NULL) { - struct timeval timeout; - struct yppasswd yppwd; - CLIENT *clnt; - int status; - enum clnt_stat err; - - /* Unlock passwd file to avoid deadlock */ - unlock_pwdf(); - unlocked = 1; - - /* Initialize password information */ - yppwd.newpw.pw_passwd = pwd->pw_passwd; - yppwd.newpw.pw_name = pwd->pw_name; - yppwd.newpw.pw_uid = pwd->pw_uid; - yppwd.newpw.pw_gid = pwd->pw_gid; - yppwd.newpw.pw_gecos = pwd->pw_gecos; - yppwd.newpw.pw_dir = pwd->pw_dir; - yppwd.newpw.pw_shell = pwd->pw_shell; - yppwd.oldpass = fromwhat ? strdup (fromwhat) : strdup (""); - yppwd.newpw.pw_passwd = towhat; - - D(("Set password %s for %s", yppwd.newpw.pw_passwd, forwho)); - - /* The yppasswd.x file said `unix authentication required', - * so I added it. This is the only reason it is in here. - * My yppasswdd doesn't use it, but maybe some others out there - * do. --okir - */ - clnt = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp"); - clnt->cl_auth = authunix_create_default(); - memset((char *) &status, '\0', sizeof(status)); - timeout.tv_sec = 25; - timeout.tv_usec = 0; - err = clnt_call(clnt, YPPASSWDPROC_UPDATE, - (xdrproc_t) xdr_yppasswd, (char *) &yppwd, - (xdrproc_t) xdr_int, (char *) &status, - timeout); - - free (yppwd.oldpass); - - if (err) { - _make_remark(pamh, ctrl, PAM_TEXT_INFO, - clnt_sperrno(err)); - } else if (status) { - D(("Error while changing NIS password.\n")); - } - D(("The password has%s been changed on %s.", - (err || status) ? " not" : "", master)); - pam_syslog(pamh, LOG_NOTICE, "password%s changed for %s on %s", - (err || status) ? " not" : "", pwd->pw_name, master); - - auth_destroy(clnt->cl_auth); - clnt_destroy(clnt); - if (err || status) { - _make_remark(pamh, ctrl, PAM_TEXT_INFO, - _("NIS password could not be changed.")); - retval = PAM_TRY_AGAIN; - } -#ifdef DEBUG - sleep(5); -#endif - } else { - retval = PAM_TRY_AGAIN; - } - } - - if (_unix_comesfromsource(pamh, forwho, 1, 0)) { - if(unlocked) { - if (lock_pwdf() != PAM_SUCCESS) { - return PAM_AUTHTOK_LOCK_BUSY; - } - } -#ifdef WITH_SELINUX - if (unix_selinux_confined()) - return _unix_run_update_binary(pamh, ctrl, forwho, fromwhat, towhat, remember); -#endif - /* first, save old password */ - if (save_old_password(forwho, fromwhat, remember)) { - retval = PAM_AUTHTOK_ERR; - goto done; - } - if (on(UNIX_SHADOW, ctrl) || is_pwd_shadowed(pwd)) { - retval = unix_update_shadow(pamh, forwho, towhat); - if (retval == PAM_SUCCESS) - if (!is_pwd_shadowed(pwd)) - retval = unix_update_passwd(pamh, forwho, "x"); - } else { - retval = unix_update_passwd(pamh, forwho, towhat); - } - } - - -done: - unlock_pwdf(); - - return retval; -} - -static int _unix_verify_shadow(pam_handle_t *pamh, const char *user, unsigned int ctrl) -{ - struct passwd *pwent = NULL; /* Password and shadow password */ - struct spwd *spent = NULL; /* file entries for the user */ - int daysleft; - int retval; - - retval = get_account_info(pamh, user, &pwent, &spent); - if (retval == PAM_USER_UNKNOWN) { - return retval; - } - - if (retval == PAM_SUCCESS && spent == NULL) - return PAM_SUCCESS; - - if (retval == PAM_UNIX_RUN_HELPER) { - retval = _unix_run_verify_binary(pamh, ctrl, user, &daysleft); - if (retval == PAM_AUTH_ERR || retval == PAM_USER_UNKNOWN) - return retval; - } - else if (retval == PAM_SUCCESS) - retval = check_shadow_expiry(pamh, spent, &daysleft); - - if (on(UNIX__IAMROOT, ctrl) || retval == PAM_NEW_AUTHTOK_REQD) - return PAM_SUCCESS; - - return retval; -} - -static int _pam_unix_approve_pass(pam_handle_t * pamh - ,unsigned int ctrl - ,const char *pass_old - ,const char *pass_new) -{ - const void *user; - const char *remark = NULL; - int retval = PAM_SUCCESS; - - D(("&new=%p, &old=%p", pass_old, pass_new)); - D(("new=[%s]", pass_new)); - D(("old=[%s]", pass_old)); - - if (pass_new == NULL || (pass_old && !strcmp(pass_old, pass_new))) { - if (on(UNIX_DEBUG, ctrl)) { - pam_syslog(pamh, LOG_DEBUG, "bad authentication token"); - } - _make_remark(pamh, ctrl, PAM_ERROR_MSG, pass_new == NULL ? - _("No password supplied") : _("Password unchanged")); - return PAM_AUTHTOK_ERR; - } - /* - * if one wanted to hardwire authentication token strength - * checking this would be the place - AGM - */ - - retval = pam_get_item(pamh, PAM_USER, &user); - if (retval != PAM_SUCCESS) { - if (on(UNIX_DEBUG, ctrl)) { - pam_syslog(pamh, LOG_ERR, "Can not get username"); - return PAM_AUTHTOK_ERR; - } - } - if (off(UNIX__IAMROOT, ctrl)) { -#ifdef USE_CRACKLIB - remark = FascistCheck (pass_new, CRACKLIB_DICTS); - D(("called cracklib [%s]", remark)); -#else - if (strlen(pass_new) < 6) - remark = _("You must choose a longer password"); - D(("length check [%s]", remark)); -#endif - if (on(UNIX_REMEMBER_PASSWD, ctrl)) { - if ((retval = check_old_password(user, pass_new)) == PAM_AUTHTOK_ERR) - remark = _("Password has been already used. Choose another."); - if (retval == PAM_ABORT) { - pam_syslog(pamh, LOG_ERR, "can't open %s file to check old passwords", - OLD_PASSWORDS_FILE); - return retval; - } - } - } - if (remark) { - _make_remark(pamh, ctrl, PAM_ERROR_MSG, remark); - retval = PAM_AUTHTOK_ERR; - } - return retval; -} - - -PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, - int argc, const char **argv) -{ - unsigned int ctrl, lctrl; - int retval; - int remember = -1; - int rounds = -1; - - /* <DO NOT free() THESE> */ - const char *user; - const void *pass_old, *pass_new; - /* </DO NOT free() THESE> */ - - D(("called.")); - - ctrl = _set_ctrl(pamh, flags, &remember, &rounds, argc, argv); - - /* - * First get the name of a user - */ - retval = pam_get_user(pamh, &user, NULL); - if (retval == PAM_SUCCESS) { - /* - * Various libraries at various times have had bugs related to - * '+' or '-' as the first character of a user name. Don't - * allow them. - */ - if (user == NULL || user[0] == '-' || user[0] == '+') { - pam_syslog(pamh, LOG_ERR, "bad username [%s]", user); - return PAM_USER_UNKNOWN; - } - if (retval == PAM_SUCCESS && on(UNIX_DEBUG, ctrl)) - pam_syslog(pamh, LOG_DEBUG, "username [%s] obtained", - user); - } else { - if (on(UNIX_DEBUG, ctrl)) - pam_syslog(pamh, LOG_DEBUG, - "password - could not identify user"); - return retval; - } - - D(("Got username of %s", user)); - - /* - * Before we do anything else, check to make sure that the user's - * info is in one of the databases we can modify from this module, - * which currently is 'files' and 'nis'. We have to do this because - * getpwnam() doesn't tell you *where* the information it gives you - * came from, nor should it. That's our job. - */ - if (_unix_comesfromsource(pamh, user, 1, on(UNIX_NIS, ctrl)) == 0) { - pam_syslog(pamh, LOG_DEBUG, - "user \"%s\" does not exist in /etc/passwd%s", - user, on(UNIX_NIS, ctrl) ? " or NIS" : ""); - return PAM_USER_UNKNOWN; - } else { - struct passwd *pwd; - _unix_getpwnam(pamh, user, 1, 1, &pwd); - if (pwd == NULL) { - pam_syslog(pamh, LOG_DEBUG, - "user \"%s\" has corrupted passwd entry", - user); - return PAM_USER_UNKNOWN; - } - } - - /* - * This is not an AUTH module! - */ - if (on(UNIX__NONULL, ctrl)) - set(UNIX__NULLOK, ctrl); - - if (on(UNIX__PRELIM, ctrl)) { - /* - * obtain and verify the current password (OLDAUTHTOK) for - * the user. - */ - char *Announce; - - D(("prelim check")); - - if (_unix_blankpasswd(pamh, ctrl, user)) { - return PAM_SUCCESS; - } else if (off(UNIX__IAMROOT, ctrl)) { - /* instruct user what is happening */ - if (asprintf(&Announce, _("Changing password for %s."), - user) < 0) { - pam_syslog(pamh, LOG_CRIT, - "password - out of memory"); - return PAM_BUF_ERR; - } - - lctrl = ctrl; - set(UNIX__OLD_PASSWD, lctrl); - retval = _unix_read_password(pamh, lctrl - ,Announce - ,_("(current) UNIX password: ") - ,NULL - ,_UNIX_OLD_AUTHTOK - ,&pass_old); - free(Announce); - - if (retval != PAM_SUCCESS) { - pam_syslog(pamh, LOG_NOTICE, - "password - (old) token not obtained"); - return retval; - } - /* verify that this is the password for this user */ - - retval = _unix_verify_password(pamh, user, pass_old, ctrl); - } else { - D(("process run by root so do nothing this time around")); - pass_old = NULL; - retval = PAM_SUCCESS; /* root doesn't have too */ - } - - if (retval != PAM_SUCCESS) { - D(("Authentication failed")); - pass_old = NULL; - return retval; - } - retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old); - pass_old = NULL; - if (retval != PAM_SUCCESS) { - pam_syslog(pamh, LOG_CRIT, - "failed to set PAM_OLDAUTHTOK"); - } - retval = _unix_verify_shadow(pamh,user, ctrl); - if (retval == PAM_AUTHTOK_ERR) { - if (off(UNIX__IAMROOT, ctrl)) - _make_remark(pamh, ctrl, PAM_ERROR_MSG, - _("You must wait longer to change your password")); - else - retval = PAM_SUCCESS; - } - } else if (on(UNIX__UPDATE, ctrl)) { - /* - * tpass is used below to store the _pam_md() return; it - * should be _pam_delete()'d. - */ - - char *tpass = NULL; - int retry = 0; - - /* - * obtain the proposed password - */ - - D(("do update")); - - /* - * get the old token back. NULL was ok only if root [at this - * point we assume that this has already been enforced on a - * previous call to this function]. - */ - - if (off(UNIX_NOT_SET_PASS, ctrl)) { - retval = pam_get_item(pamh, PAM_OLDAUTHTOK - ,&pass_old); - } else { - retval = pam_get_data(pamh, _UNIX_OLD_AUTHTOK - ,&pass_old); - if (retval == PAM_NO_MODULE_DATA) { - retval = PAM_SUCCESS; - pass_old = NULL; - } - } - D(("pass_old [%s]", pass_old)); - - if (retval != PAM_SUCCESS) { - pam_syslog(pamh, LOG_NOTICE, "user not authenticated"); - return retval; - } - - D(("get new password now")); - - lctrl = ctrl; - - if (on(UNIX_USE_AUTHTOK, lctrl)) { - set(UNIX_USE_FIRST_PASS, lctrl); - } - retry = 0; - retval = PAM_AUTHTOK_ERR; - while ((retval != PAM_SUCCESS) && (retry++ < MAX_PASSWD_TRIES)) { - /* - * use_authtok is to force the use of a previously entered - * password -- needed for pluggable password strength checking - */ - - retval = _unix_read_password(pamh, lctrl - ,NULL - ,_("Enter new UNIX password: ") - ,_("Retype new UNIX password: ") - ,_UNIX_NEW_AUTHTOK - ,&pass_new); - - if (retval != PAM_SUCCESS) { - if (on(UNIX_DEBUG, ctrl)) { - pam_syslog(pamh, LOG_ALERT, - "password - new password not obtained"); - } - pass_old = NULL; /* tidy up */ - return retval; - } - D(("returned to _unix_chauthtok")); - - /* - * At this point we know who the user is and what they - * propose as their new password. Verify that the new - * password is acceptable. - */ - - if (*(const char *)pass_new == '\0') { /* "\0" password = NULL */ - pass_new = NULL; - } - retval = _pam_unix_approve_pass(pamh, ctrl, pass_old, pass_new); - } - - if (retval != PAM_SUCCESS) { - pam_syslog(pamh, LOG_NOTICE, - "new password not acceptable"); - pass_new = pass_old = NULL; /* tidy up */ - return retval; - } - if (lock_pwdf() != PAM_SUCCESS) { - return PAM_AUTHTOK_LOCK_BUSY; - } - - if (pass_old) { - retval = _unix_verify_password(pamh, user, pass_old, ctrl); - if (retval != PAM_SUCCESS) { - pam_syslog(pamh, LOG_NOTICE, "user password changed by another process"); - unlock_pwdf(); - return retval; - } - } - - retval = _unix_verify_shadow(pamh, user, ctrl); - if (retval != PAM_SUCCESS) { - pam_syslog(pamh, LOG_NOTICE, "user shadow entry expired"); - unlock_pwdf(); - return retval; - } - - retval = _pam_unix_approve_pass(pamh, ctrl, pass_old, pass_new); - if (retval != PAM_SUCCESS) { - pam_syslog(pamh, LOG_NOTICE, - "new password not acceptable 2"); - pass_new = pass_old = NULL; /* tidy up */ - unlock_pwdf(); - return retval; - } - - /* - * By reaching here we have approved the passwords and must now - * rebuild the password database file. - */ - - /* - * First we encrypt the new password. - */ - - tpass = create_password_hash(pass_new, ctrl, rounds); - if (tpass == NULL) { - pam_syslog(pamh, LOG_CRIT, - "out of memory for password"); - pass_new = pass_old = NULL; /* tidy up */ - unlock_pwdf(); - return PAM_BUF_ERR; - } - - D(("password processed")); - - /* update the password database(s) -- race conditions..? */ - - retval = _do_setpass(pamh, user, pass_old, tpass, ctrl, - remember); - /* _do_setpass has called unlock_pwdf for us */ - - _pam_delete(tpass); - pass_old = pass_new = NULL; - } else { /* something has broken with the module */ - pam_syslog(pamh, LOG_ALERT, - "password received unknown request"); - retval = PAM_ABORT; - } - - D(("retval was %d", retval)); - - return retval; -} - - -/* static module data */ -#ifdef PAM_STATIC -struct pam_module _pam_unix_passwd_modstruct = { - "pam_unix_passwd", - NULL, - NULL, - NULL, - NULL, - NULL, - pam_sm_chauthtok, -}; -#endif diff --git a/modules/pam_unix/pam_unix_sess.c b/modules/pam_unix/pam_unix_sess.c deleted file mode 100644 index e984578c..00000000 --- a/modules/pam_unix/pam_unix_sess.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * $Id$ - * - * Copyright Alexander O. Yuriev, 1996. All rights reserved. - * Copyright Jan Rêkorajski, 1999. 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. - */ - -#include "config.h" - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <unistd.h> -#include <syslog.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> - -/* indicate the following groups are defined */ - -#define PAM_SM_SESSION - -#include <security/_pam_macros.h> -#include <security/pam_modules.h> -#include <security/pam_ext.h> -#include <security/pam_modutil.h> - -#include "support.h" - -/* - * PAM framework looks for these entry-points to pass control to the - * session module. - */ - -PAM_EXTERN int pam_sm_open_session(pam_handle_t * pamh, int flags, - int argc, const char **argv) -{ - char *user_name, *service; - unsigned int ctrl; - int retval; - const char *login_name; - - D(("called.")); - - ctrl = _set_ctrl(pamh, flags, NULL, NULL, argc, argv); - - retval = pam_get_item(pamh, PAM_USER, (void *) &user_name); - if (user_name == NULL || *user_name == '\0' || retval != PAM_SUCCESS) { - pam_syslog(pamh, LOG_CRIT, - "open_session - error recovering username"); - return PAM_SESSION_ERR; /* How did we get authenticated with - no username?! */ - } - retval = pam_get_item(pamh, PAM_SERVICE, (void *) &service); - if (service == NULL || *service == '\0' || retval != PAM_SUCCESS) { - pam_syslog(pamh, LOG_CRIT, - "open_session - error recovering service"); - return PAM_SESSION_ERR; - } - login_name = pam_modutil_getlogin(pamh); - if (login_name == NULL) { - login_name = ""; - } - pam_syslog(pamh, LOG_INFO, "session opened for user %s by %s(uid=%lu)", - user_name, login_name, (unsigned long)getuid()); - - return PAM_SUCCESS; -} - -PAM_EXTERN int pam_sm_close_session(pam_handle_t * pamh, int flags, - int argc, const char **argv) -{ - char *user_name, *service; - unsigned int ctrl; - int retval; - - D(("called.")); - - ctrl = _set_ctrl(pamh, flags, NULL, NULL, argc, argv); - - retval = pam_get_item(pamh, PAM_USER, (void *) &user_name); - if (user_name == NULL || *user_name == '\0' || retval != PAM_SUCCESS) { - pam_syslog(pamh, LOG_CRIT, - "close_session - error recovering username"); - return PAM_SESSION_ERR; /* How did we get authenticated with - no username?! */ - } - retval = pam_get_item(pamh, PAM_SERVICE, (void *) &service); - if (service == NULL || *service == '\0' || retval != PAM_SUCCESS) { - pam_syslog(pamh, LOG_CRIT, - "close_session - error recovering service"); - return PAM_SESSION_ERR; - } - pam_syslog(pamh, LOG_INFO, "session closed for user %s", - user_name); - - return PAM_SUCCESS; -} - -/* static module data */ -#ifdef PAM_STATIC -struct pam_module _pam_unix_session_modstruct = { - "pam_unix_session", - NULL, - NULL, - NULL, - pam_sm_open_session, - pam_sm_close_session, - NULL, -}; -#endif - diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c deleted file mode 100644 index 6d588e63..00000000 --- a/modules/pam_unix/passverify.c +++ /dev/null @@ -1,1129 +0,0 @@ -/* - * Copyright information at end of file. - */ -#include "config.h" -#include <security/_pam_macros.h> -#include <security/pam_modules.h> -#include "support.h" -#include <stdio.h> -#include <string.h> -#include <sys/types.h> -#include <unistd.h> -#include <pwd.h> -#include <shadow.h> -#include <syslog.h> -#include <stdarg.h> -#include <signal.h> -#include <errno.h> -#include <time.h> -#include <sys/time.h> -#include <sys/stat.h> -#include <fcntl.h> -#ifdef HAVE_CRYPT_H -#include <crypt.h> -#endif - -#include "md5.h" -#include "bigcrypt.h" -#include "passverify.h" - -#ifdef WITH_SELINUX -#include <selinux/selinux.h> -#define SELINUX_ENABLED is_selinux_enabled()>0 -#else -#define SELINUX_ENABLED 0 -#endif - -#ifdef HELPER_COMPILE -#define pam_modutil_getpwnam(h,n) getpwnam(n) -#define pam_modutil_getspnam(h,n) getspnam(n) -#define pam_syslog(h,a,b,c) helper_log_err(a,b,c) -#else -#include <security/pam_modutil.h> -#include <security/pam_ext.h> -#endif - -#if defined(USE_LCKPWDF) && !defined(HAVE_LCKPWDF) -# include "./lckpwdf.-c" -#endif - -static void -strip_hpux_aging(char *hash) -{ - static const char valid[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789./"; - if ((*hash != '$') && (strlen(hash) > 13)) { - for (hash += 13; *hash != '\0'; hash++) { - if (strchr(valid, *hash) == NULL) { - *hash = '\0'; - break; - } - } - } -} - -int -verify_pwd_hash(const char *p, char *hash, unsigned int nullok) -{ - size_t hash_len; - char *pp = NULL; - int retval; - D(("called")); - - strip_hpux_aging(hash); - hash_len = strlen(hash); - if (!hash_len) { - /* the stored password is NULL */ - if (nullok) { /* this means we've succeeded */ - D(("user has empty password - access granted")); - retval = PAM_SUCCESS; - } else { - D(("user has empty password - access denied")); - retval = PAM_AUTH_ERR; - } - } else if (!p || *hash == '*' || *hash == '!') { - retval = PAM_AUTH_ERR; - } else { - if (!strncmp(hash, "$1$", 3)) { - pp = Goodcrypt_md5(p, hash); - if (pp && strcmp(pp, hash) != 0) { - _pam_delete(pp); - pp = Brokencrypt_md5(p, hash); - } - } else if (*hash != '$' && hash_len >= 13) { - pp = bigcrypt(p, hash); - if (pp && hash_len == 13 && strlen(pp) > hash_len) { - _pam_overwrite(pp + hash_len); - } - } else { - /* - * Ok, we don't know the crypt algorithm, but maybe - * libcrypt knows about it? We should try it. - */ -#ifdef HAVE_CRYPT_R - struct crypt_data *cdata; - cdata = malloc(sizeof(*cdata)); - if (cdata != NULL) { - cdata->initialized = 0; - pp = x_strdup(crypt_r(p, hash, cdata)); - memset(cdata, '\0', sizeof(*cdata)); - free(cdata); - } -#else - pp = x_strdup(crypt(p, hash)); -#endif - } - p = NULL; /* no longer needed here */ - - /* the moment of truth -- do we agree with the password? */ - D(("comparing state of pp[%s] and salt[%s]", pp, salt)); - - if (pp && strcmp(pp, hash) == 0) { - retval = PAM_SUCCESS; - } else { - retval = PAM_AUTH_ERR; - } - } - - if (pp) - _pam_delete(pp); - D(("done [%d].", retval)); - - return retval; -} - -int -is_pwd_shadowed(const struct passwd *pwd) -{ - if (pwd != NULL) { - if (strcmp(pwd->pw_passwd, "x") == 0) { - return 1; - } - if ((pwd->pw_passwd[0] == '#') && - (pwd->pw_passwd[1] == '#') && - (strcmp(pwd->pw_name, pwd->pw_passwd + 2) == 0)) { - return 1; - } - } - return 0; -} - -#ifdef HELPER_COMPILE -int -get_account_info(const char *name, - struct passwd **pwd, struct spwd **spwdent) -#else -int -get_account_info(pam_handle_t *pamh, const char *name, - struct passwd **pwd, struct spwd **spwdent) -#endif -{ - /* UNIX passwords area */ - *pwd = pam_modutil_getpwnam(pamh, name); /* Get password file entry... */ - *spwdent = NULL; - - if (*pwd != NULL) { - if (strcmp((*pwd)->pw_passwd, "*NP*") == 0) - { /* NIS+ */ -#ifdef HELPER_COMPILE - uid_t save_euid, save_uid; - - save_euid = geteuid(); - save_uid = getuid(); - if (save_uid == (*pwd)->pw_uid) - setreuid(save_euid, save_uid); - else { - setreuid(0, -1); - if (setreuid(-1, (*pwd)->pw_uid) == -1) { - setreuid(-1, 0); - setreuid(0, -1); - if(setreuid(-1, (*pwd)->pw_uid) == -1) - return PAM_CRED_INSUFFICIENT; - } - } - - *spwdent = pam_modutil_getspnam(pamh, name); - if (save_uid == (*pwd)->pw_uid) - setreuid(save_uid, save_euid); - else { - setreuid(-1, 0); - setreuid(save_uid, -1); - setreuid(-1, save_euid); - } - - if (*spwdent == NULL || (*spwdent)->sp_pwdp == NULL) - return PAM_AUTHINFO_UNAVAIL; -#else - /* we must run helper for NIS+ passwords */ - return PAM_UNIX_RUN_HELPER; -#endif - } else if (is_pwd_shadowed(*pwd)) { - /* - * ...and shadow password file entry for this user, - * if shadowing is enabled - */ -#ifndef HELPER_COMPILE - if (geteuid() || SELINUX_ENABLED) - return PAM_UNIX_RUN_HELPER; -#endif - *spwdent = pam_modutil_getspnam(pamh, name); - if (*spwdent == NULL || (*spwdent)->sp_pwdp == NULL) - return PAM_AUTHINFO_UNAVAIL; - } - } else { - return PAM_USER_UNKNOWN; - } - return PAM_SUCCESS; -} - -#ifdef HELPER_COMPILE -int -get_pwd_hash(const char *name, - struct passwd **pwd, char **hash) -#else -int -get_pwd_hash(pam_handle_t *pamh, const char *name, - struct passwd **pwd, char **hash) -#endif -{ - int retval; - struct spwd *spwdent = NULL; - -#ifdef HELPER_COMPILE - retval = get_account_info(name, pwd, &spwdent); -#else - retval = get_account_info(pamh, name, pwd, &spwdent); -#endif - if (retval != PAM_SUCCESS) { - return retval; - } - - if (spwdent) - *hash = x_strdup(spwdent->sp_pwdp); - else - *hash = x_strdup((*pwd)->pw_passwd); - if (*hash == NULL) - return PAM_BUF_ERR; - - return PAM_SUCCESS; -} - -#ifdef HELPER_COMPILE -int -check_shadow_expiry(struct spwd *spent, int *daysleft) -#else -int -check_shadow_expiry(pam_handle_t *pamh, struct spwd *spent, int *daysleft) -#endif -{ - long int curdays; - *daysleft = -1; - curdays = (long int)(time(NULL) / (60 * 60 * 24)); - D(("today is %d, last change %d", curdays, spent->sp_lstchg)); - if ((curdays > spent->sp_expire) && (spent->sp_expire != -1)) { - D(("account expired")); - return PAM_ACCT_EXPIRED; - } - if (spent->sp_lstchg == 0) { - D(("need a new password")); - *daysleft = 0; - return PAM_NEW_AUTHTOK_REQD; - } - if (curdays < spent->sp_lstchg) { - pam_syslog(pamh, LOG_DEBUG, - "account %s has password changed in future", - spent->sp_namp); - return PAM_SUCCESS; - } - if ((curdays - spent->sp_lstchg > spent->sp_max) - && (curdays - spent->sp_lstchg > spent->sp_inact) - && (curdays - spent->sp_lstchg > spent->sp_max + spent->sp_inact) - && (spent->sp_max != -1) && (spent->sp_inact != -1)) { - *daysleft = (int)((spent->sp_lstchg + spent->sp_max) - curdays); - D(("authtok expired")); - return PAM_AUTHTOK_EXPIRED; - } - if ((curdays - spent->sp_lstchg > spent->sp_max) && (spent->sp_max != -1)) { - D(("need a new password 2")); - return PAM_NEW_AUTHTOK_REQD; - } - if ((curdays - spent->sp_lstchg > spent->sp_max - spent->sp_warn) - && (spent->sp_max != -1) && (spent->sp_warn != -1)) { - *daysleft = (int)((spent->sp_lstchg + spent->sp_max) - curdays); - D(("warn before expiry")); - } - return PAM_SUCCESS; - -} - -/* passwd/salt conversion macros */ - -#define PW_TMPFILE "/etc/npasswd" -#define SH_TMPFILE "/etc/nshadow" -#define OPW_TMPFILE "/etc/security/nopasswd" - -/* - * i64c - convert an integer to a radix 64 character - */ -static int -i64c(int i) -{ - if (i < 0) - return ('.'); - else if (i > 63) - return ('z'); - if (i == 0) - return ('.'); - if (i == 1) - return ('/'); - if (i >= 2 && i <= 11) - return ('0' - 2 + i); - if (i >= 12 && i <= 37) - return ('A' - 12 + i); - if (i >= 38 && i <= 63) - return ('a' - 38 + i); - return ('\0'); -} - -/* <where> must point to a buffer of at least <length>+1 length */ -static void -crypt_make_salt(char *where, int length) -{ - struct timeval tv; - MD5_CTX ctx; - unsigned char tmp[16]; - unsigned char *src = (unsigned char *)where; - int i; -#ifdef PAM_PATH_RANDOMDEV - int fd; - int rv; - - if ((rv = fd = open(PAM_PATH_RANDOMDEV, O_RDONLY)) != -1) { - while ((rv = read(fd, where, length)) != length && errno == EINTR); - close (fd); - } - if (rv != length) { -#endif - /* - * Code lifted from Marek Michalkiewicz's shadow suite. (CG) - * removed use of static variables (AGM) - * - * will work correctly only for length <= 16 */ - src = tmp; - GoodMD5Init(&ctx); - gettimeofday(&tv, (struct timezone *) 0); - GoodMD5Update(&ctx, (void *) &tv, sizeof tv); - i = getpid(); - GoodMD5Update(&ctx, (void *) &i, sizeof i); - i = clock(); - GoodMD5Update(&ctx, (void *) &i, sizeof i); - GoodMD5Update(&ctx, src, length); - GoodMD5Final(tmp, &ctx); -#ifdef PAM_PATH_RANDOMDEV - } -#endif - for (i = 0; i < length; i++) - *where++ = i64c(src[i] & 077); - *where = '\0'; -} - -char * -crypt_md5_wrapper(const char *pass_new) -{ - unsigned char result[16]; - char *cp = (char *) result; - - cp = stpcpy(cp, "$1$"); /* magic for the MD5 */ - crypt_make_salt(cp, 8); - - /* no longer need cleartext */ - cp = Goodcrypt_md5(pass_new, (const char *) result); - pass_new = NULL; - - return cp; -} - -char * -create_password_hash(const char *password, unsigned int ctrl, int rounds) -{ - const char *algoid; - char salt[64]; /* contains rounds number + max 16 bytes of salt + algo id */ - char *sp; - - if (on(UNIX_MD5_PASS, ctrl)) { - return crypt_md5_wrapper(password); - } - if (on(UNIX_SHA256_PASS, ctrl)) { - algoid = "$5$"; - } else if (on(UNIX_SHA512_PASS, ctrl)) { - algoid = "$6$"; - } else { /* must be crypt/bigcrypt */ - char tmppass[9]; - char *crypted; - - crypt_make_salt(salt, 2); - if (off(UNIX_BIGCRYPT, ctrl) && strlen(password) > 8) { - strncpy(tmppass, password, sizeof(tmppass)-1); - tmppass[sizeof(tmppass)-1] = '\0'; - password = tmppass; - } - crypted = bigcrypt(password, salt); - memset(tmppass, '\0', sizeof(tmppass)); - password = NULL; - return crypted; - } - - sp = stpcpy(salt, algoid); - if (on(UNIX_ALGO_ROUNDS, ctrl)) { - sp += snprintf(sp, sizeof(salt) - 3, "rounds=%u$", rounds); - } - crypt_make_salt(sp, 8); - /* For now be conservative so the resulting hashes - * are not too long. 8 bytes of salt prevents dictionary - * attacks well enough. */ - sp = crypt(password, salt); - if (strncmp(algoid, sp, strlen(algoid)) != 0) { - /* libc doesn't know the algorithm, use MD5 */ - memset(sp, '\0', strlen(sp)); - return crypt_md5_wrapper(password); - } - - return x_strdup(sp); -} - -#ifdef WITH_SELINUX -int -unix_selinux_confined(void) -{ - static int confined = -1; - int fd; - char tempfile[]="/etc/.pwdXXXXXX"; - - if (confined != -1) - return confined; - - /* cannot be confined without SELinux enabled */ - if (!SELINUX_ENABLED){ - confined = 0; - return confined; - } - - /* let's try opening shadow read only */ - if ((fd=open("/etc/shadow", O_RDONLY)) != -1) { - close(fd); - confined = 0; - return confined; - } - - if (errno == EACCES) { - confined = 1; - return confined; - } - - /* shadow opening failed because of other reasons let's try - creating a file in /etc */ - if ((fd=mkstemp(tempfile)) != -1) { - unlink(tempfile); - close(fd); - confined = 0; - return confined; - } - - confined = 1; - return confined; -} - -#else -int -unix_selinux_confined(void) -{ - return 0; -} -#endif - -#ifdef USE_LCKPWDF -int -lock_pwdf(void) -{ - int i; - int retval; - -#ifndef HELPER_COMPILE - if (unix_selinux_confined()) { - return PAM_SUCCESS; - } -#endif - /* These values for the number of attempts and the sleep time - are, of course, completely arbitrary. - My reading of the PAM docs is that, once pam_chauthtok() has been - called with PAM_UPDATE_AUTHTOK, we are obliged to take any - reasonable steps to make sure the token is updated; so retrying - for 1/10 sec. isn't overdoing it. */ - i=0; - while((retval = lckpwdf()) != 0 && i < 100) { - usleep(1000); - i++; - } - if(retval != 0) { - return PAM_AUTHTOK_LOCK_BUSY; - } - return PAM_SUCCESS; -} - -void -unlock_pwdf(void) -{ -#ifndef HELPER_COMPILE - if (unix_selinux_confined()) { - return; - } -#endif - ulckpwdf(); -} -#else -int -lock_pwdf(void) -{ - return PAM_SUCCESS; -} - -void -unlock_pwdf(void) -{ - return; -} -#endif - -int -save_old_password(const char *forwho, const char *oldpass, - int howmany) -{ - static char buf[16384]; - static char nbuf[16384]; - char *s_luser, *s_uid, *s_npas, *s_pas, *pass; - int npas; - FILE *pwfile, *opwfile; - int err = 0; - int oldmask; - int found = 0; - struct passwd *pwd = NULL; - struct stat st; -#ifdef WITH_SELINUX - security_context_t prev_context=NULL; -#endif - - if (howmany < 0) { - return PAM_SUCCESS; - } - - if (oldpass == NULL) { - return PAM_SUCCESS; - } - - oldmask = umask(077); - -#ifdef WITH_SELINUX - if (SELINUX_ENABLED) { - security_context_t passwd_context=NULL; - if (getfilecon("/etc/passwd",&passwd_context)<0) { - return PAM_AUTHTOK_ERR; - }; - if (getfscreatecon(&prev_context)<0) { - freecon(passwd_context); - return PAM_AUTHTOK_ERR; - } - if (setfscreatecon(passwd_context)) { - freecon(passwd_context); - freecon(prev_context); - return PAM_AUTHTOK_ERR; - } - freecon(passwd_context); - } -#endif - pwfile = fopen(OPW_TMPFILE, "w"); - umask(oldmask); - if (pwfile == NULL) { - err = 1; - goto done; - } - - opwfile = fopen(OLD_PASSWORDS_FILE, "r"); - if (opwfile == NULL) { - fclose(pwfile); - err = 1; - goto done; - } - - if (fstat(fileno(opwfile), &st) == -1) { - fclose(opwfile); - fclose(pwfile); - err = 1; - goto done; - } - - if (fchown(fileno(pwfile), st.st_uid, st.st_gid) == -1) { - fclose(opwfile); - fclose(pwfile); - err = 1; - goto done; - } - if (fchmod(fileno(pwfile), st.st_mode) == -1) { - fclose(opwfile); - fclose(pwfile); - err = 1; - goto done; - } - - while (fgets(buf, 16380, opwfile)) { - if (!strncmp(buf, forwho, strlen(forwho))) { - char *sptr = NULL; - found = 1; - if (howmany == 0) - continue; - buf[strlen(buf) - 1] = '\0'; - s_luser = strtok_r(buf, ":", &sptr); - s_uid = strtok_r(NULL, ":", &sptr); - s_npas = strtok_r(NULL, ":", &sptr); - s_pas = strtok_r(NULL, ":", &sptr); - npas = strtol(s_npas, NULL, 10) + 1; - while (npas > howmany) { - s_pas = strpbrk(s_pas, ","); - if (s_pas != NULL) - s_pas++; - npas--; - } - pass = crypt_md5_wrapper(oldpass); - if (s_pas == NULL) - snprintf(nbuf, sizeof(nbuf), "%s:%s:%d:%s\n", - s_luser, s_uid, npas, pass); - else - snprintf(nbuf, sizeof(nbuf),"%s:%s:%d:%s,%s\n", - s_luser, s_uid, npas, s_pas, pass); - _pam_delete(pass); - if (fputs(nbuf, pwfile) < 0) { - err = 1; - break; - } - } else if (fputs(buf, pwfile) < 0) { - err = 1; - break; - } - } - fclose(opwfile); - - if (!found) { - pwd = getpwnam(forwho); - if (pwd == NULL) { - err = 1; - } else { - pass = crypt_md5_wrapper(oldpass); - snprintf(nbuf, sizeof(nbuf), "%s:%lu:1:%s\n", - forwho, (unsigned long)pwd->pw_uid, pass); - _pam_delete(pass); - if (fputs(nbuf, pwfile) < 0) { - err = 1; - } - } - } - - if (fclose(pwfile)) { - D(("error writing entries to old passwords file: %m")); - err = 1; - } - -done: - if (!err) { - if (rename(OPW_TMPFILE, OLD_PASSWORDS_FILE)) - err = 1; - } -#ifdef WITH_SELINUX - if (SELINUX_ENABLED) { - if (setfscreatecon(prev_context)) { - err = 1; - } - if (prev_context) - freecon(prev_context); - prev_context=NULL; - } -#endif - if (!err) { - return PAM_SUCCESS; - } else { - unlink(OPW_TMPFILE); - return PAM_AUTHTOK_ERR; - } -} - -#ifdef HELPER_COMPILE -int -unix_update_passwd(const char *forwho, const char *towhat) -#else -int -unix_update_passwd(pam_handle_t *pamh, const char *forwho, const char *towhat) -#endif -{ - struct passwd *tmpent = NULL; - struct stat st; - FILE *pwfile, *opwfile; - int err = 1; - int oldmask; -#ifdef WITH_SELINUX - security_context_t prev_context=NULL; -#endif - - oldmask = umask(077); -#ifdef WITH_SELINUX - if (SELINUX_ENABLED) { - security_context_t passwd_context=NULL; - if (getfilecon("/etc/passwd",&passwd_context)<0) { - return PAM_AUTHTOK_ERR; - }; - if (getfscreatecon(&prev_context)<0) { - freecon(passwd_context); - return PAM_AUTHTOK_ERR; - } - if (setfscreatecon(passwd_context)) { - freecon(passwd_context); - freecon(prev_context); - return PAM_AUTHTOK_ERR; - } - freecon(passwd_context); - } -#endif - pwfile = fopen(PW_TMPFILE, "w"); - umask(oldmask); - if (pwfile == NULL) { - err = 1; - goto done; - } - - opwfile = fopen("/etc/passwd", "r"); - if (opwfile == NULL) { - fclose(pwfile); - err = 1; - goto done; - } - - if (fstat(fileno(opwfile), &st) == -1) { - fclose(opwfile); - fclose(pwfile); - err = 1; - goto done; - } - - if (fchown(fileno(pwfile), st.st_uid, st.st_gid) == -1) { - fclose(opwfile); - fclose(pwfile); - err = 1; - goto done; - } - if (fchmod(fileno(pwfile), st.st_mode) == -1) { - fclose(opwfile); - fclose(pwfile); - err = 1; - goto done; - } - - tmpent = fgetpwent(opwfile); - while (tmpent) { - if (!strcmp(tmpent->pw_name, forwho)) { - /* To shut gcc up */ - union { - const char *const_charp; - char *charp; - } assigned_passwd; - assigned_passwd.const_charp = towhat; - - tmpent->pw_passwd = assigned_passwd.charp; - err = 0; - } - if (putpwent(tmpent, pwfile)) { - D(("error writing entry to password file: %m")); - err = 1; - break; - } - tmpent = fgetpwent(opwfile); - } - fclose(opwfile); - - if (fclose(pwfile)) { - D(("error writing entries to password file: %m")); - err = 1; - } - -done: - if (!err) { - if (!rename(PW_TMPFILE, "/etc/passwd")) -#ifdef HELPER_COMPILE - helper_log_err( -#else - pam_syslog(pamh, -#endif - LOG_NOTICE, "password changed for %s", forwho); - else - err = 1; - } -#ifdef WITH_SELINUX - if (SELINUX_ENABLED) { - if (setfscreatecon(prev_context)) { - err = 1; - } - if (prev_context) - freecon(prev_context); - prev_context=NULL; - } -#endif - if (!err) { - return PAM_SUCCESS; - } else { - unlink(PW_TMPFILE); - return PAM_AUTHTOK_ERR; - } -} - -#ifdef HELPER_COMPILE -int -unix_update_shadow(const char *forwho, char *towhat) -#else -int -unix_update_shadow(pam_handle_t *pamh, const char *forwho, char *towhat) -#endif -{ - struct spwd *spwdent = NULL, *stmpent = NULL; - struct stat st; - FILE *pwfile, *opwfile; - int err = 1; - int oldmask; -#ifdef WITH_SELINUX - security_context_t prev_context=NULL; -#endif - - spwdent = getspnam(forwho); - if (spwdent == NULL) { - return PAM_USER_UNKNOWN; - } - oldmask = umask(077); - -#ifdef WITH_SELINUX - if (SELINUX_ENABLED) { - security_context_t shadow_context=NULL; - if (getfilecon("/etc/shadow",&shadow_context)<0) { - return PAM_AUTHTOK_ERR; - }; - if (getfscreatecon(&prev_context)<0) { - freecon(shadow_context); - return PAM_AUTHTOK_ERR; - } - if (setfscreatecon(shadow_context)) { - freecon(shadow_context); - freecon(prev_context); - return PAM_AUTHTOK_ERR; - } - freecon(shadow_context); - } -#endif - pwfile = fopen(SH_TMPFILE, "w"); - umask(oldmask); - if (pwfile == NULL) { - err = 1; - goto done; - } - - opwfile = fopen("/etc/shadow", "r"); - if (opwfile == NULL) { - fclose(pwfile); - err = 1; - goto done; - } - - if (fstat(fileno(opwfile), &st) == -1) { - fclose(opwfile); - fclose(pwfile); - err = 1; - goto done; - } - - if (fchown(fileno(pwfile), st.st_uid, st.st_gid) == -1) { - fclose(opwfile); - fclose(pwfile); - err = 1; - goto done; - } - if (fchmod(fileno(pwfile), st.st_mode) == -1) { - fclose(opwfile); - fclose(pwfile); - err = 1; - goto done; - } - - stmpent = fgetspent(opwfile); - while (stmpent) { - - if (!strcmp(stmpent->sp_namp, forwho)) { - stmpent->sp_pwdp = towhat; - stmpent->sp_lstchg = time(NULL) / (60 * 60 * 24); - err = 0; - D(("Set password %s for %s", stmpent->sp_pwdp, forwho)); - } - - if (putspent(stmpent, pwfile)) { - D(("error writing entry to shadow file: %m")); - err = 1; - break; - } - - stmpent = fgetspent(opwfile); - } - fclose(opwfile); - - if (fclose(pwfile)) { - D(("error writing entries to shadow file: %m")); - err = 1; - } - - done: - if (!err) { - if (!rename(SH_TMPFILE, "/etc/shadow")) -#ifdef HELPER_COMPILE - helper_log_err( -#else - pam_syslog(pamh, -#endif - LOG_NOTICE, "password changed for %s", forwho); - else - err = 1; - } - -#ifdef WITH_SELINUX - if (SELINUX_ENABLED) { - if (setfscreatecon(prev_context)) { - err = 1; - } - if (prev_context) - freecon(prev_context); - prev_context=NULL; - } -#endif - - if (!err) { - return PAM_SUCCESS; - } else { - unlink(SH_TMPFILE); - return PAM_AUTHTOK_ERR; - } -} - -#ifdef HELPER_COMPILE - -int -helper_verify_password(const char *name, const char *p, int nullok) -{ - struct passwd *pwd = NULL; - char *salt = NULL; - int retval; - - retval = get_pwd_hash(name, &pwd, &salt); - - if (pwd == NULL || salt == NULL) { - helper_log_err(LOG_WARNING, "check pass; user unknown"); - retval = PAM_USER_UNKNOWN; - } else { - retval = verify_pwd_hash(p, salt, nullok); - } - - if (salt) { - _pam_overwrite(salt); - _pam_drop(salt); - } - - p = NULL; /* no longer needed here */ - - return retval; -} - -void -helper_log_err(int err, const char *format, ...) -{ - va_list args; - - va_start(args, format); - openlog(HELPER_COMPILE, LOG_CONS | LOG_PID, LOG_AUTHPRIV); - vsyslog(err, format, args); - va_end(args); - closelog(); -} - -static void -su_sighandler(int sig) -{ -#ifndef SA_RESETHAND - /* emulate the behaviour of the SA_RESETHAND flag */ - if ( sig == SIGILL || sig == SIGTRAP || sig == SIGBUS || sig = SIGSERV ) - signal(sig, SIG_DFL); -#endif - if (sig > 0) { - _exit(sig); - } -} - -void -setup_signals(void) -{ - struct sigaction action; /* posix signal structure */ - - /* - * Setup signal handlers - */ - (void) memset((void *) &action, 0, sizeof(action)); - action.sa_handler = su_sighandler; -#ifdef SA_RESETHAND - action.sa_flags = SA_RESETHAND; -#endif - (void) sigaction(SIGILL, &action, NULL); - (void) sigaction(SIGTRAP, &action, NULL); - (void) sigaction(SIGBUS, &action, NULL); - (void) sigaction(SIGSEGV, &action, NULL); - action.sa_handler = SIG_IGN; - action.sa_flags = 0; - (void) sigaction(SIGTERM, &action, NULL); - (void) sigaction(SIGHUP, &action, NULL); - (void) sigaction(SIGINT, &action, NULL); - (void) sigaction(SIGQUIT, &action, NULL); -} - -char * -getuidname(uid_t uid) -{ - struct passwd *pw; - static char username[256]; - - pw = getpwuid(uid); - if (pw == NULL) - return NULL; - - strncpy(username, pw->pw_name, sizeof(username)); - username[sizeof(username) - 1] = '\0'; - - return username; -} - -int -read_passwords(int fd, int npass, char **passwords) -{ - int rbytes = 0; - int offset = 0; - int i = 0; - char *pptr; - while (npass > 0) { - rbytes = read(fd, passwords[i]+offset, MAXPASS-offset); - - if (rbytes < 0) { - if (errno == EINTR) continue; - break; - } - if (rbytes == 0) - break; - - while (npass > 0 && (pptr=memchr(passwords[i]+offset, '\0', rbytes)) - != NULL) { - rbytes -= pptr - (passwords[i]+offset) + 1; - i++; - offset = 0; - npass--; - if (rbytes > 0) { - if (npass > 0) - memcpy(passwords[i], pptr+1, rbytes); - memset(pptr+1, '\0', rbytes); - } - } - offset += rbytes; - } - - /* clear up */ - if (offset > 0 && npass > 0) { - memset(passwords[i], '\0', offset); - } - - return i; -} - -#endif -/* ****************************************************************** * - * Copyright (c) Jan Rêkorajski 1999. - * Copyright (c) Andrew G. Morgan 1996-8. - * Copyright (c) Alex O. Yuriev, 1996. - * Copyright (c) Cristian Gafton 1996. - * Copyright (c) Red Hat, Inc. 1996, 2007, 2008. - * - * 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. - */ diff --git a/modules/pam_unix/passverify.h b/modules/pam_unix/passverify.h deleted file mode 100644 index e8e112d0..00000000 --- a/modules/pam_unix/passverify.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright information at end of file. - */ - -#include <sys/types.h> -#include <pwd.h> -#include <security/pam_modules.h> - -#define PAM_UNIX_RUN_HELPER PAM_CRED_INSUFFICIENT - -#define MAXPASS 200 /* the maximum length of a password */ - -#define OLD_PASSWORDS_FILE "/etc/security/opasswd" - -int -verify_pwd_hash(const char *p, char *hash, unsigned int nullok); - -int -is_pwd_shadowed(const struct passwd *pwd); - -char * -crypt_md5_wrapper(const char *pass_new); - -char * -create_password_hash(const char *password, unsigned int ctrl, int rounds); - -int -unix_selinux_confined(void); - -int -lock_pwdf(void); - -void -unlock_pwdf(void); - -int -save_old_password(const char *forwho, const char *oldpass, - int howmany); - -#ifdef HELPER_COMPILE -void -helper_log_err(int err, const char *format,...); - -int -helper_verify_password(const char *name, const char *p, int nullok); - -void -setup_signals(void); - -char * -getuidname(uid_t uid); - -int -read_passwords(int fd, int npass, char **passwords); - -int -get_account_info(const char *name, - struct passwd **pwd, struct spwd **spwdent); - -int -get_pwd_hash(const char *name, - struct passwd **pwd, char **hash); - -int -check_shadow_expiry(struct spwd *spent, int *daysleft); - -int -unix_update_passwd(const char *forwho, const char *towhat); - -int -unix_update_shadow(const char *forwho, char *towhat); -#else -int -get_account_info(pam_handle_t *pamh, const char *name, - struct passwd **pwd, struct spwd **spwdent); - -int -get_pwd_hash(pam_handle_t *pamh, const char *name, - struct passwd **pwd, char **hash); - -int -check_shadow_expiry(pam_handle_t *pamh, struct spwd *spent, int *daysleft); - -int -unix_update_passwd(pam_handle_t *pamh, const char *forwho, const char *towhat); - -int -unix_update_shadow(pam_handle_t *pamh, const char *forwho, char *towhat); -#endif - -/* ****************************************************************** * - * Copyright (c) Red Hat, Inc. 2007. - * - * 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. - */ diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c deleted file mode 100644 index b82cad26..00000000 --- a/modules/pam_unix/support.c +++ /dev/null @@ -1,893 +0,0 @@ -/* - * Copyright information at end of file. - */ - -#include "config.h" - -#include <stdlib.h> -#include <unistd.h> -#include <stdarg.h> -#include <stdio.h> -#include <string.h> -#include <malloc.h> -#include <pwd.h> -#include <shadow.h> -#include <limits.h> -#include <utmp.h> -#include <errno.h> -#include <signal.h> -#include <ctype.h> -#include <syslog.h> -#include <sys/resource.h> -#include <rpcsvc/ypclnt.h> - -#include <security/_pam_macros.h> -#include <security/pam_modules.h> -#include <security/pam_ext.h> -#include <security/pam_modutil.h> - -#include "support.h" -#include "passverify.h" -#ifdef WITH_SELINUX -#include <selinux/selinux.h> -#define SELINUX_ENABLED is_selinux_enabled()>0 -#else -#define SELINUX_ENABLED 0 -#endif - -/* this is a front-end for module-application conversations */ - -int _make_remark(pam_handle_t * pamh, unsigned int ctrl, - int type, const char *text) -{ - int retval = PAM_SUCCESS; - - if (off(UNIX__QUIET, ctrl)) { - retval = pam_prompt(pamh, type, NULL, "%s", text); - } - return retval; -} - -/* - * set the control flags for the UNIX module. - */ - -int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds, - int argc, const char **argv) -{ - unsigned int ctrl; - - D(("called.")); - - ctrl = UNIX_DEFAULTS; /* the default selection of options */ - - /* set some flags manually */ - - if (getuid() == 0 && !(flags & PAM_CHANGE_EXPIRED_AUTHTOK)) { - D(("IAMROOT")); - set(UNIX__IAMROOT, ctrl); - } - if (flags & PAM_UPDATE_AUTHTOK) { - D(("UPDATE_AUTHTOK")); - set(UNIX__UPDATE, ctrl); - } - if (flags & PAM_PRELIM_CHECK) { - D(("PRELIM_CHECK")); - set(UNIX__PRELIM, ctrl); - } - if (flags & PAM_SILENT) { - D(("SILENT")); - set(UNIX__QUIET, ctrl); - } - /* now parse the arguments to this module */ - - while (argc-- > 0) { - int j; - - D(("pam_unix arg: %s", *argv)); - - for (j = 0; j < UNIX_CTRLS_; ++j) { - if (unix_args[j].token - && !strncmp(*argv, unix_args[j].token, strlen(unix_args[j].token))) { - break; - } - } - - if (j >= UNIX_CTRLS_) { - pam_syslog(pamh, LOG_ERR, - "unrecognized option [%s]", *argv); - } else { - ctrl &= unix_args[j].mask; /* for turning things off */ - ctrl |= unix_args[j].flag; /* for turning things on */ - - if (remember != NULL) { - if (j == UNIX_REMEMBER_PASSWD) { - *remember = strtol(*argv + 9, NULL, 10); - if ((*remember == INT_MIN) || (*remember == INT_MAX)) - *remember = -1; - if (*remember > 400) - *remember = 400; - } - } - if (rounds != NULL) { - if (j == UNIX_ALGO_ROUNDS) { - *rounds = strtol(*argv + 7, NULL, 10); - if ((*rounds < 1000) || (*rounds == INT_MAX)) - /* don't care about bogus values */ - unset(UNIX_ALGO_ROUNDS, ctrl); - if (*rounds >= 10000000) - *rounds = 9999999; - } - } - } - - ++argv; /* step to next argument */ - } - - if (flags & PAM_DISALLOW_NULL_AUTHTOK) { - D(("DISALLOW_NULL_AUTHTOK")); - set(UNIX__NONULL, ctrl); - } - - /* auditing is a more sensitive version of debug */ - - if (on(UNIX_AUDIT, ctrl)) { - set(UNIX_DEBUG, ctrl); - } - /* return the set of flags */ - - D(("done.")); - return ctrl; -} - -static void _cleanup(pam_handle_t * pamh UNUSED, void *x, int error_status UNUSED) -{ - _pam_delete(x); -} - -/* ************************************************************** * - * Useful non-trivial functions * - * ************************************************************** */ - - /* - * the following is used to keep track of the number of times a user fails - * to authenticate themself. - */ - -#define FAIL_PREFIX "-UN*X-FAIL-" -#define UNIX_MAX_RETRIES 3 - -struct _pam_failed_auth { - char *user; /* user that's failed to be authenticated */ - char *name; /* attempt from user with name */ - int uid; /* uid of calling user */ - int euid; /* euid of calling process */ - int count; /* number of failures so far */ -}; - -#ifndef PAM_DATA_REPLACE -#error "Need to get an updated libpam 0.52 or better" -#endif - -static void _cleanup_failures(pam_handle_t * pamh, void *fl, int err) -{ - int quiet; - const void *service = NULL; - const void *ruser = NULL; - const void *rhost = NULL; - const void *tty = NULL; - struct _pam_failed_auth *failure; - - D(("called")); - - quiet = err & PAM_DATA_SILENT; /* should we log something? */ - err &= PAM_DATA_REPLACE; /* are we just replacing data? */ - failure = (struct _pam_failed_auth *) fl; - - if (failure != NULL) { - - if (!quiet && !err) { /* under advisement from Sun,may go away */ - - /* log the number of authentication failures */ - if (failure->count > 1) { - (void) pam_get_item(pamh, PAM_SERVICE, - &service); - (void) pam_get_item(pamh, PAM_RUSER, - &ruser); - (void) pam_get_item(pamh, PAM_RHOST, - &rhost); - (void) pam_get_item(pamh, PAM_TTY, - &tty); - pam_syslog(pamh, LOG_NOTICE, - "%d more authentication failure%s; " - "logname=%s uid=%d euid=%d " - "tty=%s ruser=%s rhost=%s " - "%s%s", - failure->count - 1, failure->count == 2 ? "" : "s", - failure->name, failure->uid, failure->euid, - tty ? (const char *)tty : "", ruser ? (const char *)ruser : "", - rhost ? (const char *)rhost : "", - (failure->user && failure->user[0] != '\0') - ? " user=" : "", failure->user - ); - - if (failure->count > UNIX_MAX_RETRIES) { - pam_syslog(pamh, LOG_ALERT, - "service(%s) ignoring max retries; %d > %d", - service == NULL ? "**unknown**" : (const char *)service, - failure->count, - UNIX_MAX_RETRIES); - } - } - } - _pam_delete(failure->user); /* tidy up */ - _pam_delete(failure->name); /* tidy up */ - free(failure); - } -} - -/* - * _unix_getpwnam() searches only /etc/passwd and NIS to find user information - */ -static void _unix_cleanup(pam_handle_t *pamh UNUSED, void *data, int error_status UNUSED) -{ - free(data); -} - -int _unix_getpwnam(pam_handle_t *pamh, const char *name, - int files, int nis, struct passwd **ret) -{ - FILE *passwd; - char buf[16384]; - int matched = 0, buflen; - char *slogin, *spasswd, *suid, *sgid, *sgecos, *shome, *sshell, *p; - - memset(buf, 0, sizeof(buf)); - - if (!matched && files) { - int userlen = strlen(name); - passwd = fopen("/etc/passwd", "r"); - if (passwd != NULL) { - while (fgets(buf, sizeof(buf), passwd) != NULL) { - if ((buf[userlen] == ':') && - (strncmp(name, buf, userlen) == 0)) { - p = buf + strlen(buf) - 1; - while (isspace(*p) && (p >= buf)) { - *p-- = '\0'; - } - matched = 1; - break; - } - } - fclose(passwd); - } - } - - if (!matched && nis) { - char *userinfo = NULL, *domain = NULL; - int len = 0, i; - len = yp_get_default_domain(&domain); - if (len == YPERR_SUCCESS) { - len = yp_bind(domain); - } - if (len == YPERR_SUCCESS) { - i = yp_match(domain, "passwd.byname", name, - strlen(name), &userinfo, &len); - yp_unbind(domain); - if ((i == YPERR_SUCCESS) && ((size_t)len < sizeof(buf))) { - strncpy(buf, userinfo, sizeof(buf) - 1); - buf[sizeof(buf) - 1] = '\0'; - matched = 1; - } - } - } - - if (matched && (ret != NULL)) { - *ret = NULL; - - slogin = buf; - - spasswd = strchr(slogin, ':'); - if (spasswd == NULL) { - return matched; - } - *spasswd++ = '\0'; - - suid = strchr(spasswd, ':'); - if (suid == NULL) { - return matched; - } - *suid++ = '\0'; - - sgid = strchr(suid, ':'); - if (sgid == NULL) { - return matched; - } - *sgid++ = '\0'; - - sgecos = strchr(sgid, ':'); - if (sgecos == NULL) { - return matched; - } - *sgecos++ = '\0'; - - shome = strchr(sgecos, ':'); - if (shome == NULL) { - return matched; - } - *shome++ = '\0'; - - sshell = strchr(shome, ':'); - if (sshell == NULL) { - return matched; - } - *sshell++ = '\0'; - - buflen = sizeof(struct passwd) + - strlen(slogin) + 1 + - strlen(spasswd) + 1 + - strlen(suid) + 1 + - strlen(sgid) + 1 + - strlen(sgecos) + 1 + - strlen(shome) + 1 + - strlen(sshell) + 1; - *ret = malloc(buflen); - if (*ret == NULL) { - return matched; - } - memset(*ret, '\0', buflen); - - (*ret)->pw_uid = strtol(suid, &p, 10); - if ((strlen(suid) == 0) || (*p != '\0')) { - free(*ret); - *ret = NULL; - return matched; - } - - (*ret)->pw_gid = strtol(sgid, &p, 10); - if ((strlen(sgid) == 0) || (*p != '\0')) { - free(*ret); - *ret = NULL; - return matched; - } - - p = ((char*)(*ret)) + sizeof(struct passwd); - (*ret)->pw_name = strcpy(p, slogin); - p += strlen(p) + 1; - (*ret)->pw_passwd = strcpy(p, spasswd); - p += strlen(p) + 1; - (*ret)->pw_gecos = strcpy(p, sgecos); - p += strlen(p) + 1; - (*ret)->pw_dir = strcpy(p, shome); - p += strlen(p) + 1; - (*ret)->pw_shell = strcpy(p, sshell); - - snprintf(buf, sizeof(buf), "_pam_unix_getpwnam_%s", name); - - if (pam_set_data(pamh, buf, - *ret, _unix_cleanup) != PAM_SUCCESS) { - free(*ret); - *ret = NULL; - } - } - - return matched; -} - -/* - * _unix_comsefromsource() is a quick check to see if information about a given - * user comes from a particular source (just files and nis for now) - * - */ -int _unix_comesfromsource(pam_handle_t *pamh, - const char *name, int files, int nis) -{ - return _unix_getpwnam(pamh, name, files, nis, NULL); -} - -/* - * verify the password of a user - */ - -#include <sys/types.h> -#include <sys/wait.h> - -static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd, - unsigned int ctrl, const char *user) -{ - int retval, child, fds[2]; - void (*sighandler)(int) = NULL; - - D(("called.")); - /* create a pipe for the password */ - if (pipe(fds) != 0) { - D(("could not make pipe")); - return PAM_AUTH_ERR; - } - - if (off(UNIX_NOREAP, ctrl)) { - /* - * This code arranges that the demise of the child does not cause - * the application to receive a signal it is not expecting - which - * may kill the application or worse. - * - * The "noreap" module argument is provided so that the admin can - * override this behavior. - */ - sighandler = signal(SIGCHLD, SIG_DFL); - } - - /* fork */ - child = fork(); - if (child == 0) { - int i=0; - struct rlimit rlim; - static char *envp[] = { NULL }; - char *args[] = { NULL, NULL, NULL, NULL }; - - /* XXX - should really tidy up PAM here too */ - - close(0); close(1); - /* reopen stdin as pipe */ - close(fds[1]); - dup2(fds[0], STDIN_FILENO); - - if (getrlimit(RLIMIT_NOFILE,&rlim)==0) { - for (i=2; i < (int)rlim.rlim_max; i++) { - if (fds[0] != i) - close(i); - } - } - - if (geteuid() == 0) { - /* must set the real uid to 0 so the helper will not error - out if pam is called from setuid binary (su, sudo...) */ - setuid(0); - } - - /* exec binary helper */ - args[0] = strdup(CHKPWD_HELPER); - args[1] = x_strdup(user); - if (off(UNIX__NONULL, ctrl)) { /* this means we've succeeded */ - args[2]=strdup("nullok"); - } else { - args[2]=strdup("nonull"); - } - - execve(CHKPWD_HELPER, args, envp); - - /* should not get here: exit with error */ - D(("helper binary is not available")); - exit(PAM_AUTHINFO_UNAVAIL); - } else if (child > 0) { - /* wait for child */ - /* if the stored password is NULL */ - int rc=0; - if (passwd != NULL) { /* send the password to the child */ - write(fds[1], passwd, strlen(passwd)+1); - passwd = NULL; - } else { - write(fds[1], "", 1); /* blank password */ - } - close(fds[0]); /* close here to avoid possible SIGPIPE above */ - close(fds[1]); - rc=waitpid(child, &retval, 0); /* wait for helper to complete */ - if (rc<0) { - pam_syslog(pamh, LOG_ERR, "unix_chkpwd waitpid returned %d: %m", rc); - retval = PAM_AUTH_ERR; - } else { - retval = WEXITSTATUS(retval); - } - } else { - D(("fork failed")); - close(fds[0]); - close(fds[1]); - retval = PAM_AUTH_ERR; - } - - if (sighandler != SIG_ERR) { - (void) signal(SIGCHLD, sighandler); /* restore old signal handler */ - } - - D(("returning %d", retval)); - return retval; -} - -/* - * _unix_blankpasswd() is a quick check for a blank password - * - * returns TRUE if user does not have a password - * - to avoid prompting for one in such cases (CG) - */ - -int -_unix_blankpasswd (pam_handle_t *pamh, unsigned int ctrl, const char *name) -{ - struct passwd *pwd = NULL; - char *salt = NULL; - int retval; - - D(("called")); - - /* - * This function does not have to be too smart if something goes - * wrong, return FALSE and let this case to be treated somewhere - * else (CG) - */ - - if (on(UNIX__NONULL, ctrl)) - return 0; /* will fail but don't let on yet */ - - /* UNIX passwords area */ - - retval = get_pwd_hash(pamh, name, &pwd, &salt); - - if (retval == PAM_UNIX_RUN_HELPER) { - /* salt will not be set here so we can return immediately */ - if (_unix_run_helper_binary(pamh, NULL, ctrl, name) == PAM_SUCCESS) - return 1; - else - return 0; - } - - /* Does this user have a password? */ - if (salt == NULL) { - retval = 0; - } else { - if (strlen(salt) == 0) - retval = 1; - else - retval = 0; - } - - /* tidy up */ - - if (salt) - _pam_delete(salt); - - return retval; -} - -int _unix_verify_password(pam_handle_t * pamh, const char *name - ,const char *p, unsigned int ctrl) -{ - struct passwd *pwd = NULL; - char *salt = NULL; - char *data_name; - int retval; - - - D(("called")); - -#ifdef HAVE_PAM_FAIL_DELAY - if (off(UNIX_NODELAY, ctrl)) { - D(("setting delay")); - (void) pam_fail_delay(pamh, 2000000); /* 2 sec delay for on failure */ - } -#endif - - /* locate the entry for this user */ - - D(("locating user's record")); - - retval = get_pwd_hash(pamh, name, &pwd, &salt); - - data_name = (char *) malloc(sizeof(FAIL_PREFIX) + strlen(name)); - if (data_name == NULL) { - pam_syslog(pamh, LOG_CRIT, "no memory for data-name"); - } else { - strcpy(data_name, FAIL_PREFIX); - strcpy(data_name + sizeof(FAIL_PREFIX) - 1, name); - } - - if (retval != PAM_SUCCESS) { - if (retval == PAM_UNIX_RUN_HELPER) { - D(("running helper binary")); - retval = _unix_run_helper_binary(pamh, p, ctrl, name); - } else { - D(("user's record unavailable")); - p = NULL; - if (on(UNIX_AUDIT, ctrl)) { - /* this might be a typo and the user has given a password - instead of a username. Careful with this. */ - pam_syslog(pamh, LOG_WARNING, - "check pass; user (%s) unknown", name); - } else { - name = NULL; - if (on(UNIX_DEBUG, ctrl) || pwd == NULL) { - pam_syslog(pamh, LOG_WARNING, - "check pass; user unknown"); - } else { - /* don't log failure as another pam module can succeed */ - goto cleanup; - } - } - } - } else { - retval = verify_pwd_hash(p, salt, off(UNIX__NONULL, ctrl)); - } - - if (retval == PAM_SUCCESS) { - if (data_name) /* reset failures */ - pam_set_data(pamh, data_name, NULL, _cleanup_failures); - } else { - if (data_name != NULL) { - struct _pam_failed_auth *new = NULL; - const struct _pam_failed_auth *old = NULL; - - /* get a failure recorder */ - - new = (struct _pam_failed_auth *) - malloc(sizeof(struct _pam_failed_auth)); - - if (new != NULL) { - - const char *login_name; - const void *void_old; - - - login_name = pam_modutil_getlogin(pamh); - if (login_name == NULL) { - login_name = ""; - } - - new->user = x_strdup(name ? name : ""); - new->uid = getuid(); - new->euid = geteuid(); - new->name = x_strdup(login_name); - - /* any previous failures for this user ? */ - if (pam_get_data(pamh, data_name, &void_old) - == PAM_SUCCESS) - old = void_old; - else - old = NULL; - - if (old != NULL) { - new->count = old->count + 1; - if (new->count >= UNIX_MAX_RETRIES) { - retval = PAM_MAXTRIES; - } - } else { - const void *service=NULL; - const void *ruser=NULL; - const void *rhost=NULL; - const void *tty=NULL; - - (void) pam_get_item(pamh, PAM_SERVICE, - &service); - (void) pam_get_item(pamh, PAM_RUSER, - &ruser); - (void) pam_get_item(pamh, PAM_RHOST, - &rhost); - (void) pam_get_item(pamh, PAM_TTY, - &tty); - - pam_syslog(pamh, LOG_NOTICE, - "authentication failure; " - "logname=%s uid=%d euid=%d " - "tty=%s ruser=%s rhost=%s " - "%s%s", - new->name, new->uid, new->euid, - tty ? (const char *)tty : "", - ruser ? (const char *)ruser : "", - rhost ? (const char *)rhost : "", - (new->user && new->user[0] != '\0') - ? " user=" : "", - new->user - ); - new->count = 1; - } - - pam_set_data(pamh, data_name, new, _cleanup_failures); - - } else { - pam_syslog(pamh, LOG_CRIT, - "no memory for failure recorder"); - } - } - } - -cleanup: - if (data_name) - _pam_delete(data_name); - if (salt) - _pam_delete(salt); - - D(("done [%d].", retval)); - - return retval; -} - -/* - * obtain a password from the user - */ - -int _unix_read_password(pam_handle_t * pamh - ,unsigned int ctrl - ,const char *comment - ,const char *prompt1 - ,const char *prompt2 - ,const char *data_name - ,const void **pass) -{ - int authtok_flag; - int retval = PAM_SUCCESS; - char *token; - - D(("called")); - - /* - * make sure nothing inappropriate gets returned - */ - - *pass = token = NULL; - - /* - * which authentication token are we getting? - */ - - authtok_flag = on(UNIX__OLD_PASSWD, ctrl) ? PAM_OLDAUTHTOK : PAM_AUTHTOK; - - /* - * should we obtain the password from a PAM item ? - */ - - if (on(UNIX_TRY_FIRST_PASS, ctrl) || on(UNIX_USE_FIRST_PASS, ctrl)) { - retval = pam_get_item(pamh, authtok_flag, pass); - if (retval != PAM_SUCCESS) { - /* very strange. */ - pam_syslog(pamh, LOG_ALERT, - "pam_get_item returned error to unix-read-password" - ); - return retval; - } else if (*pass != NULL) { /* we have a password! */ - return PAM_SUCCESS; - } else if (on(UNIX_USE_FIRST_PASS, ctrl)) { - return PAM_AUTHTOK_RECOVERY_ERR; /* didn't work */ - } else if (on(UNIX_USE_AUTHTOK, ctrl) - && off(UNIX__OLD_PASSWD, ctrl)) { - return PAM_AUTHTOK_ERR; - } - } - /* - * getting here implies we will have to get the password from the - * user directly. - */ - - { - int replies=1; - char *resp[2] = { NULL, NULL }; - - if (comment != NULL && off(UNIX__QUIET, ctrl)) { - retval = pam_info(pamh, "%s", comment); - } - - if (retval == PAM_SUCCESS) { - retval = pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, - &resp[0], "%s", prompt1); - - if (retval == PAM_SUCCESS && prompt2 != NULL) { - retval = pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, - &resp[1], "%s", prompt2); - ++replies; - } - } - - if (resp[0] != NULL && resp[replies-1] != NULL) { - /* interpret the response */ - - if (retval == PAM_SUCCESS) { /* a good conversation */ - - token = resp[0]; - if (token != NULL) { - if (replies == 2) { - /* verify that password entered correctly */ - if (strcmp(token, resp[replies - 1])) { - /* mistyped */ - retval = PAM_AUTHTOK_RECOVERY_ERR; - _make_remark(pamh, ctrl, - PAM_ERROR_MSG, MISTYPED_PASS); - } - } - } else { - pam_syslog(pamh, LOG_NOTICE, - "could not recover authentication token"); - } - - } - - } else { - retval = (retval == PAM_SUCCESS) - ? PAM_AUTHTOK_RECOVERY_ERR : retval; - } - - resp[0] = NULL; - if (replies > 1) - _pam_delete(resp[1]); - } - - if (retval != PAM_SUCCESS) { - _pam_delete(token); - - if (on(UNIX_DEBUG, ctrl)) - pam_syslog(pamh, LOG_DEBUG, - "unable to obtain a password"); - return retval; - } - /* 'token' is the entered password */ - - if (off(UNIX_NOT_SET_PASS, ctrl)) { - - /* we store this password as an item */ - - retval = pam_set_item(pamh, authtok_flag, token); - _pam_delete(token); /* clean it up */ - if (retval != PAM_SUCCESS - || (retval = pam_get_item(pamh, authtok_flag, pass)) - != PAM_SUCCESS) { - - *pass = NULL; - pam_syslog(pamh, LOG_CRIT, "error manipulating password"); - return retval; - - } - } else { - /* - * then store it as data specific to this module. pam_end() - * will arrange to clean it up. - */ - - retval = pam_set_data(pamh, data_name, (void *) token, _cleanup); - if (retval != PAM_SUCCESS) { - pam_syslog(pamh, LOG_CRIT, - "error manipulating password data [%s]", - pam_strerror(pamh, retval)); - _pam_delete(token); - return retval; - } - *pass = token; - token = NULL; /* break link to password */ - } - - return PAM_SUCCESS; -} - -/* ****************************************************************** * - * Copyright (c) Jan Rêkorajski 1999. - * Copyright (c) Andrew G. Morgan 1996-8. - * Copyright (c) Alex O. Yuriev, 1996. - * Copyright (c) Cristian Gafton 1996. - * Copyright (c) Red Hat, Inc. 2007. - * - * 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. - */ diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h deleted file mode 100644 index 9d4f8b85..00000000 --- a/modules/pam_unix/support.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * $Id$ - */ - -#ifndef _PAM_UNIX_SUPPORT_H -#define _PAM_UNIX_SUPPORT_H - -#include <pwd.h> - -/* - * here is the string to inform the user that the new passwords they - * typed were not the same. - */ - -#define MISTYPED_PASS "Sorry, passwords do not match" - -/* type definition for the control options */ - -typedef struct { - const char *token; - unsigned int mask; /* shall assume 32 bits of flags */ - unsigned int flag; -} UNIX_Ctrls; - -/* - * macro to determine if a given flag is on - */ - -#define on(x,ctrl) (unix_args[x].flag & ctrl) - -/* - * macro to determine that a given flag is NOT on - */ - -#define off(x,ctrl) (!on(x,ctrl)) - -/* - * macro to turn on/off a ctrl flag manually - */ - -#define set(x,ctrl) (ctrl = ((ctrl)&unix_args[x].mask)|unix_args[x].flag) -#define unset(x,ctrl) (ctrl &= ~(unix_args[x].flag)) - -/* the generic mask */ - -#define _ALL_ON_ (~0U) - -/* end of macro definitions definitions for the control flags */ - -/* ****************************************************************** * - * ctrl flags proper.. - */ - -/* - * here are the various options recognized by the unix module. They - * are enumerated here and then defined below. Internal arguments are - * given NULL tokens. - */ - -#define UNIX__OLD_PASSWD 0 /* internal */ -#define UNIX__VERIFY_PASSWD 1 /* internal */ -#define UNIX__IAMROOT 2 /* internal */ - -#define UNIX_AUDIT 3 /* print more things than debug.. - some information may be sensitive */ -#define UNIX_USE_FIRST_PASS 4 -#define UNIX_TRY_FIRST_PASS 5 -#define UNIX_NOT_SET_PASS 6 /* don't set the AUTHTOK items */ - -#define UNIX__PRELIM 7 /* internal */ -#define UNIX__UPDATE 8 /* internal */ -#define UNIX__NONULL 9 /* internal */ -#define UNIX__QUIET 10 /* internal */ -#define UNIX_USE_AUTHTOK 11 /* insist on reading PAM_AUTHTOK */ -#define UNIX_SHADOW 12 /* signal shadow on */ -#define UNIX_MD5_PASS 13 /* force the use of MD5 passwords */ -#define UNIX__NULLOK 14 /* Null token ok */ -#define UNIX_DEBUG 15 /* send more info to syslog(3) */ -#define UNIX_NODELAY 16 /* admin does not want a fail-delay */ -#define UNIX_NIS 17 /* wish to use NIS for pwd */ -#define UNIX_BIGCRYPT 18 /* use DEC-C2 crypt()^x function */ -#define UNIX_LIKE_AUTH 19 /* need to auth for setcred to work */ -#define UNIX_REMEMBER_PASSWD 20 /* Remember N previous passwords */ -#define UNIX_NOREAP 21 /* don't reap child process */ -#define UNIX_BROKEN_SHADOW 22 /* ignore errors reading password aging - * information during acct management */ -#define UNIX_SHA256_PASS 23 /* new password hashes will use SHA256 */ -#define UNIX_SHA512_PASS 24 /* new password hashes will use SHA512 */ -#define UNIX_ALGO_ROUNDS 25 /* optional number of rounds for new - password hash algorithms */ -/* -------------- */ -#define UNIX_CTRLS_ 26 /* number of ctrl arguments defined */ - - -static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = -{ -/* symbol token name ctrl mask ctrl * - * ----------------------- ------------------- --------------------- -------- */ - -/* UNIX__OLD_PASSWD */ {NULL, _ALL_ON_, 01}, -/* UNIX__VERIFY_PASSWD */ {NULL, _ALL_ON_, 02}, -/* UNIX__IAMROOT */ {NULL, _ALL_ON_, 04}, -/* UNIX_AUDIT */ {"audit", _ALL_ON_, 010}, -/* UNIX_USE_FIRST_PASS */ {"use_first_pass", _ALL_ON_^(060), 020}, -/* UNIX_TRY_FIRST_PASS */ {"try_first_pass", _ALL_ON_^(060), 040}, -/* UNIX_NOT_SET_PASS */ {"not_set_pass", _ALL_ON_, 0100}, -/* UNIX__PRELIM */ {NULL, _ALL_ON_^(0600), 0200}, -/* UNIX__UPDATE */ {NULL, _ALL_ON_^(0600), 0400}, -/* UNIX__NONULL */ {NULL, _ALL_ON_, 01000}, -/* UNIX__QUIET */ {NULL, _ALL_ON_, 02000}, -/* UNIX_USE_AUTHTOK */ {"use_authtok", _ALL_ON_, 04000}, -/* UNIX_SHADOW */ {"shadow", _ALL_ON_, 010000}, -/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(0400000), 020000}, -/* UNIX__NULLOK */ {"nullok", _ALL_ON_^(01000), 0}, -/* UNIX_DEBUG */ {"debug", _ALL_ON_, 040000}, -/* UNIX_NODELAY */ {"nodelay", _ALL_ON_, 0100000}, -/* UNIX_NIS */ {"nis", _ALL_ON_, 0200000}, -/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(020000), 0400000}, -/* UNIX_LIKE_AUTH */ {"likeauth", _ALL_ON_, 01000000}, -/* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 02000000}, -/* UNIX_NOREAP */ {"noreap", _ALL_ON_, 04000000}, -/* UNIX_BROKEN_SHADOW */ {"broken_shadow", _ALL_ON_, 010000000}, -/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(040420000), 020000000}, -/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(020420000), 040000000}, -/* UNIX_ALGO_ROUNDS */ {"rounds=", _ALL_ON_, 0100000000}, -}; - -#define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag) - - -/* use this to free strings. ESPECIALLY password strings */ - -#define _pam_delete(xx) \ -{ \ - _pam_overwrite(xx); \ - _pam_drop(xx); \ -} - -extern int _make_remark(pam_handle_t * pamh, unsigned int ctrl - ,int type, const char *text); -extern int _set_ctrl(pam_handle_t * pamh, int flags, int *remember, int *rounds, - int argc, const char **argv); -extern int _unix_getpwnam (pam_handle_t *pamh, - const char *name, int files, int nis, - struct passwd **ret); -extern int _unix_comesfromsource (pam_handle_t *pamh, - const char *name, int files, int nis); -extern int _unix_blankpasswd(pam_handle_t *pamh,unsigned int ctrl, - const char *name); -extern int _unix_verify_password(pam_handle_t * pamh, const char *name - ,const char *p, unsigned int ctrl); -extern int _unix_read_password(pam_handle_t * pamh - ,unsigned int ctrl - ,const char *comment - ,const char *prompt1 - ,const char *prompt2 - ,const char *data_name - ,const void **pass); - -extern int _unix_run_verify_binary(pam_handle_t *pamh, - unsigned int ctrl, const char *user, int *daysleft); -#endif /* _PAM_UNIX_SUPPORT_H */ diff --git a/modules/pam_unix/tst-pam_unix b/modules/pam_unix/tst-pam_unix deleted file mode 100755 index 22922800..00000000 --- a/modules/pam_unix/tst-pam_unix +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -../../tests/tst-dlopen .libs/pam_unix.so diff --git a/modules/pam_unix/unix_chkpwd.8.xml b/modules/pam_unix/unix_chkpwd.8.xml deleted file mode 100644 index a10dbe33..00000000 --- a/modules/pam_unix/unix_chkpwd.8.xml +++ /dev/null @@ -1,67 +0,0 @@ -<?xml version="1.0" encoding='UTF-8'?> -<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" - "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"> - -<refentry id="unix_chkpwd"> - - <refmeta> - <refentrytitle>unix_chkpwd</refentrytitle> - <manvolnum>8</manvolnum> - <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo> - </refmeta> - - <refnamediv id="unix_chkpwd-name"> - <refname>unix_chkpwd</refname> - <refpurpose>Helper binary that verifies the password of the current user</refpurpose> - </refnamediv> - - <refsynopsisdiv> - <cmdsynopsis id="unix_chkpwd-cmdsynopsis"> - <command>unix_chkpwd</command> - <arg choice="opt"> - ... - </arg> - </cmdsynopsis> - </refsynopsisdiv> - - <refsect1 id="unix_chkpwd-description"> - - <title>DESCRIPTION</title> - - <para> - <emphasis>unix_chkpwd</emphasis> is a helper program for the - <emphasis>pam_unix</emphasis> module that verifies the - password of the current user. It also checks password and account - expiration dates in <emphasis>shadow</emphasis>. It is not intended to - be run directly from the command line and logs a security violation if - done so. - </para> - - <para> - It is typically installed setuid root or setgid shadow. - </para> - - <para> - The interface of the helper - command line options, and input/output - data format are internal to the <emphasis>pam_unix</emphasis> - module and it should not be called directly from applications. - </para> - </refsect1> - - <refsect1 id='unix_chkpwd-see_also'> - <title>SEE ALSO</title> - <para> - <citerefentry> - <refentrytitle>pam_unix</refentrytitle><manvolnum>8</manvolnum> - </citerefentry> - </para> - </refsect1> - - <refsect1 id='unix_chkpwd-author'> - <title>AUTHOR</title> - <para> - Written by Andrew Morgan and other various people. - </para> - </refsect1> - -</refentry> diff --git a/modules/pam_unix/unix_chkpwd.c b/modules/pam_unix/unix_chkpwd.c deleted file mode 100644 index 11ac3aac..00000000 --- a/modules/pam_unix/unix_chkpwd.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * 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. - */ diff --git a/modules/pam_unix/unix_update.8.xml b/modules/pam_unix/unix_update.8.xml deleted file mode 100644 index 07695951..00000000 --- a/modules/pam_unix/unix_update.8.xml +++ /dev/null @@ -1,67 +0,0 @@ -<?xml version="1.0" encoding='UTF-8'?> -<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" - "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"> - -<refentry id="unix_update"> - - <refmeta> - <refentrytitle>unix_update</refentrytitle> - <manvolnum>8</manvolnum> - <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo> - </refmeta> - - <refnamediv id="unix_update-name"> - <refname>unix_update</refname> - <refpurpose>Helper binary that updates the password of a given user</refpurpose> - </refnamediv> - - <refsynopsisdiv> - <cmdsynopsis id="unix_update-cmdsynopsis"> - <command>unix_update</command> - <arg choice="opt"> - ... - </arg> - </cmdsynopsis> - </refsynopsisdiv> - - <refsect1 id="unix_update-description"> - - <title>DESCRIPTION</title> - - <para> - <emphasis>unix_update</emphasis> is a helper program for the - <emphasis>pam_unix</emphasis> module that updates the - password of a given user. It is not intended to be run directly - from the command line and logs a security violation if done so. - </para> - - <para> - The purpose of the helper is to enable tighter confinement of - login and password changing services. The helper is thus called only - when SELinux is enabled and in the enforcing mode on the system. - </para> - - <para> - The interface of the helper - command line options, and input/output - data format are internal to the <emphasis>pam_unix</emphasis> - module and it should not be called directly from applications. - </para> - </refsect1> - - <refsect1 id='unix_update-see_also'> - <title>SEE ALSO</title> - <para> - <citerefentry> - <refentrytitle>pam_unix</refentrytitle><manvolnum>8</manvolnum> - </citerefentry> - </para> - </refsect1> - - <refsect1 id='unix_update-author'> - <title>AUTHOR</title> - <para> - Written by Tomas Mraz and other various people. - </para> - </refsect1> - -</refentry> diff --git a/modules/pam_unix/unix_update.c b/modules/pam_unix/unix_update.c deleted file mode 100644 index 595b7f8b..00000000 --- a/modules/pam_unix/unix_update.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * 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 <stdarg.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 <sys/time.h> - -#include <security/_pam_types.h> -#include <security/_pam_macros.h> - -#include "passverify.h" - -static int -set_password(const char *forwho, const char *shadow, const char *remember) -{ - struct passwd *pwd = NULL; - int retval; - char pass[MAXPASS + 1]; - char towhat[MAXPASS + 1]; - int npass = 0; - /* we don't care about number format errors because the helper - should be called internally only */ - int doshadow = atoi(shadow); - int nremember = atoi(remember); - char *passwords[] = { pass, towhat }; - - /* read the password from stdin (a pipe from the pam_unix module) */ - - npass = read_passwords(STDIN_FILENO, 2, passwords); - - if (npass != 2) { /* is it a valid password? */ - if (npass == 1) { - helper_log_err(LOG_DEBUG, "no new password supplied"); - memset(pass, '\0', MAXPASS); - } else { - helper_log_err(LOG_DEBUG, "no valid passwords supplied"); - } - return PAM_AUTHTOK_ERR; - } - - if (lock_pwdf() != PAM_SUCCESS) - return PAM_AUTHTOK_LOCK_BUSY; - - pwd = getpwnam(forwho); - - if (pwd == NULL) { - retval = PAM_USER_UNKNOWN; - goto done; - } - - /* does pass agree with the official one? - we always allow change from null pass */ - retval = helper_verify_password(forwho, pass, 1); - if (retval != PAM_SUCCESS) { - goto done; - } - - /* first, save old password */ - if (save_old_password(forwho, pass, nremember)) { - retval = PAM_AUTHTOK_ERR; - goto done; - } - - if (doshadow || is_pwd_shadowed(pwd)) { - retval = unix_update_shadow(forwho, towhat); - if (retval == PAM_SUCCESS) - if (!is_pwd_shadowed(pwd)) - retval = unix_update_passwd(forwho, "x"); - } else { - retval = unix_update_passwd(forwho, towhat); - } - -done: - memset(pass, '\0', MAXPASS); - memset(towhat, '\0', MAXPASS); - - unlock_pwdf(); - - if (retval == PAM_SUCCESS) { - return PAM_SUCCESS; - } else { - return PAM_AUTHTOK_ERR; - } -} - -int main(int argc, char *argv[]) -{ - char *option; - - /* - * 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 != 5 ) { - 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; - } - - /* We must be root to read/update shadow. - */ - if (geteuid() != 0) { - return PAM_CRED_INSUFFICIENT; - } - - option = argv[2]; - - if (strcmp(option, "update") == 0) { - /* Attempting to change the password */ - return set_password(argv[1], argv[3], argv[4]); - } - - return PAM_SYSTEM_ERR; -} - -/* - * 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. - */ diff --git a/modules/pam_unix/yppasswd.h b/modules/pam_unix/yppasswd.h deleted file mode 100644 index 6b414be0..00000000 --- a/modules/pam_unix/yppasswd.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * yppasswdd - * Copyright 1994, 1995, 1996 Olaf Kirch, <okir@monad.swb.de> - * - * This program is covered by the GNU General Public License, version 2. - * It is provided in the hope that it is useful. However, the author - * disclaims ALL WARRANTIES, expressed or implied. See the GPL for details. - * - * This file was generated automatically by rpcgen from yppasswd.x, and - * editied manually. - */ - -#ifndef _YPPASSWD_H_ -#define _YPPASSWD_H_ - -#define YPPASSWDPROG ((u_long)100009) -#define YPPASSWDVERS ((u_long)1) -#define YPPASSWDPROC_UPDATE ((u_long)1) - -/* - * The password struct passed by the update call. I renamed it to - * xpasswd to avoid a type clash with the one defined in <pwd.h>. - */ -#ifndef __sgi -typedef struct xpasswd { - char *pw_name; - char *pw_passwd; - int pw_uid; - int pw_gid; - char *pw_gecos; - char *pw_dir; - char *pw_shell; -} xpasswd; - -#else -#include <pwd.h> -typedef struct xpasswd xpasswd; -#endif - -/* The updated password information, plus the old password. - */ -typedef struct yppasswd { - char *oldpass; - xpasswd newpw; -} yppasswd; - -/* XDR encoding/decoding routines */ -bool_t xdr_xpasswd(XDR * xdrs, xpasswd * objp); -bool_t xdr_yppasswd(XDR * xdrs, yppasswd * objp); - -#endif /* _YPPASSWD_H_ */ diff --git a/modules/pam_unix/yppasswd_xdr.c b/modules/pam_unix/yppasswd_xdr.c deleted file mode 100644 index bf3f2fc6..00000000 --- a/modules/pam_unix/yppasswd_xdr.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * yppasswdd - * Copyright 1994, 1995, 1996 Olaf Kirch, <okir@monad.swb.de> - * - * This program is covered by the GNU General Public License, version 2. - * It is provided in the hope that it is useful. However, the author - * disclaims ALL WARRANTIES, expressed or implied. See the GPL for details. - * - * This file was generated automatically by rpcgen from yppasswd.x, and - * editied manually. - */ - -#include "config.h" - -#include <rpc/rpc.h> -#include <rpcsvc/yp_prot.h> -#include <rpcsvc/ypclnt.h> -#include "yppasswd.h" - -bool_t -xdr_xpasswd(XDR * xdrs, xpasswd * objp) -{ - return xdr_string(xdrs, &objp->pw_name, ~0) - && xdr_string(xdrs, &objp->pw_passwd, ~0) - && xdr_int(xdrs, &objp->pw_uid) - && xdr_int(xdrs, &objp->pw_gid) - && xdr_string(xdrs, &objp->pw_gecos, ~0) - && xdr_string(xdrs, &objp->pw_dir, ~0) - && xdr_string(xdrs, &objp->pw_shell, ~0); -} - - -bool_t -xdr_yppasswd(XDR * xdrs, yppasswd * objp) -{ - return xdr_string(xdrs, &objp->oldpass, ~0) - && xdr_xpasswd(xdrs, &objp->newpw); -} |