From 2f3534248cfca18c52b6e23b3844e23d69106fe1 Mon Sep 17 00:00:00 2001 From: dongyuzhen Date: Tue, 28 Jun 2022 15:02:37 +0800 Subject: [PATCH] add sm3 crypt support --- add-sm3-crypt-support.patch | 392 ++++++++++++++++++++++++++++++++++++ pam.spec | 12 +- 2 files changed, 402 insertions(+), 2 deletions(-) create mode 100644 add-sm3-crypt-support.patch diff --git a/add-sm3-crypt-support.patch b/add-sm3-crypt-support.patch new file mode 100644 index 0000000..a28462e --- /dev/null +++ b/add-sm3-crypt-support.patch @@ -0,0 +1,392 @@ +From 163031d0338a49b4390dc380840c4c7d615f6775 Mon Sep 17 00:00:00 2001 +From: houmingyong +Date: Fri, 29 Oct 2021 10:43:32 +0800 +Subject: [PATCH] add sm3 crypt support + +--- + modules/pam_unix/pam_unix.8.xml | 17 +++- + modules/pam_unix/pam_unix.8 | 9 +- + modules/pam_unix/passverify.c | 5 +- + modules/pam_unix/support.c | 4 +- + modules/pam_unix/support.h | 6 +- + xtests/Makefile.am | 6 +- + xtests/tst-pam_unix5.c | 151 ++++++++++++++++++++++++++++++++ + xtests/tst-pam_unix5.pamd | 5 ++ + xtests/tst-pam_unix5.sh | 41 +++++++++ + 9 files changed, 234 insertions(+), 10 deletions(-) + create mode 100644 xtests/tst-pam_unix5.c + create mode 100644 xtests/tst-pam_unix5.pamd + create mode 100755 xtests/tst-pam_unix5.sh + +diff --git a/modules/pam_unix/pam_unix.8.xml b/modules/pam_unix/pam_unix.8.xml +index fa02c3a..07dfa28 100644 +--- a/modules/pam_unix/pam_unix.8.xml ++++ b/modules/pam_unix/pam_unix.8.xml +@@ -368,7 +368,22 @@ + function. + + ++ ++ ++ ++ ++ ++ ++ ++ When a user changes their password next, ++ encrypt it with the SM3 algorithm. The ++ SM3 algorithm must be supported by the ++ crypt3 ++ function. ++ ++ + ++ + + + +@@ -376,7 +391,7 @@ + + + Set the optional number of rounds of the SHA256, SHA512, +- blowfish, gost-yescrypt, and yescrypt password hashing ++ blowfish, gost-yescrypt, yescrypt and SM3 password hashing + algorithms to + n. + +diff --git a/modules/pam_unix/pam_unix.8 b/modules/pam_unix/pam_unix.8 +index b396b66..e2aab34 100644 +--- a/modules/pam_unix/pam_unix.8 ++++ b/modules/pam_unix/pam_unix.8 +@@ -201,9 +201,16 @@ When a user changes their password next, encrypt it with the yescrypt algorithm\ + function\&. + .RE + .PP ++\fBsm3\fR ++.RS 4 ++When a user changes their password next, encrypt it with the SM3 algorithm\&. The SM3 algorithm must be supported by the ++\fBcrypt\fR(3) ++function\&. ++.RE ++.PP + \fBrounds=\fR\fB\fIn\fR\fR + .RS 4 +-Set the optional number of rounds of the SHA256, SHA512, blowfish, gost\-yescrypt, and yescrypt password hashing algorithms to ++Set the optional number of rounds of the SHA256, SHA512, blowfish, gost\-yescrypt, yescrypt and SM3 password hashing algorithms to + \fIn\fR\&. + .RE + .PP +diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c +index 4094b31..fc2eaff 100644 +--- a/modules/pam_unix/passverify.c ++++ b/modules/pam_unix/passverify.c +@@ -450,6 +450,8 @@ PAMH_ARG_DECL(char * create_password_hash, + algoid = "$5$"; + } else if (on(UNIX_SHA512_PASS, ctrl)) { + algoid = "$6$"; ++ } else if (on(UNIX_SM3_PASS, ctrl)) { ++ algoid = "$sm3$"; + } else { /* must be crypt/bigcrypt */ + char tmppass[9]; + char *crypted; +@@ -509,7 +511,8 @@ PAMH_ARG_DECL(char * create_password_hash, + on(UNIX_GOST_YESCRYPT_PASS, ctrl) ? "gost_yescrypt" : + on(UNIX_BLOWFISH_PASS, ctrl) ? "blowfish" : + on(UNIX_SHA256_PASS, ctrl) ? "sha256" : +- on(UNIX_SHA512_PASS, ctrl) ? "sha512" : algoid); ++ on(UNIX_SHA512_PASS, ctrl) ? "sha512" : ++ on(UNIX_SM3_PASS, ctrl) ? "sm3" : algoid); + if(sp) { + memset(sp, '\0', strlen(sp)); + } +diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c +index 41db1f0..2af3aea 100644 +--- a/modules/pam_unix/support.c ++++ b/modules/pam_unix/support.c +@@ -99,7 +99,7 @@ unsigned long long _set_ctrl(pam_handle_t *pamh, int flags, int *remember, + free (val); + + /* read number of rounds for crypt algo */ +- if (rounds && (on(UNIX_SHA256_PASS, ctrl) || on(UNIX_SHA512_PASS, ctrl))) { ++ if (rounds && (on(UNIX_SHA256_PASS, ctrl) || on(UNIX_SHA512_PASS, ctrl) || on(UNIX_SM3_PASS, ctrl))) { + val = pam_modutil_search_key(pamh, LOGIN_DEFS, "SHA_CRYPT_MAX_ROUNDS"); + + if (val) { +@@ -194,7 +194,7 @@ unsigned long long _set_ctrl(pam_handle_t *pamh, int flags, int *remember, + } else if (on(UNIX_BLOWFISH_PASS, ctrl)) { + if (*rounds < 4 || *rounds > 31) + *rounds = 5; +- } else if (on(UNIX_SHA256_PASS, ctrl) || on(UNIX_SHA512_PASS, ctrl)) { ++ } else if (on(UNIX_SHA256_PASS, ctrl) || on(UNIX_SHA512_PASS, ctrl) || on(UNIX_SM3_PASS, ctrl)) { + if ((*rounds < 1000) || (*rounds == INT_MAX)) { + /* don't care about bogus values */ + *rounds = 0; +diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h +index 19754dc..c18750c 100644 +--- a/modules/pam_unix/support.h ++++ b/modules/pam_unix/support.h +@@ -101,10 +101,11 @@ typedef struct { + #define UNIX_GOST_YESCRYPT_PASS 31 /* new password hashes will use gost-yescrypt */ + #define UNIX_YESCRYPT_PASS 32 /* new password hashes will use yescrypt */ + #define UNIX_NULLRESETOK 33 /* allow empty password if password reset is enforced */ ++#define UNIX_SM3_PASS 34 /* new password hashes will use SM3 */ + /* -------------- */ +-#define UNIX_CTRLS_ 34 /* number of ctrl arguments defined */ ++#define UNIX_CTRLS_ 35 /* number of ctrl arguments defined */ + +-#define UNIX_DES_CRYPT(ctrl) (off(UNIX_MD5_PASS,ctrl)&&off(UNIX_BIGCRYPT,ctrl)&&off(UNIX_SHA256_PASS,ctrl)&&off(UNIX_SHA512_PASS,ctrl)&&off(UNIX_BLOWFISH_PASS,ctrl)&&off(UNIX_GOST_YESCRYPT_PASS,ctrl)&&off(UNIX_YESCRYPT_PASS,ctrl)) ++#define UNIX_DES_CRYPT(ctrl) (off(UNIX_MD5_PASS,ctrl)&&off(UNIX_BIGCRYPT,ctrl)&&off(UNIX_SHA256_PASS,ctrl)&&off(UNIX_SHA512_PASS,ctrl)&&off(UNIX_BLOWFISH_PASS,ctrl)&&off(UNIX_GOST_YESCRYPT_PASS,ctrl)&&off(UNIX_YESCRYPT_PASS,ctrl)&&off(UNIX_SM3_PASS,ctrl)) + + static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = + { +@@ -145,6 +146,7 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = + /* UNIX_GOST_YESCRYPT_PASS */ {"gost_yescrypt", _ALL_ON_^(015660420000ULL), 04000000000, 1}, + /* UNIX_YESCRYPT_PASS */ {"yescrypt", _ALL_ON_^(015660420000ULL), 010000000000, 1}, + /* UNIX_NULLRESETOK */ {"nullresetok", _ALL_ON_, 020000000000, 0}, ++/* UNIX_SM3_PASS */ {"sm3", _ALL_ON_^(015660420000ULL), 040000000000, 1}, + }; + + #define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag) +diff --git a/xtests/Makefile.am b/xtests/Makefile.am +index 2e942e8..a327850 100644 +--- a/xtests/Makefile.am ++++ b/xtests/Makefile.am +@@ -15,9 +15,9 @@ EXTRA_DIST = run-xtests.sh tst-pam_dispatch1.pamd tst-pam_dispatch2.pamd \ + tst-pam_dispatch5.pamd \ + tst-pam_cracklib1.pamd tst-pam_cracklib2.pamd \ + tst-pam_unix1.pamd tst-pam_unix2.pamd tst-pam_unix3.pamd \ +- tst-pam_unix4.pamd \ ++ tst-pam_unix4.pamd tst-pam_unix5.pamd \ + tst-pam_unix1.sh tst-pam_unix2.sh tst-pam_unix3.sh \ +- tst-pam_unix4.sh \ ++ tst-pam_unix4.sh tst-pam_unix5.sh \ + access.conf tst-pam_access1.pamd tst-pam_access1.sh \ + tst-pam_access2.pamd tst-pam_access2.sh \ + tst-pam_access3.pamd tst-pam_access3.sh \ +@@ -41,7 +41,7 @@ EXTRA_DIST = run-xtests.sh tst-pam_dispatch1.pamd tst-pam_dispatch2.pamd \ + XTESTS = tst-pam_dispatch1 tst-pam_dispatch2 tst-pam_dispatch3 \ + tst-pam_dispatch4 tst-pam_dispatch5 \ + tst-pam_cracklib1 tst-pam_cracklib2 \ +- tst-pam_unix1 tst-pam_unix2 tst-pam_unix3 tst-pam_unix4 \ ++ tst-pam_unix1 tst-pam_unix2 tst-pam_unix3 tst-pam_unix4 tst-pam_unix5 \ + tst-pam_access1 tst-pam_access2 tst-pam_access3 \ + tst-pam_access4 tst-pam_limits1 tst-pam_succeed_if1 \ + tst-pam_group1 tst-pam_authfail tst-pam_authsucceed \ +diff --git a/xtests/tst-pam_unix5.c b/xtests/tst-pam_unix5.c +new file mode 100644 +index 0000000..6e6e378 +--- /dev/null ++++ b/xtests/tst-pam_unix5.c +@@ -0,0 +1,151 @@ ++/* ++ * 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. ++ */ ++ ++/* ++ * Check password authtok. ++ */ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* A conversation function which uses an internally-stored value for ++ the responses. */ ++static int ++fake_conv (int num_msg, const struct pam_message **msgm, ++ struct pam_response **response, void *appdata_ptr) ++{ ++ struct pam_response *reply; ++ int count; ++ ++ /* Sanity test. */ ++ if (num_msg <= 0) ++ return PAM_CONV_ERR; ++ ++ /* Allocate memory for the responses. */ ++ reply = calloc (num_msg, sizeof (struct pam_response)); ++ if (reply == NULL) ++ return PAM_CONV_ERR; ++ ++ /* Each prompt elicits the same response */ ++ for (count = 0; count < num_msg; ++count) ++ { ++ if (msgm[count]->msg_style == PAM_PROMPT_ECHO_OFF) ++ { ++ reply[count].resp_retcode = 0; ++ reply[count].resp = strdup(appdata_ptr); ++ } else { ++ reply[count].resp_retcode = 0; ++ reply[count].resp = strdup(""); ++ } ++ } ++ ++ /* Set the pointers in the response structure and return. */ ++ *response = reply; ++ return PAM_SUCCESS; ++} ++ ++static struct pam_conv conv = { ++ fake_conv, ++ NULL ++}; ++ ++ ++/* Check that errors of optional modules are ignored and that ++ required modules after a sufficient one are not executed. */ ++ ++int ++main(int argc, char *argv[]) ++{ ++ pam_handle_t *pamh=NULL; ++ const char *user="tstpamunix"; ++ int retval; ++ int debug = 0; ++ int fail; ++ struct passwd *pwd; ++ ++ if (argc < 2 || (*argv[1] != 'f' && ++ *argv[1] != 'p')) ++ { ++ fprintf (stderr, "Need fail or pass argument.\n"); ++ return 2; ++ } ++ ++ fail = *argv[1] == 'f'; ++ ++ if (argc > 2 && strcmp (argv[2], "-d") == 0) ++ debug = 1; ++ ++ pwd = getpwnam (user); ++ ++ if (pwd == NULL) ++ { ++ if (debug) ++ fprintf (stderr, "unix5: Missing tstpamunix user.\n"); ++ return 2; ++ } ++ ++ conv.appdata_ptr = "zhangsan@123"; ++ retval = pam_start("tst-pam_unix5", user, &conv, &pamh); ++ if (retval != PAM_SUCCESS) ++ { ++ if (debug) ++ fprintf (stderr, "unix5: pam_start returned %d\n", retval); ++ return 1; ++ } ++ ++ retval = pam_chauthtok (pamh, PAM_SILENT); ++ if ((!fail && retval != PAM_SUCCESS) || (fail && retval == PAM_SUCCESS)) ++ { ++ if (debug) ++ fprintf (stderr, "unix5-1: pam_chauthtok returned %d\n", retval); ++ return 1; ++ } ++ ++ retval = pam_end (pamh,retval); ++ if (retval != PAM_SUCCESS) ++ { ++ if (debug) ++ fprintf (stderr, "unix5: pam_end returned %d\n", retval); ++ return 1; ++ } ++ return 0; ++} +diff --git a/xtests/tst-pam_unix5.pamd b/xtests/tst-pam_unix5.pamd +new file mode 100644 +index 0000000..4c77a6c +--- /dev/null ++++ b/xtests/tst-pam_unix5.pamd +@@ -0,0 +1,5 @@ ++#%PAM-1.0 ++auth required pam_unix.so ++account required pam_unix.so ++password required pam_unix.so sm3 ++session required pam_unix.so +diff --git a/xtests/tst-pam_unix5.sh b/xtests/tst-pam_unix5.sh +new file mode 100755 +index 0000000..a6be19b +--- /dev/null ++++ b/xtests/tst-pam_unix5.sh +@@ -0,0 +1,41 @@ ++#!/bin/sh ++ ++# testcase1 modify password, desire password encrypt with sm3 ++/usr/sbin/useradd tstpamunix ++# this run must successfully change the password ++./tst-pam_unix5 pass ++RET=$? ++# verify tstpamunix hash algo ++if test -z "$(nl /etc/shadow | sed -n '/tstpamunix:$sm3/p')"; then ++ /usr/sbin/userdel -r tstpamunix 2> /dev/null ++ exit 1 ++fi ++# testcase2 config valid rounds, desire password encrypt with sm3 and rounds ++sed -i 's/password.*/& rounds=6666/g' /etc/pam.d/tst-pam_unix5 ++./tst-pam_unix5 pass ++RET=$? ++if test -z "$(nl /etc/shadow | sed -n '/tstpamunix:$sm3$rounds=6666/p')"; then ++ /usr/sbin/userdel -r tstpamunix 2> /dev/null ++ exit 1 ++fi ++ ++# testcase3 config rounds=999, desire password encrypt with sm3, but without rounds ++sed -i 's/rounds=6666/rounds=999/g' /etc/pam.d/tst-pam_unix5 ++./tst-pam_unix5 pass ++RET=$? ++if test -z "$(nl /etc/shadow | sed -n '/tstpamunix:$sm3/p')"; then ++ /usr/sbin/userdel -r tstpamunix 2> /dev/null ++ exit 1 ++fi ++ ++# testcase4 config rounds=10000000, desire password encrypt with sm3, but with rounds=9999999 ++sed -i 's/rounds=999/rounds=10000000/g' /etc/pam.d/tst-pam_unix5 ++./tst-pam_unix5 pass ++RET=$? ++if test -z "$(nl /etc/shadow | sed -n '/tstpamunix:$sm3$rounds=9999999/p')"; then ++ /usr/sbin/userdel -r tstpamunix 2> /dev/null ++ exit 1 ++fi ++ ++/usr/sbin/userdel -r tstpamunix 2> /dev/null ++exit $RET +-- +2.27.0 + diff --git a/pam.spec b/pam.spec index 8c97d32..61c26ba 100644 --- a/pam.spec +++ b/pam.spec @@ -4,7 +4,7 @@ %define _pamconfdir %{_sysconfdir}/pam.d Name: pam Version: 1.4.0 -Release: 5 +Release: 6 Summary: Pluggable Authentication Modules for Linux License: BSD and GPLv2+ URL: http://www.linux-pam.org/ @@ -18,6 +18,8 @@ Source15: pamtmp.conf Source16: postlogin.pamd Source18: https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt +Provides: %{name}-sm3 = %{version}-%{release} + Patch0: bugfix-pam-1.1.8-faillock-failmessages.patch Patch1: bugfix-pam-1.1.8-faillock-systemtime.patch Patch2: fix-login-message.patch @@ -29,12 +31,15 @@ Patch7: change-ndbm-to-gdbm.patch Patch8: zh_CN_po_fix_str_meaning_error.patch Patch6000: backport-Move-read_passwords-function-from-pam_unix-to-pam_inline.h.patch Patch6001: backport-add-helper-to-handle-SELinux.patch + +Patch9000: add-sm3-crypt-support.patch + BuildRequires: autoconf automake libtool bison flex sed cracklib-devel BuildRequires: perl-interpreter pkgconfig gettext-devel libtirpc-devel libnsl2-devel BuildRequires: audit-libs-devel libselinux-devel libdb-devel BuildRequires: linuxdoc-tools elinks libxslt docbook-style-xsl docbook-dtds -Requires: cracklib libpwquality coreutils glibc audit libselinux +Requires: cracklib libpwquality coreutils glibc audit libselinux libxcrypt-sm3 %description PAM (Pluggable Authentication Modules) is a system of libraries that @@ -179,6 +184,9 @@ fi %changelog +* Tue Jun 28 2022 dongyuzhen - 1.4.0-6 +- add sm3 crypt support + * Thu Jul 29 2021 guoqinglan - 1.4.0-5 - Fix zh_CN msgstr meaning error -- Gitee