Blame SOURCES/pam-1.3.1-pam-userdb-prevent-garbage-characters-from-db.patch

5ed8a7
From a7453aeeb398d6cbb7a709c4e2a1d75905220fff Mon Sep 17 00:00:00 2001
5ed8a7
From: Stanislav Zidek <szidek@redhat.com>
5ed8a7
Date: Fri, 16 Apr 2021 19:14:18 +0200
5ed8a7
Subject: [PATCH] pam_userdb: Prevent garbage characters from db
5ed8a7
5ed8a7
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1791965
5ed8a7
---
5ed8a7
 modules/pam_userdb/pam_userdb.8.xml |  3 +-
5ed8a7
 modules/pam_userdb/pam_userdb.c     | 56 +++++++++++++++++------------
5ed8a7
 2 files changed, 36 insertions(+), 23 deletions(-)
5ed8a7
5ed8a7
diff --git a/modules/pam_userdb/pam_userdb.8.xml b/modules/pam_userdb/pam_userdb.8.xml
5ed8a7
index fa628ada..bce92850 100644
5ed8a7
--- a/modules/pam_userdb/pam_userdb.8.xml
5ed8a7
+++ b/modules/pam_userdb/pam_userdb.8.xml
5ed8a7
@@ -100,7 +100,8 @@
5ed8a7
         </term>
5ed8a7
         <listitem>
5ed8a7
           <para>
5ed8a7
-            Print debug information.
5ed8a7
+            Print debug information. Note that password hashes, both from db
5ed8a7
+            and computed, will be printed to syslog.
5ed8a7
           </para>
5ed8a7
         </listitem>
5ed8a7
       </varlistentry>
5ed8a7
diff --git a/modules/pam_userdb/pam_userdb.c b/modules/pam_userdb/pam_userdb.c
5ed8a7
index dc2ca232..d59801bf 100644
5ed8a7
--- a/modules/pam_userdb/pam_userdb.c
5ed8a7
+++ b/modules/pam_userdb/pam_userdb.c
5ed8a7
@@ -194,7 +194,7 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode,
5ed8a7
     }
5ed8a7
 
5ed8a7
     if (data.dptr != NULL) {
5ed8a7
-	int compare = 0;
5ed8a7
+	int compare = -2;
5ed8a7
 
5ed8a7
 	if (ctrl & PAM_KEY_ONLY_ARG)
5ed8a7
 	  {
5ed8a7
@@ -209,36 +209,48 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode,
5ed8a7
 	  char *cryptpw = NULL;
5ed8a7
 
5ed8a7
 	  if (data.dsize < 13) {
5ed8a7
-	    compare = -2;
5ed8a7
+	    /* hash is too short */
5ed8a7
+	    pam_syslog(pamh, LOG_INFO, "password hash in database is too short");
5ed8a7
 	  } else if (ctrl & PAM_ICASE_ARG) {
5ed8a7
-	    compare = -2;
5ed8a7
+	    pam_syslog(pamh, LOG_INFO,
5ed8a7
+	       "case-insensitive comparison only works with plaintext passwords");
5ed8a7
 	  } else {
5ed8a7
+	    /* libdb is not guaranteed to produce null terminated strings */
5ed8a7
+	    char *pwhash = strndup(data.dptr, data.dsize);
5ed8a7
+
5ed8a7
+	    if (pwhash == NULL) {
5ed8a7
+	      pam_syslog(pamh, LOG_CRIT, "strndup failed: data.dptr");
5ed8a7
+	    } else {
5ed8a7
 #ifdef HAVE_CRYPT_R
5ed8a7
-	    struct crypt_data *cdata = NULL;
5ed8a7
-	    cdata = malloc(sizeof(*cdata));
5ed8a7
-	    if (cdata != NULL) {
5ed8a7
-		cdata->initialized = 0;
5ed8a7
-		cryptpw = crypt_r(pass, data.dptr, cdata);
5ed8a7
-	    }
5ed8a7
+	      struct crypt_data *cdata = NULL;
5ed8a7
+	      cdata = malloc(sizeof(*cdata));
5ed8a7
+	      if (cdata == NULL) {
5ed8a7
+	        pam_syslog(pamh, LOG_CRIT, "malloc failed: struct crypt_data");
5ed8a7
+	      } else {
5ed8a7
+	        cdata->initialized = 0;
5ed8a7
+	        cryptpw = crypt_r(pass, pwhash, cdata);
5ed8a7
+	      }
5ed8a7
 #else
5ed8a7
-	    cryptpw = crypt (pass, data.dptr);
5ed8a7
+	      cryptpw = crypt (pass, pwhash);
5ed8a7
 #endif
5ed8a7
-	    if (cryptpw && strlen(cryptpw) == (size_t)data.dsize) {
5ed8a7
-	      compare = memcmp(data.dptr, cryptpw, data.dsize);
5ed8a7
-	    } else {
5ed8a7
-	      compare = -2;
5ed8a7
-	      if (ctrl & PAM_DEBUG_ARG) {
5ed8a7
-		if (cryptpw)
5ed8a7
-		  pam_syslog(pamh, LOG_INFO, "lengths of computed and stored hashes differ");
5ed8a7
-		else
5ed8a7
-		  pam_syslog(pamh, LOG_INFO, "crypt() returned NULL");
5ed8a7
+	      if (cryptpw && strlen(cryptpw) == (size_t)data.dsize) {
5ed8a7
+	        compare = memcmp(data.dptr, cryptpw, data.dsize);
5ed8a7
+	      } else {
5ed8a7
+	        if (ctrl & PAM_DEBUG_ARG) {
5ed8a7
+	          if (cryptpw) {
5ed8a7
+	            pam_syslog(pamh, LOG_INFO, "lengths of computed and stored hashes differ");
5ed8a7
+	            pam_syslog(pamh, LOG_INFO, "computed hash: %s", cryptpw);
5ed8a7
+	          } else {
5ed8a7
+	            pam_syslog(pamh, LOG_ERR, "crypt() returned NULL");
5ed8a7
+	          }
5ed8a7
+	        }
5ed8a7
 	      }
5ed8a7
-	    }
5ed8a7
 #ifdef HAVE_CRYPT_R
5ed8a7
-	    free(cdata);
5ed8a7
+	      free(cdata);
5ed8a7
 #endif
5ed8a7
+	    }
5ed8a7
+	    free(pwhash);
5ed8a7
 	  }
5ed8a7
-
5ed8a7
 	} else {
5ed8a7
 
5ed8a7
 	  /* Unknown password encryption method -
5ed8a7
-- 
5ed8a7
2.30.2
5ed8a7