Skip to content

Releases: shadow-maint/shadow

4.19.0: Herve

30 Dec 17:09
4.19.0

Choose a tag to compare

Release 4.19.0

Breaking changes:

  • Remove support for escaped newlines in configuration files.
    It never worked correctly.
    b0a7ce5 (2025-12-05; "lib/, po/: Remove fgetsx() and fputsx()")

  • Some user names and group names are too dangerous and are rejected,
    even with --badname.
    25aea74 (2025-12-25; "lib/chkname.c, src/: Strictly disallow really bad names")

Future breaking changes:

  • SHA512 and SHA256 will be supported unconditionally in the next
    release. The build-time flag '--with-sha-crypt' will be removed.
    See #1452.

Support:

  • Several years ago, there were talks about deprecating su(1) and
    login(1), back when this project was maintained as part of Debian.
    However, nothing was clearly stated, and there were doubts about the
    status of these programs. Let's clarify them now.

    Our implementations of su(1) and login(1) are fully supported, and we
    don't have any plans to remove them. They are NOT deprecated.
    See #464.

Deprecations:

  • groupmems(8)
    The program will be removed in a future release.
    See #1343.

  • logoutd(8)
    The program will be removed in the next release.
    See #999,
    and #1344.

  • DES
    This hashing algorithm has been deprecated for a long time,
    and support for it will be removed in a future release.
    See #1456

  • MD5
    This hashing algorithm has been deprecated for a long time,
    and support for it will be removed in a future release.
    See #1457

  • login.defs(5): MD_CRYPT_ENAB
    This feature had been deprecated for decades. It will be
    removed in a future release.
    The command-line equivalents (-m, --md5) of this feature in
    chpasswd(8) and chgpasswd(8) will also be removed in a future
    release.
    See #1455.

  • login.defs(5): PASS_MAX_LEN
    This feature is ignored except for DES. Once DES is removed,
    it makes no sense keeping it. It may be removed in a future
    release.

  • Password aging
    Scientific research shows that periodic password expiration
    leads to predictable password patterns, and that even in a
    theoretical scenario where that wouldn't happen the gains in
    security are mathematically negligible.
    https://people.scs.carleton.ca/~paulv/papers/expiration-authorcopy.pdf

    Modern security standards, such as NIST SP 800-63B-4 in the USA,
    prohibit periodic password expiration.
    https://pages.nist.gov/800-63-4/sp800-63b.html#passwordver
    https://pages.nist.gov/800-63-FAQ/#q-b05
    https://www.ncsc.gov.uk/collection/passwords/updating-your-approach#PasswordGuidance:UpdatingYourApproach-Don'tenforceregularpasswordexpiry

    To align with these, we're deprecating the ability to
    periodically expire passwords. The specifics and long-term
    roadmap are currently being discussed, and we invite feedback
    from users, particularly from those in regulated environments.
    See #1432.

    This deprecation includes the following programs and features:

     expiry(1)
     chage(1):
             -I,--inactive (also the interactive version)
             -m,--mindays (also the interactive version)
             -M,--maxdays (also the interactive version)
             -W,--warndays (also the interactive version)
     passwd(1):
             -k,--keep-tokens
             -n,--mindays
             -x,--maxdays
             -i,--inactive
             -w,--warndays
     useradd(8):
             -f,--inactive
     usermod(8):
             -f,--inactive
     login.defs(5):
             PASS_MIN_DAYS
             PASS_MAX_DAYS
             PASS_WARN_AGE
     /etc/default/useradd:
             INACTIVE
     shadow(5):
             sp_lstchg: Restrict to just the values 0 and empty.
             sp_min
             sp_max
             sp_warn
             sp_inact
    

    We recognize that many users operate in environments with
    regulatory or contractual requirements that still mandate
    password aging. To minimize disruption, these features will
    remain functional for a significant period. However, we
    encourage administrators to review their internal policies,
    talk to their regulators if appropriate, and participate in the
    roadmap discussion linked above.

herve rc1

07 Dec 16:55
4.19.0-rc1

Choose a tag to compare

herve rc1 Pre-release
Pre-release

What's Changed

New Contributors

Full Changelog: 4.18.0...4.19.0-rc1

4.18.0: Gorgonzola

24 Jun 20:40
4.18.0

Choose a tag to compare

What's Changed

New Contributors

Full Changelog: 4.17.4...4.18.0

4.18.0-rc2

23 Jun 17:41
4.18.0-rc2

