File pam_modutil_get-overwrite-password-at-free.patch of Package pam

From e2fdc55d9d8d277c9395f96c3bf2938bacc84f62 Mon Sep 17 00:00:00 2001
From: Thorsten Kukuk <kukuk@suse.com>
Date: Thu, 14 Aug 2025 12:01:25 +0200
Subject: [PATCH] pam_modutil_get*: overwrite password at free (#846)

Make sure that the buffer containing encrypted passwords (struct group,
passwd and shadow) get's erased before free, so that they are not
available anymore if the memory get allocated again.
---
 libpam/pam_modutil_cleanup.c  | 40 +++++++++++++++++++++++++++++++++++
 libpam/pam_modutil_getgrgid.c |  2 +-
 libpam/pam_modutil_getgrnam.c |  2 +-
 libpam/pam_modutil_getpwnam.c |  2 +-
 libpam/pam_modutil_getpwuid.c |  2 +-
 libpam/pam_modutil_getspnam.c |  2 +-
 libpam/pam_modutil_private.h  |  9 ++++++++
 7 files changed, 54 insertions(+), 5 deletions(-)

diff --git a/libpam/pam_modutil_cleanup.c b/libpam/pam_modutil_cleanup.c
index 2077cbd7..46233736 100644
--- a/libpam/pam_modutil_cleanup.c
+++ b/libpam/pam_modutil_cleanup.c
@@ -5,8 +5,12 @@
  */
 
 #include "pam_modutil_private.h"
+#include "pam_inline.h"
 
+#include <grp.h>
+#include <pwd.h>
 #include <stdlib.h>
+#include <shadow.h>
 
 void
 pam_modutil_cleanup (pam_handle_t *pamh UNUSED, void *data,
@@ -15,3 +19,39 @@ pam_modutil_cleanup (pam_handle_t *pamh UNUSED, void *data,
 	/* junk it */
 	free(data);
 }
+
+void
+pam_modutil_cleanup_group (pam_handle_t *pamh UNUSED, void *data,
+			   int error_status UNUSED)
+{
+	struct group *gr = data;
+
+	if (gr && gr->gr_passwd)
+		pam_overwrite_string(gr->gr_passwd);
+
+	free(data);
+}
+
+void
+pam_modutil_cleanup_passwd (pam_handle_t *pamh UNUSED, void *data,
+			    int error_status UNUSED)
+{
+	struct passwd *pw = data;
+
+	if (pw && pw->pw_passwd)
+		pam_overwrite_string(pw->pw_passwd);
+
+	free(data);
+}
+
+void
+pam_modutil_cleanup_shadow (pam_handle_t *pamh UNUSED, void *data,
+			    int error_status UNUSED)
+{
+	struct spwd *sp = data;
+
+	if (sp && sp->sp_pwdp)
+		pam_overwrite_string(sp->sp_pwdp);
+
+	free(data);
+}
diff --git a/libpam/pam_modutil_getgrgid.c b/libpam/pam_modutil_getgrgid.c
index 6c2bb31b..fa3436c5 100644
--- a/libpam/pam_modutil_getgrgid.c
+++ b/libpam/pam_modutil_getgrgid.c
@@ -62,7 +62,7 @@ pam_modutil_getgrgid(pam_handle_t *pamh, gid_t gid)
 		    status = PAM_NO_MODULE_DATA;
 	            if (pam_get_data(pamh, data_name, &ignore) != PAM_SUCCESS) {
 		        status = pam_set_data(pamh, data_name,
-					      result, pam_modutil_cleanup);
+					      result, pam_modutil_cleanup_group);
 		    }
 		    free(data_name);
 		    if (status == PAM_SUCCESS) {
diff --git a/libpam/pam_modutil_getgrnam.c b/libpam/pam_modutil_getgrnam.c
index 418b9e47..533a8ce6 100644
--- a/libpam/pam_modutil_getgrnam.c
+++ b/libpam/pam_modutil_getgrnam.c
@@ -62,7 +62,7 @@ pam_modutil_getgrnam(pam_handle_t *pamh, const char *group)
 		    status = PAM_NO_MODULE_DATA;
 	            if (pam_get_data(pamh, data_name, &ignore) != PAM_SUCCESS) {
 		        status = pam_set_data(pamh, data_name,
-					      result, pam_modutil_cleanup);
+					      result, pam_modutil_cleanup_group);
 		    }
 		    free(data_name);
 		    if (status == PAM_SUCCESS) {
diff --git a/libpam/pam_modutil_getpwnam.c b/libpam/pam_modutil_getpwnam.c
index 5701ba9c..de654aeb 100644
--- a/libpam/pam_modutil_getpwnam.c
+++ b/libpam/pam_modutil_getpwnam.c
@@ -62,7 +62,7 @@ pam_modutil_getpwnam(pam_handle_t *pamh, const char *user)
 		    status = PAM_NO_MODULE_DATA;
 	            if (pam_get_data(pamh, data_name, &ignore) != PAM_SUCCESS) {
 		        status = pam_set_data(pamh, data_name,
-					      result, pam_modutil_cleanup);
+					      result, pam_modutil_cleanup_passwd);
 		    }
 		    free(data_name);
 		    if (status == PAM_SUCCESS) {
diff --git a/libpam/pam_modutil_getpwuid.c b/libpam/pam_modutil_getpwuid.c
index d3bb7231..6534958c 100644
--- a/libpam/pam_modutil_getpwuid.c
+++ b/libpam/pam_modutil_getpwuid.c
@@ -62,7 +62,7 @@ pam_modutil_getpwuid(pam_handle_t *pamh, uid_t uid)
 		    status = PAM_NO_MODULE_DATA;
 	            if (pam_get_data(pamh, data_name, &ignore) != PAM_SUCCESS) {
 		        status = pam_set_data(pamh, data_name,
-					      result, pam_modutil_cleanup);
+					      result, pam_modutil_cleanup_passwd);
 		    }
 		    free(data_name);
 		    if (status == PAM_SUCCESS) {
diff --git a/libpam/pam_modutil_getspnam.c b/libpam/pam_modutil_getspnam.c
index 9aa6ac9a..9733eda0 100644
--- a/libpam/pam_modutil_getspnam.c
+++ b/libpam/pam_modutil_getspnam.c
@@ -62,7 +62,7 @@ pam_modutil_getspnam(pam_handle_t *pamh, const char *user)
 		    status = PAM_NO_MODULE_DATA;
 	            if (pam_get_data(pamh, data_name, &ignore) != PAM_SUCCESS) {
 		        status = pam_set_data(pamh, data_name,
-					      result, pam_modutil_cleanup);
+					      result, pam_modutil_cleanup_shadow);
 		    }
 		    free(data_name);
 		    if (status == PAM_SUCCESS) {
diff --git a/libpam/pam_modutil_private.h b/libpam/pam_modutil_private.h
index 98a30f68..611c7696 100644
--- a/libpam/pam_modutil_private.h
+++ b/libpam/pam_modutil_private.h
@@ -20,5 +20,14 @@
 extern void
 pam_modutil_cleanup(pam_handle_t *pamh, void *data,
                     int error_status);
+extern void
+pam_modutil_cleanup_group(pam_handle_t *pamh, void *data,
+			  int error_status);
+extern void
+pam_modutil_cleanup_passwd(pam_handle_t *pamh, void *data,
+			   int error_status);
+extern void
+pam_modutil_cleanup_shadow(pam_handle_t *pamh, void *data,
+			   int error_status);
 
 #endif /* PAMMODUTIL_PRIVATE_H */
-- 
2.50.1

openSUSE Build Service is sponsored by