Compare commits
48 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81de782d1e | ||
|
|
d83eccdded | ||
|
|
681b66b13c | ||
|
|
2958bd050b | ||
|
|
38f493aff2 | ||
|
|
19bac44dde | ||
|
|
b49712ed32 | ||
|
|
cdbe1310cc | ||
|
|
b462f5335f | ||
|
|
115a4e89e2 | ||
|
|
9d935d9be1 | ||
|
|
7eca1112fb | ||
|
|
fe2a266c50 | ||
|
|
e97df9b1ec | ||
|
|
d048459d36 | ||
|
|
88fa0651bf | ||
|
|
4e038f3ae7 | ||
|
|
6c6c8d3a33 | ||
|
|
a8a921184f | ||
|
|
cbd2472b7c | ||
|
|
a0efca4581 | ||
|
|
4e1da34601 | ||
|
|
b03df41906 | ||
|
|
8ca6eea938 | ||
|
|
1c2ad5e6b9 | ||
|
|
991fee82df | ||
|
|
b52ce71c27 | ||
|
|
e78d22469f | ||
|
|
c4e8b411d4 | ||
|
|
3a51b90145 | ||
|
|
a2cd3e9ef0 | ||
|
|
1cbb562c23 | ||
|
|
558977bb2b | ||
|
|
332709da65 | ||
|
|
a74587a4ea | ||
|
|
1e13749483 | ||
|
|
1a1b8fcc36 | ||
|
|
23262b249c | ||
|
|
5687be5f31 | ||
|
|
e293aa9cfc | ||
|
|
edf7547ad5 | ||
|
|
2cac079ef4 | ||
|
|
5afc1c5b5f | ||
|
|
3025fefc41 | ||
|
|
00a5cff244 | ||
|
|
fc0ed79e5d | ||
|
|
13c618465d | ||
|
|
3c52a84ff8 |
21
ChangeLog
21
ChangeLog
@@ -1,3 +1,24 @@
|
||||
2019-12-01 Serge Hallyn <serge@hallyn.com>
|
||||
|
||||
* Release 4.8
|
||||
* Initial optional bcrypt support.
|
||||
* Make build/install of 'su' optional.
|
||||
* Fix for vipw not resuming correctly when suspended
|
||||
* Sync password field descriptions in manpages
|
||||
* Check for valid shell argument in useradd
|
||||
* Allow translation of new strings through POTFILES.in
|
||||
* Migrate to itstool for translations
|
||||
* Migrate to new SELinux api
|
||||
* Support --enable-vendordir
|
||||
* pwck: Only check homedir if set and not a system user
|
||||
* Support nonstandard usernames
|
||||
* sget{pw,gr}ent: check for data at EOL
|
||||
* Add YYY-MM-DD support in chage
|
||||
* Fix failing chmod calls for suidubins
|
||||
* Fix --sbindir and --bindir for binary installations
|
||||
* Fix LASTLOG_UID_MAX in login.defs
|
||||
* Fix configure error with dash
|
||||
|
||||
2019-06-13 Serge Hallyn <serge@hallyn.com>
|
||||
|
||||
* Release 4.7
|
||||
|
||||
33
configure.ac
33
configure.ac
@@ -1,6 +1,6 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_PREREQ([2.64])
|
||||
AC_INIT([shadow], [4.7], [pkg-shadow-devel@lists.alioth.debian.org], [],
|
||||
AC_INIT([shadow], [4.8], [pkg-shadow-devel@lists.alioth.debian.org], [],
|
||||
[https://github.com/shadow-maint/shadow])
|
||||
AM_INIT_AUTOMAKE([1.11 foreign dist-xz])
|
||||
AM_SILENT_RULES([yes])
|
||||
@@ -247,7 +247,7 @@ AC_ARG_ENABLE(subordinate-ids,
|
||||
[enable_subids="maybe"]
|
||||
)
|
||||
|
||||
AC_ARG_WITH(audit,
|
||||
AC_ARG_WITH(audit,
|
||||
[AC_HELP_STRING([--with-audit], [use auditing support @<:@default=yes if found@:>@])],
|
||||
[with_audit=$withval], [with_audit=maybe])
|
||||
AC_ARG_WITH(libpam,
|
||||
@@ -277,6 +277,9 @@ AC_ARG_WITH(libcrack,
|
||||
AC_ARG_WITH(sha-crypt,
|
||||
[AC_HELP_STRING([--with-sha-crypt], [allow the SHA256 and SHA512 password encryption algorithms @<:@default=yes@:>@])],
|
||||
[with_sha_crypt=$withval], [with_sha_crypt=yes])
|
||||
AC_ARG_WITH(bcrypt,
|
||||
[AC_HELP_STRING([--with-bcrypt], [allow the bcrypt password encryption algorithm @<:@default=no@:>@])],
|
||||
[with_bcrypt=$withval], [with_bcrypt=no])
|
||||
AC_ARG_WITH(nscd,
|
||||
[AC_HELP_STRING([--with-nscd], [enable support for nscd @<:@default=yes@:>@])],
|
||||
[with_nscd=$withval], [with_nscd=yes])
|
||||
@@ -286,6 +289,9 @@ AC_ARG_WITH(sssd,
|
||||
AC_ARG_WITH(group-name-max-length,
|
||||
[AC_HELP_STRING([--with-group-name-max-length], [set max group name length @<:@default=16@:>@])],
|
||||
[with_group_name_max_length=$withval], [with_group_name_max_length=yes])
|
||||
AC_ARG_WITH(su,
|
||||
[AC_HELP_STRING([--with-su], [build and install su program and man page @<:@default=yes@:>@])],
|
||||
[with_su=$withval], [with_su=yes])
|
||||
|
||||
if test "$with_group_name_max_length" = "no" ; then
|
||||
with_group_name_max_length=0
|
||||
@@ -301,6 +307,11 @@ if test "$with_sha_crypt" = "yes"; then
|
||||
AC_DEFINE(USE_SHA_CRYPT, 1, [Define to allow the SHA256 and SHA512 password encryption algorithms])
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(USE_BCRYPT, test "x$with_bcrypt" = "xyes")
|
||||
if test "$with_bcrypt" = "yes"; then
|
||||
AC_DEFINE(USE_BCRYPT, 1, [Define to allow the bcrypt password encryption algorithm])
|
||||
fi
|
||||
|
||||
if test "$with_nscd" = "yes"; then
|
||||
AC_CHECK_FUNC(posix_spawn,
|
||||
[AC_DEFINE(USE_NSCD, 1, [Define to support flushing of nscd caches])],
|
||||
@@ -313,6 +324,9 @@ if test "$with_sssd" = "yes"; then
|
||||
[AC_MSG_ERROR([posix_spawn is needed for sssd support])])
|
||||
fi
|
||||
|
||||
AS_IF([test "$with_su" != "no"], AC_DEFINE(WITH_SU, 1, [Build with su])])
|
||||
AM_CONDITIONAL([WITH_SU], [test "x$with_su" != "xno"])
|
||||
|
||||
dnl Check for some functions in libc first, only if not found check for
|
||||
dnl other libraries. This should prevent linking libnsl if not really
|
||||
dnl needed (Linux glibc, Irix), but still link it if needed (Solaris).
|
||||
@@ -321,6 +335,17 @@ AC_SEARCH_LIBS(inet_ntoa, inet)
|
||||
AC_SEARCH_LIBS(socket, socket)
|
||||
AC_SEARCH_LIBS(gethostbyname, nsl)
|
||||
|
||||
AC_CHECK_LIB([econf],[econf_readDirs],[LIBECONF="-leconf"],[LIBECONF=""])
|
||||
if test -n "$LIBECONF"; then
|
||||
ECONF_CPPFLAGS="-DUSE_ECONF=1"
|
||||
AC_ARG_ENABLE([vendordir],
|
||||
AS_HELP_STRING([--enable-vendordir=DIR], [Directory for distribution provided configuration files]),,[])
|
||||
fi
|
||||
AC_SUBST(ECONF_CPPFLAGS)
|
||||
AC_SUBST(LIBECONF)
|
||||
AC_SUBST([VENDORDIR], [$enable_vendordir])
|
||||
AM_CONDITIONAL([HAVE_VENDORDIR], [test "x$enable_vendordir" != x])
|
||||
|
||||
if test "$enable_shadowgrp" = "yes"; then
|
||||
AC_DEFINE(SHADOWGRP, 1, [Define to support the shadow group file.])
|
||||
fi
|
||||
@@ -500,7 +525,7 @@ if test "$with_selinux" != "no"; then
|
||||
AC_MSG_ERROR([libsemanage not found])
|
||||
fi
|
||||
|
||||
if test "$selinux_lib$semanage_lib" == "yesyes" ; then
|
||||
if test "$selinux_lib$semanage_lib" = "yesyes" ; then
|
||||
AC_DEFINE(WITH_SELINUX, 1,
|
||||
[Build shadow with SELinux support])
|
||||
LIBSELINUX="-lselinux"
|
||||
@@ -715,8 +740,10 @@ echo " tcb support (incomplete): $with_tcb"
|
||||
echo " shadow group support: $enable_shadowgrp"
|
||||
echo " S/Key support: $with_skey"
|
||||
echo " SHA passwords encryption: $with_sha_crypt"
|
||||
echo " bcrypt passwords encryption: $with_bcrypt"
|
||||
echo " nscd support: $with_nscd"
|
||||
echo " sssd support: $with_sssd"
|
||||
echo " subordinate IDs support: $enable_subids"
|
||||
echo " use file caps: $with_fcaps"
|
||||
echo " install su: $with_su"
|
||||
echo
|
||||
|
||||
@@ -31,6 +31,15 @@ LOG_OK_LOGINS no
|
||||
#
|
||||
LASTLOG_ENAB yes
|
||||
|
||||
#
|
||||
# Limit the highest user ID number for which the lastlog entries should
|
||||
# be updated.
|
||||
#
|
||||
# No LASTLOG_UID_MAX means that there is no user ID limit for writing
|
||||
# lastlog entries.
|
||||
#
|
||||
#LASTLOG_UID_MAX
|
||||
|
||||
#
|
||||
# Enable checking and display of mailbox status upon login.
|
||||
#
|
||||
@@ -311,6 +320,7 @@ CHFN_RESTRICT rwh
|
||||
# If set to MD5, MD5-based algorithm will be used for encrypting password
|
||||
# If set to SHA256, SHA256-based algorithm will be used for encrypting password
|
||||
# If set to SHA512, SHA512-based algorithm will be used for encrypting password
|
||||
# If set to BCRYPT, BCRYPT-based algorithm will be used for encrypting password
|
||||
# If set to DES, DES-based algorithm will be used for encrypting password (default)
|
||||
# Overrides the MD5_CRYPT_ENAB option
|
||||
#
|
||||
@@ -332,8 +342,23 @@ CHFN_RESTRICT rwh
|
||||
# If only one of the MIN or MAX values is set, then this value will be used.
|
||||
# If MIN > MAX, the highest value will be used.
|
||||
#
|
||||
# SHA_CRYPT_MIN_ROUNDS 5000
|
||||
# SHA_CRYPT_MAX_ROUNDS 5000
|
||||
#SHA_CRYPT_MIN_ROUNDS 5000
|
||||
#SHA_CRYPT_MAX_ROUNDS 5000
|
||||
|
||||
#
|
||||
# Only works if ENCRYPT_METHOD is set to BCRYPT.
|
||||
#
|
||||
# Define the number of BCRYPT rounds.
|
||||
# With a lot of rounds, it is more difficult to brute-force the password.
|
||||
# However, more CPU resources will be needed to authenticate users if
|
||||
# this value is increased.
|
||||
#
|
||||
# If not specified, 13 rounds will be attempted.
|
||||
# If only one of the MIN or MAX values is set, then this value will be used.
|
||||
# If MIN > MAX, the highest value will be used.
|
||||
#
|
||||
#BCRYPT_MIN_ROUNDS 13
|
||||
#BCRYPT_MAX_ROUNDS 13
|
||||
|
||||
#
|
||||
# List of groups to add to the user's supplementary group set
|
||||
|
||||
@@ -6,8 +6,7 @@ pamd_files = \
|
||||
chsh \
|
||||
groupmems \
|
||||
login \
|
||||
passwd \
|
||||
su
|
||||
passwd
|
||||
|
||||
pamd_acct_tools_files = \
|
||||
chage \
|
||||
@@ -29,4 +28,8 @@ pamd_DATA += $(pamd_acct_tools_files)
|
||||
endif
|
||||
endif
|
||||
|
||||
if WITH_SU
|
||||
pamd_files += su
|
||||
endif
|
||||
|
||||
EXTRA_DIST = $(pamd_files) $(pamd_acct_tools_files)
|
||||
|
||||
@@ -6,6 +6,10 @@ DEFS =
|
||||
noinst_LTLIBRARIES = libshadow.la
|
||||
|
||||
libshadow_la_LDFLAGS = -version-info 0:0:0
|
||||
libshadow_la_CPPFLAGS = $(ECONF_CPPFLAGS)
|
||||
if HAVE_VENDORDIR
|
||||
libshadow_la_CPPFLAGS += -DVENDORDIR=\"$(VENDORDIR)\"
|
||||
endif
|
||||
|
||||
libshadow_la_SOURCES = \
|
||||
commonio.c \
|
||||
|
||||
@@ -65,6 +65,9 @@
|
||||
case '1':
|
||||
method = "MD5";
|
||||
break;
|
||||
case '2':
|
||||
method = "BCRYPT";
|
||||
break;
|
||||
case '5':
|
||||
method = "SHA256";
|
||||
break;
|
||||
|
||||
80
lib/getdef.c
80
lib/getdef.c
@@ -40,6 +40,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#ifdef USE_ECONF
|
||||
#include <libeconf.h>
|
||||
#endif
|
||||
#include "getdef.h"
|
||||
/*
|
||||
* A configuration item definition.
|
||||
@@ -107,6 +110,10 @@ static struct itemdef def_table[] = {
|
||||
#ifdef USE_SHA_CRYPT
|
||||
{"SHA_CRYPT_MAX_ROUNDS", NULL},
|
||||
{"SHA_CRYPT_MIN_ROUNDS", NULL},
|
||||
#endif
|
||||
#ifdef USE_BCRYPT
|
||||
{"BCRYPT_MAX_ROUNDS", NULL},
|
||||
{"BCRYPT_MIN_ROUNDS", NULL},
|
||||
#endif
|
||||
{"SUB_GID_COUNT", NULL},
|
||||
{"SUB_GID_MAX", NULL},
|
||||
@@ -152,11 +159,20 @@ static struct itemdef knowndef_table[] = {
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
#ifdef USE_ECONF
|
||||
#ifdef VENDORDIR
|
||||
static const char* vendordir = VENDORDIR;
|
||||
#else
|
||||
static const char* vendordir = NULL;
|
||||
#endif
|
||||
static const char* sysconfdir = "/etc";
|
||||
#else
|
||||
#ifndef LOGINDEFS
|
||||
#define LOGINDEFS "/etc/login.defs"
|
||||
#endif
|
||||
|
||||
static const char* def_fname = LOGINDEFS; /* login config defs file */
|
||||
#endif
|
||||
static bool def_loaded = false; /* are defs already loaded? */
|
||||
|
||||
/* local function prototypes */
|
||||
@@ -433,7 +449,27 @@ out:
|
||||
|
||||
void setdef_config_file (const char* file)
|
||||
{
|
||||
#ifdef USE_ECONF
|
||||
size_t len;
|
||||
char* cp;
|
||||
|
||||
len = strlen(file) + strlen(sysconfdir) + 2;
|
||||
cp = malloc(len);
|
||||
if (cp == NULL)
|
||||
exit (13);
|
||||
snprintf(cp, len, "%s/%s", file, sysconfdir);
|
||||
sysconfdir = cp;
|
||||
#ifdef VENDORDIR
|
||||
len = strlen(file) + strlen(vendordir) + 2;
|
||||
cp = malloc(len);
|
||||
if (cp == NULL)
|
||||
exit (13);
|
||||
snprintf(cp, len, "%s/%s", file, vendordir);
|
||||
vendordir = cp;
|
||||
#endif
|
||||
#else
|
||||
def_fname = file;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -444,9 +480,16 @@ void setdef_config_file (const char* file)
|
||||
|
||||
static void def_load (void)
|
||||
{
|
||||
#ifdef USE_ECONF
|
||||
econf_file *defs_file = NULL;
|
||||
econf_err error;
|
||||
char **keys;
|
||||
size_t key_number;
|
||||
#else
|
||||
int i;
|
||||
FILE *fp;
|
||||
char buf[1024], *name, *value, *s;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set the initialized flag.
|
||||
@@ -454,6 +497,42 @@ static void def_load (void)
|
||||
*/
|
||||
def_loaded = true;
|
||||
|
||||
#ifdef USE_ECONF
|
||||
|
||||
error = econf_readDirs (&defs_file, vendordir, sysconfdir, "login", "defs", " \t", "#");
|
||||
if (error) {
|
||||
if (error == ECONF_NOFILE)
|
||||
return;
|
||||
|
||||
SYSLOG ((LOG_CRIT, "cannot open login definitions [%s]",
|
||||
econf_errString(error)));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if ((error = econf_getKeys(defs_file, NULL, &key_number, &keys))) {
|
||||
SYSLOG ((LOG_CRIT, "cannot read login definitions [%s]",
|
||||
econf_errString(error)));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < key_number; i++) {
|
||||
char *value;
|
||||
|
||||
econf_getStringValue(defs_file, NULL, keys[i], &value);
|
||||
|
||||
/*
|
||||
* Store the value in def_table.
|
||||
*
|
||||
* Ignore failures to load the login.defs file.
|
||||
* The error was already reported to the user and to
|
||||
* syslog. The tools will just use their default values.
|
||||
*/
|
||||
(void)putdef_str (keys[i], value);
|
||||
}
|
||||
|
||||
econf_free (keys);
|
||||
econf_free (defs_file);
|
||||
#else
|
||||
/*
|
||||
* Open the configuration definitions file.
|
||||
*/
|
||||
@@ -517,6 +596,7 @@ static void def_load (void)
|
||||
}
|
||||
|
||||
(void) fclose (fp);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -336,6 +336,7 @@ extern /*@observer@*/const char *crypt_make_salt (/*@null@*//*@observer@*/const
|
||||
#ifdef WITH_SELINUX
|
||||
extern int set_selinux_file_context (const char *dst_name);
|
||||
extern int reset_selinux_file_context (void);
|
||||
extern int check_selinux_permit (const char *perm_name);
|
||||
#endif
|
||||
|
||||
/* semanage.c */
|
||||
|
||||
100
lib/selinux.c
100
lib/selinux.c
@@ -34,6 +34,7 @@
|
||||
#include "defines.h"
|
||||
|
||||
#include <selinux/selinux.h>
|
||||
#include <selinux/context.h>
|
||||
#include "prototypes.h"
|
||||
|
||||
|
||||
@@ -98,6 +99,105 @@ int reset_selinux_file_context (void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Log callback for libselinux internal error reporting.
|
||||
*/
|
||||
__attribute__((__format__ (printf, 2, 3)))
|
||||
static int selinux_log_cb (int type, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
char *buf;
|
||||
int r;
|
||||
#ifdef WITH_AUDIT
|
||||
static int selinux_audit_fd = -2;
|
||||
#endif
|
||||
|
||||
va_start (ap, fmt);
|
||||
r = vasprintf (&buf, fmt, ap);
|
||||
va_end (ap);
|
||||
|
||||
if (r < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WITH_AUDIT
|
||||
if (-2 == selinux_audit_fd) {
|
||||
selinux_audit_fd = audit_open ();
|
||||
|
||||
if (-1 == selinux_audit_fd) {
|
||||
/* You get these only when the kernel doesn't have
|
||||
* audit compiled in. */
|
||||
if ( (errno != EINVAL)
|
||||
&& (errno != EPROTONOSUPPORT)
|
||||
&& (errno != EAFNOSUPPORT)) {
|
||||
|
||||
(void) fputs (_("Cannot open audit interface.\n"),
|
||||
stderr);
|
||||
SYSLOG ((LOG_WARN, "Cannot open audit interface."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (-1 != selinux_audit_fd) {
|
||||
if (SELINUX_AVC == type) {
|
||||
if (audit_log_user_avc_message (selinux_audit_fd,
|
||||
AUDIT_USER_AVC, buf, NULL, NULL,
|
||||
NULL, 0) > 0) {
|
||||
goto skip_syslog;
|
||||
}
|
||||
} else if (SELINUX_ERROR == type) {
|
||||
if (audit_log_user_avc_message (selinux_audit_fd,
|
||||
AUDIT_USER_SELINUX_ERR, buf, NULL, NULL,
|
||||
NULL, 0) > 0) {
|
||||
goto skip_syslog;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
SYSLOG ((LOG_WARN, "libselinux: %s", buf));
|
||||
|
||||
skip_syslog:
|
||||
free (buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* check_selinux_permit - Check whether SELinux grants the given
|
||||
* operation
|
||||
*
|
||||
* Parameter is the SELinux permission name, e.g. rootok
|
||||
*
|
||||
* Returns 0 when permission is granted
|
||||
* or something failed but running in
|
||||
* permissive mode
|
||||
*/
|
||||
int check_selinux_permit (const char *perm_name)
|
||||
{
|
||||
char *user_context_str;
|
||||
int r;
|
||||
|
||||
if (0 == is_selinux_enabled ()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
selinux_set_callback (SELINUX_CB_LOG, (union selinux_callback) selinux_log_cb);
|
||||
|
||||
if (getprevcon (&user_context_str) != 0) {
|
||||
fprintf (stderr,
|
||||
_("%s: can not get previous SELinux process context: %s\n"),
|
||||
Prog, strerror (errno));
|
||||
SYSLOG ((LOG_WARN,
|
||||
"can not get previous SELinux process context: %s",
|
||||
strerror (errno)));
|
||||
return (security_getenforce () != 0);
|
||||
}
|
||||
|
||||
r = selinux_check_access (user_context_str, user_context_str, "passwd", perm_name, NULL);
|
||||
freecon (user_context_str);
|
||||
return r;
|
||||
}
|
||||
|
||||
#else /* !WITH_SELINUX */
|
||||
extern int errno; /* warning: ANSI C forbids an empty source file */
|
||||
#endif /* !WITH_SELINUX */
|
||||
|
||||
@@ -136,7 +136,7 @@ struct group *sgetgrent (const char *buf)
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
if (i < (NFIELDS - 1) || *grpfields[2] == '\0') {
|
||||
if (i < (NFIELDS - 1) || *grpfields[2] == '\0' || cp != NULL) {
|
||||
return (struct group *) 0;
|
||||
}
|
||||
grent.gr_name = grpfields[0];
|
||||
|
||||
@@ -90,6 +90,11 @@ struct passwd *sgetpwent (const char *buf)
|
||||
}
|
||||
}
|
||||
|
||||
/* something at the end, columns over shot */
|
||||
if( cp != NULL ) {
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
/*
|
||||
* There must be exactly NFIELDS colon separated fields or
|
||||
* the entry is invalid. Also, the UID and GID must be non-blank.
|
||||
|
||||
@@ -152,11 +152,6 @@ static struct commonio_ops subordinate_ops = {
|
||||
NULL, /* close_hook */
|
||||
};
|
||||
|
||||
static /*@observer@*/ /*@null*/const struct subordinate_range *subordinate_next(struct commonio_db *db)
|
||||
{
|
||||
return (const struct subordinate_range *)commonio_next (db);
|
||||
}
|
||||
|
||||
/*
|
||||
* range_exists: Check whether @owner owns any ranges
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
EXTRA_DIST = .indent.pro xgetXXbyYY.c
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/lib
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/lib $(ECONF_CPPFLAGS)
|
||||
|
||||
noinst_LIBRARIES = libmisc.a
|
||||
|
||||
|
||||
@@ -46,11 +46,18 @@
|
||||
#include "defines.h"
|
||||
#include "chkname.h"
|
||||
|
||||
int allow_bad_names = false;
|
||||
|
||||
static bool is_valid_name (const char *name)
|
||||
{
|
||||
if (allow_bad_names) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* User/group names must match [a-z_][a-z0-9_-]*[$]
|
||||
*/
|
||||
|
||||
if (('\0' == *name) ||
|
||||
!((('a' <= *name) && ('z' >= *name)) || ('_' == *name))) {
|
||||
return false;
|
||||
|
||||
@@ -167,7 +167,7 @@ int find_new_gid (bool sys_group,
|
||||
bool *used_gids;
|
||||
const struct group *grp;
|
||||
gid_t gid_min, gid_max, preferred_min;
|
||||
gid_t group_id, id;
|
||||
gid_t id;
|
||||
gid_t lowest_found, highest_found;
|
||||
int result;
|
||||
int nospam = 0;
|
||||
|
||||
@@ -167,7 +167,7 @@ int find_new_uid(bool sys_user,
|
||||
bool *used_uids;
|
||||
const struct passwd *pwd;
|
||||
uid_t uid_min, uid_max, preferred_min;
|
||||
uid_t user_id, id;
|
||||
uid_t id;
|
||||
uid_t lowest_found, highest_found;
|
||||
int result;
|
||||
int nospam = 0;
|
||||
|
||||
@@ -268,6 +268,9 @@ static /*@observer@*//*@null@*/const char *obscure_msg (
|
||||
#ifdef USE_SHA_CRYPT
|
||||
|| (strcmp (result, "SHA256") == 0)
|
||||
|| (strcmp (result, "SHA512") == 0)
|
||||
#endif
|
||||
#ifdef USE_BCRYPT
|
||||
|| (strcmp (result, "BCRYPT") == 0)
|
||||
#endif
|
||||
) {
|
||||
return NULL;
|
||||
|
||||
@@ -96,7 +96,7 @@ extern const char* process_prefix_flag (const char* short_opt, int argc, char **
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (prefix != NULL) {
|
||||
if ( prefix[0] == '\0' || !strcmp(prefix, "/"))
|
||||
@@ -113,7 +113,7 @@ extern const char* process_prefix_flag (const char* short_opt, int argc, char **
|
||||
group_db_file = xmalloc(len);
|
||||
snprintf(group_db_file, len, "%s/%s", prefix, GROUP_FILE);
|
||||
gr_setdbname(group_db_file);
|
||||
|
||||
|
||||
#ifdef SHADOWGRP
|
||||
len = strlen(prefix) + strlen(SGROUP_FILE) + 2;
|
||||
sgroup_db_file = xmalloc(len);
|
||||
@@ -128,7 +128,7 @@ extern const char* process_prefix_flag (const char* short_opt, int argc, char **
|
||||
spw_db_file = xmalloc(len);
|
||||
snprintf(spw_db_file, len, "%s/%s", prefix, SHADOW_FILE);
|
||||
spw_setdbname(spw_db_file);
|
||||
|
||||
|
||||
#ifdef ENABLE_SUBIDS
|
||||
len = strlen(prefix) + strlen("/etc/subuid") + 2;
|
||||
suid_db_file = xmalloc(len);
|
||||
@@ -141,11 +141,15 @@ extern const char* process_prefix_flag (const char* short_opt, int argc, char **
|
||||
sub_gid_setdbname(sgid_db_file);
|
||||
#endif
|
||||
|
||||
#ifdef USE_ECONF
|
||||
setdef_config_file(prefix);
|
||||
#else
|
||||
len = strlen(prefix) + strlen("/etc/login.defs") + 2;
|
||||
def_conf_file = xmalloc(len);
|
||||
snprintf(def_conf_file, len, "%s/%s", prefix, "/etc/login.defs");
|
||||
setdef_config_file(def_conf_file);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (prefix == NULL)
|
||||
return "";
|
||||
@@ -169,7 +173,7 @@ extern struct group *prefix_getgrnam(const char *name)
|
||||
fclose(fg);
|
||||
return grp;
|
||||
}
|
||||
|
||||
|
||||
return getgrnam(name);
|
||||
}
|
||||
|
||||
@@ -262,7 +266,7 @@ extern void prefix_setpwent()
|
||||
}
|
||||
if (fp_pwent)
|
||||
fclose (fp_pwent);
|
||||
|
||||
|
||||
fp_pwent = fopen(passwd_db_file, "rt");
|
||||
if(!fp_pwent)
|
||||
return;
|
||||
@@ -293,7 +297,7 @@ extern void prefix_setgrent()
|
||||
}
|
||||
if (fp_grent)
|
||||
fclose (fp_grent);
|
||||
|
||||
|
||||
fp_grent = fopen(group_db_file, "rt");
|
||||
if(!fp_grent)
|
||||
return;
|
||||
|
||||
123
libmisc/salt.c
123
libmisc/salt.c
@@ -22,10 +22,16 @@
|
||||
/* local function prototypes */
|
||||
static void seedRNG (void);
|
||||
static /*@observer@*/const char *gensalt (size_t salt_size);
|
||||
#ifdef USE_SHA_CRYPT
|
||||
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
|
||||
static long shadow_random (long min, long max);
|
||||
#endif /* USE_SHA_CRYPT || USE_BCRYPT */
|
||||
#ifdef USE_SHA_CRYPT
|
||||
static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds);
|
||||
#endif /* USE_SHA_CRYPT */
|
||||
#ifdef USE_BCRYPT
|
||||
static /*@observer@*/const char *gensalt_bcrypt (void);
|
||||
static /*@observer@*/const char *BCRYPT_salt_rounds (/*@null@*/int *prefered_rounds);
|
||||
#endif /* USE_BCRYPT */
|
||||
|
||||
#ifndef HAVE_L64A
|
||||
static /*@observer@*/char *l64a(long value)
|
||||
@@ -79,8 +85,16 @@ static void seedRNG (void)
|
||||
* Add the salt prefix.
|
||||
*/
|
||||
#define MAGNUM(array,ch) (array)[0]=(array)[2]='$',(array)[1]=(ch),(array)[3]='\0'
|
||||
#ifdef USE_BCRYPT
|
||||
/*
|
||||
* Using the Prefix $2a$ to enable an anti-collision safety measure in musl libc.
|
||||
* Negatively affects a subset of passwords containing the '\xff' character,
|
||||
* which is not valid UTF-8 (so "unlikely to cause much annoyance").
|
||||
*/
|
||||
#define BCRYPTMAGNUM(array) (array)[0]=(array)[3]='$',(array)[1]='2',(array)[2]='a',(array)[4]='\0'
|
||||
#endif /* USE_BCRYPT */
|
||||
|
||||
#ifdef USE_SHA_CRYPT
|
||||
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
|
||||
/* It is not clear what is the maximum value of random().
|
||||
* We assume 2^31-1.*/
|
||||
#define RANDOM_MAX 0x7FFFFFFF
|
||||
@@ -105,14 +119,15 @@ static long shadow_random (long min, long max)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif /* USE_SHA_CRYPT || USE_BCRYPT */
|
||||
|
||||
#ifdef USE_SHA_CRYPT
|
||||
/* Default number of rounds if not explicitly specified. */
|
||||
#define ROUNDS_DEFAULT 5000
|
||||
/* Minimum number of rounds. */
|
||||
#define ROUNDS_MIN 1000
|
||||
/* Maximum number of rounds. */
|
||||
#define ROUNDS_MAX 999999999
|
||||
|
||||
/*
|
||||
* Return a salt prefix specifying the rounds number for the SHA crypt methods.
|
||||
*/
|
||||
@@ -165,6 +180,89 @@ static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds
|
||||
}
|
||||
#endif /* USE_SHA_CRYPT */
|
||||
|
||||
#ifdef USE_BCRYPT
|
||||
/* Default number of rounds if not explicitly specified. */
|
||||
#define B_ROUNDS_DEFAULT 13
|
||||
/* Minimum number of rounds. */
|
||||
#define B_ROUNDS_MIN 4
|
||||
/* Maximum number of rounds. */
|
||||
#define B_ROUNDS_MAX 31
|
||||
/*
|
||||
* Return a salt prefix specifying the rounds number for the BCRYPT method.
|
||||
*/
|
||||
static /*@observer@*/const char *BCRYPT_salt_rounds (/*@null@*/int *prefered_rounds)
|
||||
{
|
||||
static char rounds_prefix[4]; /* Max size: 31$ */
|
||||
long rounds;
|
||||
|
||||
if (NULL == prefered_rounds) {
|
||||
long min_rounds = getdef_long ("BCRYPT_MIN_ROUNDS", -1);
|
||||
long max_rounds = getdef_long ("BCRYPT_MAX_ROUNDS", -1);
|
||||
|
||||
if (((-1 == min_rounds) && (-1 == max_rounds)) || (0 == *prefered_rounds)) {
|
||||
rounds = B_ROUNDS_DEFAULT;
|
||||
}
|
||||
else {
|
||||
if (-1 == min_rounds) {
|
||||
min_rounds = max_rounds;
|
||||
}
|
||||
|
||||
if (-1 == max_rounds) {
|
||||
max_rounds = min_rounds;
|
||||
}
|
||||
|
||||
if (min_rounds > max_rounds) {
|
||||
max_rounds = min_rounds;
|
||||
}
|
||||
|
||||
rounds = shadow_random (min_rounds, max_rounds);
|
||||
}
|
||||
} else {
|
||||
rounds = *prefered_rounds;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sanity checks.
|
||||
* Use 19 as an upper bound for now,
|
||||
* because musl doesn't allow rounds >= 20.
|
||||
*/
|
||||
if (rounds < B_ROUNDS_MIN) {
|
||||
rounds = B_ROUNDS_MIN;
|
||||
}
|
||||
|
||||
if (rounds > 19) {
|
||||
/* rounds = B_ROUNDS_MAX; */
|
||||
rounds = 19;
|
||||
}
|
||||
|
||||
(void) snprintf (rounds_prefix, sizeof rounds_prefix,
|
||||
"%2.2ld$", rounds);
|
||||
|
||||
return rounds_prefix;
|
||||
}
|
||||
|
||||
#define BCRYPT_SALT_SIZE 22
|
||||
/*
|
||||
* Generate a 22 character salt string for bcrypt.
|
||||
*/
|
||||
static /*@observer@*/const char *gensalt_bcrypt (void)
|
||||
{
|
||||
static char salt[32];
|
||||
|
||||
salt[0] = '\0';
|
||||
|
||||
seedRNG ();
|
||||
strcat (salt, l64a (random()));
|
||||
do {
|
||||
strcat (salt, l64a (random()));
|
||||
} while (strlen (salt) < BCRYPT_SALT_SIZE);
|
||||
|
||||
salt[BCRYPT_SALT_SIZE] = '\0';
|
||||
|
||||
return salt;
|
||||
}
|
||||
#endif /* USE_BCRYPT */
|
||||
|
||||
/*
|
||||
* Generate salt of size salt_size.
|
||||
*/
|
||||
@@ -230,6 +328,11 @@ static /*@observer@*/const char *gensalt (size_t salt_size)
|
||||
|
||||
if (0 == strcmp (method, "MD5")) {
|
||||
MAGNUM(result, '1');
|
||||
#ifdef USE_BCRYPT
|
||||
} else if (0 == strcmp (method, "BCRYPT")) {
|
||||
BCRYPTMAGNUM(result);
|
||||
strcat(result, BCRYPT_salt_rounds((int *)arg));
|
||||
#endif /* USE_BCRYPT */
|
||||
#ifdef USE_SHA_CRYPT
|
||||
} else if (0 == strcmp (method, "SHA256")) {
|
||||
MAGNUM(result, '5');
|
||||
@@ -252,8 +355,18 @@ static /*@observer@*/const char *gensalt (size_t salt_size)
|
||||
* Concatenate a pseudo random salt.
|
||||
*/
|
||||
assert (sizeof (result) > strlen (result) + salt_len);
|
||||
strncat (result, gensalt (salt_len),
|
||||
sizeof (result) - strlen (result) - 1);
|
||||
#ifdef USE_BCRYPT
|
||||
if (0 == strcmp (method, "BCRYPT")) {
|
||||
strncat (result, gensalt_bcrypt (),
|
||||
sizeof (result) - strlen (result) - 1);
|
||||
return result;
|
||||
} else {
|
||||
#endif /* USE_BCRYPT */
|
||||
strncat (result, gensalt (salt_len),
|
||||
sizeof (result) - strlen (result) - 1);
|
||||
#ifdef USE_BCRYPT
|
||||
}
|
||||
#endif /* USE_BCRYPT */
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ man_MANS = \
|
||||
man1/sg.1 \
|
||||
man3/shadow.3 \
|
||||
man5/shadow.5 \
|
||||
man1/su.1 \
|
||||
man5/suauth.5 \
|
||||
man8/useradd.8 \
|
||||
man8/userdel.8 \
|
||||
@@ -54,6 +53,10 @@ man_nopam = \
|
||||
man5/login.access.5 \
|
||||
man5/porttime.5
|
||||
|
||||
if WITH_SU
|
||||
man_MANS += man1/su.1
|
||||
endif
|
||||
|
||||
if !USE_PAM
|
||||
man_MANS += $(man_nopam)
|
||||
endif
|
||||
|
||||
@@ -7,4 +7,4 @@ pre-built ones might not fit your version of shadow. To build them yourself use
|
||||
- xsltproc
|
||||
- docbook 4
|
||||
- docbook stylesheets
|
||||
- xml2po
|
||||
- itstool
|
||||
|
||||
@@ -131,6 +131,12 @@
|
||||
<para>Display help message and exit.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-i</option>, <option>--iso8601</option></term>
|
||||
<listitem>
|
||||
<para>When printing dates, use YYYY-MM-DD format.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>-I</option>, <option>--inactive</option> <replaceable>INACTIVE</replaceable>
|
||||
|
||||
@@ -5,8 +5,19 @@ config.xml: ../config.xml.in
|
||||
$(MAKE) -C .. config.xml
|
||||
cp ../config.xml $@
|
||||
|
||||
%.xml: ../%.xml ../po/$(LANG).po
|
||||
xml2po --expand-all-entities -l $(LANG) -p ../po/$(LANG).po -o $@ ../$@
|
||||
messages.mo: ../po/$(LANG).po
|
||||
msgfmt ../po/$(LANG).po -o messages.mo
|
||||
|
||||
login.defs.d:
|
||||
ln -sf ../login.defs.d login.defs.d
|
||||
|
||||
%.xml: ../%.xml messages.mo login.defs.d
|
||||
if grep -q SHADOW-CONFIG-HERE $< ; then \
|
||||
sed -e 's/^<!-- SHADOW-CONFIG-HERE -->/<!ENTITY % config SYSTEM "config.xml">%config;/' $< > $@; \
|
||||
else \
|
||||
sed -e 's/^\(<!DOCTYPE .*docbookx.dtd"\)>/\1 [<!ENTITY % config SYSTEM "config.xml">%config;]>/' $< > $@; \
|
||||
fi
|
||||
itstool -d -l $(LANG) -m messages.mo -o . $@
|
||||
sed -i 's:\(^<refentry .*\)>:\1 lang="$(LANG)">:' $@
|
||||
|
||||
include ../generate_mans.mak
|
||||
@@ -16,4 +27,4 @@ $(man_MANS):
|
||||
@echo you need to run configure with --enable-man to generate man pages
|
||||
endif
|
||||
|
||||
CLEANFILES = .xml2po.mo $(EXTRA_DIST) $(addsuffix .xml,$(EXTRA_DIST)) config.xml
|
||||
CLEANFILES = messages.mo login.defs.d $(EXTRA_DIST) $(addsuffix .xml,$(EXTRA_DIST)) config.xml
|
||||
|
||||
@@ -266,6 +266,18 @@
|
||||
<para>
|
||||
The options which apply to the <command>newusers</command> command are:
|
||||
</para>
|
||||
<variablelist remap='IP'>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--badname</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Allow names that do not conform to standards.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
<variablelist remap='IP' condition="no_pam">
|
||||
<varlistentry>
|
||||
<term><option>-c</option>, <option>--crypt-method</option></term>
|
||||
|
||||
@@ -98,24 +98,43 @@
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
The encrypted password field may be blank, in which case no password
|
||||
is required to authenticate as the specified login name. However,
|
||||
some applications which read the <filename>/etc/passwd</filename> file
|
||||
may decide not to permit <emphasis>any</emphasis> access at all if the
|
||||
<emphasis>password</emphasis> field is blank. If the
|
||||
<emphasis>password</emphasis> field is a lower-case <quote>x</quote>,
|
||||
then the encrypted password is actually stored in the
|
||||
If the <emphasis>password</emphasis> field is a lower-case
|
||||
<quote>x</quote>, then the encrypted password is actually stored in the
|
||||
<citerefentry><refentrytitle>shadow</refentrytitle>
|
||||
<manvolnum>5</manvolnum></citerefentry> file instead; there
|
||||
<emphasis>must</emphasis> be a corresponding line in the
|
||||
<filename>/etc/shadow</filename> file, or else the user account is invalid.
|
||||
If the <emphasis>password</emphasis> field is any other string, then
|
||||
it will be treated as an encrypted password, as specified by
|
||||
<citerefentry><refentrytitle>crypt</refentrytitle>
|
||||
<manvolnum>3</manvolnum></citerefentry>.
|
||||
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The encrypted <emphasis>password</emphasis> field may be empty,
|
||||
in which case no password is required to authenticate as the
|
||||
specified login name. However, some applications which read the
|
||||
<filename>/etc/passwd</filename> file may decide not to permit
|
||||
<emphasis>any</emphasis> access at all if the
|
||||
<emphasis>password</emphasis> field is blank.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
A <emphasis>password</emphasis> field which starts with an
|
||||
exclamation mark means that the password is locked. The
|
||||
remaining characters on the line represent the
|
||||
<emphasis>password</emphasis> field before the password was
|
||||
locked.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Refer to <citerefentry><refentrytitle>crypt</refentrytitle>
|
||||
<manvolnum>3</manvolnum></citerefentry> for details on how
|
||||
this string is interpreted.
|
||||
</para>
|
||||
<para>
|
||||
If the password field contains some string that is not a valid
|
||||
result of <citerefentry><refentrytitle>crypt</refentrytitle>
|
||||
<manvolnum>3</manvolnum></citerefentry>, for instance ! or *,
|
||||
the user will not be able to use a unix password to log in
|
||||
(but the user may log in the system by other means).
|
||||
</para>
|
||||
<para>
|
||||
The comment field is used by various system utilities, such as
|
||||
<citerefentry><refentrytitle>finger</refentrytitle>
|
||||
|
||||
@@ -182,6 +182,16 @@
|
||||
The options which apply to the <command>pwck</command> command are:
|
||||
</para>
|
||||
<variablelist remap='IP'>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--badname</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Allow names that do not conform to standards.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-h</option>, <option>--help</option></term>
|
||||
<listitem>
|
||||
|
||||
@@ -95,18 +95,6 @@
|
||||
<varlistentry>
|
||||
<term><emphasis role="bold">encrypted password</emphasis></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Refer to <citerefentry><refentrytitle>crypt</refentrytitle>
|
||||
<manvolnum>3</manvolnum></citerefentry> for details on how
|
||||
this string is interpreted.
|
||||
</para>
|
||||
<para>
|
||||
If the password field contains some string that is not a valid
|
||||
result of <citerefentry><refentrytitle>crypt</refentrytitle>
|
||||
<manvolnum>3</manvolnum></citerefentry>, for instance ! or *,
|
||||
the user will not be able to use a unix password to log in
|
||||
(but the user may log in the system by other means).
|
||||
</para>
|
||||
<para>
|
||||
This field may be empty, in which case no passwords are
|
||||
required to authenticate as the specified login name.
|
||||
@@ -120,6 +108,18 @@
|
||||
line represent the password field before the password was
|
||||
locked.
|
||||
</para>
|
||||
<para>
|
||||
Refer to <citerefentry><refentrytitle>crypt</refentrytitle>
|
||||
<manvolnum>3</manvolnum></citerefentry> for details on how
|
||||
this string is interpreted.
|
||||
</para>
|
||||
<para>
|
||||
If the password field contains some string that is not a valid
|
||||
result of <citerefentry><refentrytitle>crypt</refentrytitle>
|
||||
<manvolnum>3</manvolnum></citerefentry>, for instance ! or *,
|
||||
the user will not be able to use a unix password to log in
|
||||
(but the user may log in the system by other means).
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
|
||||
@@ -126,6 +126,16 @@
|
||||
<para>The options which apply to the <command>useradd</command> command are:
|
||||
</para>
|
||||
<variablelist remap='IP'>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--badname</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Allow names that do not conform to standards.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>-b</option>, <option>--base-dir</option> <replaceable>BASE_DIR</replaceable>
|
||||
|
||||
@@ -108,6 +108,26 @@
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>-b</option>, <option>--badnames</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Allow names that do not conform to standards.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>-b</option>, <option>--badnames</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Allow names that do not conform to standards.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>-c</option>, <option>--comment</option> <replaceable>COMMENT</replaceable>
|
||||
|
||||
@@ -45,10 +45,13 @@ libmisc/entry.c
|
||||
libmisc/env.c
|
||||
libmisc/failure.c
|
||||
libmisc/find_new_gid.c
|
||||
libmisc/find_new_sub_gids.c
|
||||
libmisc/find_new_sub_uids.c
|
||||
libmisc/find_new_uid.c
|
||||
libmisc/getgr_nam_gid.c
|
||||
libmisc/getrange.c
|
||||
libmisc/hushed.c
|
||||
libmisc/idmapping.c
|
||||
libmisc/isexpired.c
|
||||
libmisc/limits.c
|
||||
libmisc/list.c
|
||||
@@ -59,6 +62,7 @@ libmisc/motd.c
|
||||
libmisc/myname.c
|
||||
libmisc/obscure.c
|
||||
libmisc/pam_pass.c
|
||||
libmisc/pam_pass_non_interactive.c
|
||||
libmisc/pwd2spwd.c
|
||||
libmisc/pwdcheck.c
|
||||
libmisc/pwd_init.c
|
||||
@@ -75,6 +79,7 @@ libmisc/sulog.c
|
||||
libmisc/ttytype.c
|
||||
libmisc/tz.c
|
||||
libmisc/ulimit.c
|
||||
libmisc/user_busy.c
|
||||
libmisc/utmp.c
|
||||
libmisc/valid.c
|
||||
libmisc/xgetXXbyYY.c
|
||||
@@ -101,7 +106,9 @@ src/lastlog.c
|
||||
src/login.c
|
||||
src/login_nopam.c
|
||||
src/logoutd.c
|
||||
src/newgidmap.c
|
||||
src/newgrp.c
|
||||
src/newuidmap.c
|
||||
src/newusers.c
|
||||
src/passwd.c
|
||||
src/pwck.c
|
||||
|
||||
1566
po/zh_TW.po
1566
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
@@ -2,8 +2,8 @@
|
||||
EXTRA_DIST = \
|
||||
.indent.pro
|
||||
|
||||
ubindir = ${prefix}/bin
|
||||
usbindir = ${prefix}/sbin
|
||||
ubindir = ${bindir}
|
||||
usbindir = ${sbindir}
|
||||
suidperms = 4755
|
||||
sgidperms = 2755
|
||||
|
||||
@@ -23,12 +23,15 @@ AM_CPPFLAGS = \
|
||||
# and installation would be much simpler (just two directories,
|
||||
# $prefix/bin and $prefix/sbin, no install-data hacks...)
|
||||
|
||||
bin_PROGRAMS = groups login su
|
||||
bin_PROGRAMS = groups login
|
||||
sbin_PROGRAMS = nologin
|
||||
ubin_PROGRAMS = faillog lastlog chage chfn chsh expiry gpasswd newgrp passwd
|
||||
if ENABLE_SUBIDS
|
||||
ubin_PROGRAMS += newgidmap newuidmap
|
||||
endif
|
||||
if WITH_SU
|
||||
bin_PROGRAMS += su
|
||||
endif
|
||||
usbin_PROGRAMS = \
|
||||
chgpasswd \
|
||||
chpasswd \
|
||||
@@ -52,13 +55,17 @@ usbin_PROGRAMS = \
|
||||
# id and groups are from gnu, sulogin from sysvinit
|
||||
noinst_PROGRAMS = id sulogin
|
||||
|
||||
suidbins = su
|
||||
suidusbins =
|
||||
suidbins =
|
||||
suidubins = chage chfn chsh expiry gpasswd newgrp
|
||||
if WITH_SU
|
||||
suidbins += su
|
||||
endif
|
||||
if !WITH_TCB
|
||||
suidubins += passwd
|
||||
endif
|
||||
if ACCT_TOOLS_SETUID
|
||||
suidubins += chgpasswd chpasswd groupadd groupdel groupmod newusers useradd userdel usermod
|
||||
suidusbins += chgpasswd chpasswd groupadd groupdel groupmod newusers useradd userdel usermod
|
||||
endif
|
||||
if ENABLE_SUBIDS
|
||||
if !FCAPS
|
||||
@@ -87,42 +94,43 @@ else
|
||||
LIBCRYPT_NOPAM = $(LIBCRYPT)
|
||||
endif
|
||||
|
||||
chage_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX)
|
||||
newuidmap_LDADD = $(LDADD) $(LIBSELINUX) $(LIBCAP)
|
||||
newgidmap_LDADD = $(LDADD) $(LIBSELINUX) $(LIBCAP)
|
||||
chfn_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD)
|
||||
chgpasswd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBSELINUX) $(LIBCRYPT)
|
||||
chsh_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD)
|
||||
chpasswd_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT)
|
||||
gpasswd_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT)
|
||||
groupadd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX)
|
||||
groupdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX)
|
||||
groupmems_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX)
|
||||
groupmod_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX)
|
||||
grpck_LDADD = $(LDADD) $(LIBSELINUX)
|
||||
grpconv_LDADD = $(LDADD) $(LIBSELINUX)
|
||||
grpunconv_LDADD = $(LDADD) $(LIBSELINUX)
|
||||
lastlog_LDADD = $(LDADD) $(LIBAUDIT)
|
||||
chage_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
|
||||
newuidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP)
|
||||
newgidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP)
|
||||
chfn_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF)
|
||||
chgpasswd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF)
|
||||
chsh_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF)
|
||||
chpasswd_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF)
|
||||
expiry_LDADD = $(LDADD) $(LIBECONF)
|
||||
gpasswd_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF)
|
||||
groupadd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
|
||||
groupdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
|
||||
groupmems_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
|
||||
groupmod_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
|
||||
grpck_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
|
||||
grpconv_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
|
||||
grpunconv_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
|
||||
lastlog_LDADD = $(LDADD) $(LIBAUDIT) $(LIBECONF)
|
||||
login_SOURCES = \
|
||||
login.c \
|
||||
login_nopam.c
|
||||
login_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD)
|
||||
newgrp_LDADD = $(LDADD) $(LIBAUDIT) $(LIBCRYPT)
|
||||
newusers_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT)
|
||||
login_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF)
|
||||
newgrp_LDADD = $(LDADD) $(LIBAUDIT) $(LIBCRYPT) $(LIBECONF)
|
||||
newusers_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF)
|
||||
nologin_LDADD =
|
||||
passwd_LDADD = $(LDADD) $(LIBPAM) $(LIBCRACK) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM)
|
||||
pwck_LDADD = $(LDADD) $(LIBSELINUX)
|
||||
pwconv_LDADD = $(LDADD) $(LIBSELINUX)
|
||||
pwunconv_LDADD = $(LDADD) $(LIBSELINUX)
|
||||
passwd_LDADD = $(LDADD) $(LIBPAM) $(LIBCRACK) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBECONF)
|
||||
pwck_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
|
||||
pwconv_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
|
||||
pwunconv_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
|
||||
su_SOURCES = \
|
||||
su.c \
|
||||
suauth.c
|
||||
su_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD)
|
||||
sulogin_LDADD = $(LDADD) $(LIBCRYPT)
|
||||
useradd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBACL) $(LIBATTR)
|
||||
userdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE)
|
||||
usermod_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBACL) $(LIBATTR)
|
||||
vipw_LDADD = $(LDADD) $(LIBSELINUX)
|
||||
su_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF)
|
||||
sulogin_LDADD = $(LDADD) $(LIBCRYPT) $(LIBECONF)
|
||||
useradd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBACL) $(LIBATTR) $(LIBECONF)
|
||||
userdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBECONF)
|
||||
usermod_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBACL) $(LIBATTR) $(LIBECONF)
|
||||
vipw_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
|
||||
|
||||
install-am: all-am
|
||||
$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
@@ -134,6 +142,9 @@ install-am: all-am
|
||||
for i in $(suidubins); do \
|
||||
chmod $(suidperms) $(DESTDIR)$(ubindir)/$$i; \
|
||||
done
|
||||
for i in $(suidusbins); do \
|
||||
chmod $(suidperms) $(DESTDIR)$(usbindir)/$$i; \
|
||||
done
|
||||
if WITH_TCB
|
||||
for i in $(shadowsgidubins); do \
|
||||
chown root:shadow $(DESTDIR)$(ubindir)/$$i; \
|
||||
|
||||
26
src/chage.c
26
src/chage.c
@@ -48,10 +48,6 @@
|
||||
#endif /* USE_PAM */
|
||||
#endif /* ACCT_TOOLS_SETUID */
|
||||
#include <pwd.h>
|
||||
#ifdef WITH_SELINUX
|
||||
#include <selinux/selinux.h>
|
||||
#include <selinux/av_permissions.h>
|
||||
#endif
|
||||
#include "prototypes.h"
|
||||
#include "defines.h"
|
||||
#include "pwio.h"
|
||||
@@ -70,6 +66,7 @@ const char *Prog;
|
||||
static bool
|
||||
dflg = false, /* set last password change date */
|
||||
Eflg = false, /* set account expiration date */
|
||||
iflg = false, /* set iso8601 date formatting */
|
||||
Iflg = false, /* set password inactive after expiration */
|
||||
lflg = false, /* show account aging information */
|
||||
mflg = false, /* set minimum number of days before password change */
|
||||
@@ -149,6 +146,7 @@ static /*@noreturn@*/void usage (int status)
|
||||
(void) fputs (_(" -d, --lastday LAST_DAY set date of last password change to LAST_DAY\n"), usageout);
|
||||
(void) fputs (_(" -E, --expiredate EXPIRE_DATE set account expiration date to EXPIRE_DATE\n"), usageout);
|
||||
(void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
|
||||
(void) fputs (_(" -i, --iso8601 use YYYY-MM-DD when printing dates\n"), usageout);
|
||||
(void) fputs (_(" -I, --inactive INACTIVE set password inactive after expiration\n"
|
||||
" to INACTIVE\n"), usageout);
|
||||
(void) fputs (_(" -l, --list show account aging information\n"), usageout);
|
||||
@@ -262,12 +260,20 @@ static void print_date (time_t date)
|
||||
#ifdef HAVE_STRFTIME
|
||||
struct tm *tp;
|
||||
char buf[80];
|
||||
char format[80];
|
||||
|
||||
if( iflg ) {
|
||||
(void) snprintf (format, 80, "%%Y-%%m-%%d");
|
||||
}
|
||||
else {
|
||||
(void) snprintf (format, 80, "%%b %%d, %%Y");
|
||||
}
|
||||
|
||||
tp = gmtime (&date);
|
||||
if (NULL == tp) {
|
||||
(void) printf ("time_t: %lu\n", (unsigned long)date);
|
||||
} else {
|
||||
(void) strftime (buf, sizeof buf, "%b %d, %Y", tp);
|
||||
(void) strftime (buf, sizeof buf, format, tp);
|
||||
(void) puts (buf);
|
||||
}
|
||||
#else
|
||||
@@ -395,10 +401,11 @@ static void process_flags (int argc, char **argv)
|
||||
{"maxdays", required_argument, NULL, 'M'},
|
||||
{"root", required_argument, NULL, 'R'},
|
||||
{"warndays", required_argument, NULL, 'W'},
|
||||
{"iso8601", no_argument, NULL, 'i'},
|
||||
{NULL, 0, NULL, '\0'}
|
||||
};
|
||||
|
||||
while ((c = getopt_long (argc, argv, "d:E:hI:lm:M:R:W:",
|
||||
while ((c = getopt_long (argc, argv, "d:E:hiI:lm:M:R:W:",
|
||||
long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'd':
|
||||
@@ -424,6 +431,9 @@ static void process_flags (int argc, char **argv)
|
||||
case 'h':
|
||||
usage (E_SUCCESS);
|
||||
/*@notreached@*/break;
|
||||
case 'i':
|
||||
iflg = true;
|
||||
break;
|
||||
case 'I':
|
||||
Iflg = true;
|
||||
if ( (getlong (optarg, &inactdays) == 0)
|
||||
@@ -818,8 +828,8 @@ int main (int argc, char **argv)
|
||||
rgid = getgid ();
|
||||
amroot = (ruid == 0);
|
||||
#ifdef WITH_SELINUX
|
||||
if (amroot && (is_selinux_enabled () > 0)) {
|
||||
amroot = (selinux_check_passwd_access (PASSWD__ROOTOK) == 0);
|
||||
if (amroot) {
|
||||
amroot = (check_selinux_permit ("rootok") == 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -40,10 +40,6 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <getopt.h>
|
||||
#ifdef WITH_SELINUX
|
||||
#include <selinux/selinux.h>
|
||||
#include <selinux/av_permissions.h>
|
||||
#endif
|
||||
#include "defines.h"
|
||||
#include "getdef.h"
|
||||
#include "nscd.h"
|
||||
@@ -379,8 +375,7 @@ static void check_perms (const struct passwd *pw)
|
||||
* check if the change is allowed by SELinux policy.
|
||||
*/
|
||||
if ((pw->pw_uid != getuid ())
|
||||
&& (is_selinux_enabled () > 0)
|
||||
&& (selinux_check_passwd_access (PASSWD__CHFN) != 0)) {
|
||||
&& (check_selinux_permit ("chfn") != 0)) {
|
||||
fprintf (stderr, _("%s: Permission denied.\n"), Prog);
|
||||
closelog ();
|
||||
exit (E_NOPERM);
|
||||
|
||||
@@ -61,15 +61,18 @@
|
||||
const char *Prog;
|
||||
static bool eflg = false;
|
||||
static bool md5flg = false;
|
||||
#ifdef USE_SHA_CRYPT
|
||||
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
|
||||
static bool sflg = false;
|
||||
#endif
|
||||
#endif /* USE_SHA_CRYPT || USE_BCRYPT */
|
||||
|
||||
static /*@null@*//*@observer@*/const char *crypt_method = NULL;
|
||||
#define cflg (NULL != crypt_method)
|
||||
#ifdef USE_SHA_CRYPT
|
||||
static long sha_rounds = 5000;
|
||||
#endif
|
||||
#ifdef USE_BCRYPT
|
||||
static long bcrypt_rounds = 13;
|
||||
#endif
|
||||
|
||||
#ifdef SHADOWGRP
|
||||
static bool is_shadow_grp;
|
||||
@@ -125,11 +128,15 @@ static /*@noreturn@*/void usage (int status)
|
||||
Prog);
|
||||
(void) fprintf (usageout,
|
||||
_(" -c, --crypt-method METHOD the crypt method (one of %s)\n"),
|
||||
#ifndef USE_SHA_CRYPT
|
||||
#if !defined(USE_SHA_CRYPT) && !defined(USE_BCRYPT)
|
||||
"NONE DES MD5"
|
||||
#else /* USE_SHA_CRYPT */
|
||||
#elif defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
|
||||
"NONE DES MD5 SHA256 SHA512 BCRYPT"
|
||||
#elif defined(USE_SHA_CRYPT)
|
||||
"NONE DES MD5 SHA256 SHA512"
|
||||
#endif /* USE_SHA_CRYPT */
|
||||
#else
|
||||
"NONE DES MD5 BCRYPT"
|
||||
#endif
|
||||
);
|
||||
(void) fputs (_(" -e, --encrypted supplied passwords are encrypted\n"), usageout);
|
||||
(void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
|
||||
@@ -137,11 +144,11 @@ static /*@noreturn@*/void usage (int status)
|
||||
" the MD5 algorithm\n"),
|
||||
usageout);
|
||||
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
|
||||
#ifdef USE_SHA_CRYPT
|
||||
(void) fputs (_(" -s, --sha-rounds number of SHA rounds for the SHA*\n"
|
||||
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
|
||||
(void) fputs (_(" -s, --sha-rounds number of rounds for the SHA or BCRYPT\n"
|
||||
" crypt algorithms\n"),
|
||||
usageout);
|
||||
#endif /* USE_SHA_CRYPT */
|
||||
#endif /* USE_SHA_CRYPT || USE_BCRYPT */
|
||||
(void) fputs ("\n", usageout);
|
||||
|
||||
exit (status);
|
||||
@@ -161,14 +168,13 @@ static void process_flags (int argc, char **argv)
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"md5", no_argument, NULL, 'm'},
|
||||
{"root", required_argument, NULL, 'R'},
|
||||
#ifdef USE_SHA_CRYPT
|
||||
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
|
||||
{"sha-rounds", required_argument, NULL, 's'},
|
||||
#endif
|
||||
#endif /* USE_SHA_CRYPT || USE_BCRYPT */
|
||||
{NULL, 0, NULL, '\0'}
|
||||
};
|
||||
|
||||
while ((c = getopt_long (argc, argv,
|
||||
#ifdef USE_SHA_CRYPT
|
||||
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
|
||||
"c:ehmR:s:",
|
||||
#else
|
||||
"c:ehmR:",
|
||||
@@ -189,10 +195,33 @@ static void process_flags (int argc, char **argv)
|
||||
break;
|
||||
case 'R': /* no-op, handled in process_root_flag () */
|
||||
break;
|
||||
#ifdef USE_SHA_CRYPT
|
||||
#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
|
||||
case 's':
|
||||
sflg = true;
|
||||
if (getlong(optarg, &sha_rounds) == 0) {
|
||||
if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512")))
|
||||
&& (0 == getlong(optarg, &sha_rounds)))
|
||||
|| ( (0 == strcmp (crypt_method, "BCRYPT"))
|
||||
&& (0 == getlong(optarg, &bcrypt_rounds)))) {
|
||||
fprintf (stderr,
|
||||
_("%s: invalid numeric argument '%s'\n"),
|
||||
Prog, optarg);
|
||||
usage (E_USAGE);
|
||||
}
|
||||
break;
|
||||
#elif defined(USE_SHA_CRYPT)
|
||||
case 's':
|
||||
sflg = true;
|
||||
if (0 == getlong(optarg, &sha_rounds)) {
|
||||
fprintf (stderr,
|
||||
_("%s: invalid numeric argument '%s'\n"),
|
||||
Prog, optarg);
|
||||
usage (E_USAGE);
|
||||
}
|
||||
break;
|
||||
#elif defined(USE_BCRYPT)
|
||||
case 's':
|
||||
sflg = true;
|
||||
if (0 == getlong(optarg, &bcrypt_rounds)) {
|
||||
fprintf (stderr,
|
||||
_("%s: invalid numeric argument '%s'\n"),
|
||||
Prog, optarg);
|
||||
@@ -200,6 +229,7 @@ static void process_flags (int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
usage (E_USAGE);
|
||||
/*@notreached@*/break;
|
||||
@@ -217,7 +247,7 @@ static void process_flags (int argc, char **argv)
|
||||
*/
|
||||
static void check_flags (void)
|
||||
{
|
||||
#ifdef USE_SHA_CRYPT
|
||||
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
|
||||
if (sflg && !cflg) {
|
||||
fprintf (stderr,
|
||||
_("%s: %s flag is only allowed with the %s flag\n"),
|
||||
@@ -241,6 +271,9 @@ static void check_flags (void)
|
||||
#ifdef USE_SHA_CRYPT
|
||||
&& (0 != strcmp (crypt_method, "SHA256"))
|
||||
&& (0 != strcmp (crypt_method, "SHA512"))
|
||||
#endif
|
||||
#ifdef USE_BCRYPT
|
||||
&& (0 != strcmp (crypt_method, "BCRYPT"))
|
||||
#endif
|
||||
) {
|
||||
fprintf (stderr,
|
||||
@@ -464,10 +497,24 @@ int main (int argc, char **argv)
|
||||
if (md5flg) {
|
||||
crypt_method = "MD5";
|
||||
}
|
||||
#ifdef USE_SHA_CRYPT
|
||||
#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
|
||||
if (sflg) {
|
||||
if ( (0 == strcmp (crypt_method, "SHA256"))
|
||||
|| (0 == strcmp (crypt_method, "SHA512"))) {
|
||||
arg = &sha_rounds;
|
||||
}
|
||||
else if (0 == strcmp (crypt_method, "BCRYPT")) {
|
||||
arg = &bcrypt_rounds;
|
||||
}
|
||||
}
|
||||
#elif defined(USE_SHA_CRYPT)
|
||||
if (sflg) {
|
||||
arg = &sha_rounds;
|
||||
}
|
||||
#elif defined(USE_BCRYPT)
|
||||
if (sflg) {
|
||||
arg = &bcrypt_rounds;
|
||||
}
|
||||
#endif
|
||||
salt = crypt_make_salt (crypt_method, arg);
|
||||
cp = pw_encrypt (newpwd, salt);
|
||||
|
||||
@@ -58,15 +58,18 @@
|
||||
const char *Prog;
|
||||
static bool eflg = false;
|
||||
static bool md5flg = false;
|
||||
#ifdef USE_SHA_CRYPT
|
||||
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
|
||||
static bool sflg = false;
|
||||
#endif /* USE_SHA_CRYPT */
|
||||
#endif
|
||||
|
||||
static /*@null@*//*@observer@*/const char *crypt_method = NULL;
|
||||
#define cflg (NULL != crypt_method)
|
||||
#ifdef USE_SHA_CRYPT
|
||||
static long sha_rounds = 5000;
|
||||
#endif /* USE_SHA_CRYPT */
|
||||
#endif
|
||||
#ifdef USE_BCRYPT
|
||||
static long bcrypt_rounds = 13;
|
||||
#endif
|
||||
|
||||
static bool is_shadow_pwd;
|
||||
static bool pw_locked = false;
|
||||
@@ -118,11 +121,15 @@ static /*@noreturn@*/void usage (int status)
|
||||
Prog);
|
||||
(void) fprintf (usageout,
|
||||
_(" -c, --crypt-method METHOD the crypt method (one of %s)\n"),
|
||||
#ifndef USE_SHA_CRYPT
|
||||
#if !defined(USE_SHA_CRYPT) && !defined(USE_BCRYPT)
|
||||
"NONE DES MD5"
|
||||
#else /* USE_SHA_CRYPT */
|
||||
#elif defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
|
||||
"NONE DES MD5 SHA256 SHA512 BCRYPT"
|
||||
#elif defined(USE_SHA_CRYPT)
|
||||
"NONE DES MD5 SHA256 SHA512"
|
||||
#endif /* USE_SHA_CRYPT */
|
||||
#else
|
||||
"NONE DES MD5 BCRYPT"
|
||||
#endif
|
||||
);
|
||||
(void) fputs (_(" -e, --encrypted supplied passwords are encrypted\n"), usageout);
|
||||
(void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
|
||||
@@ -130,11 +137,11 @@ static /*@noreturn@*/void usage (int status)
|
||||
" the MD5 algorithm\n"),
|
||||
usageout);
|
||||
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
|
||||
#ifdef USE_SHA_CRYPT
|
||||
(void) fputs (_(" -s, --sha-rounds number of SHA rounds for the SHA*\n"
|
||||
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
|
||||
(void) fputs (_(" -s, --sha-rounds number of rounds for the SHA or BCRYPT\n"
|
||||
" crypt algorithms\n"),
|
||||
usageout);
|
||||
#endif /* USE_SHA_CRYPT */
|
||||
#endif /* USE_SHA_CRYPT || USE_BCRYPT */
|
||||
(void) fputs ("\n", usageout);
|
||||
|
||||
exit (status);
|
||||
@@ -154,18 +161,18 @@ static void process_flags (int argc, char **argv)
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"md5", no_argument, NULL, 'm'},
|
||||
{"root", required_argument, NULL, 'R'},
|
||||
#ifdef USE_SHA_CRYPT
|
||||
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
|
||||
{"sha-rounds", required_argument, NULL, 's'},
|
||||
#endif /* USE_SHA_CRYPT */
|
||||
#endif /* USE_SHA_CRYPT || USE_BCRYPT */
|
||||
{NULL, 0, NULL, '\0'}
|
||||
};
|
||||
|
||||
while ((c = getopt_long (argc, argv,
|
||||
#ifdef USE_SHA_CRYPT
|
||||
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
|
||||
"c:ehmR:s:",
|
||||
#else /* !USE_SHA_CRYPT */
|
||||
#else
|
||||
"c:ehmR:",
|
||||
#endif /* !USE_SHA_CRYPT */
|
||||
#endif
|
||||
long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'c':
|
||||
@@ -182,17 +189,41 @@ static void process_flags (int argc, char **argv)
|
||||
break;
|
||||
case 'R': /* no-op, handled in process_root_flag () */
|
||||
break;
|
||||
#ifdef USE_SHA_CRYPT
|
||||
#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
|
||||
case 's':
|
||||
sflg = true;
|
||||
if (getlong(optarg, &sha_rounds) == 0) {
|
||||
if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512")))
|
||||
&& (0 == getlong(optarg, &sha_rounds)))
|
||||
|| ( (0 == strcmp (crypt_method, "BCRYPT"))
|
||||
&& (0 == getlong(optarg, &bcrypt_rounds)))) {
|
||||
fprintf (stderr,
|
||||
_("%s: invalid numeric argument '%s'\n"),
|
||||
Prog, optarg);
|
||||
usage (E_USAGE);
|
||||
}
|
||||
break;
|
||||
#endif /* USE_SHA_CRYPT */
|
||||
#elif defined(USE_SHA_CRYPT)
|
||||
case 's':
|
||||
sflg = true;
|
||||
if (0 == getlong(optarg, &sha_rounds)) {
|
||||
fprintf (stderr,
|
||||
_("%s: invalid numeric argument '%s'\n"),
|
||||
Prog, optarg);
|
||||
usage (E_USAGE);
|
||||
}
|
||||
break;
|
||||
#elif defined(USE_BCRYPT)
|
||||
case 's':
|
||||
sflg = true;
|
||||
if (0 == getlong(optarg, &bcrypt_rounds)) {
|
||||
fprintf (stderr,
|
||||
_("%s: invalid numeric argument '%s'\n"),
|
||||
Prog, optarg);
|
||||
usage (E_USAGE);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
usage (E_USAGE);
|
||||
/*@notreached@*/break;
|
||||
@@ -210,7 +241,7 @@ static void process_flags (int argc, char **argv)
|
||||
*/
|
||||
static void check_flags (void)
|
||||
{
|
||||
#ifdef USE_SHA_CRYPT
|
||||
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
|
||||
if (sflg && !cflg) {
|
||||
fprintf (stderr,
|
||||
_("%s: %s flag is only allowed with the %s flag\n"),
|
||||
@@ -235,6 +266,9 @@ static void check_flags (void)
|
||||
&& (0 != strcmp (crypt_method, "SHA256"))
|
||||
&& (0 != strcmp (crypt_method, "SHA512"))
|
||||
#endif /* USE_SHA_CRYPT */
|
||||
#ifdef USE_BCRYPT
|
||||
&& (0 != strcmp (crypt_method, "BCRYPT"))
|
||||
#endif /* USE_BCRYPT */
|
||||
) {
|
||||
fprintf (stderr,
|
||||
_("%s: unsupported crypt method: %s\n"),
|
||||
@@ -496,10 +530,24 @@ int main (int argc, char **argv)
|
||||
if (md5flg) {
|
||||
crypt_method = "MD5";
|
||||
}
|
||||
#ifdef USE_SHA_CRYPT
|
||||
#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
|
||||
if (sflg) {
|
||||
if ( (0 == strcmp (crypt_method, "SHA256"))
|
||||
|| (0 == strcmp (crypt_method, "SHA512"))) {
|
||||
arg = &sha_rounds;
|
||||
}
|
||||
else if (0 == strcmp (crypt_method, "BCRYPT")) {
|
||||
arg = &bcrypt_rounds;
|
||||
}
|
||||
}
|
||||
#elif defined(USE_SHA_CRYPT)
|
||||
if (sflg) {
|
||||
arg = &sha_rounds;
|
||||
}
|
||||
#elif defined(USE_BCRYPT)
|
||||
if (sflg) {
|
||||
arg = &bcrypt_rounds;
|
||||
}
|
||||
#endif
|
||||
salt = crypt_make_salt (crypt_method, arg);
|
||||
cp = pw_encrypt (newpwd, salt);
|
||||
|
||||
@@ -39,10 +39,6 @@
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef WITH_SELINUX
|
||||
#include <selinux/selinux.h>
|
||||
#include <selinux/av_permissions.h>
|
||||
#endif
|
||||
#include "defines.h"
|
||||
#include "getdef.h"
|
||||
#include "nscd.h"
|
||||
@@ -286,8 +282,7 @@ static void check_perms (const struct passwd *pw)
|
||||
* check if the change is allowed by SELinux policy.
|
||||
*/
|
||||
if ((pw->pw_uid != getuid ())
|
||||
&& (is_selinux_enabled () > 0)
|
||||
&& (selinux_check_passwd_access (PASSWD__CHSH) != 0)) {
|
||||
&& (check_selinux_permit("chsh") != 0)) {
|
||||
SYSLOG ((LOG_WARN, "can't change shell for '%s'", pw->pw_name));
|
||||
fprintf (stderr,
|
||||
_("You may not change the shell for '%s'.\n"),
|
||||
|
||||
@@ -165,7 +165,7 @@ int main(int argc, char **argv)
|
||||
{
|
||||
char proc_dir_name[32];
|
||||
char *target_str;
|
||||
pid_t target, parent;
|
||||
pid_t target;
|
||||
int proc_dir_fd;
|
||||
int ranges;
|
||||
struct map_range *mappings;
|
||||
|
||||
@@ -96,7 +96,7 @@ int main(int argc, char **argv)
|
||||
{
|
||||
char proc_dir_name[32];
|
||||
char *target_str;
|
||||
pid_t target, parent;
|
||||
pid_t target;
|
||||
int proc_dir_fd;
|
||||
int ranges;
|
||||
struct map_range *mappings;
|
||||
|
||||
122
src/newusers.c
122
src/newusers.c
@@ -80,10 +80,15 @@ static bool rflg = false; /* create a system account */
|
||||
#ifndef USE_PAM
|
||||
static /*@null@*//*@observer@*/char *crypt_method = NULL;
|
||||
#define cflg (NULL != crypt_method)
|
||||
#ifdef USE_SHA_CRYPT
|
||||
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
|
||||
static bool sflg = false;
|
||||
#endif
|
||||
#ifdef USE_SHA_CRYPT
|
||||
static long sha_rounds = 5000;
|
||||
#endif /* USE_SHA_CRYPT */
|
||||
#ifdef USE_BCRYPT
|
||||
static long bcrypt_rounds = 13;
|
||||
#endif /* USE_BCRYPT */
|
||||
#endif /* !USE_PAM */
|
||||
|
||||
static bool is_shadow;
|
||||
@@ -117,6 +122,8 @@ static void check_perms (void);
|
||||
static void open_files (void);
|
||||
static void close_files (void);
|
||||
|
||||
extern int allow_bad_names;
|
||||
|
||||
/*
|
||||
* usage - display usage message and exit
|
||||
*/
|
||||
@@ -128,25 +135,30 @@ static void usage (int status)
|
||||
"\n"
|
||||
"Options:\n"),
|
||||
Prog);
|
||||
(void) fputs (_(" -b, --badnames allow bad names\n"), usageout);
|
||||
#ifndef USE_PAM
|
||||
(void) fprintf (usageout,
|
||||
_(" -c, --crypt-method METHOD the crypt method (one of %s)\n"),
|
||||
#ifndef USE_SHA_CRYPT
|
||||
#if !defined(USE_SHA_CRYPT) && !defined(USE_BCRYPT)
|
||||
"NONE DES MD5"
|
||||
#else /* USE_SHA_CRYPT */
|
||||
#elif defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
|
||||
"NONE DES MD5 SHA256 SHA512 BCRYPT"
|
||||
#elif defined(USE_SHA_CRYPT)
|
||||
"NONE DES MD5 SHA256 SHA512"
|
||||
#endif /* USE_SHA_CRYPT */
|
||||
#else
|
||||
"NONE DES MD5 BCRYPT"
|
||||
#endif
|
||||
);
|
||||
#endif /* !USE_PAM */
|
||||
(void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
|
||||
(void) fputs (_(" -r, --system create system accounts\n"), usageout);
|
||||
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
|
||||
#ifndef USE_PAM
|
||||
#ifdef USE_SHA_CRYPT
|
||||
(void) fputs (_(" -s, --sha-rounds number of SHA rounds for the SHA*\n"
|
||||
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
|
||||
(void) fputs (_(" -s, --sha-rounds number of rounds for the SHA or BCRYPT\n"
|
||||
" crypt algorithms\n"),
|
||||
usageout);
|
||||
#endif /* USE_SHA_CRYPT */
|
||||
#endif /* USE_SHA_CRYPT || USE_BCRYPT */
|
||||
#endif /* !USE_PAM */
|
||||
(void) fputs ("\n", usageout);
|
||||
|
||||
@@ -420,15 +432,29 @@ static int update_passwd (struct passwd *pwd, const char *password)
|
||||
{
|
||||
void *crypt_arg = NULL;
|
||||
char *cp;
|
||||
if (crypt_method != NULL) {
|
||||
#ifdef USE_SHA_CRYPT
|
||||
if (NULL != crypt_method) {
|
||||
#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
|
||||
if (sflg) {
|
||||
if ( (0 == strcmp (crypt_method, "SHA256"))
|
||||
|| (0 == strcmp (crypt_method, "SHA512"))) {
|
||||
crypt_arg = &sha_rounds;
|
||||
}
|
||||
else if (0 == strcmp (crypt_method, "BCRYPT")) {
|
||||
crypt_arg = &bcrypt_rounds;
|
||||
}
|
||||
}
|
||||
#elif defined(USE_SHA_CRYPT)
|
||||
if (sflg) {
|
||||
crypt_arg = &sha_rounds;
|
||||
}
|
||||
#elif defined(USE_BCRYPT)
|
||||
if (sflg) {
|
||||
crypt_arg = &bcrypt_rounds;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((crypt_method != NULL) && (0 == strcmp(crypt_method, "NONE"))) {
|
||||
if ((NULL != crypt_method) && (0 == strcmp(crypt_method, "NONE"))) {
|
||||
pwd->pw_passwd = (char *)password;
|
||||
} else {
|
||||
const char *salt = crypt_make_salt (crypt_method, crypt_arg);
|
||||
@@ -457,12 +483,26 @@ static int add_passwd (struct passwd *pwd, const char *password)
|
||||
|
||||
#ifndef USE_PAM
|
||||
void *crypt_arg = NULL;
|
||||
if (crypt_method != NULL) {
|
||||
#ifdef USE_SHA_CRYPT
|
||||
if (NULL != crypt_method) {
|
||||
#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
|
||||
if (sflg) {
|
||||
if ( (0 == strcmp (crypt_method, "SHA256"))
|
||||
|| (0 == strcmp (crypt_method, "SHA512"))) {
|
||||
crypt_arg = &sha_rounds;
|
||||
}
|
||||
else if (0 == strcmp (crypt_method, "BCRYPT")) {
|
||||
crypt_arg = &bcrypt_rounds;
|
||||
}
|
||||
}
|
||||
#elif defined(USE_SHA_CRYPT)
|
||||
if (sflg) {
|
||||
crypt_arg = &sha_rounds;
|
||||
}
|
||||
#endif /* USE_SHA_CRYPT */
|
||||
#elif defined(USE_BCRYPT)
|
||||
if (sflg) {
|
||||
crypt_arg = &bcrypt_rounds;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -580,6 +620,7 @@ static void process_flags (int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
static struct option long_options[] = {
|
||||
{"badnames", no_argument, NULL, 'b'},
|
||||
#ifndef USE_PAM
|
||||
{"crypt-method", required_argument, NULL, 'c'},
|
||||
#endif /* !USE_PAM */
|
||||
@@ -587,25 +628,28 @@ static void process_flags (int argc, char **argv)
|
||||
{"system", no_argument, NULL, 'r'},
|
||||
{"root", required_argument, NULL, 'R'},
|
||||
#ifndef USE_PAM
|
||||
#ifdef USE_SHA_CRYPT
|
||||
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
|
||||
{"sha-rounds", required_argument, NULL, 's'},
|
||||
#endif /* USE_SHA_CRYPT */
|
||||
#endif /* USE_SHA_CRYPT || USE_BCRYPT */
|
||||
#endif /* !USE_PAM */
|
||||
{NULL, 0, NULL, '\0'}
|
||||
};
|
||||
|
||||
while ((c = getopt_long (argc, argv,
|
||||
#ifndef USE_PAM
|
||||
#ifdef USE_SHA_CRYPT
|
||||
"c:hrs:",
|
||||
#else /* !USE_SHA_CRYPT */
|
||||
"c:hr",
|
||||
#endif /* !USE_SHA_CRYPT */
|
||||
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
|
||||
"c:bhrs:",
|
||||
#else /* !USE_SHA_CRYPT && !USE_BCRYPT */
|
||||
"c:bhr",
|
||||
#endif /* USE_SHA_CRYPT || USE_BCRYPT */
|
||||
#else /* USE_PAM */
|
||||
"hr",
|
||||
"bhr",
|
||||
#endif
|
||||
long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'b':
|
||||
allow_bad_names = true;
|
||||
break;
|
||||
#ifndef USE_PAM
|
||||
case 'c':
|
||||
crypt_method = optarg;
|
||||
@@ -620,17 +664,40 @@ static void process_flags (int argc, char **argv)
|
||||
case 'R': /* no-op, handled in process_root_flag () */
|
||||
break;
|
||||
#ifndef USE_PAM
|
||||
#ifdef USE_SHA_CRYPT
|
||||
#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
|
||||
case 's':
|
||||
sflg = true;
|
||||
if (getlong(optarg, &sha_rounds) == 0) {
|
||||
if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512")))
|
||||
&& (0 == getlong(optarg, &sha_rounds)))
|
||||
|| ( (0 == strcmp (crypt_method, "BCRYPT"))
|
||||
&& (0 == getlong(optarg, &bcrypt_rounds)))) {
|
||||
fprintf (stderr,
|
||||
_("%s: invalid numeric argument '%s'\n"),
|
||||
Prog, optarg);
|
||||
usage (EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
#endif /* USE_SHA_CRYPT */
|
||||
#elif defined(USE_SHA_CRYPT)
|
||||
case 's':
|
||||
sflg = true;
|
||||
if (0 == getlong(optarg, &sha_rounds)) {
|
||||
fprintf (stderr,
|
||||
_("%s: invalid numeric argument '%s'\n"),
|
||||
Prog, optarg);
|
||||
usage (EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
#elif defined(USE_BCRYPT)
|
||||
case 's':
|
||||
sflg = true;
|
||||
if (0 == getlong(optarg, &bcrypt_rounds)) {
|
||||
fprintf (stderr,
|
||||
_("%s: invalid numeric argument '%s'\n"),
|
||||
Prog, optarg);
|
||||
usage (EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#endif /* !USE_PAM */
|
||||
default:
|
||||
usage (EXIT_FAILURE);
|
||||
@@ -664,14 +731,14 @@ static void process_flags (int argc, char **argv)
|
||||
static void check_flags (void)
|
||||
{
|
||||
#ifndef USE_PAM
|
||||
#ifdef USE_SHA_CRYPT
|
||||
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
|
||||
if (sflg && !cflg) {
|
||||
fprintf (stderr,
|
||||
_("%s: %s flag is only allowed with the %s flag\n"),
|
||||
Prog, "-s", "-c");
|
||||
usage (EXIT_FAILURE);
|
||||
}
|
||||
#endif /* USE_SHA_CRYPT */
|
||||
#endif
|
||||
|
||||
if (cflg) {
|
||||
if ( (0 != strcmp (crypt_method, "DES"))
|
||||
@@ -681,6 +748,9 @@ static void check_flags (void)
|
||||
&& (0 != strcmp (crypt_method, "SHA256"))
|
||||
&& (0 != strcmp (crypt_method, "SHA512"))
|
||||
#endif /* USE_SHA_CRYPT */
|
||||
#ifdef USE_BCRYPT
|
||||
&& (0 != strcmp (crypt_method, "BCRYPT"))
|
||||
#endif /* USE_BCRYPT */
|
||||
) {
|
||||
fprintf (stderr,
|
||||
_("%s: unsupported crypt method: %s\n"),
|
||||
|
||||
85
src/passwd.c
85
src/passwd.c
@@ -41,12 +41,6 @@
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef WITH_SELINUX
|
||||
#include <selinux/selinux.h>
|
||||
#include <selinux/flask.h>
|
||||
#include <selinux/av_permissions.h>
|
||||
#include <selinux/context.h>
|
||||
#endif /* WITH_SELINUX */
|
||||
#include <time.h>
|
||||
#include "defines.h"
|
||||
#include "getdef.h"
|
||||
@@ -149,11 +143,6 @@ static char *update_crypt_pw (char *);
|
||||
static void update_noshadow (void);
|
||||
|
||||
static void update_shadow (void);
|
||||
#ifdef WITH_SELINUX
|
||||
static int check_selinux_access (const char *changed_user,
|
||||
uid_t changed_uid,
|
||||
access_vector_t requested_access);
|
||||
#endif /* WITH_SELINUX */
|
||||
|
||||
/*
|
||||
* usage - print command usage and exit
|
||||
@@ -290,7 +279,11 @@ static int new_password (const struct passwd *pw)
|
||||
#ifdef USE_SHA_CRYPT
|
||||
|| (strcmp (method, "SHA256") == 0)
|
||||
|| (strcmp (method, "SHA512") == 0)
|
||||
#endif /* USE_SHA_CRYPT */
|
||||
#endif /* USE_SHA_CRYPT */
|
||||
#ifdef USE_BCRYPT
|
||||
|| (strcmp (method, "BCRYPT") == 0)
|
||||
#endif /* USE_SHA_CRYPT */
|
||||
|
||||
) {
|
||||
pass_max_len = -1;
|
||||
} else {
|
||||
@@ -710,55 +703,6 @@ static void update_shadow (void)
|
||||
spw_locked = false;
|
||||
}
|
||||
|
||||
#ifdef WITH_SELINUX
|
||||
static int check_selinux_access (const char *changed_user,
|
||||
uid_t changed_uid,
|
||||
access_vector_t requested_access)
|
||||
{
|
||||
int status = -1;
|
||||
security_context_t user_context;
|
||||
context_t c;
|
||||
const char *user;
|
||||
|
||||
/* if in permissive mode then allow the operation */
|
||||
if (security_getenforce() == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get the context of the process which executed passwd */
|
||||
if (getprevcon(&user_context) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* get the "user" portion of the context (the part before the first
|
||||
colon) */
|
||||
c = context_new(user_context);
|
||||
user = context_user_get(c);
|
||||
|
||||
/* if changing a password for an account with UID==0 or for an account
|
||||
where the identity matches then return success */
|
||||
if (changed_uid != 0 && strcmp(changed_user, user) == 0) {
|
||||
status = 0;
|
||||
} else {
|
||||
struct av_decision avd;
|
||||
int retval;
|
||||
retval = security_compute_av(user_context,
|
||||
user_context,
|
||||
SECCLASS_PASSWD,
|
||||
requested_access,
|
||||
&avd);
|
||||
if ((retval == 0) &&
|
||||
((requested_access & avd.allowed) == requested_access)) {
|
||||
status = 0;
|
||||
}
|
||||
}
|
||||
context_free(c);
|
||||
freecon(user_context);
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* WITH_SELINUX */
|
||||
|
||||
/*
|
||||
* passwd - change a user's password file information
|
||||
*
|
||||
@@ -1034,22 +978,13 @@ int main (int argc, char **argv)
|
||||
#ifdef WITH_SELINUX
|
||||
/* only do this check when getuid()==0 because it's a pre-condition for
|
||||
changing a password without entering the old one */
|
||||
if ((is_selinux_enabled() > 0) && (getuid() == 0) &&
|
||||
(check_selinux_access (name, pw->pw_uid, PASSWD__PASSWD) != 0)) {
|
||||
security_context_t user_context = NULL;
|
||||
const char *user = "Unknown user context";
|
||||
if (getprevcon (&user_context) == 0) {
|
||||
user = user_context; /* FIXME: use context_user_get? */
|
||||
}
|
||||
if (amroot && (check_selinux_permit ("passwd") != 0)) {
|
||||
SYSLOG ((LOG_ALERT,
|
||||
"%s is not authorized to change the password of %s",
|
||||
user, name));
|
||||
"root is not authorized by SELinux to change the password of %s",
|
||||
name));
|
||||
(void) fprintf(stderr,
|
||||
_("%s: %s is not authorized to change the password of %s\n"),
|
||||
Prog, user, name);
|
||||
if (NULL != user_context) {
|
||||
freecon (user_context);
|
||||
}
|
||||
_("%s: root is not authorized by SELinux to change the password of %s\n"),
|
||||
Prog, name);
|
||||
exit (E_NOPERM);
|
||||
}
|
||||
#endif /* WITH_SELINUX */
|
||||
|
||||
29
src/pwck.c
29
src/pwck.c
@@ -95,6 +95,8 @@ static void close_files (bool changed);
|
||||
static void check_pw_file (int *errors, bool *changed);
|
||||
static void check_spw_file (int *errors, bool *changed);
|
||||
|
||||
extern int allow_bad_names;
|
||||
|
||||
/*
|
||||
* fail_exit - do some cleanup and exit with the given error code
|
||||
*/
|
||||
@@ -148,6 +150,7 @@ static /*@noreturn@*/void usage (int status)
|
||||
"Options:\n"),
|
||||
Prog);
|
||||
}
|
||||
(void) fputs (_(" -b, --badnames allow bad names\n"), usageout);
|
||||
(void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
|
||||
(void) fputs (_(" -q, --quiet report errors only\n"), usageout);
|
||||
(void) fputs (_(" -r, --read-only display errors and warnings\n"
|
||||
@@ -172,6 +175,7 @@ static void process_flags (int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
static struct option long_options[] = {
|
||||
{"badnames", no_argument, NULL, 'b'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"quiet", no_argument, NULL, 'q'},
|
||||
{"read-only", no_argument, NULL, 'r'},
|
||||
@@ -183,9 +187,12 @@ static void process_flags (int argc, char **argv)
|
||||
/*
|
||||
* Parse the command line arguments
|
||||
*/
|
||||
while ((c = getopt_long (argc, argv, "ehqrR:s",
|
||||
while ((c = getopt_long (argc, argv, "behqrR:s",
|
||||
long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'b':
|
||||
allow_bad_names = true;
|
||||
break;
|
||||
case 'h':
|
||||
usage (E_SUCCESS);
|
||||
/*@notreached@*/break;
|
||||
@@ -382,6 +389,8 @@ static void check_pw_file (int *errors, bool *changed)
|
||||
struct commonio_entry *pfe, *tpfe;
|
||||
struct passwd *pwd;
|
||||
struct spwd *spw;
|
||||
uid_t min_sys_id = (uid_t) getdef_ulong ("SYS_UID_MIN", 101UL);
|
||||
uid_t max_sys_id = (uid_t) getdef_ulong ("SYS_UID_MAX", 999UL);
|
||||
|
||||
/*
|
||||
* Loop through the entire password file.
|
||||
@@ -481,6 +490,7 @@ static void check_pw_file (int *errors, bool *changed)
|
||||
/*
|
||||
* Check for invalid usernames. --marekm
|
||||
*/
|
||||
|
||||
if (!is_valid_user_name (pwd->pw_name)) {
|
||||
printf (_("invalid user name '%s'\n"), pwd->pw_name);
|
||||
*errors += 1;
|
||||
@@ -510,15 +520,20 @@ static void check_pw_file (int *errors, bool *changed)
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure the home directory exists
|
||||
* If uid is system and has a home directory, then check
|
||||
*/
|
||||
if (!quiet && (access (pwd->pw_dir, F_OK) != 0)) {
|
||||
if (!(pwd->pw_uid >= min_sys_id && pwd->pw_uid <= max_sys_id && pwd->pw_dir && pwd->pw_dir[0])) {
|
||||
/*
|
||||
* Home directory doesn't exist, give a warning
|
||||
* Make sure the home directory exists
|
||||
*/
|
||||
printf (_("user '%s': directory '%s' does not exist\n"),
|
||||
pwd->pw_name, pwd->pw_dir);
|
||||
*errors += 1;
|
||||
if (!quiet && (access (pwd->pw_dir, F_OK) != 0)) {
|
||||
/*
|
||||
* Home directory doesn't exist, give a warning
|
||||
*/
|
||||
printf (_("user '%s': directory '%s' does not exist\n"),
|
||||
pwd->pw_name, pwd->pw_dir);
|
||||
*errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -148,6 +148,8 @@ static char **user_groups; /* NULL-terminated list */
|
||||
static long sys_ngroups;
|
||||
static bool do_grp_update = false; /* group files need to be updated */
|
||||
|
||||
extern int allow_bad_names;
|
||||
|
||||
static bool
|
||||
bflg = false, /* new default root of home directory */
|
||||
cflg = false, /* comment (GECOS) field for new account */
|
||||
@@ -821,6 +823,7 @@ static void usage (int status)
|
||||
"\n"
|
||||
"Options:\n"),
|
||||
Prog, Prog, Prog);
|
||||
(void) fputs (_(" --badnames do not check for bad names\n"), usageout);
|
||||
(void) fputs (_(" -b, --base-dir BASE_DIR base directory for the home directory of the\n"
|
||||
" new account\n"), usageout);
|
||||
#ifdef WITH_BTRFS
|
||||
@@ -1098,6 +1101,7 @@ static void process_flags (int argc, char **argv)
|
||||
const struct group *grp;
|
||||
bool anyflag = false;
|
||||
char *cp;
|
||||
struct stat st;
|
||||
|
||||
{
|
||||
/*
|
||||
@@ -1109,6 +1113,7 @@ static void process_flags (int argc, char **argv)
|
||||
#ifdef WITH_BTRFS
|
||||
{"btrfs-subvolume-home", no_argument, NULL, 200},
|
||||
#endif
|
||||
{"badnames", no_argument, NULL, 201},
|
||||
{"comment", required_argument, NULL, 'c'},
|
||||
{"home-dir", required_argument, NULL, 'd'},
|
||||
{"defaults", no_argument, NULL, 'D'},
|
||||
@@ -1158,6 +1163,9 @@ static void process_flags (int argc, char **argv)
|
||||
case 200:
|
||||
subvolflg = true;
|
||||
break;
|
||||
case 201:
|
||||
allow_bad_names = true;
|
||||
break;
|
||||
case 'c':
|
||||
if (!VALID (optarg)) {
|
||||
fprintf (stderr,
|
||||
@@ -1320,7 +1328,10 @@ static void process_flags (int argc, char **argv)
|
||||
if ( ( !VALID (optarg) )
|
||||
|| ( ('\0' != optarg[0])
|
||||
&& ('/' != optarg[0])
|
||||
&& ('*' != optarg[0]) )) {
|
||||
&& ('*' != optarg[0]) )
|
||||
|| (stat(optarg, &st) != 0)
|
||||
|| (S_ISDIR(st.st_mode))
|
||||
|| (access(optarg, X_OK) != 0)) {
|
||||
fprintf (stderr,
|
||||
_("%s: invalid shell '%s'\n"),
|
||||
Prog, optarg);
|
||||
@@ -2449,9 +2460,9 @@ int main (int argc, char **argv)
|
||||
(uid_t)-1, user_id, (gid_t)-1, user_gid);
|
||||
} else {
|
||||
fprintf (stderr,
|
||||
_("%s: warning: the home directory already exists.\n"
|
||||
"Not copying any file from skel directory into it.\n"),
|
||||
Prog);
|
||||
_("%s: warning: the home directory %s already exists.\n"
|
||||
"%s: Not copying any file from skel directory into it.\n"),
|
||||
Prog, user_home, Prog);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -97,7 +97,9 @@ static char *user_home;
|
||||
|
||||
static bool fflg = false;
|
||||
static bool rflg = false;
|
||||
#ifdef WITH_SELINUX
|
||||
static bool Zflg = false;
|
||||
#endif
|
||||
static bool Rflg = false;
|
||||
|
||||
static bool is_shadow_pwd;
|
||||
|
||||
@@ -206,6 +206,8 @@ static void update_faillog (void);
|
||||
static void move_mailbox (void);
|
||||
#endif
|
||||
|
||||
extern int allow_bad_names;
|
||||
|
||||
static void date_to_str (/*@unique@*//*@out@*/char *buf, size_t maxsize,
|
||||
long int date)
|
||||
{
|
||||
@@ -408,6 +410,7 @@ static /*@noreturn@*/void usage (int status)
|
||||
"\n"
|
||||
"Options:\n"),
|
||||
Prog);
|
||||
(void) fputs (_(" -b, --badnames allow bad names\n"), usageout);
|
||||
(void) fputs (_(" -c, --comment COMMENT new value of the GECOS field\n"), usageout);
|
||||
(void) fputs (_(" -d, --home HOME_DIR new home directory for the user account\n"), usageout);
|
||||
(void) fputs (_(" -e, --expiredate EXPIRE_DATE set account expiration date to EXPIRE_DATE\n"), usageout);
|
||||
@@ -991,6 +994,7 @@ static void process_flags (int argc, char **argv)
|
||||
int c;
|
||||
static struct option long_options[] = {
|
||||
{"append", no_argument, NULL, 'a'},
|
||||
{"badnames", no_argument, NULL, 'b'},
|
||||
{"comment", required_argument, NULL, 'c'},
|
||||
{"home", required_argument, NULL, 'd'},
|
||||
{"expiredate", required_argument, NULL, 'e'},
|
||||
@@ -1020,7 +1024,7 @@ static void process_flags (int argc, char **argv)
|
||||
{NULL, 0, NULL, '\0'}
|
||||
};
|
||||
while ((c = getopt_long (argc, argv,
|
||||
"ac:d:e:f:g:G:hl:Lmop:R:s:u:UP:"
|
||||
"abc:d:e:f:g:G:hl:Lmop:R:s:u:UP:"
|
||||
#ifdef ENABLE_SUBIDS
|
||||
"v:w:V:W:"
|
||||
#endif /* ENABLE_SUBIDS */
|
||||
@@ -1032,6 +1036,9 @@ static void process_flags (int argc, char **argv)
|
||||
case 'a':
|
||||
aflg = true;
|
||||
break;
|
||||
case 'b':
|
||||
allow_bad_names = true;
|
||||
break;
|
||||
case 'c':
|
||||
if (!VALID (optarg)) {
|
||||
fprintf (stderr,
|
||||
@@ -1879,7 +1886,7 @@ static void update_lastlog (void)
|
||||
return;
|
||||
}
|
||||
|
||||
max_uid = (uid_t) getdef_ulong ("LASTLOG_MAX_UID", 0xFFFFFFFFUL);
|
||||
max_uid = (uid_t) getdef_ulong ("LASTLOG_UID_MAX", 0xFFFFFFFFUL);
|
||||
if (user_newid > max_uid) {
|
||||
/* do not touch lastlog for large uids */
|
||||
return;
|
||||
|
||||
47
src/vipw.c
47
src/vipw.c
@@ -207,6 +207,8 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
|
||||
struct stat st1, st2;
|
||||
int status;
|
||||
FILE *f;
|
||||
pid_t orig_pgrp, editor_pgrp = -1;
|
||||
sigset_t mask, omask;
|
||||
/* FIXME: the following should have variable sizes */
|
||||
char filebackup[1024], fileedit[1024];
|
||||
char *to_rename;
|
||||
@@ -294,6 +296,8 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
|
||||
editor = DEFAULT_EDITOR;
|
||||
}
|
||||
|
||||
orig_pgrp = tcgetpgrp(STDIN_FILENO);
|
||||
|
||||
pid = fork ();
|
||||
if (-1 == pid) {
|
||||
vipwexit ("fork", 1, 1);
|
||||
@@ -303,6 +307,14 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
|
||||
char *buf;
|
||||
int status;
|
||||
|
||||
/* Wait for parent to make us the foreground pgrp. */
|
||||
if (orig_pgrp != -1) {
|
||||
pid = getpid();
|
||||
setpgid(0, 0);
|
||||
while (tcgetpgrp(STDIN_FILENO) != pid)
|
||||
continue;
|
||||
}
|
||||
|
||||
buf = (char *) malloc (strlen (editor) + strlen (fileedit) + 2);
|
||||
snprintf (buf, strlen (editor) + strlen (fileedit) + 2,
|
||||
"%s %s", editor, fileedit);
|
||||
@@ -325,19 +337,50 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
|
||||
}
|
||||
}
|
||||
|
||||
/* Run child in a new pgrp and make it the foreground pgrp. */
|
||||
if (orig_pgrp != -1) {
|
||||
setpgid(pid, pid);
|
||||
tcsetpgrp(STDIN_FILENO, pid);
|
||||
|
||||
/* Avoid SIGTTOU when changing foreground pgrp below. */
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGTTOU);
|
||||
sigprocmask(SIG_BLOCK, &mask, &omask);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
pid = waitpid (pid, &status, WUNTRACED);
|
||||
if ((pid != -1) && (WIFSTOPPED (status) != 0)) {
|
||||
/* The child (editor) was suspended.
|
||||
* Suspend vipw. */
|
||||
* Restore terminal pgrp and suspend vipw. */
|
||||
if (orig_pgrp != -1) {
|
||||
editor_pgrp = tcgetpgrp(STDIN_FILENO);
|
||||
if (editor_pgrp == -1) {
|
||||
fprintf (stderr, "%s: %s: %s", Prog,
|
||||
"tcgetpgrp", strerror (errno));
|
||||
}
|
||||
if (tcsetpgrp(STDIN_FILENO, orig_pgrp) == -1) {
|
||||
fprintf (stderr, "%s: %s: %s", Prog,
|
||||
"tcsetpgrp", strerror (errno));
|
||||
}
|
||||
}
|
||||
kill (getpid (), SIGSTOP);
|
||||
/* wake child when resumed */
|
||||
kill (pid, SIGCONT);
|
||||
if (editor_pgrp != -1) {
|
||||
if (tcsetpgrp(STDIN_FILENO, editor_pgrp) == -1) {
|
||||
fprintf (stderr, "%s: %s: %s", Prog,
|
||||
"tcsetpgrp", strerror (errno));
|
||||
}
|
||||
}
|
||||
killpg (pid, SIGCONT);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (orig_pgrp != -1)
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
|
||||
if (-1 == pid) {
|
||||
vipwexit (editor, 1, 1);
|
||||
} else if ( WIFEXITED (status)
|
||||
|
||||
Reference in New Issue
Block a user