Choose a tag to compare

4.18.0-rc2 Pre-release
Pre-release

This is a pre-release for last minute testing. 4.18.0-rc1 appeared to go smoothly, so I expect no issues. We expect to release 4.18.0 tomorrow.

What's Changed

New Contributors

Full Changelog: 4.17.4...4.18.0-rc2

Pre-release 4.18.0-rc1

08 Jun 18:29
4.18.0-rc1

Choose a tag to compare

Pre-release

This is a pre-release for testing by distributions. New release to follow later this month.

Release 4.17.4

19 Mar 19:12
4.17.4

Choose a tag to compare

Changes since 4.17.3:

Alejandro Colomar (12):
      Revert "lib/, src/: Use local time for human-readable dates"
      lib/getdate.y: Ignore time-zone information and use UTC
      src/chfn.c: Partially revert "lib/, src/: Use strsep(3) instead of its pattern"
      src/chfn.c: Use stpsep() instead of its pattern
      src/chfn.c: Add local variable to refer to the separated field
      src/chfn.c: copy_field(): Rename local variable
      lib/commonio.c: Rely on the POSIX.1-2008 behavior of realpath(3)
      lib/fs/readlink/: readlinknul(): Use ssize_t to simplify
      autogen.sh: Promote -Wsign-compare to an error
      lib/sizeof.h: ssizeof(): Add signed variant of sizeof
      src/lastlog.c: Use ssizeof() to avoid a -Wsign-compare diagnostic
      tests/unit/test_xasprintf.c: Fix sign-mismatch diagnostic

Chris Hofstaedtler (2):
      configure.ac: stop checking for utmp location
      configure.ac: be deterministic about passwd location

Iker Pedrosa (3):
      lib/, src/: update audit messages
      lib/: audit function for groups
      src/: update group audit messages

Michael Vetter (1):
      doc/: Remove list of distributions

Serge Hallyn (1):
      release 4.17.4

4.17.3

24 Feb 14:16
4.17.3

Choose a tag to compare

4.17.2 was accidentally created as an unsigned tag. 4.17.3 is created from current master branch with a signed tag.

4.17.2

11 Jan 16:00

Choose a tag to compare

What's Changed

New Contributors

  • @scottdotweb made their first contribution in #1164

Full Changelog: 4.17.1...4.17.2

4.17.1

31 Dec 19:40
4.17.1

Choose a tag to compare

What's Changed

Full Changelog: 4.17.0...4.17.1

4.17.0: Fleuron de Bruges

25 Dec 22:49

Choose a tag to compare

