--- proftpd-1.3.3e/include/auth.h	Tue Sep  8 22:34:03 2009
+++ proftpd-1.3.3e-pam/include/auth.h	Tue May 24 10:37:40 2011
@@ -59,6 +59,35 @@
 /* Account has been disabled */
 #define PR_AUTH_DISABLEDPWD		-5
 
+/* Insufficient credentials */
+#define PR_AUTH_CRED_INSUFF		-6
+
+/* Unavailable user credentials */
+#define PR_AUTH_CRED_UNAVAIL		-7
+
+/* Failure setting user credentials */
+#define PR_AUTH_CRED_ERR		-8
+
+/* Unavailable authentication service */
+#define PR_AUTH_UNAVAIL			-9
+
+/* Max retries reached */
+#define PR_AUTH_MAXTRIES		-10
+
+/* Initialization of authentization failed */
+#define PR_AUTH_INIT_FAIL		-11
+
+/* New auth token needed */
+#define PR_AUTH_NEWTOK			-12
+
+#define PR_AUTH_OPEN_ERR		-15
+#define PR_AUTH_SYMBOL_ERR		-16
+#define PR_AUTH_SERVICE_ERR		-17
+#define PR_AUTH_SYSTEM_ERR		-18
+#define PR_AUTH_BUF_ERR			-19
+#define PR_AUTH_CONV_ERR		-20
+#define PR_AUTH_PERM_DENIED		-21
+
 void pr_auth_setpwent(pool *);
 void pr_auth_endpwent(pool *);
 void pr_auth_setgrent(pool *);
--- proftpd-1.3.3e/modules/mod_auth.c	Mon Feb 21 03:36:38 2011
+++ proftpd-1.3.3e-pam/modules/mod_auth.c	Tue May 24 11:32:55 2011
@@ -898,6 +898,44 @@
           user);
         goto auth_failure;
 
+      case PR_AUTH_CRED_INSUFF:
+        pr_log_auth(PR_LOG_NOTICE,
+          "USER %s (Login failed): Insufficient credentials.", origuser);
+        goto auth_failure;
+
+      case PR_AUTH_CRED_UNAVAIL:
+        pr_log_auth(PR_LOG_NOTICE, 
+          "USER %s (Login failed): Unavailable credentials.", origuser);
+        goto auth_failure;
+
+
+      case PR_AUTH_CRED_ERR:
+        pr_log_auth(PR_LOG_NOTICE, 
+          "USER %s (Login failed): Failure setting user credentials.",
+          origuser);
+        goto auth_failure;
+
+      case PR_AUTH_UNAVAIL:
+        pr_log_auth(PR_LOG_NOTICE,
+          "USER %s (Login failed): Unavailable authentication service.", user);
+        goto auth_failure;
+
+      case PR_AUTH_MAXTRIES:
+        pr_log_auth(PR_LOG_NOTICE,
+          "USER %s (Login failed): Max retries reached.", user);
+        goto auth_failure;
+
+      case PR_AUTH_INIT_FAIL:
+        pr_log_auth(PR_LOG_NOTICE,
+          "USER %s (Login failed): Authentization initialization failed.",
+          origuser);
+        goto auth_failure;
+
+      case PR_AUTH_NEWTOK:
+        pr_log_auth(PR_LOG_NOTICE,
+          "USER %s (Login failed): New authentication token needed.", user);
+        goto auth_failure;
+
       default:
         break;
     };
--- proftpd-1.3.3e/modules/mod_auth_pam.c	Thu Mar  5 06:24:06 2009
+++ proftpd-1.3.3e-pam/modules/mod_auth_pam.c	Tue May 24 10:28:58 2011
@@ -349,6 +349,24 @@
 
   if (pam_error != PAM_SUCCESS) {
     switch (pam_error) {
+#ifdef PAM_CRED_INSUFFICIENT
+      case PAM_CRED_INSUFFICIENT:
+        retval = PR_AUTH_CRED_INSUFF;
+        break;
+#endif /* PAM_CRED_INSUFFICIENT */
+
+#ifdef PAM_AUTHINFO_UNAVAIL
+      case PAM_AUTHINFO_UNAVAIL:
+        retval = PR_AUTH_UNAVAIL;
+        break;
+#endif /* PAM_AUTHINFO_UNAVAIL */
+
+#ifdef PAM_MAXTRIES
+      case PAM_MAXTRIES:
+        retval = PR_AUTH_MAXTRIES;
+        break;
+#endif /* PAM_MAXTRIES */
+
       case PAM_USER_UNKNOWN:
         retval = PR_AUTH_NOPWD;
         break;
@@ -373,6 +391,14 @@
 
   if (pam_error != PAM_SUCCESS) {
     switch (pam_error) {
+#ifdef PAM_NEW_AUTHTOK_REQD
+      case PAM_NEW_AUTHTOK_REQD:
+        pr_trace_msg(trace_channel, 8,
+          "account mgmt error: PAM_NEW_AUTH_REQD");
+        retval = PR_AUTH_NEWTOK;
+        break;
+#endif /* PAM_NEW_AUTHTOK_REQD */
+
 #ifdef PAM_AUTHTOKEN_REQD
       case PAM_AUTHTOKEN_REQD:
         pr_trace_msg(trace_channel, 8,
@@ -417,7 +443,7 @@
     switch (pam_error) {
       case PAM_SESSION_ERR:
       default:
-        retval = PR_AUTH_DISABLEDPWD;
+        retval = PR_AUTH_INIT_FAIL;
         break;
     }
 
@@ -435,6 +461,20 @@
 
   if (pam_error != PAM_SUCCESS) {
     switch (pam_error) {
+#ifdef PAM_CRED_UNAVAIL
+      case PAM_CRED_UNAVAIL:
+        pr_trace_msg(trace_channel, 8, "credentials error: PAM_CRED_UNAVAIL");
+        retval = PR_AUTH_CRED_UNAVAIL;
+        break;
+#endif /* PAM_CRED_UNAVAIL */
+
+#ifdef PAM_CRED_ERR
+      case PAM_CRED_ERR:
+        pr_trace_msg(trace_channel, 8, "credentials error: PAM_CRED_ERR");
+        retval = PR_AUTH_CRED_ERR;
+        break;
+#endif /* PAM_CRED_ERR */
+
       case PAM_CRED_EXPIRED:
         pr_trace_msg(trace_channel, 8, "credentials error: PAM_CRED_EXPIRED");
         retval = PR_AUTH_AGEPWD;
