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

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