!30 fix error in change-ndbm-to-gdbm.patch and sync community patch
From: @tong_1001 Reviewed-by: @zhujianwei001 Signed-off-by: @zhujianwei001
This commit is contained in:
commit
b6e37036bf
@ -0,0 +1,202 @@
|
||||
From 48f44125fac8873237ade9e94942f82a8e6d6e1d Mon Sep 17 00:00:00 2001
|
||||
From: ikerexxe <ipedrosa@redhat.com>
|
||||
Date: Wed, 15 Jul 2020 09:45:12 +0200
|
||||
Subject: [PATCH] Move read_passwords function from pam_unix to pam_inline.h
|
||||
|
||||
[ldv: rewrote commit message]
|
||||
|
||||
* modules/pam_unix/passverify.h (read_passwords): Remove prototype.
|
||||
* modules/pam_unix/passverify.c (read_passwords): Move ...
|
||||
* libpam/include/pam_inline.h: ... here, rename to pam_read_passwords,
|
||||
add static inline qualifiers.
|
||||
Include <unistd.h> and <errno.h>.
|
||||
* modules/pam_unix/unix_chkpwd.c: Include "pam_inline.h".
|
||||
(main): Replace read_passwords with pam_read_passwords.
|
||||
* modules/pam_unix/unix_update.c: Include "pam_inline.h".
|
||||
(set_password): Replace read_passwords with pam_read_passwords.
|
||||
---
|
||||
libpam/include/pam_inline.h | 50 ++++++++++++++++++++++++++++++++++++++++++
|
||||
modules/pam_unix/passverify.c | 43 ------------------------------------
|
||||
modules/pam_unix/passverify.h | 2 --
|
||||
modules/pam_unix/unix_chkpwd.c | 3 ++-
|
||||
modules/pam_unix/unix_update.c | 3 ++-
|
||||
5 files changed, 54 insertions(+), 47 deletions(-)
|
||||
|
||||
diff --git a/libpam/include/pam_inline.h b/libpam/include/pam_inline.h
|
||||
index ec05fe4..8040b86 100644
|
||||
--- a/libpam/include/pam_inline.h
|
||||
+++ b/libpam/include/pam_inline.h
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
#include "pam_cc_compat.h"
|
||||
#include <string.h>
|
||||
+#include <unistd.h>
|
||||
+#include <errno.h>
|
||||
|
||||
/*
|
||||
* Evaluates to
|
||||
@@ -64,4 +66,52 @@ pam_str_skip_icase_prefix_len(const char *str, const char *prefix, size_t prefix
|
||||
#define pam_str_skip_icase_prefix(str_, prefix_) \
|
||||
pam_str_skip_icase_prefix_len((str_), (prefix_), sizeof(prefix_) - 1 + PAM_MUST_BE_ARRAY(prefix_))
|
||||
|
||||
+static inline int
|
||||
+pam_read_passwords(int fd, int npass, char **passwords)
|
||||
+{
|
||||
+ /*
|
||||
+ * The passwords array must contain npass preallocated
|
||||
+ * buffers of length PAM_MAX_RESP_SIZE + 1.
|
||||
+ */
|
||||
+ int rbytes = 0;
|
||||
+ int offset = 0;
|
||||
+ int i = 0;
|
||||
+ char *pptr;
|
||||
+ while (npass > 0) {
|
||||
+ rbytes = read(fd, passwords[i]+offset, PAM_MAX_RESP_SIZE+1-offset);
|
||||
+
|
||||
+ if (rbytes < 0) {
|
||||
+ if (errno == EINTR) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ if (rbytes == 0) {
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ while (npass > 0 && (pptr=memchr(passwords[i]+offset, '\0', rbytes))
|
||||
+ != NULL) {
|
||||
+ rbytes -= pptr - (passwords[i]+offset) + 1;
|
||||
+ i++;
|
||||
+ offset = 0;
|
||||
+ npass--;
|
||||
+ if (rbytes > 0) {
|
||||
+ if (npass > 0) {
|
||||
+ memcpy(passwords[i], pptr+1, rbytes);
|
||||
+ }
|
||||
+ memset(pptr+1, '\0', rbytes);
|
||||
+ }
|
||||
+ }
|
||||
+ offset += rbytes;
|
||||
+ }
|
||||
+
|
||||
+ /* clear up */
|
||||
+ if (offset > 0 && npass > 0) {
|
||||
+ memset(passwords[i], '\0', offset);
|
||||
+ }
|
||||
+
|
||||
+ return i;
|
||||
+}
|
||||
+
|
||||
#endif /* PAM_INLINE_H */
|
||||
diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c
|
||||
index a571b4f..4094b31 100644
|
||||
--- a/modules/pam_unix/passverify.c
|
||||
+++ b/modules/pam_unix/passverify.c
|
||||
@@ -1180,49 +1180,6 @@ getuidname(uid_t uid)
|
||||
return username;
|
||||
}
|
||||
|
||||
-int
|
||||
-read_passwords(int fd, int npass, char **passwords)
|
||||
-{
|
||||
- /* The passwords array must contain npass preallocated
|
||||
- * buffers of length MAXPASS + 1
|
||||
- */
|
||||
- int rbytes = 0;
|
||||
- int offset = 0;
|
||||
- int i = 0;
|
||||
- char *pptr;
|
||||
- while (npass > 0) {
|
||||
- rbytes = read(fd, passwords[i]+offset, MAXPASS+1-offset);
|
||||
-
|
||||
- if (rbytes < 0) {
|
||||
- if (errno == EINTR) continue;
|
||||
- break;
|
||||
- }
|
||||
- if (rbytes == 0)
|
||||
- break;
|
||||
-
|
||||
- while (npass > 0 && (pptr=memchr(passwords[i]+offset, '\0', rbytes))
|
||||
- != NULL) {
|
||||
- rbytes -= pptr - (passwords[i]+offset) + 1;
|
||||
- i++;
|
||||
- offset = 0;
|
||||
- npass--;
|
||||
- if (rbytes > 0) {
|
||||
- if (npass > 0)
|
||||
- memcpy(passwords[i], pptr+1, rbytes);
|
||||
- memset(pptr+1, '\0', rbytes);
|
||||
- }
|
||||
- }
|
||||
- offset += rbytes;
|
||||
- }
|
||||
-
|
||||
- /* clear up */
|
||||
- if (offset > 0 && npass > 0) {
|
||||
- memset(passwords[i], '\0', offset);
|
||||
- }
|
||||
-
|
||||
- return i;
|
||||
-}
|
||||
-
|
||||
#endif
|
||||
/* ****************************************************************** *
|
||||
* Copyright (c) Jan Rękorajski 1999.
|
||||
diff --git a/modules/pam_unix/passverify.h b/modules/pam_unix/passverify.h
|
||||
index e9a88fb..abd3f3e 100644
|
||||
--- a/modules/pam_unix/passverify.h
|
||||
+++ b/modules/pam_unix/passverify.h
|
||||
@@ -50,8 +50,6 @@ setup_signals(void);
|
||||
char *
|
||||
getuidname(uid_t uid);
|
||||
|
||||
-int
|
||||
-read_passwords(int fd, int npass, char **passwords);
|
||||
#endif
|
||||
|
||||
#ifdef HELPER_COMPILE
|
||||
diff --git a/modules/pam_unix/unix_chkpwd.c b/modules/pam_unix/unix_chkpwd.c
|
||||
index 4384deb..7d0718c 100644
|
||||
--- a/modules/pam_unix/unix_chkpwd.c
|
||||
+++ b/modules/pam_unix/unix_chkpwd.c
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <security/_pam_macros.h>
|
||||
|
||||
#include "passverify.h"
|
||||
+#include "pam_inline.h"
|
||||
|
||||
static int _check_expiry(const char *uname)
|
||||
{
|
||||
@@ -162,7 +163,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
/* read the password from stdin (a pipe from the pam_unix module) */
|
||||
|
||||
- npass = read_passwords(STDIN_FILENO, 1, passwords);
|
||||
+ npass = pam_read_passwords(STDIN_FILENO, 1, passwords);
|
||||
|
||||
if (npass != 1) { /* is it a valid password? */
|
||||
helper_log_err(LOG_DEBUG, "no password supplied");
|
||||
diff --git a/modules/pam_unix/unix_update.c b/modules/pam_unix/unix_update.c
|
||||
index 6ea7ea5..b6236cc 100644
|
||||
--- a/modules/pam_unix/unix_update.c
|
||||
+++ b/modules/pam_unix/unix_update.c
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <security/_pam_macros.h>
|
||||
|
||||
#include "passverify.h"
|
||||
+#include "pam_inline.h"
|
||||
|
||||
static int
|
||||
set_password(const char *forwho, const char *shadow, const char *remember)
|
||||
@@ -49,7 +50,7 @@ set_password(const char *forwho, const char *shadow, const char *remember)
|
||||
|
||||
/* read the password from stdin (a pipe from the pam_unix module) */
|
||||
|
||||
- npass = read_passwords(STDIN_FILENO, 2, passwords);
|
||||
+ npass = pam_read_passwords(STDIN_FILENO, 2, passwords);
|
||||
|
||||
if (npass != 2) { /* is it a valid password? */
|
||||
if (npass == 1) {
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
751
backport-add-helper-to-handle-SELinux.patch
Normal file
751
backport-add-helper-to-handle-SELinux.patch
Normal file
@ -0,0 +1,751 @@
|
||||
From f787845843da96cc29ea1f864e29fb17379b36b7 Mon Sep 17 00:00:00 2001
|
||||
From: ikerexxe <ipedrosa@redhat.com>
|
||||
Date: Wed, 15 Jul 2020 09:54:45 +0200
|
||||
Subject: [PATCH] pam_pwhistory: add helper to handle SELinux
|
||||
|
||||
The purpose of the helper is to enable tighter confinement of login and
|
||||
password changing services. The helper is thus called only when SELinux
|
||||
is enabled on the system.
|
||||
|
||||
Resolves: https://github.com/linux-pam/linux-pam/pull/247
|
||||
---
|
||||
modules/pam_pwhistory/.gitignore | 1 +
|
||||
modules/pam_pwhistory/Makefile.am | 21 +-
|
||||
modules/pam_pwhistory/opasswd.c | 67 +++++-
|
||||
modules/pam_pwhistory/opasswd.h | 31 ++-
|
||||
modules/pam_pwhistory/pam_pwhistory.c | 218 ++++++++++++++++---
|
||||
modules/pam_pwhistory/pwhistory_helper.8.xml | 68 ++++++
|
||||
modules/pam_pwhistory/pwhistory_helper.c | 119 ++++++++++
|
||||
7 files changed, 478 insertions(+), 47 deletions(-)
|
||||
create mode 100644 modules/pam_pwhistory/.gitignore
|
||||
create mode 100644 modules/pam_pwhistory/pwhistory_helper.8.xml
|
||||
create mode 100644 modules/pam_pwhistory/pwhistory_helper.c
|
||||
|
||||
diff --git a/modules/pam_pwhistory/.gitignore b/modules/pam_pwhistory/.gitignore
|
||||
new file mode 100644
|
||||
index 00000000..358515af
|
||||
--- /dev/null
|
||||
+++ b/modules/pam_pwhistory/.gitignore
|
||||
@@ -0,0 +1 @@
|
||||
+pwhistory_helper
|
||||
diff --git a/modules/pam_pwhistory/Makefile.am b/modules/pam_pwhistory/Makefile.am
|
||||
index bd9f1ea9..32b9fcc4 100644
|
||||
--- a/modules/pam_pwhistory/Makefile.am
|
||||
+++ b/modules/pam_pwhistory/Makefile.am
|
||||
@@ -1,5 +1,6 @@
|
||||
#
|
||||
# Copyright (c) 2008, 2009 Thorsten Kukuk <kukuk@suse.de>
|
||||
+# Copyright (c) 2013 Red Hat, Inc.
|
||||
#
|
||||
|
||||
CLEANFILES = *~
|
||||
@@ -8,9 +9,9 @@ MAINTAINERCLEANFILES = $(MANS) README
|
||||
EXTRA_DIST = $(XMLS)
|
||||
|
||||
if HAVE_DOC
|
||||
-dist_man_MANS = pam_pwhistory.8
|
||||
+dist_man_MANS = pam_pwhistory.8 pwhistory_helper.8
|
||||
endif
|
||||
-XMLS = README.xml pam_pwhistory.8.xml
|
||||
+XMLS = README.xml pam_pwhistory.8.xml pwhistory_helper.8.xml
|
||||
dist_check_SCRIPTS = tst-pam_pwhistory
|
||||
TESTS = $(dist_check_SCRIPTS)
|
||||
|
||||
@@ -18,18 +19,26 @@ securelibdir = $(SECUREDIR)
|
||||
secureconfdir = $(SCONFIGDIR)
|
||||
|
||||
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
|
||||
- $(WARN_CFLAGS)
|
||||
-AM_LDFLAGS = -no-undefined -avoid-version -module
|
||||
+ $(WARN_CFLAGS) -DPWHISTORY_HELPER=\"$(sbindir)/pwhistory_helper\"
|
||||
+
|
||||
+pam_pwhistory_la_LDFLAGS = -no-undefined -avoid-version -module
|
||||
if HAVE_VERSIONING
|
||||
- AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
|
||||
+ pam_pwhistory_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
|
||||
endif
|
||||
|
||||
noinst_HEADERS = opasswd.h
|
||||
|
||||
securelib_LTLIBRARIES = pam_pwhistory.la
|
||||
-pam_pwhistory_la_LIBADD = $(top_builddir)/libpam/libpam.la @LIBCRYPT@
|
||||
+pam_pwhistory_la_CFLAGS = $(AM_CFLAGS)
|
||||
+pam_pwhistory_la_LIBADD = $(top_builddir)/libpam/libpam.la @LIBCRYPT@ @LIBSELINUX@
|
||||
pam_pwhistory_la_SOURCES = pam_pwhistory.c opasswd.c
|
||||
|
||||
+sbin_PROGRAMS = pwhistory_helper
|
||||
+pwhistory_helper_CFLAGS = $(AM_CFLAGS) -DHELPER_COMPILE=\"pwhistory_helper\" @PIE_CFLAGS@
|
||||
+pwhistory_helper_SOURCES = pwhistory_helper.c opasswd.c
|
||||
+pwhistory_helper_LDFLAGS = @PIE_LDFLAGS@
|
||||
+pwhistory_helper_LDADD = $(top_builddir)/libpam/libpam.la @LIBCRYPT@
|
||||
+
|
||||
if ENABLE_REGENERATE_MAN
|
||||
dist_noinst_DATA = README
|
||||
-include $(top_srcdir)/Make.xml.rules
|
||||
diff --git a/modules/pam_pwhistory/opasswd.c b/modules/pam_pwhistory/opasswd.c
|
||||
index 77142f2c..ac10f691 100644
|
||||
--- a/modules/pam_pwhistory/opasswd.c
|
||||
+++ b/modules/pam_pwhistory/opasswd.c
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Thorsten Kukuk <kukuk@suse.de>
|
||||
+ * Copyright (c) 2013 Red Hat, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -38,6 +39,7 @@
|
||||
#endif
|
||||
|
||||
#include <pwd.h>
|
||||
+#include <shadow.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
@@ -47,6 +49,9 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
+#ifdef HELPER_COMPILE
|
||||
+#include <stdarg.h>
|
||||
+#endif
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if defined HAVE_LIBXCRYPT
|
||||
@@ -55,7 +60,14 @@
|
||||
#include <crypt.h>
|
||||
#endif
|
||||
|
||||
+#ifdef HELPER_COMPILE
|
||||
+#define pam_modutil_getpwnam(h,n) getpwnam(n)
|
||||
+#define pam_modutil_getspnam(h,n) getspnam(n)
|
||||
+#define pam_syslog(h,a,...) helper_log_err(a,__VA_ARGS__)
|
||||
+#else
|
||||
+#include <security/pam_modutil.h>
|
||||
#include <security/pam_ext.h>
|
||||
+#endif
|
||||
#include <security/pam_modules.h>
|
||||
|
||||
#include "opasswd.h"
|
||||
@@ -76,6 +88,19 @@ typedef struct {
|
||||
char *old_passwords;
|
||||
} opwd;
|
||||
|
||||
+#ifdef HELPER_COMPILE
|
||||
+void
|
||||
+helper_log_err(int err, const char *format, ...)
|
||||
+{
|
||||
+ va_list args;
|
||||
+
|
||||
+ va_start(args, format);
|
||||
+ openlog(HELPER_COMPILE, LOG_CONS | LOG_PID, LOG_AUTHPRIV);
|
||||
+ vsyslog(err, format, args);
|
||||
+ va_end(args);
|
||||
+ closelog();
|
||||
+}
|
||||
+#endif
|
||||
|
||||
static int
|
||||
parse_entry (char *line, opwd *data)
|
||||
@@ -117,9 +142,8 @@ compare_password(const char *newpass, const char *oldpass)
|
||||
}
|
||||
|
||||
/* Check, if the new password is already in the opasswd file. */
|
||||
-int
|
||||
-check_old_pass (pam_handle_t *pamh, const char *user,
|
||||
- const char *newpass, int debug)
|
||||
+PAMH_ARG_DECL(int
|
||||
+check_old_pass, const char *user, const char *newpass, int debug)
|
||||
{
|
||||
int retval = PAM_SUCCESS;
|
||||
FILE *oldpf;
|
||||
@@ -128,6 +152,11 @@ check_old_pass (pam_handle_t *pamh, const char *user,
|
||||
opwd entry;
|
||||
int found = 0;
|
||||
|
||||
+#ifndef HELPER_COMPILE
|
||||
+ if (SELINUX_ENABLED)
|
||||
+ return PAM_PWHISTORY_RUN_HELPER;
|
||||
+#endif
|
||||
+
|
||||
if ((oldpf = fopen (OLD_PASSWORDS_FILE, "r")) == NULL)
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
@@ -213,9 +242,8 @@ check_old_pass (pam_handle_t *pamh, const char *user,
|
||||
return retval;
|
||||
}
|
||||
|
||||
-int
|
||||
-save_old_pass (pam_handle_t *pamh, const char *user, uid_t uid,
|
||||
- const char *oldpass, int howmany, int debug UNUSED)
|
||||
+PAMH_ARG_DECL(int
|
||||
+save_old_pass, const char *user, int howmany, int debug UNUSED)
|
||||
{
|
||||
char opasswd_tmp[] = TMP_PASSWORDS_FILE;
|
||||
struct stat opasswd_stat;
|
||||
@@ -226,10 +254,35 @@ save_old_pass (pam_handle_t *pamh, const char *user, uid_t uid,
|
||||
char *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
int found = 0;
|
||||
+ struct passwd *pwd;
|
||||
+ const char *oldpass;
|
||||
+
|
||||
+ pwd = pam_modutil_getpwnam (pamh, user);
|
||||
+ if (pwd == NULL)
|
||||
+ return PAM_USER_UNKNOWN;
|
||||
|
||||
if (howmany <= 0)
|
||||
return PAM_SUCCESS;
|
||||
|
||||
+#ifndef HELPER_COMPILE
|
||||
+ if (SELINUX_ENABLED)
|
||||
+ return PAM_PWHISTORY_RUN_HELPER;
|
||||
+#endif
|
||||
+
|
||||
+ if ((strcmp(pwd->pw_passwd, "x") == 0) ||
|
||||
+ ((pwd->pw_passwd[0] == '#') &&
|
||||
+ (pwd->pw_passwd[1] == '#') &&
|
||||
+ (strcmp(pwd->pw_name, pwd->pw_passwd + 2) == 0)))
|
||||
+ {
|
||||
+ struct spwd *spw = pam_modutil_getspnam (pamh, user);
|
||||
+
|
||||
+ if (spw == NULL)
|
||||
+ return PAM_USER_UNKNOWN;
|
||||
+ oldpass = spw->sp_pwdp;
|
||||
+ }
|
||||
+ else
|
||||
+ oldpass = pwd->pw_passwd;
|
||||
+
|
||||
if (oldpass == NULL || *oldpass == '\0')
|
||||
return PAM_SUCCESS;
|
||||
|
||||
@@ -452,7 +505,7 @@ save_old_pass (pam_handle_t *pamh, const char *user, uid_t uid,
|
||||
{
|
||||
char *out;
|
||||
|
||||
- if (asprintf (&out, "%s:%d:1:%s\n", user, uid, oldpass) < 0)
|
||||
+ if (asprintf (&out, "%s:%d:1:%s\n", user, pwd->pw_uid, oldpass) < 0)
|
||||
{
|
||||
retval = PAM_AUTHTOK_ERR;
|
||||
if (oldpf)
|
||||
diff --git a/modules/pam_pwhistory/opasswd.h b/modules/pam_pwhistory/opasswd.h
|
||||
index db3e6568..3f257288 100644
|
||||
--- a/modules/pam_pwhistory/opasswd.h
|
||||
+++ b/modules/pam_pwhistory/opasswd.h
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Thorsten Kukuk <kukuk@suse.de>
|
||||
+ * Copyright (c) 2013 Red Hat, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -36,10 +37,30 @@
|
||||
#ifndef __OPASSWD_H__
|
||||
#define __OPASSWD_H__
|
||||
|
||||
-extern int check_old_pass (pam_handle_t *pamh, const char *user,
|
||||
- const char *newpass, int debug);
|
||||
-extern int save_old_pass (pam_handle_t *pamh, const char *user,
|
||||
- uid_t uid, const char *oldpass,
|
||||
- int howmany, int debug);
|
||||
+#define PAM_PWHISTORY_RUN_HELPER PAM_CRED_INSUFFICIENT
|
||||
+
|
||||
+#ifdef WITH_SELINUX
|
||||
+#include <selinux/selinux.h>
|
||||
+#define SELINUX_ENABLED (is_selinux_enabled()>0)
|
||||
+#else
|
||||
+#define SELINUX_ENABLED 0
|
||||
+#endif
|
||||
+
|
||||
+#ifdef HELPER_COMPILE
|
||||
+#define PAMH_ARG_DECL(fname, ...) fname(__VA_ARGS__)
|
||||
+#else
|
||||
+#define PAMH_ARG_DECL(fname, ...) fname(pam_handle_t *pamh, __VA_ARGS__)
|
||||
+#endif
|
||||
+
|
||||
+#ifdef HELPER_COMPILE
|
||||
+void
|
||||
+helper_log_err(int err, const char *format, ...);
|
||||
+#endif
|
||||
+
|
||||
+PAMH_ARG_DECL(int
|
||||
+check_old_pass, const char *user, const char *newpass, int debug);
|
||||
+
|
||||
+PAMH_ARG_DECL(int
|
||||
+save_old_pass, const char *user, int howmany, int debug);
|
||||
|
||||
#endif /* __OPASSWD_H__ */
|
||||
diff --git a/modules/pam_pwhistory/pam_pwhistory.c b/modules/pam_pwhistory/pam_pwhistory.c
|
||||
index cf4fc078..a16365f8 100644
|
||||
--- a/modules/pam_pwhistory/pam_pwhistory.c
|
||||
+++ b/modules/pam_pwhistory/pam_pwhistory.c
|
||||
@@ -3,6 +3,7 @@
|
||||
*
|
||||
* Copyright (c) 2008, 2012 Thorsten Kukuk
|
||||
* Author: Thorsten Kukuk <kukuk@thkukuk.de>
|
||||
+ * Copyright (c) 2013 Red Hat, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -46,10 +47,14 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
-#include <shadow.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
+#include <sys/time.h>
|
||||
+#include <sys/resource.h>
|
||||
+#include <sys/wait.h>
|
||||
+#include <signal.h>
|
||||
+#include <fcntl.h>
|
||||
|
||||
#include <security/pam_modules.h>
|
||||
#include <security/pam_modutil.h>
|
||||
@@ -59,8 +64,6 @@
|
||||
#include "opasswd.h"
|
||||
#include "pam_inline.h"
|
||||
|
||||
-#define DEFAULT_BUFLEN 2048
|
||||
-
|
||||
struct options_t {
|
||||
int debug;
|
||||
int enforce_for_root;
|
||||
@@ -105,6 +108,179 @@ parse_option (pam_handle_t *pamh, const char *argv, options_t *options)
|
||||
pam_syslog (pamh, LOG_ERR, "pam_pwhistory: unknown option: %s", argv);
|
||||
}
|
||||
|
||||
+static int
|
||||
+run_save_helper(pam_handle_t *pamh, const char *user,
|
||||
+ int howmany, int debug)
|
||||
+{
|
||||
+ int retval, child;
|
||||
+ struct sigaction newsa, oldsa;
|
||||
+
|
||||
+ memset(&newsa, '\0', sizeof(newsa));
|
||||
+ newsa.sa_handler = SIG_DFL;
|
||||
+ sigaction(SIGCHLD, &newsa, &oldsa);
|
||||
+
|
||||
+ child = fork();
|
||||
+ if (child == 0)
|
||||
+ {
|
||||
+ static char *envp[] = { NULL };
|
||||
+ char *args[] = { NULL, NULL, NULL, NULL, NULL, NULL };
|
||||
+
|
||||
+ if (pam_modutil_sanitize_helper_fds(pamh, PAM_MODUTIL_PIPE_FD,
|
||||
+ PAM_MODUTIL_PIPE_FD,
|
||||
+ PAM_MODUTIL_PIPE_FD) < 0)
|
||||
+ {
|
||||
+ _exit(PAM_SYSTEM_ERR);
|
||||
+ }
|
||||
+
|
||||
+ /* exec binary helper */
|
||||
+ DIAG_PUSH_IGNORE_CAST_QUAL;
|
||||
+ args[0] = (char *)PWHISTORY_HELPER;
|
||||
+ args[1] = (char *)"save";
|
||||
+ args[2] = (char *)user;
|
||||
+ DIAG_POP_IGNORE_CAST_QUAL;
|
||||
+ if (asprintf(&args[3], "%d", howmany) < 0 ||
|
||||
+ asprintf(&args[4], "%d", debug) < 0)
|
||||
+ {
|
||||
+ pam_syslog(pamh, LOG_ERR, "asprintf: %m");
|
||||
+ _exit(PAM_SYSTEM_ERR);
|
||||
+ }
|
||||
+
|
||||
+ execve(args[0], args, envp);
|
||||
+
|
||||
+ pam_syslog(pamh, LOG_ERR, "helper binary execve failed: %s: %m", args[0]);
|
||||
+
|
||||
+ _exit(PAM_SYSTEM_ERR);
|
||||
+ }
|
||||
+ else if (child > 0)
|
||||
+ {
|
||||
+ /* wait for child */
|
||||
+ int rc = 0;
|
||||
+ while ((rc = waitpid (child, &retval, 0)) == -1 &&
|
||||
+ errno == EINTR);
|
||||
+ if (rc < 0)
|
||||
+ {
|
||||
+ pam_syslog(pamh, LOG_ERR, "pwhistory_helper save: waitpid: %m");
|
||||
+ retval = PAM_SYSTEM_ERR;
|
||||
+ }
|
||||
+ else if (!WIFEXITED(retval))
|
||||
+ {
|
||||
+ pam_syslog(pamh, LOG_ERR, "pwhistory_helper save abnormal exit: %d", retval);
|
||||
+ retval = PAM_SYSTEM_ERR;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ retval = WEXITSTATUS(retval);
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ pam_syslog(pamh, LOG_ERR, "fork failed: %m");
|
||||
+ retval = PAM_SYSTEM_ERR;
|
||||
+ }
|
||||
+
|
||||
+ sigaction(SIGCHLD, &oldsa, NULL); /* restore old signal handler */
|
||||
+
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+run_check_helper(pam_handle_t *pamh, const char *user,
|
||||
+ const char *newpass, int debug)
|
||||
+{
|
||||
+ int retval, child, fds[2];
|
||||
+ struct sigaction newsa, oldsa;
|
||||
+
|
||||
+ /* create a pipe for the password */
|
||||
+ if (pipe(fds) != 0)
|
||||
+ return PAM_SYSTEM_ERR;
|
||||
+
|
||||
+ memset(&newsa, '\0', sizeof(newsa));
|
||||
+ newsa.sa_handler = SIG_DFL;
|
||||
+ sigaction(SIGCHLD, &newsa, &oldsa);
|
||||
+
|
||||
+ child = fork();
|
||||
+ if (child == 0)
|
||||
+ {
|
||||
+ static char *envp[] = { NULL };
|
||||
+ char *args[] = { NULL, NULL, NULL, NULL, NULL };
|
||||
+
|
||||
+ /* reopen stdin as pipe */
|
||||
+ if (dup2(fds[0], STDIN_FILENO) != STDIN_FILENO)
|
||||
+ {
|
||||
+ pam_syslog(pamh, LOG_ERR, "dup2 of %s failed: %m", "stdin");
|
||||
+ _exit(PAM_SYSTEM_ERR);
|
||||
+ }
|
||||
+
|
||||
+ if (pam_modutil_sanitize_helper_fds(pamh, PAM_MODUTIL_IGNORE_FD,
|
||||
+ PAM_MODUTIL_PIPE_FD,
|
||||
+ PAM_MODUTIL_PIPE_FD) < 0)
|
||||
+ {
|
||||
+ _exit(PAM_SYSTEM_ERR);
|
||||
+ }
|
||||
+
|
||||
+ /* exec binary helper */
|
||||
+ DIAG_PUSH_IGNORE_CAST_QUAL;
|
||||
+ args[0] = (char *)PWHISTORY_HELPER;
|
||||
+ args[1] = (char *)"check";
|
||||
+ args[2] = (char *)user;
|
||||
+ DIAG_POP_IGNORE_CAST_QUAL;
|
||||
+ if (asprintf(&args[3], "%d", debug) < 0)
|
||||
+ {
|
||||
+ pam_syslog(pamh, LOG_ERR, "asprintf: %m");
|
||||
+ _exit(PAM_SYSTEM_ERR);
|
||||
+ }
|
||||
+
|
||||
+ execve(args[0], args, envp);
|
||||
+
|
||||
+ pam_syslog(pamh, LOG_ERR, "helper binary execve failed: %s: %m", args[0]);
|
||||
+
|
||||
+ _exit(PAM_SYSTEM_ERR);
|
||||
+ }
|
||||
+ else if (child > 0)
|
||||
+ {
|
||||
+ /* wait for child */
|
||||
+ int rc = 0;
|
||||
+ if (newpass == NULL)
|
||||
+ newpass = "";
|
||||
+
|
||||
+ /* send the password to the child */
|
||||
+ if (write(fds[1], newpass, strlen(newpass)+1) == -1)
|
||||
+ {
|
||||
+ pam_syslog(pamh, LOG_ERR, "Cannot send password to helper: %m");
|
||||
+ retval = PAM_SYSTEM_ERR;
|
||||
+ }
|
||||
+ newpass = NULL;
|
||||
+ close(fds[0]); /* close here to avoid possible SIGPIPE above */
|
||||
+ close(fds[1]);
|
||||
+ while ((rc = waitpid (child, &retval, 0)) == -1 &&
|
||||
+ errno == EINTR);
|
||||
+ if (rc < 0)
|
||||
+ {
|
||||
+ pam_syslog(pamh, LOG_ERR, "pwhistory_helper check: waitpid: %m");
|
||||
+ retval = PAM_SYSTEM_ERR;
|
||||
+ }
|
||||
+ else if (!WIFEXITED(retval))
|
||||
+ {
|
||||
+ pam_syslog(pamh, LOG_ERR, "pwhistory_helper check abnormal exit: %d", retval);
|
||||
+ retval = PAM_SYSTEM_ERR;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ retval = WEXITSTATUS(retval);
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ pam_syslog(pamh, LOG_ERR, "fork failed: %m");
|
||||
+ close(fds[0]);
|
||||
+ close(fds[1]);
|
||||
+ retval = PAM_SYSTEM_ERR;
|
||||
+ }
|
||||
+
|
||||
+ sigaction(SIGCHLD, &oldsa, NULL); /* restore old signal handler */
|
||||
+
|
||||
+ return retval;
|
||||
+}
|
||||
|
||||
/* This module saves the current crypted password in /etc/security/opasswd
|
||||
and then compares the new password with all entries in this file. */
|
||||
@@ -112,7 +288,6 @@ parse_option (pam_handle_t *pamh, const char *argv, options_t *options)
|
||||
int
|
||||
pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv)
|
||||
{
|
||||
- struct passwd *pwd;
|
||||
const char *newpass;
|
||||
const char *user;
|
||||
int retval, tries;
|
||||
@@ -148,31 +323,13 @@ pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv)
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
- pwd = pam_modutil_getpwnam (pamh, user);
|
||||
- if (pwd == NULL)
|
||||
- return PAM_USER_UNKNOWN;
|
||||
+ retval = save_old_pass (pamh, user, options.remember, options.debug);
|
||||
|
||||
- if ((strcmp(pwd->pw_passwd, "x") == 0) ||
|
||||
- ((pwd->pw_passwd[0] == '#') &&
|
||||
- (pwd->pw_passwd[1] == '#') &&
|
||||
- (strcmp(pwd->pw_name, pwd->pw_passwd + 2) == 0)))
|
||||
- {
|
||||
- struct spwd *spw = pam_modutil_getspnam (pamh, user);
|
||||
- if (spw == NULL)
|
||||
- return PAM_USER_UNKNOWN;
|
||||
+ if (retval == PAM_PWHISTORY_RUN_HELPER)
|
||||
+ retval = run_save_helper(pamh, user, options.remember, options.debug);
|
||||
|
||||
- retval = save_old_pass (pamh, user, pwd->pw_uid, spw->sp_pwdp,
|
||||
- options.remember, options.debug);
|
||||
- if (retval != PAM_SUCCESS)
|
||||
- return retval;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- retval = save_old_pass (pamh, user, pwd->pw_uid, pwd->pw_passwd,
|
||||
- options.remember, options.debug);
|
||||
- if (retval != PAM_SUCCESS)
|
||||
- return retval;
|
||||
- }
|
||||
+ if (retval != PAM_SUCCESS)
|
||||
+ return retval;
|
||||
|
||||
newpass = NULL;
|
||||
tries = 0;
|
||||
@@ -201,8 +358,11 @@ pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv)
|
||||
if (options.debug)
|
||||
pam_syslog (pamh, LOG_DEBUG, "check against old password file");
|
||||
|
||||
- if (check_old_pass (pamh, user, newpass,
|
||||
- options.debug) != PAM_SUCCESS)
|
||||
+ retval = check_old_pass (pamh, user, newpass, options.debug);
|
||||
+ if (retval == PAM_PWHISTORY_RUN_HELPER)
|
||||
+ retval = run_check_helper(pamh, user, newpass, options.debug);
|
||||
+
|
||||
+ if (retval != PAM_SUCCESS)
|
||||
{
|
||||
if (getuid() || options.enforce_for_root ||
|
||||
(flags & PAM_CHANGE_EXPIRED_AUTHTOK))
|
||||
diff --git a/modules/pam_pwhistory/pwhistory_helper.8.xml b/modules/pam_pwhistory/pwhistory_helper.8.xml
|
||||
new file mode 100644
|
||||
index 00000000..a0301764
|
||||
--- /dev/null
|
||||
+++ b/modules/pam_pwhistory/pwhistory_helper.8.xml
|
||||
@@ -0,0 +1,68 @@
|
||||
+<?xml version="1.0" encoding='UTF-8'?>
|
||||
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
||||
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
|
||||
+
|
||||
+<refentry id="pwhistory_helper">
|
||||
+
|
||||
+ <refmeta>
|
||||
+ <refentrytitle>pwhistory_helper</refentrytitle>
|
||||
+ <manvolnum>8</manvolnum>
|
||||
+ <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo>
|
||||
+ </refmeta>
|
||||
+
|
||||
+ <refnamediv id="pwhistory_helper-name">
|
||||
+ <refname>pwhistory_helper</refname>
|
||||
+ <refpurpose>Helper binary that transfers password hashes from passwd or shadow to opasswd</refpurpose>
|
||||
+ </refnamediv>
|
||||
+
|
||||
+ <refsynopsisdiv>
|
||||
+ <cmdsynopsis id="pwhistory_helper-cmdsynopsis">
|
||||
+ <command>pwhistory_helper</command>
|
||||
+ <arg choice="opt">
|
||||
+ ...
|
||||
+ </arg>
|
||||
+ </cmdsynopsis>
|
||||
+ </refsynopsisdiv>
|
||||
+
|
||||
+ <refsect1 id="pwhistory_helper-description">
|
||||
+
|
||||
+ <title>DESCRIPTION</title>
|
||||
+
|
||||
+ <para>
|
||||
+ <emphasis>pwhistory_helper</emphasis> is a helper program for the
|
||||
+ <emphasis>pam_pwhistory</emphasis> module that transfers password hashes
|
||||
+ from passwd or shadow file to the opasswd file and checks a password
|
||||
+ supplied by user against the existing hashes in the opasswd file.
|
||||
+ </para>
|
||||
+
|
||||
+ <para>
|
||||
+ The purpose of the helper is to enable tighter confinement of
|
||||
+ login and password changing services. The helper is thus called only
|
||||
+ when SELinux is enabled on the system.
|
||||
+ </para>
|
||||
+
|
||||
+ <para>
|
||||
+ The interface of the helper - command line options, and input/output
|
||||
+ data format are internal to the <emphasis>pam_pwhistory</emphasis>
|
||||
+ module and it should not be called directly from applications.
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id='pwhistory_helper-see_also'>
|
||||
+ <title>SEE ALSO</title>
|
||||
+ <para>
|
||||
+ <citerefentry>
|
||||
+ <refentrytitle>pam_pwhistory</refentrytitle><manvolnum>8</manvolnum>
|
||||
+ </citerefentry>
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id='pwhistory_helper-author'>
|
||||
+ <title>AUTHOR</title>
|
||||
+ <para>
|
||||
+ Written by Tomas Mraz based on the code originally in
|
||||
+ <emphasis>pam_pwhistory and pam_unix</emphasis> modules.
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+</refentry>
|
||||
diff --git a/modules/pam_pwhistory/pwhistory_helper.c b/modules/pam_pwhistory/pwhistory_helper.c
|
||||
new file mode 100644
|
||||
index 00000000..b08a14a7
|
||||
--- /dev/null
|
||||
+++ b/modules/pam_pwhistory/pwhistory_helper.c
|
||||
@@ -0,0 +1,119 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2013 Red Hat, Inc.
|
||||
+ * Author: Tomas Mraz <tmraz@redhat.com>
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions
|
||||
+ * are met:
|
||||
+ * 1. Redistributions of source code must retain the above copyright
|
||||
+ * notice, and the entire permission notice in its entirety,
|
||||
+ * including the disclaimer of warranties.
|
||||
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer in the
|
||||
+ * documentation and/or other materials provided with the distribution.
|
||||
+ * 3. The name of the author may not be used to endorse or promote
|
||||
+ * products derived from this software without specific prior
|
||||
+ * written permission.
|
||||
+ *
|
||||
+ * ALTERNATIVELY, this product may be distributed under the terms of
|
||||
+ * the GNU Public License, in which case the provisions of the GPL are
|
||||
+ * required INSTEAD OF the above restrictions. (This clause is
|
||||
+ * necessary due to a potential bad interaction between the GPL and
|
||||
+ * the restrictions contained in a BSD-style copyright.)
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+ */
|
||||
+
|
||||
+#include "config.h"
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <syslog.h>
|
||||
+#include <errno.h>
|
||||
+#include <unistd.h>
|
||||
+#include <signal.h>
|
||||
+#include <security/_pam_types.h>
|
||||
+#include <security/_pam_macros.h>
|
||||
+#include <security/pam_modutil.h>
|
||||
+#include "opasswd.h"
|
||||
+#include "pam_inline.h"
|
||||
+
|
||||
+
|
||||
+static int
|
||||
+check_history(const char *user, const char *debug)
|
||||
+{
|
||||
+ char pass[PAM_MAX_RESP_SIZE + 1];
|
||||
+ char *passwords[] = { pass };
|
||||
+ int npass;
|
||||
+ int dbg = atoi(debug); /* no need to be too fancy here */
|
||||
+ int retval;
|
||||
+
|
||||
+ /* read the password from stdin (a pipe from the pam_pwhistory module) */
|
||||
+ npass = pam_read_passwords(STDIN_FILENO, 1, passwords);
|
||||
+
|
||||
+ if (npass != 1)
|
||||
+ { /* is it a valid password? */
|
||||
+ helper_log_err(LOG_DEBUG, "no password supplied");
|
||||
+ return PAM_AUTHTOK_ERR;
|
||||
+ }
|
||||
+
|
||||
+ retval = check_old_pass(user, pass, dbg);
|
||||
+
|
||||
+ memset(pass, '\0', PAM_MAX_RESP_SIZE); /* clear memory of the password */
|
||||
+
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+save_history(const char *user, const char *howmany, const char *debug)
|
||||
+{
|
||||
+ int num = atoi(howmany);
|
||||
+ int dbg = atoi(debug); /* no need to be too fancy here */
|
||||
+ int retval;
|
||||
+
|
||||
+ retval = save_old_pass(user, num, dbg);
|
||||
+
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main(int argc, char *argv[])
|
||||
+{
|
||||
+ const char *option;
|
||||
+ const char *user;
|
||||
+
|
||||
+ /*
|
||||
+ * we establish that this program is running with non-tty stdin.
|
||||
+ * this is to discourage casual use.
|
||||
+ */
|
||||
+
|
||||
+ if (isatty(STDIN_FILENO) || argc < 4)
|
||||
+ {
|
||||
+ fprintf(stderr,
|
||||
+ "This binary is not designed for running in this way.\n");
|
||||
+ return PAM_SYSTEM_ERR;
|
||||
+ }
|
||||
+
|
||||
+ option = argv[1];
|
||||
+ user = argv[2];
|
||||
+
|
||||
+ if (strcmp(option, "check") == 0 && argc == 4)
|
||||
+ return check_history(user, argv[3]);
|
||||
+ else if (strcmp(option, "save") == 0 && argc == 5)
|
||||
+ return save_history(user, argv[3], argv[4]);
|
||||
+
|
||||
+ fprintf(stderr, "This binary is not designed for running in this way.\n");
|
||||
+
|
||||
+ return PAM_SYSTEM_ERR;
|
||||
+}
|
||||
@ -16,7 +16,7 @@ index d537907..ecbaa2d 100644
|
||||
fi
|
||||
if test -z "$LIBDB" ; then
|
||||
- AC_CHECK_LIB([ndbm],[dbm_store], LIBDB="-lndbm", LIBDB="")
|
||||
+ AC_CHECK_LIB([gdbm_compat],[dbm_stroe], LIBDB="-lgdbm_compat", LIBDB="")
|
||||
+ AC_CHECK_LIB([gdbm_compat],[dbm_store], LIBDB="-lgdbm_compat", LIBDB="")
|
||||
if test -n "$LIBDB" ; then
|
||||
AC_CHECK_HEADERS(ndbm.h)
|
||||
fi
|
||||
|
||||
8
pam.spec
8
pam.spec
@ -4,7 +4,7 @@
|
||||
%define _pamconfdir %{_sysconfdir}/pam.d
|
||||
Name: pam
|
||||
Version: 1.4.0
|
||||
Release: 4
|
||||
Release: 5
|
||||
Summary: Pluggable Authentication Modules for Linux
|
||||
License: BSD and GPLv2+
|
||||
URL: http://www.linux-pam.org/
|
||||
@ -26,6 +26,8 @@ Patch4: pam_faillock-fix-build-on-musl.patch
|
||||
Patch5: pam_modutil_check_user_in_passwd-avoid-timing-attack.patch
|
||||
Patch6: Prevent-SEGFAULT-for-unknown-UID.patch
|
||||
Patch7: change-ndbm-to-gdbm.patch
|
||||
Patch6000: backport-Move-read_passwords-function-from-pam_unix-to-pam_inline.h.patch
|
||||
Patch6001: backport-add-helper-to-handle-SELinux.patch
|
||||
|
||||
BuildRequires: autoconf automake libtool bison flex sed cracklib-devel gdbm-devel
|
||||
BuildRequires: perl-interpreter pkgconfig gettext-devel libtirpc-devel libnsl2-devel
|
||||
@ -140,6 +142,7 @@ fi
|
||||
%{_sbindir}/faillock
|
||||
%{_sbindir}/mkhomedir_helper
|
||||
%{_sbindir}/pam_namespace_helper
|
||||
%attr(0755,root,root) %{_sbindir}/pwhistory_helper
|
||||
%dir %{_moduledir}
|
||||
%{_moduledir}/pam*.so
|
||||
%{_moduledir}/pam_filter/
|
||||
@ -177,6 +180,9 @@ fi
|
||||
|
||||
|
||||
%changelog
|
||||
* Mon May 17 2021 shixuantong <shixuantong@huawei.com> - 1.4.0-5
|
||||
- fix error in change-ndbm-to-gdbm.patch and sync community patch
|
||||
|
||||
* Fri Jan 8 2021 wangchen <wangchen137@huawei.com> - 1.4.0-4
|
||||
- Use gdbm
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user