- Rebase to version 4.13

- SPDX license migration

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
This commit is contained in:
Iker Pedrosa 2022-11-09 10:12:41 +01:00
parent 47d965b5dc
commit d3e12503af
13 changed files with 58 additions and 418 deletions

2
.gitignore vendored
View File

@ -20,3 +20,5 @@ shadow-4.1.4.2.tar.bz2
/shadow-4.11.1.tar.xz.asc
/shadow-4.12.3.tar.xz
/shadow-4.12.3.tar.xz.asc
/shadow-4.13.tar.xz
/shadow-4.13.tar.xz.asc

View File

@ -1,22 +0,0 @@
diff -up shadow-4.11.1/src/chage.c.null-tm shadow-4.11.1/src/chage.c
diff -up shadow-4.11.1/src/lastlog.c.null-tm shadow-4.11.1/src/lastlog.c
--- shadow-4.11.1/src/lastlog.c.null-tm 2022-01-03 15:31:56.348555620 +0100
+++ shadow-4.11.1/src/lastlog.c 2022-01-03 15:38:41.262229024 +0100
@@ -151,9 +151,12 @@ static void print_one (/*@null@*/const s
ll_time = ll.ll_time;
tm = localtime (&ll_time);
- strftime (ptime, sizeof (ptime), "%a %b %e %H:%M:%S %z %Y", tm);
- cp = ptime;
-
+ if (tm == NULL) {
+ cp = "(unknown)";
+ } else {
+ strftime (ptime, sizeof (ptime), "%a %b %e %H:%M:%S %z %Y", tm);
+ cp = ptime;
+ }
if (ll.ll_time == (time_t) 0) {
cp = _("**Never logged in**\0");
}
diff -up shadow-4.11.1/src/passwd.c.null-tm shadow-4.11.1/src/passwd.c
diff -up shadow-4.11.1/src/usermod.c.null-tm shadow-4.11.1/src/usermod.c

View File

@ -1,32 +0,0 @@
From e503fd574b7dbf6b21b1168e20938f0922807916 Mon Sep 17 00:00:00 2001
From: Xiami <1927254+Xiami2012@users.noreply.github.com>
Date: Wed, 5 Oct 2022 18:11:28 +0800
Subject: [PATCH] chage: Fix regression in print_date
Introduced by c6c8130db4319613a91dd07bbb845f6c33c5f79f
After removing snprintf, the format string should get unescaped once.
Fixes #564
Reporter and patch author: DerMouse (github.com/DerMouse)
---
src/chage.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/chage.c b/src/chage.c
index 8cf67794..01570d72 100644
--- a/src/chage.c
+++ b/src/chage.c
@@ -228,7 +228,7 @@ static void print_date (time_t date)
if (NULL == tp) {
(void) printf ("time_t: %lu\n", (unsigned long)date);
} else {
- (void) strftime (buf, sizeof buf, iflg ? "%%Y-%%m-%%d" : "%%b %%d, %%Y", tp);
+ (void) strftime (buf, sizeof buf, iflg ? "%Y-%m-%d" : "%b %d, %Y", tp);
(void) puts (buf);
}
}
--
2.37.3

View File

