diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c
index 2799845..bc75e4e 100644
--- a/modules/pam_unix/pam_unix_acct.c
+++ b/modules/pam_unix/pam_unix_acct.c
@@ -235,6 +235,19 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
 	} else
 		retval = check_shadow_expiry(pamh, spent, &daysleft);
 
+	if (on(UNIX_NO_PASS_EXPIRY, ctrl)) {
+		const void *pretval = NULL;
+		int authrv = PAM_SUCCESS;
+
+		if (pam_get_data(pamh, "unix_setcred_return", &pretval) == PAM_SUCCESS
+			&& pretval)
+			authrv = *(const int *)pretval;
+
+		if (authrv != PAM_SUCCESS 
+			&& (retval == PAM_NEW_AUTHTOK_REQD || retval == PAM_AUTHTOK_EXPIRED))
+			retval = PAM_SUCCESS;
+	}
+
 	switch (retval) {
 	case PAM_ACCT_EXPIRED:
 		pam_syslog(pamh, LOG_NOTICE,
diff --git a/modules/pam_unix/pam_unix_auth.c b/modules/pam_unix/pam_unix_auth.c
index 44573e6..9a547b3 100644
--- a/modules/pam_unix/pam_unix_auth.c
+++ b/modules/pam_unix/pam_unix_auth.c
@@ -82,14 +82,13 @@
 
 #define AUTH_RETURN						\
 do {								\
-	if (on(UNIX_LIKE_AUTH, ctrl) && ret_data) {		\
+	if (ret_data) {						\
 		D(("recording return code for next time [%d]",	\
 					retval));		\
 		*ret_data = retval;				\
 		pam_set_data(pamh, "unix_setcred_return",	\
 		             (void *) ret_data, setcred_free);	\
-	} else if (ret_data)					\
-	  free (ret_data);                                      \
+	}							\
 	D(("done. [%s]", pam_strerror(pamh, retval)));		\
 	return retval;						\
 } while (0)
@@ -115,9 +114,8 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
 	ctrl = _set_ctrl(pamh, flags, NULL, NULL, NULL, argc, argv);
 
 	/* Get a few bytes so we can pass our return value to
-	   pam_sm_setcred(). */
-	if (on(UNIX_LIKE_AUTH, ctrl))
-		ret_data = malloc(sizeof(int));
+	   pam_sm_setcred() and pam_sm_acct_mgmt(). */
+	ret_data = malloc(sizeof(int));
 
 	/* get the user'name' */
 
@@ -194,20 +192,24 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
  */
 
 int
-pam_sm_setcred (pam_handle_t *pamh, int flags UNUSED,
-		int argc UNUSED, const char **argv UNUSED)
+pam_sm_setcred (pam_handle_t *pamh, int flags,
+		int argc, const char **argv)
 {
 	int retval;
 	const void *pretval = NULL;
+	unsigned int ctrl;
 
 	D(("called."));
 
+	ctrl = _set_ctrl(pamh, flags, NULL, NULL, NULL, argc, argv);
+
 	retval = PAM_SUCCESS;
 
 	D(("recovering return code from auth call"));
 	/* We will only find something here if UNIX_LIKE_AUTH is set --
 	   don't worry about an explicit check of argv. */
-	if (pam_get_data(pamh, "unix_setcred_return", &pretval) == PAM_SUCCESS
+	if (on(UNIX_LIKE_AUTH, ctrl)
+	    && pam_get_data(pamh, "unix_setcred_return", &pretval) == PAM_SUCCESS
 	    && pretval) {
 	        retval = *(const int *)pretval;
 		pam_set_data(pamh, "unix_setcred_return", NULL, NULL);
diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h
index 3729ce0..b767c26 100644
--- a/modules/pam_unix/support.h
+++ b/modules/pam_unix/support.h
@@ -98,9 +98,10 @@ typedef struct {
 #define UNIX_BLOWFISH_PASS       26	/* new password hashes will use blowfish */
 #define UNIX_MIN_PASS_LEN        27	/* min length for password */
 #define UNIX_QUIET		 28	/* Don't print informational messages */
-#define UNIX_DES                 29     /* DES, default */
+#define UNIX_NO_PASS_EXPIRY      29     /* Don't check for password expiration if not used for authentication */
+#define UNIX_DES                 30     /* DES, default */
 /* -------------- */
-#define UNIX_CTRLS_              30	/* number of ctrl arguments defined */
+#define UNIX_CTRLS_              31	/* number of ctrl arguments defined */
 
 #define UNIX_DES_CRYPT(ctrl)	(off(UNIX_MD5_PASS,ctrl)&&off(UNIX_BIGCRYPT,ctrl)&&off(UNIX_SHA256_PASS,ctrl)&&off(UNIX_SHA512_PASS,ctrl)&&off(UNIX_BLOWFISH_PASS,ctrl))
 
@@ -138,6 +139,7 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] =
 /* UNIX_BLOWFISH_PASS */   {"blowfish",    _ALL_ON_^(0260420000), 0200000000, 1},
 /* UNIX_MIN_PASS_LEN */    {"minlen=",		_ALL_ON_,         0400000000, 0},
 /* UNIX_QUIET */           {"quiet",           _ALL_ON_,         01000000000, 0},
+/* UNIX_NO_PASS_EXPIRY */  {"no_pass_expiry",  _ALL_ON_,         02000000000, 0},
 /* UNIX_DES */             {"des",             _ALL_ON_^(0260420000),      0, 1},
 };
 

