Be compatible with AIX-style shadowing, which uses "##<username>" as the
marker for shadowed accounts instead of "x".  (This includes preserving the
value of the field if it already signifies shadowing.)  Haven't got a box
handy to try this with, though it passes my tests.

diff -ur Linux-PAM-0.75/modules/pam_unix/pam_unix_acct.c Linux-PAM-0.75/modules/pam_unix/pam_unix_acct.c
--- Linux-PAM-0.75/modules/pam_unix/pam_unix_acct.c	Tue Apr  9 21:57:44 2002
+++ Linux-PAM-0.75/modules/pam_unix/pam_unix_acct.c	Tue Apr  9 22:03:36 2002
@@ -131,7 +131,7 @@
 			setreuid( -1, save_euid );
 		}
 
-	} else if (!strcmp( pwent->pw_passwd, "x" )) {
+	} else if (_unix_shadowed(pwent)) {
 		if(_pam_getspnam_r(uname, &spwd, &sbuf, &sbuflen, &spent) != 0)
 			spent = NULL;
 	} else {
diff -ur Linux-PAM-0.75/modules/pam_unix/pam_unix_passwd.c Linux-PAM-0.75/modules/pam_unix/pam_unix_passwd.c
--- Linux-PAM-0.75/modules/pam_unix/pam_unix_passwd.c	Tue Apr  9 21:57:44 2002
+++ Linux-PAM-0.75/modules/pam_unix/pam_unix_passwd.c	Tue Apr  9 22:07:51 2002
@@ -556,10 +556,11 @@
 		return PAM_AUTHTOK_ERR;
 	}
 	if (_unix_comesfromsource(forwho, 1, 0)) {
-		if (on(UNIX_SHADOW, ctrl)||(strcmp(pwd->pw_passwd, "x") == 0)) {
+		if (on(UNIX_SHADOW, ctrl)||(_unix_shadowed(pwd))) {
 			retval = _update_shadow(forwho, towhat);
 			if (retval == PAM_SUCCESS)
-				retval = _update_passwd(pamh, forwho, "x");
+				if (!_unix_shadowed(pwd))
+					retval = _update_passwd(pamh, forwho, "x");
 		} else {
 			retval = _update_passwd(pamh, forwho, towhat);
 		}
@@ -586,7 +588,7 @@
 	if (pwd == NULL)
 		return PAM_AUTHINFO_UNAVAIL;	/* We don't need to do the rest... */
 
-	if (strcmp(pwd->pw_passwd, "x") == 0) {
+	if (_unix_shadowed(pwd)) {
 		/* ...and shadow password file entry for this user, if shadowing
 		   is enabled */
 		if(_pam_getspnam_r(user, &spwd, &sbuf, &sbuflen, &spwdent) != 0)
@@ -792,7 +794,7 @@
 	} else {
 		struct passwd pwd;
 		_unix_getpwnam(user, 1, 1, &pwd);
-		if((strcmp(pwd.pw_passwd, "x") != 0) &&
+		if((!_unix_shadowed(&pwd)) &&
 		   (strchr(pwd.pw_passwd, '*') != NULL)) {
 			_log_err(LOG_DEBUG, pamh,
 				"user \"%s\" does not have modifiable password",
diff -ur Linux-PAM-0.75/modules/pam_unix/support.c Linux-PAM-0.75/modules/pam_unix/support.c
--- Linux-PAM-0.75/modules/pam_unix/support.c	Tue Apr  9 21:57:44 2002
+++ Linux-PAM-0.75/modules/pam_unix/support.c	Tue Apr  9 22:07:53 2002
@@ -477,7 +477,7 @@
 					setreuid( save_uid, -1 );
 				setreuid( -1, save_euid );
 			}
-		} else if (strcmp(pwd->pw_passwd, "x") == 0) {
+		} else if (_unix_shadowed(pwd)) {
 			/*
 			 * ...and shadow password file entry for this user,
 			 * if shadowing is enabled
@@ -651,7 +651,7 @@
 				setreuid( save_uid, -1 );
 				setreuid( -1, save_euid );
 			}
-		} else if (strcmp(pwd->pw_passwd, "x") == 0) {
+		} else if (_unix_shadowed(pwd)) {
 			/*
 			 * ...and shadow password file entry for this user,
 			 * if shadowing is enabled
@@ -674,7 +674,7 @@
 	}
 
 	retval = PAM_SUCCESS;
-	if (pwd == NULL || salt == NULL || !strcmp(salt, "x")) {
+	if (pwd == NULL || salt == NULL || !strcmp(salt, "x") || ((salt[0] == '#') && (salt[1] == '#') && !strcmp(salt + 2, name))) {
 		if (geteuid()) {
 			/* we are not root perhaps this is the reason? Run helper */
 			D(("running helper binary"));
@@ -1004,6 +1004,24 @@
 	return PAM_SUCCESS;
 }
 
+int _unix_shadowed(const struct passwd *pwd)
+{
+	char hashpass[1024];
+	if (pwd != NULL) {
+		if (strcmp(pwd->pw_passwd, "x") == 0) {
+			return 1;
+		}
+		if (strlen(pwd->pw_name) < sizeof(hashpass) - 2) {
+			strcpy(hashpass, "##");
+			strcpy(hashpass + 2, pwd->pw_name);
+			if (strcmp(pwd->pw_passwd, hashpass) == 0) {
+				return 1;
+			}
+		}
+	}
+	return 0;
+}
+
 /* ****************************************************************** *
  * Copyright (c) Jan Rêkorajski 1999.
  * Copyright (c) Andrew G. Morgan 1996-8.
diff -ur Linux-PAM-0.75/modules/pam_unix/support.h Linux-PAM-0.75/modules/pam_unix/support.h
--- Linux-PAM-0.75/modules/pam_unix/support.h	Tue Apr  9 21:57:44 2002
+++ Linux-PAM-0.75/modules/pam_unix/support.h	Tue Apr  9 22:01:17 2002
@@ -144,6 +144,7 @@
 			,const char *prompt2
 			,const char *data_name
 			,const char **pass);
+extern int _unix_shadowed(const struct passwd *pwd);
 
 #endif /* _PAM_UNIX_SUPPORT_H */
 
diff -ur Linux-PAM-0.75/modules/pam_unix/unix_chkpwd.c Linux-PAM-0.75/modules/pam_unix/unix_chkpwd.c
--- Linux-PAM-0.75/modules/pam_unix/unix_chkpwd.c	Tue Apr  9 21:57:44 2002
+++ Linux-PAM-0.75/modules/pam_unix/unix_chkpwd.c	Tue Apr  9 22:08:57 2002
@@ -54,6 +54,24 @@
 	closelog();
 }
 
+static int _unix_shadowed(const struct passwd *pwd)
+{
+	char hashpass[1024];
+	if (pwd != NULL) {
+		if (strcmp(pwd->pw_passwd, "x") == 0) {
+			return 1;
+		}
+		if (strlen(pwd->pw_name) < sizeof(hashpass) - 2) {
+			strcpy(hashpass, "##");
+			strcpy(hashpass + 2, pwd->pw_name);
+			if (strcmp(pwd->pw_passwd, hashpass) == 0) {
+				return 1;
+			}
+		}
+	}
+	return 0;
+}
+
 static void su_sighandler(int sig)
 {
 	if (sig > 0) {
@@ -98,7 +116,7 @@
 	if(_pam_getpwnam_r(name, &passwd, &ubuf, &ubuflen, &pwd) != 0)
 		pwd = NULL;
 	if (pwd != NULL) {
-		if (strcmp(pwd->pw_passwd, "x") == 0) {
+		if (_unix_shadowed(pwd)) {
 			/*
 			 * ...and shadow password file entry for this user,
 			 * if shadowing is enabled