Alejandro Colomar (182):
lib/csrand.c: Fix the lower part of the domain of csrand_uniform()
tests/unit/test_xasprintf.c: Cosmetic
tests/unit/test_xasprintf.c: Fix use of volatile pointer
Makefile.am: Use 'dist-hook' to clean up <tests/unit/Makefile>
lib/typetraits.h: Add macros that give information about a type
tests/unit/test_typetraits.c: Add tests for typetraits.h macros
src/: Use str2[u]l() instead of atoi(3)
lib/get_gid.c: get_gid(): Reimplement in terms of a2i()
lib/, libsubid/, po/, src/: get_gid(): Move function to "atoi/getnum.h"
lib/: Don't open-code get_gid()
lib/get_pid.c: get_pid(): Reimplement in terms of a2i()
lib/: get_pid(): Move function to "atoi/getnum.h"
lib/atoi/getnum.[ch]: get_fd(): Add function for parsing a file descriptor from a string
lib/get_pid.c: get_pidfd_from_fd(): Don't open-code get_fd()
src/usermod.c: getulong_range(): Reimplement in terms of a2ul()
lib/get_uid.c: get_uid(): Reimplement in terms of a2i()
lib/, po/, src/: get_uid(): Move function to "atoi/getnum.h"
lib/limits.c: setrlimit_value(): Reimplement in terms of a2i()
src/usermod.c: Fix const correctness
src/get_subid_owners.c: Use uid_t for holding UIDs (and GIDs)
lib/string/sprintf/, lib/, src/, tests/: Move all sprintf(3)-like APIs to a subdirectory
lib/string/strcpy/, lib/, src/, tests/: Move all copying APIs to a subdirectory
src/su.c: save_caller_context(): Remove unused parameter
src/logoutd.c: Remove unused variable
src/login.c: Remove dead code
lib/, src/: Reduce scope of local variables
lib/shadow.c: my_sgetspent(): Clarify that we're assigning an empty string
lib/getdate.y: NULL doesn't need a cast
lib/, src/: Always pass NULL to time(2)
lib/failure.c: failprint(): Remove dead code
lib/, src/: Add missing include
lib/: Use REALLOCF() instead of its pattern
lib/commonio.c: commonio_open(): MALLOC() and REALLOCF() already set ENOMEM
lib/, src/: Use strchrnul(3) instead of its pattern
src/useradd.c: tallylog_reset(): Use Basename() instead of its pattern
lib/, src/: Use strsep(3) instead of its pattern
lib/gshadow.c: build_list(): Fix forever loop on ENOMEM
lib/gshadow.c: build_list(): Fix REALLOC() nmemb calculation
src/groupmems.c: Fix number of elements in allocation
src/: Use xasprintf() instead of its pattern
lib/string/strcpy/strncat.[ch]: STRNCAT(): Add macro
lib/string/strdup/: XSTRNDUP(), STRNDUPA(): Add macros
lib/utmp.c: Use XSTRNDUP() instead of its pattern
lib/utmp.c: prepare_utmp(): Use xstrdup() instead of its pattern
src/newusers.c: Exit on ENOMEM, by calling xstrdup() instead of strdup(3)
src/logoutd.c: Use STRNDUPA() instead of its pattern
src/logoutd.c: Use STRNCAT() instead of its pattern
lib/string/strcpy/zustr2stp.[ch], tests/: Remove ZUSTR2STP()
lib/string/strdup/xstrdup.[ch], lib/, src/: Move xstrdup() to its own file
lib/alloc.[ch]: xmalloc(): Remove unused function
lib/alloc/, lib/, src/, tests/: Organize the allocation APIs in a new subdirectory
lib/: Use multi-line macro definitions
lib/: Use [[gnu::alloc_size(...)]] on allocation functions
src/: Remove dead code
lib/gshadow.c: Use XREALLOC() instead of silently continuing on ENOMEM
lib/attr.h: Use C23-style attributes
lib/idmapping.c: Use long constants in prctl(2), and remove 0s
Remove id(1)
Remove groups(1)
lib/getdef.c: getdef_num(): Simplify, by calling a2si() instead of str2sl()
lib/getdef.c: getdef_unum(): Fix wrong limit check
lib/getdef.c: getdef_long(): Simplify, by calling a2sl() instead of str2sl()
lib/limits.c: set_prio(): Simplify, by calling str2si() instead of str2sl()
lib/limits.c: set_umask(): Simplify, by calling str2i(mode_t, ) instead of str2ul()
lib/limits.c: setup_limits(): Simplify, by calling a2si() instead of str2sl()
lib/limits.c: setup_limits(): Simplify, by calling str2si() instead of str2sl()
lib/limits.c: setup_limits(): Simplify, by calling str2i(mode_t, ) instead of str2ul()
lib/sgetspent.c: sgetspent(): Simplify, by calling a2sl() instead of str2sl()
lib/shadow.c: my_sgetspent(): Merge 'else {if}' into 'else if'
lib/shadow.c: my_sgetspent(): Remove dead code
lib/shadow.c: my_sgetspent(): Simplify error handling
src/: Use get_[ug]id() where appropriate
src/useradd.c: Simplify, by calling a2sl() instead of str2sl()
src/passwd.c: Simplify, by calling a2sl() instead of str2sl()
src/usermod.c: Simplify, by calling a2sl() instead of str2sl()
src/faillog.c: Simplify, by calling str2sh() instead of str2sl()
src/chage.c: Simplify, by calling a2sl() instead of str2sl()
lib/string/strchr/: stp[c]spn(), strrspn(), strnul(): Add macros and functions
lib/getdef.c: def_load(): Use stp[c]spn() instead of their patterns
src/login_nopam.c: login_access(): Simplify, calling strchr(3)
lib/sssd.c: Style fixes
lib/, src/: Use strrspn() instead of its pattern
contrib, lib/, src/, tests/: Use stpcpy(3) instead of its pattern
contrib/adduser.c: main(): Use strcpy/cat(3) instead of their pattern
lib/port.c: getttyuser(): Remove dead code
lib/port.c: getttyuser(): Use goto to break out of nested loops
lib/port.c: getportent(): Rename goto label
lib/port.c: getportent(): Remove obvious comments
lib/port.c: getportent(): Make sure there are at least 2 ':' in the line
lib/port.c: getportent(): Make sure the aren't too many fields in the CSV
lib/port.c: getportent(): Use equivalent code to parse equally-formatted fields
lib/port.c: getttyuser(): Use pointer arithmetic to simplify
lib/port.c: getportent(): Align variables
lib/port.c: getportent(): Use strsep(3) instead of its pattern
lib/string/strtok/stpsep.[ch]: stpsep(): Add function
lib/, src/: Use stpsep() instead of its pattern
lib/attr.h: ATTR_STRING(): It only accepts one argument
lib/string/strchr/stpcspn.[ch]: stpcspn(): Remove unused function
src/suauth.c: check_su_auth(): Use stpsep() to simplify
lib/nss.c: nss_init(): Use stpsep() instead of strtok_r(3)
src/useradd.c: Use stpsep() to simplify
src/login_nopam.c: login_access(): Use stpsep() to simplify
lib/limits.c: check_logins(): Report LOGIN_ERROR_LOGIN if str2ul() ERANGE
lib/idmapping.c: get_map_ranges(): Rename local variable
lib/idmapping.c: get_map_ranges(): Move range check to a2ul() calls
lib/idmapping.c: get_map_ranges(): Move range check to a2ul() call
lib/idmapping.c: get_map_ranges(): Move range check to a2ul() call
lib/idmapping.c: get_map_ranges(): Remove dead code
lib/idmapping.c: get_map_ranges(): Simplify iterator variables
lib/idmapping.c: get_map_ranges(): Don't exit() from a library function
src/usermod.c: Rename identifiers ralated to [ug]id's
src/usermod.c: Use id_t for parsing uid_t and gid_t
lib/atoi/, : Split files
lib/atoi/strtoi/, tests/: strto[iu](): 1 is an invalid base
lib/chkname.c: An object cannot expand further than the universe in which it resides
lib/, src/: Use local time for human-readable dates
lib/, src/: Use %F instead of %Y-%m-%d with strftime(3)
src/chage.c: print_day_as_date(): Simplify error handling
src/chage.c: print_day_as_date(): Handle errors from strfime(3)
lib/string/strftime.h: STRFTIME(): Tighten macro definition
po/es.po: wsfix
lib/: Move memzero.[ch] under lib/string/memset/
lib/string/memset/: memzero(), strzero(): Return the pointer
lib/: Chain free(strzero(s))
man/userdel.8.xml: Reword '-f'
lib/chkname.c: is_valid
{user,group}_name(): Set errno to distinguish the reasons
src/: Invert logic to improve readability
src/: Recommend --badname only if it is useful
src/useradd.c: Add fmkomstemp() to fix mode of </etc/default/useradd>
src/check_subid_range.c: Remove dead code
lib/, src/: Use stpspn() instead of its pattern
lib/port.c: portcmp(): Use strcmp(3) instead of its pattern
lib/gshadow.c: endsgent(): Remove dead assignment
src/suauth.c: check_su_auth(): Use strspn(3) instead of its pattern
src/suauth.c: check_su_auth(): Use pointers to simplify
doc/contributions/introduction.md: Fix typo in link
lib/alloc/realloc
.h: Rename macro parameter
lib/alloc/realloc*.h: Always reallocate at least 1 byte
lib/fields.c: Remove dead code
lib/getdef.c: Remove dead code
lib/loginprompt.c: login_prompt(): Use strtcpy() instead of its pattern
lib/fs/readlink/: readlinknul(): Add function
lib/fs/readlink/readlinknul.h: READLINKNUL(): Add macro
lib/: Use readlinknul() instead of its pattern
lib/: Use READLINKNUL() instead of its pattern
lib/fs/readlink/, lib/: areadlink(): Move and rename function
lib/fs/readlink/areadlink.h: Cosmetic changes
lib/fs/readlink/areadlink.h: areadlink(): Use PATH_MAX instead of a magic value
lib/string/strcmp/: streq(): Add function
lib/string/strchr/: strchrcnt(): Add function
lib/list.c: comma_to_list(): Use strchrcnt() instead of its pattern
lib/gshadow.c: endsgent(): Invert logic to reduce indentation
src/login_nopam.c: Rely on the system's MAXHOSTNAMELEN
lib/shadow.c: my_sgetspent(): There can be only one!
lib/, src/: Use NULL instead of 0 as a null pointer constant
share/container-build.sh: Fix path
src/login_nopam.c: resolve_hostname(): Use NI_MAXHOST instea...

Read more