From efd31890b5ed496a5a00c08a262da240e66a4ddc Mon Sep 17 00:00:00 2001 From: Steve Langasek Date: Thu, 3 Jan 2019 12:44:11 -0800 Subject: New upstream version 0.76 --- modules/pam_unix/.cvsignore | 4 - modules/pam_unix/CHANGELOG | 55 -- modules/pam_unix/Makefile | 167 ------ modules/pam_unix/README | 35 -- modules/pam_unix/bigcrypt.c | 124 ----- modules/pam_unix/lckpwdf.-c | 117 ---- modules/pam_unix/md5.c | 256 --------- modules/pam_unix/md5.h | 31 -- modules/pam_unix/md5_crypt.c | 154 ------ modules/pam_unix/pam_unix_acct.c | 204 ------- modules/pam_unix/pam_unix_auth.c | 228 -------- modules/pam_unix/pam_unix_passwd.c | 1030 ------------------------------------ modules/pam_unix/pam_unix_sess.c | 141 ----- modules/pam_unix/support.c | 923 -------------------------------- modules/pam_unix/support.h | 144 ----- modules/pam_unix/unix_chkpwd.c | 329 ------------ modules/pam_unix/yppasswd.h | 51 -- modules/pam_unix/yppasswd_xdr.c | 38 -- 18 files changed, 4031 deletions(-) delete mode 100644 modules/pam_unix/.cvsignore delete mode 100644 modules/pam_unix/CHANGELOG delete mode 100644 modules/pam_unix/Makefile delete mode 100644 modules/pam_unix/README delete mode 100644 modules/pam_unix/bigcrypt.c delete mode 100644 modules/pam_unix/lckpwdf.-c delete mode 100644 modules/pam_unix/md5.c delete mode 100644 modules/pam_unix/md5.h delete mode 100644 modules/pam_unix/md5_crypt.c delete mode 100644 modules/pam_unix/pam_unix_acct.c delete mode 100644 modules/pam_unix/pam_unix_auth.c delete mode 100644 modules/pam_unix/pam_unix_passwd.c delete mode 100644 modules/pam_unix/pam_unix_sess.c delete mode 100644 modules/pam_unix/support.c delete mode 100644 modules/pam_unix/support.h delete mode 100644 modules/pam_unix/unix_chkpwd.c delete mode 100644 modules/pam_unix/yppasswd.h delete mode 100644 modules/pam_unix/yppasswd_xdr.c (limited to 'modules/pam_unix') diff --git a/modules/pam_unix/.cvsignore b/modules/pam_unix/.cvsignore deleted file mode 100644 index 64c5ce5c..00000000 --- a/modules/pam_unix/.cvsignore +++ /dev/null @@ -1,4 +0,0 @@ -dynamic -unix_chkpwd -*.so -*~ 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 -- 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 -- further NIS+ fixes - -* Sun Jun 27 1999 Steve Langasek -- fix to uid-handling code for NIS+ - -* Sat Jun 26 1999 Jan Rêkorajski -- merged MD5 fix and early failure syslog - by Andrey Vladimirovich Savochkin -- minor fixes -- added signal handler to unix_chkpwd - -* Fri Jun 25 1999 Stephen Langasek -- reorganized the code to let it build as separate C files - -* Sun Jun 20 1999 Jan Rêkorajski -- fixes in pam_unix_auth, it incorrectly saved and restored return - value when likeauth option was used - -* Tue Jun 15 1999 Jan Rêkorajski -- added NIS+ support - -* Mon Jun 14 1999 Jan Rêkorajski -- 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 -- Arghhh, pam_unix_passwd was not updating /etc/shadow when used with - pam_cracklib. - -* Mon Apr 19 1999 Jan Rêkorajski -- 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 -- 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 -- 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 b/modules/pam_unix/Makefile deleted file mode 100644 index e627d728..00000000 --- a/modules/pam_unix/Makefile +++ /dev/null @@ -1,167 +0,0 @@ -# $Id$ -# -# This Makefile controls a build process of the pam_unix modules -# for Linux-PAM. You should not modify this Makefile. -# - -include ../../Make.Rules - -######################################################################## -# some options... uncomment to take effect -######################################################################## - -# Unless someone wants to work out how to make this work with the new -# autoconf stuff, you should use a separate module for this type of thing -# pam_cracklib perhaps..? -# do you want cracklib? -#ifeq ($(HAVE_CRACKLIB),yes) -#USE_CRACKLIB=-D"USE_CRACKLIB" -#endif - -# do you want to use lckpwdf? -ifeq ($(WITH_LCKPWDF),yes) -USE_LCKPWDF=-D"USE_LCKPWDF" -# do you need to include the locking functions in the source? -ifeq ($(HAVE_LCKPWDF),no) - NEED_LCKPWDF=-D"NEED_LCKPWDF" -endif -endif - -ifeq ($(HAVE_LIBNSL),yes) - LIBNSL = -lnsl -endif - -ifeq ($(HAVE_LIBCRYPT),yes) - LIBCRYPT=-lcrypt -endif - -CHKPWD=unix_chkpwd - -EXTRAS += -DCHKPWD_HELPER=\"$(SUPLEMENTED)/$(CHKPWD)\" - -######################################################################## - -CFLAGS += $(USE_CRACKLIB) $(USE_LCKPWDF) $(NEED_LCKPWDF) $(EXTRAS) -LDLIBS = $(EXTRALS) - -ifdef USE_CRACKLIB -CRACKLIB = -lcrack -endif - - -LIBOBJ = pam_unix_auth.o pam_unix_acct.o pam_unix_sess.o pam_unix_passwd.o \ - support.o -LIBSRC = pam_unix_auth.c pam_unix_acct.c pam_unix_sess.c pam_unix_passwd.c \ - support.c -LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) -LIBOBJS = $(addprefix static/,$(LIBOBJ)) - -PLUS = md5_good.o md5_broken.o md5_crypt_good.o md5_crypt_broken.o \ - yppasswd_xdr.o bigcrypt.o - -ifdef DYNAMIC -LIBSHARED = pam_unix.so -endif -ifdef STATIC -LIBSTATIC = libpam_unix.o -endif - - -########################### don't edit below ####################### - -all: dirs info $(PLUS) $(LIBSHARED) $(LIBSTATIC) $(CHKPWD) register - -dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -static/%.o: %.c - $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -dummy: - @echo "**** This is not a top-level Makefile " - exit - -info: - @echo - @echo "*** Building pam-unix module of the framework..." - @echo - -dirs: -ifdef DYNAMIC - mkdir -p ./dynamic -endif -ifdef STATIC - mkdir -p ./static -endif - -register: -ifdef STATIC - ( cd .. ; ./register_static pam_unix_auth pam_unix/$(LIBSTATIC) ; \ - ./register_static pam_unix_acct "" ; \ - ./register_static pam_unix_session "" ; \ - ./register_static pam_unix_passwd "" ; \ - ) -endif - -ifdef DYNAMIC -$(LIBOBJD): $(LIBSRC) - -$(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) $(PLUS) $(CRACKLIB) $(LDLIBS) $(LIBNSL) $(LIBCRYPT) -endif - -ifdef STATIC -$(LIBOBJS): $(LIBSRC) - -$(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) $(PLUS) $(CRACKLIB) $(LDLIBS) $(LIBNSL) $(LIBCRYPT) -endif - -$(CHKPWD): unix_chkpwd.o md5_good.o md5_broken.o \ - md5_crypt_good.o md5_crypt_broken.o \ - bigcrypt.o - $(CC) -o $(CHKPWD) $^ $(LDLIBS) $(LIBCRYPT) - -unix_chkpwd.o: unix_chkpwd.c - $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ - -md5_good.o: md5.c - $(CC) $(CFLAGS) $(CPPFLAGS) -DHIGHFIRST -D'MD5Name(x)=Good##x' \ - $(TARGET_ARCH) -c $< -o $@ - -md5_broken.o: md5.c - $(CC) $(CFLAGS) $(CPPFLAGS) -D'MD5Name(x)=Broken##x' \ - $(TARGET_ARCH) -c $< -o $@ - -md5_crypt_good.o: md5_crypt.c - $(CC) $(CFLAGS) $(CPPFLAGS) -D'MD5Name(x)=Good##x' \ - $(TARGET_ARCH) -c $< -o $@ - -md5_crypt_broken.o: md5_crypt.c - $(CC) $(CFLAGS) $(CPPFLAGS) -D'MD5Name(x)=Broken##x' \ - $(TARGET_ARCH) -c $< -o $@ - -install: all - mkdir -p $(FAKEROOT)$(SECUREDIR) -ifdef DYNAMIC - install -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR) - for x in pam_unix_auth pam_unix_acct pam_unix_passwd pam_unix_session;\ - do ln -sf $(LIBSHARED) $(FAKEROOT)$(SECUREDIR)/$$x.so ; done -endif - $(MKDIR) $(FAKEROOT)$(SUPLEMENTED) - install -m 4555 $(CHKPWD) $(FAKEROOT)$(SUPLEMENTED) - -remove: - rm -f $(FAKEROOT)$(SECUREDIR)/$(LIBSHARED) - for x in pam_unix_auth pam_unix_acct pam_unix_passwd pam_unix_session;\ - do rm -f $(FAKEROOT)$(SECUREDIR)/$$x.so ; done - rm -f $(FAKEROOT)$(SUPLEMENTED)/$(CHKPWD) - -clean: - rm -f $(LIBOBJD) $(LIBOBJS) $(CHKPWD) *.o *.so core - rm -f *~ *.a *.out *.bak - rm -rf dynamic static - -.c.o: - $(CC) -c $(CFLAGS) $< - diff --git a/modules/pam_unix/README b/modules/pam_unix/README deleted file mode 100644 index d6b1f395..00000000 --- a/modules/pam_unix/README +++ /dev/null @@ -1,35 +0,0 @@ -pam_unix comes as one module pam_unix.so. - -The following links are left for compatibility with old versions: -pam_unix_auth: authentication module providing - pam_authenticate() and pam_setcred() hooks -pam_unix_sess: session module, providing session logging -pam_unix_acct: account management, providing shadow account - managment features, password aging etc.. -pam_unix_passwd: password updating facilities providing - cracklib password strength checking facilities. - -The following options are recognized: - debug - log more debugging info - audit - a little more extreme than debug - use_first_pass - don't prompt the user for passwords - take them from PAM_ items instead - try_first_pass - don't prompt the user for the passwords - unless PAM_(OLD)AUTHTOK is unset - use_authtok - like try_first_pass, but * fail * if the new - PAM_AUTHTOK has not been previously set. - (intended for stacking password modules only) - not_set_pass - don't set the PAM_ items with the passwords - used by this module. - shadow - try to maintian a shadow based system. - md5 - when a user changes their password next, - encrypt it with the md5 algorithm. - bigcrypt - when a user changes their password next, - excrypt it with the DEC C2 - algorithm(0). - nodelay - used to prevent failed authentication - resulting in a delay of about 1 second. - nis - use NIS RPC for setting new password - remember=X - remember X old passwords, they are kept in - /etc/security/opasswd in MD5 crypted form - - invalid arguments are logged to syslog. diff --git a/modules/pam_unix/bigcrypt.c b/modules/pam_unix/bigcrypt.c deleted file mode 100644 index 6b73f3d2..00000000 --- a/modules/pam_unix/bigcrypt.c +++ /dev/null @@ -1,124 +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 - */ - -#include -#include -#include - -char *crypt(const char *key, const char *salt); -char *bigcrypt(const char *key, const char *salt); - -/* - * 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; - - 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; - } - 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 */ - tmp_ptr = crypt(plaintext_ptr, salt); /* libc crypt() */ - - /* 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++) { - - tmp_ptr = crypt(plaintext_ptr, salt_ptr); - - /* 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)); - - /* this is the terminated encrypted password */ - - return dec_c2_cryptbuf; -} diff --git a/modules/pam_unix/lckpwdf.-c b/modules/pam_unix/lckpwdf.-c deleted file mode 100644 index b5ff4585..00000000 --- a/modules/pam_unix/lckpwdf.-c +++ /dev/null @@ -1,117 +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 , - * public domain. - */ - -#include -#include - -#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; - - 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 -#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<>(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_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): - * 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 -#include -#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/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c deleted file mode 100644 index 178b6037..00000000 --- a/modules/pam_unix/pam_unix_acct.c +++ /dev/null @@ -1,204 +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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for time() */ - -#include - -/* indicate that the following groups are defined */ - -#define PAM_SM_ACCOUNT - -#include - -#ifndef LINUX_PAM -#include -#endif /* LINUX_PAM */ - -#include "support.h" - -/* - * 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 char *uname; - int retval, daysleft; - time_t curdays; - struct spwd *spent; - struct passwd *pwent; - char buf[80]; - - D(("called.")); - - ctrl = _set_ctrl(pamh, flags, NULL, argc, argv); - - retval = pam_get_item(pamh, PAM_USER, (const void **) &uname); - D(("user = `%s'", uname)); - if (retval != PAM_SUCCESS || uname == NULL) { - _log_err(LOG_ALERT, pamh - ,"could not identify user (from uid=%d)" - ,getuid()); - return PAM_USER_UNKNOWN; - } - - pwent = getpwnam(uname); - if (!pwent) { - _log_err(LOG_ALERT, pamh - ,"could not identify user (from getpwnam(%s))" - ,uname); - return PAM_USER_UNKNOWN; - } - - if (!strcmp( pwent->pw_passwd, "*NP*" )) { /* NIS+ */ - uid_t save_euid, save_uid; - - save_euid = geteuid(); - save_uid = getuid(); - if (save_uid == pwent->pw_uid) - setreuid( save_euid, save_uid ); - else { - setreuid( 0, -1 ); - if (setreuid( -1, pwent->pw_uid ) == -1) { - setreuid( -1, 0 ); - setreuid( 0, -1 ); - if(setreuid( -1, pwent->pw_uid ) == -1) - return PAM_CRED_INSUFFICIENT; - } - } - spent = getspnam( uname ); - if (save_uid == pwent->pw_uid) - setreuid( save_uid, save_euid ); - else { - if (setreuid( -1, 0 ) == -1) - setreuid( save_uid, -1 ); - setreuid( -1, save_euid ); - } - - } else if (!strcmp( pwent->pw_passwd, "x" )) { - spent = getspnam(uname); - } else { - return PAM_SUCCESS; - } - - if (!spent) - return PAM_AUTHINFO_UNAVAIL; /* Couldn't get username from shadow */ - - curdays = 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) - && (spent->sp_lstchg != 0)) { - _log_err(LOG_NOTICE, pamh - ,"account %s has expired (account expired)" - ,uname); - _make_remark(pamh, ctrl, PAM_ERROR_MSG, - "Your account has expired; please contact your system administrator"); - D(("account expired")); - return PAM_ACCT_EXPIRED; - } - if ((curdays > (spent->sp_lstchg + spent->sp_max + spent->sp_inact)) - && (spent->sp_max != -1) && (spent->sp_inact != -1) - && (spent->sp_lstchg != 0)) { - _log_err(LOG_NOTICE, pamh - ,"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"); - D(("account expired 2")); - return PAM_ACCT_EXPIRED; - } - D(("when was the last change")); - if (spent->sp_lstchg == 0) { - _log_err(LOG_NOTICE, pamh - ,"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)"); - D(("need a new password")); - return PAM_NEW_AUTHTOK_REQD; - } - if (((spent->sp_lstchg + spent->sp_max) < curdays) && (spent->sp_max != -1)) { - _log_err(LOG_DEBUG, pamh - ,"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)"); - 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 = (spent->sp_lstchg + spent->sp_max) - curdays; - _log_err(LOG_DEBUG, pamh - ,"password for user %s will expire in %d days" - ,uname, daysleft); - snprintf(buf, 80, "Warning: your password will expire in %d day%.2s", - daysleft, daysleft == 1 ? "" : "s"); - _make_remark(pamh, ctrl, PAM_TEXT_INFO, buf); - } - - D(("all done")); - - return PAM_SUCCESS; -} - - -/* 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 67497e06..00000000 --- a/modules/pam_unix/pam_unix_auth.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright Alexander O. Yuriev, 1996. All rights reserved. - * NIS+ support by Thorsten Kukuk - * 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* indicate the following groups are defined */ - -#define PAM_SM_AUTH - -#define _PAM_EXTERN_FUNCTIONS -#include -#include - -#ifndef LINUX_PAM -#include -#endif /* LINUX_PAM */ - -#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); \ - } \ - D(("done. [%s]", pam_strerror(pamh, retval))); \ - return retval; \ -} while (0) - - -static void setcred_free (pam_handle_t * pamh, void *ptr, int err) -{ - 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, *p; - - D(("called.")); - - ctrl = _set_ctrl(pamh, flags, 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 take - * any chances here. Require that the username starts with an - * alphanumeric character. - */ - if (name == NULL || !isalnum(*name)) { - _log_err(LOG_ERR, pamh, "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(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) { - _log_err(LOG_CRIT, pamh, "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 - ,int argc, const char **argv) -{ - int retval; - int *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. */ - pam_get_data(pamh, "unix_setcred_return", (const void **) &pretval); - if(pretval) { - retval = *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 6b51a6b2..00000000 --- a/modules/pam_unix/pam_unix_passwd.c +++ /dev/null @@ -1,1030 +0,0 @@ -/* - * Main coding by Elliot Lee , Red Hat Software. - * Copyright (C) 1996. - * Copyright (c) Jan Rêkorajski, 1999. - * - * 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for time() */ -#include -#include -#include -#include -#include -#include -#include - -#ifdef USE_CRACKLIB -#include -#endif - -#include - -/* indicate the following groups are defined */ - -#define PAM_SM_PASSWORD - -#include - -#ifndef LINUX_PAM -#include -#endif /* LINUX_PAM */ - -#include "yppasswd.h" -#include "md5.h" -#include "support.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 */ - -/* - * PAM framework looks for these entry-points to pass control to the - * password changing module. - */ - -#ifdef NEED_LCKPWDF -#include "./lckpwdf.-c" -#endif - -extern char *bigcrypt(const char *key, const char *salt); - -/* - 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. - */ - -/* passwd/salt conversion macros */ - -#define ascii_to_bin(c) ((c)>='a'?(c-59):(c)>='A'?((c)-53):(c)-'.') -#define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.') - -/* data tokens */ - -#define _UNIX_OLD_AUTHTOK "-UN*X-OLD-PASS" -#define _UNIX_NEW_AUTHTOK "-UN*X-NEW-PASS" - -#define MAX_PASSWD_TRIES 3 -#define PW_TMPFILE "/etc/npasswd" -#define SH_TMPFILE "/etc/nshadow" -#define CRACKLIB_DICTS "/usr/share/dict/cracklib_dict" -#define OPW_TMPFILE "/etc/security/nopasswd" -#define OLD_PASSWORDS_FILE "/etc/security/opasswd" - -/* - * 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'); -} - -static char *crypt_md5_wrapper(const char *pass_new) -{ - /* - * Code lifted from Marek Michalkiewicz's shadow suite. (CG) - * removed use of static variables (AGM) - */ - - struct timeval tv; - MD5_CTX ctx; - unsigned char result[16]; - char *cp = (char *) result; - unsigned char tmp[16]; - int i; - char *x = NULL; - - 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, result, sizeof result); - GoodMD5Final(tmp, &ctx); - strcpy(cp, "$1$"); /* magic for the MD5 */ - cp += strlen(cp); - for (i = 0; i < 8; i++) - *cp++ = i64c(tmp[i] & 077); - *cp = '\0'; - - /* no longer need cleartext */ - x = Goodcrypt_md5(pass_new, (const char *) result); - - return x; -} - -static char *getNISserver(pam_handle_t *pamh) -{ - char *master; - char *domainname; - int port, err; - - if ((err = yp_get_default_domain(&domainname)) != 0) { - _log_err(LOG_WARNING, pamh, "can't get local yp domain: %s\n", - yperr_string(err)); - return NULL; - } - if ((err = yp_master(domainname, "passwd.byname", &master)) != 0) { - _log_err(LOG_WARNING, pamh, "can't find the master ypserver: %s\n", - yperr_string(err)); - return NULL; - } - port = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, IPPROTO_UDP); - if (port == 0) { - _log_err(LOG_WARNING, pamh, - "yppasswdd not running on NIS master host\n"); - return NULL; - } - if (port >= IPPORT_RESERVED) { - _log_err(LOG_WARNING, pamh, - "yppasswd daemon running on illegal port.\n"); - return NULL; - } - return master; -} - -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_AUTHTOK_ERR; - - while (fgets(buf, 16380, opwfile)) { - if (!strncmp(buf, forwho, strlen(forwho))) { - buf[strlen(buf) - 1] = '\0'; - s_luser = strtok(buf, ":,"); - s_uid = strtok(NULL, ":,"); - s_npas = strtok(NULL, ":,"); - s_pas = strtok(NULL, ":,"); - 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(NULL, ":,"); - _pam_delete(md5pass); - } - break; - } - } - fclose(opwfile); - - return retval; -} - -static 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; - - if (howmany < 0) { - return PAM_SUCCESS; - } - - if (oldpass == NULL) { - return PAM_SUCCESS; - } - - oldmask = umask(077); - pwfile = fopen(OPW_TMPFILE, "w"); - umask(oldmask); - if (pwfile == NULL) { - return PAM_AUTHTOK_ERR; - } - - opwfile = fopen(OLD_PASSWORDS_FILE, "r"); - if (opwfile == NULL) { - fclose(pwfile); - return PAM_AUTHTOK_ERR; - } - - chown(OPW_TMPFILE, 0, 0); - chmod(OPW_TMPFILE, 0600); - - while (fgets(buf, 16380, opwfile)) { - if (!strncmp(buf, forwho, strlen(forwho))) { - buf[strlen(buf) - 1] = '\0'; - s_luser = strtok(buf, ":"); - s_uid = strtok(NULL, ":"); - s_npas = strtok(NULL, ":"); - s_pas = strtok(NULL, ":"); - 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; - } - found = 1; - } 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:%d:1:%s\n", - forwho, 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: %s\n", - strerror(errno))); - err = 1; - } - - if (!err) { - rename(OPW_TMPFILE, OLD_PASSWORDS_FILE); - return PAM_SUCCESS; - } else { - unlink(OPW_TMPFILE); - return PAM_AUTHTOK_ERR; - } -} - -static int _update_passwd(pam_handle_t *pamh, - const char *forwho, const char *towhat) -{ - struct passwd *tmpent = NULL; - FILE *pwfile, *opwfile; - int err = 1; - int oldmask; - - oldmask = umask(077); - pwfile = fopen(PW_TMPFILE, "w"); - umask(oldmask); - if (pwfile == NULL) { - return PAM_AUTHTOK_ERR; - } - - opwfile = fopen("/etc/passwd", "r"); - if (opwfile == NULL) { - fclose(pwfile); - return PAM_AUTHTOK_ERR; - } - - chown(PW_TMPFILE, 0, 0); - chmod(PW_TMPFILE, 0644); - 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: %s\n", strerror(errno))); - err = 1; - break; - } - tmpent = fgetpwent(opwfile); - } - fclose(opwfile); - - if (fclose(pwfile)) { - D(("error writing entries to password file: %s\n", strerror(errno))); - err = 1; - } - - if (!err) { - rename(PW_TMPFILE, "/etc/passwd"); - _log_err(LOG_NOTICE, pamh, "password changed for %s", forwho); - return PAM_SUCCESS; - } else { - unlink(PW_TMPFILE); - return PAM_AUTHTOK_ERR; - } -} - -static int _update_shadow(const char *forwho, char *towhat) -{ - struct spwd *spwdent = NULL, *stmpent = NULL; - FILE *pwfile, *opwfile; - int err = 1; - int oldmask; - - spwdent = getspnam(forwho); - if (spwdent == NULL) { - return PAM_USER_UNKNOWN; - } - oldmask = umask(077); - pwfile = fopen(SH_TMPFILE, "w"); - umask(oldmask); - if (pwfile == NULL) { - return PAM_AUTHTOK_ERR; - } - - opwfile = fopen("/etc/shadow", "r"); - if (opwfile == NULL) { - fclose(pwfile); - return PAM_AUTHTOK_ERR; - } - - chown(SH_TMPFILE, 0, 0); - chmod(SH_TMPFILE, 0600); - 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: %s\n", strerror(errno))); - err = 1; - break; - } - - stmpent = fgetspent(opwfile); - } - fclose(opwfile); - - if (fclose(pwfile)) { - D(("error writing entries to shadow file: %s\n", strerror(errno))); - err = 1; - } - - if (!err) { - rename(SH_TMPFILE, "/etc/shadow"); - return PAM_SUCCESS; - } else { - unlink(SH_TMPFILE); - return PAM_AUTHTOK_ERR; - } -} - -static int _do_setpass(pam_handle_t* pamh, const char *forwho, char *fromwhat, - char *towhat, unsigned int ctrl, int remember) -{ - struct passwd *pwd = NULL; - int retval = 0; - - D(("called")); - - setpwent(); - pwd = getpwnam(forwho); - endpwent(); - - if (pwd == NULL) - return PAM_AUTHTOK_ERR; - - if (on(UNIX_NIS, ctrl)) { - struct timeval timeout; - struct yppasswd yppwd; - CLIENT *clnt; - char *master; - int status; - int err = 0; - - /* Make RPC call to NIS server */ - if ((master = getNISserver(pamh)) == NULL) - return PAM_TRY_AGAIN; - - /* 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; - 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); - - if (err) { - clnt_perrno(err); - retval = PAM_TRY_AGAIN; - } else if (status) { - D(("Error while changing NIS password.\n")); - retval = PAM_TRY_AGAIN; - } - D(("The password has%s been changed on %s.", - (err || status) ? " not" : "", master)); - _log_err(LOG_NOTICE, pamh, "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) != 0) { - retval = PAM_TRY_AGAIN; - } -#ifdef DEBUG - sleep(5); -#endif - return retval; - } - /* first, save old password */ - if (save_old_password(forwho, fromwhat, remember)) { - return PAM_AUTHTOK_ERR; - } - if (on(UNIX_SHADOW, ctrl) || (strcmp(pwd->pw_passwd, "x") == 0)) { - retval = _update_shadow(forwho, towhat); - if (retval == PAM_SUCCESS) - retval = _update_passwd(pamh, forwho, "x"); - } else { - retval = _update_passwd(pamh, forwho, towhat); - } - - return retval; -} - -static int _unix_verify_shadow(const char *user, unsigned int ctrl) -{ - struct passwd *pwd = NULL; /* Password and shadow password */ - struct spwd *spwdent = NULL; /* file entries for the user */ - time_t curdays; - int retval = PAM_SUCCESS; - - /* UNIX passwords area */ - setpwent(); - pwd = getpwnam(user); /* Get password file entry... */ - endpwent(); - if (pwd == NULL) - return PAM_AUTHINFO_UNAVAIL; /* We don't need to do the rest... */ - - if (strcmp(pwd->pw_passwd, "x") == 0) { - /* ...and shadow password file entry for this user, if shadowing - is enabled */ - setspent(); - spwdent = getspnam(user); - endspent(); - - if (spwdent == NULL) - return PAM_AUTHINFO_UNAVAIL; - } else { - if (strcmp(pwd->pw_passwd,"*NP*") == 0) { /* NIS+ */ - uid_t save_uid; - - save_uid = geteuid(); - seteuid (pwd->pw_uid); - spwdent = getspnam( user ); - seteuid (save_uid); - - if (spwdent == NULL) - return PAM_AUTHINFO_UNAVAIL; - } else - spwdent = NULL; - } - - if (spwdent != NULL) { - /* We have the user's information, now let's check if their account - has expired (60 * 60 * 24 = number of seconds in a day) */ - - if (off(UNIX__IAMROOT, ctrl)) { - /* Get the current number of days since 1970 */ - curdays = time(NULL) / (60 * 60 * 24); - if ((curdays < (spwdent->sp_lstchg + spwdent->sp_min)) - && (spwdent->sp_min != -1)) - retval = PAM_AUTHTOK_ERR; - else if ((curdays > (spwdent->sp_lstchg + spwdent->sp_max + spwdent->sp_inact)) - && (spwdent->sp_max != -1) && (spwdent->sp_inact != -1) - && (spwdent->sp_lstchg != 0)) - /* - * Their password change has been put off too long, - */ - retval = PAM_ACCT_EXPIRED; - else if ((curdays > spwdent->sp_expire) && (spwdent->sp_expire != -1) - && (spwdent->sp_lstchg != 0)) - /* - * OR their account has just plain expired - */ - retval = PAM_ACCT_EXPIRED; - } - } - return retval; -} - -static int _pam_unix_approve_pass(pam_handle_t * pamh - ,unsigned int ctrl - ,const char *pass_old - ,const char *pass_new) -{ - const char *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)) { - _log_err(LOG_DEBUG, pamh, "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, (const void **) &user); - if (retval != PAM_SUCCESS) { - if (on(UNIX_DEBUG, ctrl)) { - _log_err(LOG_ERR, pamh, "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(("lenth check [%s]", remark)); -#endif - if (on(UNIX_REMEMBER_PASSWD, ctrl)) - if ((retval = check_old_password(user, pass_new)) != PAM_SUCCESS) - remark = "Password has been already used. Choose another."; - } - 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, i; - int remember = -1; - - /* */ - const char *user; - char *pass_old, *pass_new; - /* */ - - D(("called.")); - -#ifdef USE_LCKPWDF - /* our current locking system requires that we lock the - entire password database. This avoids both livelock - and deadlock. */ - /* 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. - The other possibility is to call lckpwdf() on the first - pam_chauthtok() pass, and hold the lock until released in the - second pass--but is this guaranteed to work? -SRL */ - i=0; - while((retval = lckpwdf()) != 0 && i < 100) { - usleep(1000); - } - if(retval != 0) { - return PAM_AUTHTOK_LOCK_BUSY; - } -#endif - ctrl = _set_ctrl(pamh, flags, &remember, argc, argv); - - /* - * First get the name of a user - */ - retval = pam_get_user(pamh, &user, "Username: "); - 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 take - * any chances here. Require that the username starts with an - * alphanumeric character. - */ - if (user == NULL || !isalnum(*user)) { - _log_err(LOG_ERR, pamh, "bad username [%s]", user); -#ifdef USE_LCKPWDF - ulckpwdf(); -#endif - return PAM_USER_UNKNOWN; - } - if (retval == PAM_SUCCESS && on(UNIX_DEBUG, ctrl)) - _log_err(LOG_DEBUG, pamh, "username [%s] obtained", - user); - } else { - if (on(UNIX_DEBUG, ctrl)) - _log_err(LOG_DEBUG, pamh, - "password - could not identify user"); -#ifdef USE_LCKPWDF - ulckpwdf(); -#endif - return retval; - } - - D(("Got username of %s", user)); - - /* - * 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(ctrl, user)) { -#ifdef USE_LCKPWDF - ulckpwdf(); -#endif - return PAM_SUCCESS; - } else if (off(UNIX__IAMROOT, ctrl)) { - - /* instruct user what is happening */ -#define greeting "Changing password for " - Announce = (char *) malloc(sizeof(greeting) + strlen(user)); - if (Announce == NULL) { - _log_err(LOG_CRIT, pamh, - "password - out of memory"); -#ifdef USE_LCKPWDF - ulckpwdf(); -#endif - return PAM_BUF_ERR; - } - (void) strcpy(Announce, greeting); - (void) strcpy(Announce + sizeof(greeting) - 1, user); -#undef greeting - - lctrl = ctrl; - set(UNIX__OLD_PASSWD, lctrl); - retval = _unix_read_password(pamh, lctrl - ,Announce - ,"(current) UNIX password: " - ,NULL - ,_UNIX_OLD_AUTHTOK - ,(const char **) &pass_old); - free(Announce); - - if (retval != PAM_SUCCESS) { - _log_err(LOG_NOTICE, pamh - ,"password - (old) token not obtained"); -#ifdef USE_LCKPWDF - ulckpwdf(); -#endif - 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; -#ifdef USE_LCKPWDF - ulckpwdf(); -#endif - return retval; - } - retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old); - pass_old = NULL; - if (retval != PAM_SUCCESS) { - _log_err(LOG_CRIT, pamh, - "failed to set PAM_OLDAUTHTOK"); - } - retval = _unix_verify_shadow(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 - ,(const void **) &pass_old); - } else { - retval = pam_get_data(pamh, _UNIX_OLD_AUTHTOK - ,(const void **) &pass_old); - if (retval == PAM_NO_MODULE_DATA) { - retval = PAM_SUCCESS; - pass_old = NULL; - } - } - D(("pass_old [%s]", pass_old)); - - if (retval != PAM_SUCCESS) { - _log_err(LOG_NOTICE, pamh, "user not authenticated"); -#ifdef USE_LCKPWDF - ulckpwdf(); -#endif - return retval; - } - retval = _unix_verify_shadow(user, ctrl); - if (retval != PAM_SUCCESS) { - _log_err(LOG_NOTICE, pamh, "user not authenticated 2"); -#ifdef USE_LCKPWDF - ulckpwdf(); -#endif - 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 - ,(const char **) &pass_new); - - if (retval != PAM_SUCCESS) { - if (on(UNIX_DEBUG, ctrl)) { - _log_err(LOG_ALERT, pamh - ,"password - new password not obtained"); - } - pass_old = NULL; /* tidy up */ -#ifdef USE_LCKPWDF - ulckpwdf(); -#endif - 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 (pass_new[0] == '\0') { /* "\0" password = NULL */ - pass_new = NULL; - } - retval = _pam_unix_approve_pass(pamh, ctrl, pass_old, pass_new); - } - - if (retval != PAM_SUCCESS) { - _log_err(LOG_NOTICE, pamh, - "new password not acceptable"); - pass_new = pass_old = NULL; /* tidy up */ -#ifdef USE_LCKPWDF - ulckpwdf(); -#endif - return retval; - } - /* - * By reaching here we have approved the passwords and must now - * rebuild the password database file. - */ - - /* - * First we encrypt the new password. - */ - - if (on(UNIX_MD5_PASS, ctrl)) { - tpass = crypt_md5_wrapper(pass_new); - } else { - /* - * Salt manipulation is stolen from Rick Faith's passwd - * program. Sorry Rick :) -- alex - */ - - time_t tm; - char salt[3]; - - time(&tm); - salt[0] = bin_to_ascii(tm & 0x3f); - salt[1] = bin_to_ascii((tm >> 6) & 0x3f); - salt[2] = '\0'; - - if (off(UNIX_BIGCRYPT, ctrl) && strlen(pass_new) > 8) { - /* - * to avoid using the _extensions_ of the bigcrypt() - * function we truncate the newly entered password - * [Problems that followed from this are fixed as per - * Bug 521314.] - */ - char *temp = malloc(9); - - if (temp == NULL) { - _log_err(LOG_CRIT, pamh, - "out of memory for password"); - pass_new = pass_old = NULL; /* tidy up */ -#ifdef USE_LCKPWDF - ulckpwdf(); -#endif - return PAM_BUF_ERR; - } - /* copy first 8 bytes of password */ - strncpy(temp, pass_new, 8); - temp[8] = '\0'; - - /* no longer need cleartext */ - tpass = bigcrypt(temp, salt); - - _pam_delete(temp); /* tidy up */ - } else { - tpass = bigcrypt(pass_new, salt); - } - } - - D(("password processed")); - - /* update the password database(s) -- race conditions..? */ - - retval = _do_setpass(pamh, user, pass_old, tpass, ctrl, - remember); - _pam_delete(tpass); - pass_old = pass_new = NULL; - } else { /* something has broken with the module */ - _log_err(LOG_ALERT, pamh, - "password received unknown request"); - retval = PAM_ABORT; - } - - D(("retval was %d", retval)); - -#ifdef USE_LCKPWDF - ulckpwdf(); -#endif - 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 faef3e42..00000000 --- a/modules/pam_unix/pam_unix_sess.c +++ /dev/null @@ -1,141 +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 - -#include -#include -#include -#include -#include -#include -#include -#include - -/* indicate the following groups are defined */ - -#define PAM_SM_SESSION - -#include -#include - -#ifndef LINUX_PAM -#include -#endif /* LINUX_PAM */ - -#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; - - D(("called.")); - - ctrl = _set_ctrl(pamh, flags, NULL, argc, argv); - - retval = pam_get_item(pamh, PAM_USER, (void *) &user_name); - if (user_name == NULL || retval != PAM_SUCCESS) { - _log_err(LOG_CRIT, pamh, - "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 || retval != PAM_SUCCESS) { - _log_err(LOG_CRIT, pamh, - "open_session - error recovering service"); - return PAM_SESSION_ERR; - } - _log_err(LOG_INFO, pamh, "session opened for user %s by %s(uid=%d)" - ,user_name - ,PAM_getlogin() == NULL ? "" : PAM_getlogin(), 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, argc, argv); - - retval = pam_get_item(pamh, PAM_USER, (void *) &user_name); - if (user_name == NULL || retval != PAM_SUCCESS) { - _log_err(LOG_CRIT, pamh, - "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 || retval != PAM_SUCCESS) { - _log_err(LOG_CRIT, pamh, - "close_session - error recovering service"); - return PAM_SESSION_ERR; - } - _log_err(LOG_INFO, pamh, "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/support.c b/modules/pam_unix/support.c deleted file mode 100644 index 5998c7db..00000000 --- a/modules/pam_unix/support.c +++ /dev/null @@ -1,923 +0,0 @@ -/* - * $Id$ - * - * Copyright information at end of file. - */ - -#define _BSD_SOURCE - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "md5.h" -#include "support.h" - -extern char *crypt(const char *key, const char *salt); -extern char *bigcrypt(const char *key, const char *salt); - -/* syslogging function for errors and other information */ - -void _log_err(int err, pam_handle_t *pamh, const char *format,...) -{ - char *service = NULL; - char logname[256]; - va_list args; - - pam_get_item(pamh, PAM_SERVICE, (const void **) &service); - if (service) { - strncpy(logname, service, sizeof(logname)); - logname[sizeof(logname) - 1 - strlen("(pam_unix)")] = '\0'; - strncat(logname, "(pam_unix)", strlen("(pam_unix)")); - } else { - strncpy(logname, "pam_unix", sizeof(logname) - 1); - } - - va_start(args, format); - openlog(logname, LOG_CONS | LOG_PID, LOG_AUTH); - vsyslog(err, format, args); - va_end(args); - closelog(); -} - -/* this is a front-end for module-application conversations */ - -static int converse(pam_handle_t * pamh, int ctrl, int nargs - ,struct pam_message **message - ,struct pam_response **response) -{ - int retval; - struct pam_conv *conv; - - D(("begin to converse")); - - retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv); - if (retval == PAM_SUCCESS) { - - retval = conv->conv(nargs, (const struct pam_message **) message - ,response, conv->appdata_ptr); - - D(("returned from application's conversation function")); - - if (retval != PAM_SUCCESS && on(UNIX_DEBUG, ctrl)) { - _log_err(LOG_DEBUG, pamh, "conversation failure [%s]" - ,pam_strerror(pamh, retval)); - } - } else if (retval != PAM_CONV_AGAIN) { - _log_err(LOG_ERR, pamh - ,"couldn't obtain coversation function [%s]" - ,pam_strerror(pamh, retval)); - } - D(("ready to return from module conversation")); - - return retval; /* propagate error status */ -} - -int _make_remark(pam_handle_t * pamh, unsigned int ctrl - ,int type, const char *text) -{ - int retval = PAM_SUCCESS; - - if (off(UNIX__QUIET, ctrl)) { - struct pam_message *pmsg[1], msg[1]; - struct pam_response *resp; - - pmsg[0] = &msg[0]; - msg[0].msg = text; - msg[0].msg_style = type; - - resp = NULL; - retval = converse(pamh, ctrl, 1, pmsg, &resp); - - if (resp) { - _pam_drop_reply(resp, 1); - } - } - return retval; -} - - /* - * Beacause getlogin() is braindead and sometimes it just - * doesn't work, we reimplement it here. - */ -char *PAM_getlogin(void) -{ - struct utmp *ut, line; - char *curr_tty, *retval; - static char curr_user[sizeof(ut->ut_user) + 4]; - - retval = NULL; - - curr_tty = ttyname(0); - if (curr_tty != NULL) { - D(("PAM_getlogin ttyname: %s", curr_tty)); - curr_tty += 5; - setutent(); - strncpy(line.ut_line, curr_tty, sizeof(line.ut_line)); - if ((ut = getutline(&line)) != NULL) { - strncpy(curr_user, ut->ut_user, sizeof(ut->ut_user)); - curr_user[sizeof(curr_user) - 1] = '\0'; - retval = curr_user; - } - endutent(); - } - D(("PAM_getlogin retval: %s", retval)); - - return retval; -} - -/* - * set the control flags for the UNIX module. - */ - -int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, 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_DISALLOW_NULL_AUTHTOK) { - D(("DISALLOW_NULL_AUTHTOK")); - set(UNIX__NONULL, 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_) { - _log_err(LOG_ERR, pamh, - "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 == LONG_MIN) || (*remember == LONG_MAX)) - *remember = -1; - if (*remember > 400) - *remember = 400; - } - } - } - - ++argv; /* step to next argument */ - } - - /* 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, void *x, int error_status) -{ - _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 char *service = NULL; - const char *ruser = NULL; - const char *rhost = NULL; - const char *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, - (const void **)&service); - (void) pam_get_item(pamh, PAM_RUSER, - (const void **)&ruser); - (void) pam_get_item(pamh, PAM_RHOST, - (const void **)&rhost); - (void) pam_get_item(pamh, PAM_TTY, - (const void **)&tty); - _log_err(LOG_NOTICE, pamh, - "%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 ? tty : "", ruser ? ruser : "", - rhost ? rhost : "", - (failure->user && failure->user[0] != '\0') - ? " user=" : "", failure->user - ); - - if (failure->count > UNIX_MAX_RETRIES) { - _log_err(LOG_ALERT, pamh - ,"service(%s) ignoring max retries; %d > %d" - ,service == NULL ? "**unknown**" : service - ,failure->count - ,UNIX_MAX_RETRIES); - } - } - } - _pam_delete(failure->user); /* tidy up */ - _pam_delete(failure->name); /* tidy up */ - free(failure); - } -} - -/* - * _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(unsigned int ctrl, const char *name) -{ - struct passwd *pwd = NULL; - struct spwd *spwdent = NULL; - char *salt = NULL; - int retval; -#if HAVE_GETPWNAM_R - char *buf = NULL; - int bufsize = 0; - struct passwd pwd_buf; - - pwd = &pwd_buf; -#endif - - 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 */ - - /* Get password file entry... */ -#if HAVE_GETPWNAM_R - bufsize = 1024; - buf = malloc(bufsize); - - if ((retval = getpwnam_r(name, pwd, buf, bufsize, &pwd))) { - pwd = NULL; - } - while (retval == ERANGE) { - bufsize += 1024; - buf = realloc(buf, bufsize); - if ((retval = getpwnam_r(name, pwd, buf, bufsize, &pwd))) { - pwd = NULL; - } - } -#else - pwd = getpwnam(name); -#endif - - if (pwd != NULL) { - if (strcmp( pwd->pw_passwd, "*NP*" ) == 0) - { /* NIS+ */ - 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) - /* Will fail elsewhere. */ -#if HAVE_GETPWNAM_R - if (buf) - free(buf); -#endif - return 0; - } - } - - spwdent = getspnam( name ); - if (save_uid == pwd->pw_uid) - setreuid( save_uid, save_euid ); - else { - if (setreuid( -1, 0 ) == -1) - setreuid( save_uid, -1 ); - setreuid( -1, save_euid ); - } - } else if (strcmp(pwd->pw_passwd, "x") == 0) { - /* - * ...and shadow password file entry for this user, - * if shadowing is enabled - */ - spwdent = getspnam(name); - } - if (spwdent) - salt = x_strdup(spwdent->sp_pwdp); - else - salt = x_strdup(pwd->pw_passwd); - } - /* 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); - -#if HAVE_GETPWNAM_R - if (buf) - free(buf); -#endif - - return retval; -} - -/* - * verify the password of a user - */ - -#include -#include - -static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd, - unsigned int ctrl, const char *user) -{ - int retval, child, fds[2]; - - D(("called.")); - /* create a pipe for the password */ - if (pipe(fds) != 0) { - D(("could not make pipe")); - return PAM_AUTH_ERR; - } - - /* fork */ - child = fork(); - if (child == 0) { - static char *envp[] = { NULL }; - char *args[] = { NULL, NULL, NULL }; - - /* XXX - should really tidy up PAM here too */ - - /* reopen stdin as pipe */ - close(fds[1]); - dup2(fds[0], STDIN_FILENO); - - /* exec binary helper */ - args[0] = x_strdup(CHKPWD_HELPER); - args[1] = x_strdup(user); - - 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 */ - if (off(UNIX__NONULL, ctrl)) { /* this means we've succeeded */ - write(fds[1], "nullok\0\0", 8); - } else { - write(fds[1], "nonull\0\0", 8); - } - 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]); - (void) waitpid(child, &retval, 0); /* wait for helper to complete */ - retval = (retval == 0) ? PAM_SUCCESS:PAM_AUTH_ERR; - } else { - D(("fork failed")); - retval = PAM_AUTH_ERR; - } - - D(("returning %d", retval)); - return retval; -} - -int _unix_verify_password(pam_handle_t * pamh, const char *name - ,const char *p, unsigned int ctrl) -{ - struct passwd *pwd = NULL; - struct spwd *spwdent = NULL; - char *salt = NULL; - char *pp = 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")); - - /* UNIX passwords area */ - pwd = getpwnam(name); /* Get password file entry... */ - - if (pwd != NULL) { - if (strcmp( pwd->pw_passwd, "*NP*" ) == 0) - { /* NIS+ */ - 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 = getspnam( name ); - if (save_uid == pwd->pw_uid) - setreuid( save_uid, save_euid ); - else { - if (setreuid( -1, 0 ) == -1) - setreuid( save_uid, -1 ); - setreuid( -1, save_euid ); - } - } else if (strcmp(pwd->pw_passwd, "x") == 0) { - /* - * ...and shadow password file entry for this user, - * if shadowing is enabled - */ - spwdent = getspnam(name); - } - if (spwdent) - salt = x_strdup(spwdent->sp_pwdp); - else - salt = x_strdup(pwd->pw_passwd); - } - - data_name = (char *) malloc(sizeof(FAIL_PREFIX) + strlen(name)); - if (data_name == NULL) { - _log_err(LOG_CRIT, pamh, "no memory for data-name"); - } else { - strcpy(data_name, FAIL_PREFIX); - strcpy(data_name + sizeof(FAIL_PREFIX) - 1, name); - } - - retval = PAM_SUCCESS; - if (pwd == NULL || salt == NULL || !strcmp(salt, "x")) { - if (geteuid()) { - /* we are not root perhaps this is the reason? Run helper */ - D(("running helper binary")); - retval = _unix_run_helper_binary(pamh, p, ctrl, name); - if (pwd == NULL && !on(UNIX_AUDIT,ctrl) - && retval != PAM_SUCCESS) - { - name = NULL; - } - } else { - D(("user's record unavailable")); - if (on(UNIX_AUDIT, ctrl)) { - /* this might be a typo and the user has given a password - instead of a username. Careful with this. */ - _log_err(LOG_ALERT, pamh, - "check pass; user (%s) unknown", name); - } else { - name = NULL; - _log_err(LOG_ALERT, pamh, - "check pass; user unknown"); - } - p = NULL; - retval = PAM_AUTHINFO_UNAVAIL; - } - } else { - if (!strlen(salt)) { - /* the stored password is NULL */ - if (off(UNIX__NONULL, ctrl)) { /* 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) { - retval = PAM_AUTH_ERR; - } else { - if (!strncmp(salt, "$1$", 3)) { - pp = Goodcrypt_md5(p, salt); - if (strcmp(pp, salt) != 0) { - _pam_delete(pp); - pp = Brokencrypt_md5(p, salt); - } - } else { - pp = bigcrypt(p, salt); - } - 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)); - - /* - * Note, we are comparing the bigcrypt of the password with - * the contents of the password field. If the latter was - * encrypted with regular crypt (and not bigcrypt) it will - * have been truncated for storage relative to the output - * of bigcrypt here. As such we need to compare only the - * stored string with the subset of bigcrypt's result. - * Bug 521314: The strncmp comparison is for legacy support. - */ - if (strncmp(pp, salt, strlen(salt)) == 0) { - retval = PAM_SUCCESS; - } else { - retval = PAM_AUTH_ERR; - } - } - } - - 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) { - - new->user = x_strdup(name ? name : ""); - new->uid = getuid(); - new->euid = geteuid(); - new->name = x_strdup(PAM_getlogin()? PAM_getlogin() : ""); - - /* any previous failures for this user ? */ - pam_get_data(pamh, data_name, (const void **) &old); - - if (old != NULL) { - new->count = old->count + 1; - if (new->count >= UNIX_MAX_RETRIES) { - retval = PAM_MAXTRIES; - } - } else { - const char *service=NULL; - const char *ruser=NULL; - const char *rhost=NULL; - const char *tty=NULL; - - (void) pam_get_item(pamh, PAM_SERVICE, - (const void **)&service); - (void) pam_get_item(pamh, PAM_RUSER, - (const void **)&ruser); - (void) pam_get_item(pamh, PAM_RHOST, - (const void **)&rhost); - (void) pam_get_item(pamh, PAM_TTY, - (const void **)&tty); - - _log_err(LOG_NOTICE, pamh, - "authentication failure; " - "logname=%s uid=%d euid=%d " - "tty=%s ruser=%s rhost=%s " - "%s%s", - new->name, new->uid, new->euid, - tty ? tty : "", - ruser ? ruser : "", - rhost ? rhost : "", - (new->user && new->user[0] != '\0') - ? " user=" : "", - new->user - ); - new->count = 1; - } - - pam_set_data(pamh, data_name, new, _cleanup_failures); - - } else { - _log_err(LOG_CRIT, pamh, - "no memory for failure recorder"); - } - } - } - - if (data_name) - _pam_delete(data_name); - if (salt) - _pam_delete(salt); - if (pp) - _pam_delete(pp); - - 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 char **pass) -{ - int authtok_flag; - int retval; - 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, (const void **) pass); - if (retval != PAM_SUCCESS) { - /* very strange. */ - _log_err(LOG_ALERT, pamh - ,"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_RECOVER_ERR; /* didn't work */ - } else if (on(UNIX_USE_AUTHTOK, ctrl) - && off(UNIX__OLD_PASSWD, ctrl)) { - return PAM_AUTHTOK_RECOVER_ERR; - } - } - /* - * getting here implies we will have to get the password from the - * user directly. - */ - - { - struct pam_message msg[3], *pmsg[3]; - struct pam_response *resp; - int i, replies; - - /* prepare to converse */ - - if (comment != NULL && off(UNIX__QUIET, ctrl)) { - pmsg[0] = &msg[0]; - msg[0].msg_style = PAM_TEXT_INFO; - msg[0].msg = comment; - i = 1; - } else { - i = 0; - } - - pmsg[i] = &msg[i]; - msg[i].msg_style = PAM_PROMPT_ECHO_OFF; - msg[i++].msg = prompt1; - replies = 1; - - if (prompt2 != NULL) { - pmsg[i] = &msg[i]; - msg[i].msg_style = PAM_PROMPT_ECHO_OFF; - msg[i++].msg = prompt2; - ++replies; - } - /* so call the conversation expecting i responses */ - resp = NULL; - retval = converse(pamh, ctrl, i, pmsg, &resp); - - if (resp != NULL) { - - /* interpret the response */ - - if (retval == PAM_SUCCESS) { /* a good conversation */ - - token = x_strdup(resp[i - replies].resp); - if (token != NULL) { - if (replies == 2) { - - /* verify that password entered correctly */ - if (!resp[i - 1].resp - || strcmp(token, resp[i - 1].resp)) { - _pam_delete(token); /* mistyped */ - retval = PAM_AUTHTOK_RECOVER_ERR; - _make_remark(pamh, ctrl - ,PAM_ERROR_MSG, MISTYPED_PASS); - } - } - } else { - _log_err(LOG_NOTICE, pamh - ,"could not recover authentication token"); - } - - } - /* - * tidy up the conversation (resp_retcode) is ignored - * -- what is it for anyway? AGM - */ - - _pam_drop_reply(resp, i); - - } else { - retval = (retval == PAM_SUCCESS) - ? PAM_AUTHTOK_RECOVER_ERR : retval; - } - } - - if (retval != PAM_SUCCESS) { - if (on(UNIX_DEBUG, ctrl)) - _log_err(LOG_DEBUG, pamh, - "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 - ,(const void **) pass)) - != PAM_SUCCESS) { - - *pass = NULL; - _log_err(LOG_CRIT, pamh, "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) { - _log_err(LOG_CRIT, pamh - ,"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. - * - * 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 0b6b6e04..00000000 --- a/modules/pam_unix/support.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * $Id$ - */ - -#ifndef _PAM_UNIX_SUPPORT_H -#define _PAM_UNIX_SUPPORT_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_CTRLS_ 21 /* 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_^(010000), 0200000}, -/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(020000), 0400000}, -/* UNIX_LIKE_AUTH */ {"likeauth", _ALL_ON_, 01000000}, -/* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 02000000}, -}; - -#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 char *PAM_getlogin(void); -extern void _log_err(int err, pam_handle_t *pamh, const char *format,...); -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 argc, - const char **argv); -extern int _unix_blankpasswd(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 char **pass); - -#endif /* _PAM_UNIX_SUPPORT_H */ - diff --git a/modules/pam_unix/unix_chkpwd.c b/modules/pam_unix/unix_chkpwd.c deleted file mode 100644 index 9ba11041..00000000 --- a/modules/pam_unix/unix_chkpwd.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * $Id$ - * - * 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 - -#ifdef MEMORY_DEBUG -# undef exit -# undef strdup -# undef free -#endif /* MEMORY_DEBUG */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAXPASS 200 /* the maximum length of a password */ - -#include - -#include "md5.h" - -extern char *crypt(const char *key, const char *salt); -extern char *bigcrypt(const char *key, const char *salt); - -#define UNIX_PASSED 0 -#define UNIX_FAILED 1 - -/* syslogging function for errors and other information */ - -static void _log_err(int err, const char *format,...) -{ - va_list args; - - va_start(args, format); - openlog("unix_chkpwd", LOG_CONS | LOG_PID, LOG_AUTH); - vsyslog(err, format, args); - va_end(args); - closelog(); -} - -static void su_sighandler(int sig) -{ - if (sig > 0) { - _log_err(LOG_NOTICE, "caught signal %d.", sig); - exit(sig); - } -} - -static 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; - action.sa_flags = SA_RESETHAND; - (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); -} - -static int _unix_verify_password(const char *name, const char *p, int opt) -{ - struct passwd *pwd = NULL; - struct spwd *spwdent = NULL; - char *salt = NULL; - char *pp = NULL; - int retval = UNIX_FAILED; - - /* UNIX passwords area */ - setpwent(); - pwd = getpwnam(name); /* Get password file entry... */ - endpwent(); - if (pwd != NULL) { - if (strcmp(pwd->pw_passwd, "x") == 0) { - /* - * ...and shadow password file entry for this user, - * if shadowing is enabled - */ - setspent(); - spwdent = getspnam(name); - endspent(); - if (spwdent != NULL) - salt = x_strdup(spwdent->sp_pwdp); - else - pwd = NULL; - } else { - if (strcmp(pwd->pw_passwd, "*NP*") == 0) { /* NIS+ */ - uid_t save_uid; - - save_uid = geteuid(); - seteuid(pwd->pw_uid); - spwdent = getspnam(name); - seteuid(save_uid); - - salt = x_strdup(spwdent->sp_pwdp); - } else { - salt = x_strdup(pwd->pw_passwd); - } - } - } - if (pwd == NULL || salt == NULL) { - _log_err(LOG_ALERT, "check pass; user unknown"); - p = NULL; - return retval; - } - - if (strlen(salt) == 0) - return (opt == 0) ? UNIX_FAILED : UNIX_PASSED; - - /* the moment of truth -- do we agree with the password? */ - retval = UNIX_FAILED; - if (!strncmp(salt, "$1$", 3)) { - pp = Goodcrypt_md5(p, salt); - if (strcmp(pp, salt) == 0) { - retval = UNIX_PASSED; - } else { - pp = Brokencrypt_md5(p, salt); - if (strcmp(pp, salt) == 0) - retval = UNIX_PASSED; - } - } else { - pp = bigcrypt(p, salt); - /* - * Note, we are comparing the bigcrypt of the password with - * the contents of the password field. If the latter was - * encrypted with regular crypt (and not bigcrypt) it will - * have been truncated for storage relative to the output - * of bigcrypt here. As such we need to compare only the - * stored string with the subset of bigcrypt's result. - * Bug 521314: the strncmp comparison is for legacy support. - */ - if (strncmp(pp, salt, strlen(salt)) == 0) { - retval = UNIX_PASSED; - } - } - p = NULL; /* no longer needed here */ - - /* clean up */ - { - char *tp = pp; - if (pp != NULL) { - while (tp && *tp) - *tp++ = '\0'; - free(pp); - } - pp = tp = NULL; - } - - return retval; -} - -static char *getuidname(uid_t uid) -{ - struct passwd *pw; - static char username[32]; - - pw = getpwuid(uid); - if (pw == NULL) - return NULL; - - strncpy(username, pw->pw_name, sizeof(username)); - username[sizeof(username) - 1] = '\0'; - - return username; -} - -int main(int argc, char *argv[]) -{ - char pass[MAXPASS + 1]; - char option[8]; - int npass, opt; - int force_failure = 0; - int retval = UNIX_FAILED; - char *user; - - /* - * 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)) { - - _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 UNIX_FAILED; - } - - /* - * determine the current user's name is - */ - user = getuidname(getuid()); - if (argc == 2) { - /* if the caller specifies the username, verify that user - matches it */ - if (strcmp(user, argv[1])) { - force_failure = 1; - } - } - - /* read the nullok/nonull option */ - - npass = read(STDIN_FILENO, option, 8); - - if (npass < 0) { - _log_err(LOG_DEBUG, "no option supplied"); - return UNIX_FAILED; - } else { - option[7] = '\0'; - if (strncmp(option, "nullok", 8) == 0) - opt = 1; - else - opt = 0; - } - - /* read the password from stdin (a pipe from the pam_unix module) */ - - npass = read(STDIN_FILENO, pass, MAXPASS); - - if (npass < 0) { /* is it a valid password? */ - - _log_err(LOG_DEBUG, "no password supplied"); - - } else if (npass >= MAXPASS) { - - _log_err(LOG_DEBUG, "password too long"); - - } else { - if (npass == 0) { - /* the password is NULL */ - - retval = _unix_verify_password(user, NULL, opt); - - } else { - /* does pass agree with the official one? */ - - pass[npass] = '\0'; /* NUL terminate */ - retval = _unix_verify_password(user, pass, opt); - - } - } - - memset(pass, '\0', MAXPASS); /* clear memory of the password */ - - /* return pass or fail */ - - if ((retval != UNIX_PASSED) || force_failure) { - return UNIX_FAILED; - } else { - return UNIX_PASSED; - } -} - -/* - * Copyright (c) Andrew G. Morgan, 1996. 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, - * - * 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 . - */ -#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 -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 b1a60b4c..00000000 --- a/modules/pam_unix/yppasswd_xdr.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * yppasswdd - * Copyright 1994, 1995, 1996 Olaf Kirch, - * - * 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 - -#include -#include -#include -#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); -} -- cgit v1.2.3