@ -1,100 +0,0 @@
diff -up shadow-4.12.3/libmisc/chkname.c.goodname shadow-4.12.3/libmisc/chkname.c
--- shadow-4.12.3/libmisc/chkname.c.goodname 2022-06-19 16:16:48.000000000 +0200
+++ shadow-4.12.3/libmisc/chkname.c 2022-08-22 16:00:27.646087971 +0200
@@ -32,26 +32,44 @@ static bool is_valid_name (const char *n
}
/*
- * User/group names must match [a-z_][a-z0-9_-]*[$]
- */
+ * User/group names must match gnu e-regex:
+ * [a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,30}[a-zA-Z0-9_.$-]?
+ *
+ * as a non-POSIX, extension, allow "$" as the last char for
+ * sake of Samba 3.x "add machine script"
+ *
+ * Also do not allow fully numeric names or just "." or "..".
+ */
+ int numeric;
- if (('\0' == *name) ||
- !((('a' <= *name) && ('z' >= *name)) || ('_' == *name))) {
+ if ('\0' == *name ||
+ ('.' == *name && (('.' == name[1] && '\0' == name[2]) ||
+ '\0' == name[1])) ||
+ !((*name >= 'a' && *name <= 'z') ||
+ (*name >= 'A' && *name <= 'Z') ||
+ (*name >= '0' && *name <= '9') ||
+ *name == '_' ||
+ *name == '.')) {
return false;
}
+ numeric = isdigit(*name);
+
while ('\0' != *++name) {
- if (!(( ('a' <= *name) && ('z' >= *name) ) ||
- ( ('0' <= *name) && ('9' >= *name) ) ||
- ('_' == *name) ||
- ('-' == *name) ||
- ( ('$' == *name) && ('\0' == *(name + 1)) )
+ if (!((*name >= 'a' && *name <= 'z') ||
+ (*name >= 'A' && *name <= 'Z') ||
+ (*name >= '0' && *name <= '9') ||
+ *name == '_' ||
+ *name == '.' ||
+ *name == '-' ||
+ (*name == '$' && name[1] == '\0')
)) {
return false;
}
+ numeric &= isdigit(*name);
}
- return true;
+ return !numeric;
}
bool is_valid_user_name (const char *name)
diff -up shadow-4.12.3/man/groupadd.8.xml.goodname shadow-4.12.3/man/groupadd.8.xml
--- shadow-4.12.3/man/groupadd.8.xml.goodname 2022-08-22 16:00:27.646087971 +0200
+++ shadow-4.12.3/man/groupadd.8.xml 2022-08-22 16:01:59.301779733 +0200
@@ -64,10 +64,12 @@
files as needed.
</para>
<para>
- Groupnames must start with a lower case letter or an underscore,
- followed by lower case letters, digits, underscores, or dashes.
- They can end with a dollar sign.
- In regular expression terms: [a-z_][a-z0-9_-]*[$]?
+ Groupnames may contain only lower and upper case letters, digits,
+ underscores, or dashes. They can end with a dollar sign.
+
+ Dashes are not allowed at the beginning of the groupname.
+ Fully numeric groupnames and groupnames . or .. are
+ also disallowed.
</para>
<para>
Groupnames may only be up to &GROUP_NAME_MAX_LENGTH; characters long.
diff -up shadow-4.12.3/man/useradd.8.xml.goodname shadow-4.12.3/man/useradd.8.xml
--- shadow-4.12.3/man/useradd.8.xml.goodname 2022-08-22 14:46:57.000000000 +0200
+++ shadow-4.12.3/man/useradd.8.xml 2022-08-22 16:00:27.646087971 +0200
@@ -692,10 +692,14 @@
</para>
<para>
- Usernames must start with a lower case letter or an underscore,
- followed by lower case letters, digits, underscores, or dashes.
- They can end with a dollar sign.
- In regular expression terms: [a-z_][a-z0-9_-]*[$]?
+ Usernames may contain only lower and upper case letters, digits,
+ underscores, or dashes. They can end with a dollar sign.
+
+ Dashes are not allowed at the beginning of the username.
+ Fully numeric usernames and usernames . or .. are
+ also disallowed. It is not recommended to use usernames beginning
+ with . character as their home directories will be hidden in
+ the <command>ls</command> output.
</para>
<para>
Usernames may only be up to 32 characters long.

View File

@ -1,86 +0,0 @@
diff -up shadow-4.12.3/lib/defines.h.long-entry shadow-4.12.3/lib/defines.h
--- shadow-4.12.3/lib/defines.h.long-entry 2022-08-18 23:51:37.000000000 +0200
+++ shadow-4.12.3/lib/defines.h 2022-08-22 16:12:27.412522768 +0200
@@ -335,6 +335,9 @@ extern char *strerror ();
# endif
#endif
+/* Maximum length of passwd entry */
+#define PASSWD_ENTRY_MAX_LENGTH 32768
+
#ifdef HAVE_SECURE_GETENV
# define shadow_getenv(name) secure_getenv(name)
# else
diff -up shadow-4.12.3/lib/pwio.c.long-entry shadow-4.12.3/lib/pwio.c
--- shadow-4.12.3/lib/pwio.c.long-entry 2022-06-19 16:16:48.000000000 +0200
+++ shadow-4.12.3/lib/pwio.c 2022-08-22 16:12:27.412522768 +0200
@@ -56,7 +56,10 @@ static int passwd_put (const void *ent,
|| (pw->pw_gid == (gid_t)-1)
|| (valid_field (pw->pw_gecos, ":\n") == -1)
|| (valid_field (pw->pw_dir, ":\n") == -1)
- || (valid_field (pw->pw_shell, ":\n") == -1)) {
+ || (valid_field (pw->pw_shell, ":\n") == -1)
+ || (strlen (pw->pw_name) + strlen (pw->pw_passwd) +
+ strlen (pw->pw_gecos) + strlen (pw->pw_dir) +
+ strlen (pw->pw_shell) + 100 > PASSWD_ENTRY_MAX_LENGTH)) {
return -1;
}
diff -up shadow-4.12.3/lib/sgetpwent.c.long-entry shadow-4.12.3/lib/sgetpwent.c
--- shadow-4.12.3/lib/sgetpwent.c.long-entry 2022-08-09 00:30:40.000000000 +0200
+++ shadow-4.12.3/lib/sgetpwent.c 2022-08-22 16:14:10.955309200 +0200
@@ -34,7 +34,7 @@
struct passwd *sgetpwent (const char *buf)
{
static struct passwd pwent;
- static char pwdbuf[1024];
+ static char pwdbuf[PASSWD_ENTRY_MAX_LENGTH];
int i;
char *cp;
char *fields[NFIELDS];
@@ -44,8 +44,10 @@ struct passwd *sgetpwent (const char *bu
* the password structure remain valid.
*/
- if (strlen (buf) >= sizeof pwdbuf)
+ if (strlen (buf) >= sizeof pwdbuf) {
+ fprintf (stderr, "Too long passwd entry encountered, file corruption?\n");
return 0; /* fail if too long */
+ }
strcpy (pwdbuf, buf);
/*
diff -up shadow-4.12.3/lib/sgetspent.c.long-entry shadow-4.12.3/lib/sgetspent.c
--- shadow-4.12.3/lib/sgetspent.c.long-entry 2022-06-19 16:16:54.000000000 +0200
+++ shadow-4.12.3/lib/sgetspent.c 2022-08-22 16:12:27.413522776 +0200
@@ -25,7 +25,7 @@
*/
struct spwd *sgetspent (const char *string)
{
- static char spwbuf[1024];
+ static char spwbuf[PASSWD_ENTRY_MAX_LENGTH];
static struct spwd spwd;
char *fields[FIELDS];
char *cp;
@@ -37,6 +37,7 @@ struct spwd *sgetspent (const char *stri
*/
if (strlen (string) >= sizeof spwbuf) {
+ fprintf (stderr, "Too long shadow entry encountered, file corruption?\n");
return 0; /* fail if too long */
}
strcpy (spwbuf, string);
diff -up shadow-4.12.3/lib/shadowio.c.long-entry shadow-4.12.3/lib/shadowio.c
--- shadow-4.12.3/lib/shadowio.c.long-entry 2022-06-19 16:16:48.000000000 +0200
+++ shadow-4.12.3/lib/shadowio.c 2022-08-22 16:12:27.413522776 +0200
@@ -56,7 +56,9 @@ static int shadow_put (const void *ent,
if ( (NULL == sp)
|| (valid_field (sp->sp_namp, ":\n") == -1)
- || (valid_field (sp->sp_pwdp, ":\n") == -1)) {
+ || (valid_field (sp->sp_pwdp, ":\n") == -1)
+ || (strlen (sp->sp_namp) + strlen (sp->sp_pwdp) +
+ 1000 > PASSWD_ENTRY_MAX_LENGTH)) {
return -1;
}

View File

@ -1,42 +0,0 @@
From ebf9b232b012725d2be5e750876c7336cf1c37fd Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Wed, 24 Aug 2022 13:21:01 +0200
Subject: [PATCH] useradd: Do not reset non-existent data in {last,fail}log
useradd does not create the files if they don't exist, but if they exist
it will reset user data even if the data did not exist before creating
a hole and an explicitly zero'd data point resulting (especially for
high UIDs) in a lot of zeros ending up in containers and tarballs.
---
src/useradd.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/useradd.c b/src/useradd.c
index 6eaeb533..39a744ee 100644
--- a/src/useradd.c
+++ b/src/useradd.c
@@ -1996,8 +1996,9 @@ static void faillog_reset (uid_t uid)
struct faillog fl;
int fd;
off_t offset_uid = (off_t) (sizeof fl) * uid;
+ struct stat st;
- if (access (FAILLOG_FILE, F_OK) != 0) {
+ if (stat (FAILLOG_FILE, &st) != 0 || st.st_size <= offset_uid) {
return;
}
@@ -2033,8 +2034,9 @@ static void lastlog_reset (uid_t uid)
int fd;
off_t offset_uid = (off_t) (sizeof ll) * uid;
uid_t max_uid;
+ struct stat st;
- if (access (LASTLOG_FILE, F_OK) != 0) {
+ if (stat (LASTLOG_FILE, &st) != 0 || st.st_size <= offset_uid) {
return;
}
--
2.37.3

View File

@ -0,0 +1,35 @@
diff -up shadow-4.13/lib/semanage.c.default-range shadow-4.13/lib/semanage.c
--- shadow-4.13/lib/semanage.c.default-range 2022-11-09 09:37:11.955314964 +0100
+++ shadow-4.13/lib/semanage.c 2022-11-09 09:47:59.130645564 +0100
@@ -122,6 +122,7 @@ static int semanage_user_mod (semanage_h
goto done;
}
+#if 0
if (semanage_mls_enabled(handle)) {
ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE);
if (ret != 0) {
@@ -131,6 +132,7 @@ static int semanage_user_mod (semanage_h
goto done;
}
}
+#endif
ret = semanage_seuser_set_sename (handle, seuser, seuser_name);
if (ret != 0) {
@@ -181,6 +183,7 @@ static int semanage_user_add (semanage_h
goto done;
}
+#if 0
if (semanage_mls_enabled(handle)) {
ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE);
if (ret != 0) {
@@ -190,6 +193,7 @@ static int semanage_user_add (semanage_h
goto done;
}
}
+#endif
ret = semanage_seuser_set_sename (handle, seuser, seuser_name);
if (ret != 0) {

View File

@ -1,15 +0,0 @@
diff -up shadow-4.6/src/usermod.c.move-home shadow-4.6/src/usermod.c
--- shadow-4.6/src/usermod.c.move-home 2018-05-28 14:59:05.594076665 +0200
+++ shadow-4.6/src/usermod.c 2018-05-28 15:00:28.479837392 +0200
@@ -1845,6 +1845,11 @@ static void move_home (void)
Prog, prefix_user_home, prefix_user_newhome);
fail_exit (E_HOMEDIR);
}
+ } else {
+ fprintf (stderr,
+ _("%s: The previous home directory (%s) does "
+ "not exist or is inaccessible. Move cannot be completed.\n"),
+ Prog, prefix_user_home);
}
}

View File

@ -1,34 +0,0 @@
diff -up shadow-4.6/libmisc/find_new_gid.c.min-limit shadow-4.6/libmisc/find_new_gid.c
--- shadow-4.6/libmisc/find_new_gid.c.min-limit 2018-04-29 18:42:37.000000001 +0200
+++ shadow-4.6/libmisc/find_new_gid.c 2018-11-06 10:51:20.554963292 +0100
@@ -82,6 +82,13 @@ static int get_ranges (bool sys_group, g
(unsigned long) *max_id);
return EINVAL;
}
+ /*
+ * Zero is reserved for root and the allocation algorithm does not
+ * work right with it.
+ */
+ if (*min_id == 0) {
+ *min_id = (gid_t) 1;
+ }
} else {
/* Non-system groups */
diff -up shadow-4.6/libmisc/find_new_uid.c.min-limit shadow-4.6/libmisc/find_new_uid.c
--- shadow-4.6/libmisc/find_new_uid.c.min-limit 2018-04-29 18:42:37.000000001 +0200
+++ shadow-4.6/libmisc/find_new_uid.c 2018-11-06 10:51:39.341399569 +0100
@@ -82,6 +82,13 @@ static int get_ranges (bool sys_user, ui
(unsigned long) *max_id);
return EINVAL;
}
+ /*
+ * Zero is reserved for root and the allocation algorithm does not
+ * work right with it.
+ */
+ if (*min_id == 0) {
+ *min_id = (uid_t) 1;
+ }
} else {
/* Non-system users */

View File

@ -1,11 +0,0 @@
diff -up shadow-4.8/lib/getdef.c.login-prompt shadow-4.8/lib/getdef.c
--- shadow-4.8/lib/getdef.c.login-prompt 2020-01-13 10:38:44.852796681 +0100
+++ shadow-4.8/lib/getdef.c 2020-01-13 10:39:54.472612511 +0100
@@ -98,6 +98,7 @@ static struct itemdef def_table[] = {
{"LASTLOG_UID_MAX", NULL},
{"LOGIN_RETRIES", NULL},
{"LOGIN_TIMEOUT", NULL},
+ {"LOGIN_PLAIN_PROMPT", NULL},
{"LOG_OK_LOGINS", NULL},
{"LOG_UNKFAIL_ENAB", NULL},
{"MAIL_DIR", NULL},

View File

@ -1,35 +0,0 @@
diff -up shadow-4.9/lib/semanage.c.default-range shadow-4.9/lib/semanage.c
--- shadow-4.9/lib/semanage.c.default-range 2021-07-22 23:55:35.000000000 +0200
+++ shadow-4.9/lib/semanage.c 2021-08-02 12:43:16.822817392 +0200
@@ -143,6 +143,7 @@ static int semanage_user_mod (semanage_h
goto done;
}
+#if 0
ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE);
if (ret != 0) {
fprintf (shadow_logfd,
@@ -150,6 +151,7 @@ static int semanage_user_mod (semanage_h
ret = 1;
goto done;
}
+#endif
ret = semanage_seuser_set_sename (handle, seuser, seuser_name);
if (ret != 0) {
@@ -200,6 +202,7 @@ static int semanage_user_add (semanage_h
goto done;
}
+#if 0
ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE);
if (ret != 0) {
fprintf (shadow_logfd,
@@ -208,6 +211,7 @@ static int semanage_user_add (semanage_h
ret = 1;
goto done;
}
+#endif
ret = semanage_seuser_set_sename (handle, seuser, seuser_name);
if (ret != 0) {

View File

@ -1,9 +1,9 @@
Summary: Utilities for managing accounts and shadow password files
Name: shadow-utils
Version: 4.12.3
Release: 3%{?dist}
Version: 4.13
Release: 1%{?dist}
Epoch: 2
License: BSD and GPLv2+
License: BSD-3-Clause AND GPL-2.0-or-later
URL: https://github.com/shadow-maint/shadow
Source0: https://github.com/shadow-maint/shadow/releases/download/v%{version}/shadow-%{version}.tar.xz
Source1: https://github.com/shadow-maint/shadow/releases/download/v%{version}/shadow-%{version}.tar.xz.asc
@ -19,34 +19,18 @@ Source6: shadow-utils.HOME_MODE.xml
### Patches ###
# Misc small changes - most probably non-upstreamable
Patch0: shadow-4.12.3-redhat.patch
# https://github.com/shadow-maint/shadow/commit/cfc981df2afc615e3792b918e9ee49e631b0a3a9
Patch1: shadow-4.12.3-goodname.patch
# SElinux related - upstreamability unknown
Patch3: shadow-4.9-default-range.patch
Patch1: shadow-4.13-default-range.patch
# Misc manual page changes - non-upstreamable
Patch4: shadow-4.9-manfix.patch
Patch2: shadow-4.9-manfix.patch
# Date parsing improvement - could be upstreamed
Patch5: shadow-4.2.1-date-parsing.patch
# Additional error message - could be upstreamed
Patch6: shadow-4.6-move-home.patch
Patch3: shadow-4.2.1-date-parsing.patch
# Audit message changes - upstreamability unknown
Patch7: shadow-4.11.1-audit-update.patch
Patch4: shadow-4.11.1-audit-update.patch
# Changes related to password unlocking - could be upstreamed
Patch8: shadow-4.5-usermod-unlock.patch
Patch5: shadow-4.5-usermod-unlock.patch
# Additional SElinux related changes - upstreamability unknown
Patch9: shadow-4.12.3-selinux-perms.patch
# Handle NULL return from *time funcs - upstreamable
Patch10: shadow-4.11.1-null-tm.patch
# Handle /etc/passwd corruption - could be upstreamed
Patch11: shadow-4.12.3-long-entry.patch
# Limit uid/gid allocation to non-zero - could be upstreamed
Patch12: shadow-4.6-sysugid-min-limit.patch
# Ignore LOGIN_PLAIN_PROMPT in login.defs - upstreamability unknown
Patch13: shadow-4.8-ignore-login-prompt.patch
# https://github.com/shadow-maint/shadow/commit/ebf9b232b012725d2be5e750876c7336cf1c37fd
Patch14: shadow-4.12.3-useradd-stop-last-fail-log-reset.patch
# https://github.com/shadow-maint/shadow/commit/e503fd574b7dbf6b21b1168e20938f0922807916
Patch15: shadow-4.12.3-chage-print-date-regression.patch
Patch6: shadow-4.12.3-selinux-perms.patch
### Dependencies ###
Requires: audit-libs >= 1.6.5
@ -108,20 +92,12 @@ Development files for shadow-utils-subid.
%prep
%setup -q -n shadow-%{version}
%patch0 -p1 -b .redhat
%patch1 -p1 -b .goodname
%patch3 -p1 -b .default-range
%patch4 -p1 -b .manfix
%patch5 -p1 -b .date-parsing
%patch6 -p1 -b .move-home
%patch7 -p1 -b .audit-update
%patch8 -p1 -b .unlock
%patch9 -p1 -b .selinux-perms
%patch10 -p1 -b .null-tm
%patch11 -p1 -b .long-entry
%patch12 -p1 -b .sysugid-min-limit
%patch13 -p1 -b .login-prompt
%patch14 -p1 -b .useradd-stop-last-fail-log-reset
%patch15 -p1 -b .chage-print-date-regression
%patch1 -p1 -b .default-range
%patch2 -p1 -b .manfix
%patch3 -p1 -b .date-parsing
%patch4 -p1 -b .audit-update
%patch5 -p1 -b .unlock
%patch6 -p1 -b .selinux-perms
iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8
cp -f doc/HOWTO.utf8 doc/HOWTO
@ -295,6 +271,10 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a
%{_libdir}/libsubid.so
%changelog
* Wed Nov 9 2022 Iker Pedrosa <ipedrosa@redhat.com> - 2:4.13-1
- Rebase to version 4.13
- SPDX license migration
* Wed Oct 5 2022 Iker Pedrosa <ipedrosa@redhat.com> - 2:4.12.3-3
- chage: Fix regression in print_date. Resolves: #2129336

View File

@ -1,2 +1,2 @@
SHA512 (shadow-4.12.3.tar.xz) = 0529889258f54e7634762dc154aa680d55f8c5f1654afadd1b7431cfbb890a3b1ba27c7ff4b7c45986e4ee2289946db2e420b23ed13e4e5b15800a1fb3a013bc
SHA512 (shadow-4.12.3.tar.xz.asc) = d3f294d86c0e2174c88809810a801737c01cd01f9cadbe7b1ae382b2745d86e2e30c0718fa6489c2abb65500ed94c8ac1961d05243b5a1800c966384c69281c9
SHA512 (shadow-4.13.tar.xz) = 2949a728c3312bef13d23138d6b79caf402781b1cb179e33b5be546c1790971ec20778d0e9cd3dbe09691d928ffcbe88e60da42fab58c69a90d5ebe5e3e2ab8e
SHA512 (shadow-4.13.tar.xz.asc) = f8549c4e699c65721d53946d61b6127712572f7ad9ee13018ef3a25307002992aa727471c948d1bb22dcddf112715bed387d28f436123f30e153ae6bc0cd3648