New upstream version 4.11.1+dfsg1

This commit is contained in:
Balint Reczey
2022-01-21 23:41:15 +01:00
parent 749c178062
commit 0c04b92a9a
792 changed files with 136713 additions and 93536 deletions
+145 -220
View File
@@ -1,33 +1,10 @@
/*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2000 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2011, Nicolas François
* All rights reserved.
* SPDX-FileCopyrightText: 1991 - 1994, Julianne Frances Haugh
* SPDX-FileCopyrightText: 1996 - 2000, Marek Michałkiewicz
* SPDX-FileCopyrightText: 2000 - 2006, Tomasz Kłoczko
* SPDX-FileCopyrightText: 2007 - 2011, Nicolas François
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <config.h>
@@ -74,6 +51,7 @@
#ifdef WITH_TCB
#include "tcbfuncs.h"
#endif
#include "shadowlog.h"
/*
* exit status values
@@ -105,7 +83,6 @@
* Global variables
*/
const char *Prog;
FILE *shadow_logfd = NULL;
static char *user_name;
static char *user_newname;
@@ -147,6 +124,7 @@ static bool
mflg = false, /* create user's home directory if it doesn't exist */
oflg = false, /* permit non-unique user ID to be specified with -u */
pflg = false, /* new encrypted password */
rflg = false, /* remove a user from a single group */
sflg = false, /* new shell program */
#ifdef WITH_SELINUX
Zflg = false, /* new selinux user */
@@ -184,10 +162,7 @@ static bool sub_gid_locked = false;
/* local function prototypes */
static void date_to_str (/*@unique@*//*@out@*/char *buf, size_t maxsize,
long int date);
static int get_groups (char *);
static struct group * get_local_group (char * grp_name);
static /*@noreturn@*/void usage (int status);
static void new_pwent (struct passwd *);
static void new_spent (struct spwd *);
@@ -201,9 +176,7 @@ static void grp_update (void);
static void process_flags (int, char **);
static void close_files (void);
static void close_group_files (void);
static void open_files (void);
static void open_group_files (void);
static void usr_update (void);
static void move_home (void);
static void update_lastlog (void);
@@ -215,28 +188,6 @@ static void move_mailbox (void);
extern int allow_bad_names;
static void date_to_str (/*@unique@*//*@out@*/char *buf, size_t maxsize,
long int date)
{
struct tm *tp;
if (date < 0) {
strncpy (buf, "never", maxsize);
} else {
time_t t = (time_t) date;
tp = gmtime (&t);
#ifdef HAVE_STRFTIME
strftime (buf, maxsize, "%Y-%m-%d", tp);
#else
(void) snprintf (buf, maxsize, "%04d-%02d-%02d",
tp->tm_year + 1900,
tp->tm_mon + 1,
tp->tm_mday);
#endif /* HAVE_STRFTIME */
}
buf[maxsize - 1] = '\0';
}
/*
* get_groups - convert a list of group names to an array of group IDs
*
@@ -260,11 +211,6 @@ static int get_groups (char *list)
return 0;
}
/*
* Open the group files
*/
open_group_files ();
/*
* So long as there is some data to be converted, strip off each
* name and look it up. A mix of numerical and string values for
@@ -284,7 +230,7 @@ static int get_groups (char *list)
* Names starting with digits are treated as numerical GID
* values, otherwise the string is looked up as is.
*/
grp = get_local_group (list);
grp = prefix_getgr_nam_gid (list);
/*
* There must be a match, either by GID value or by
@@ -334,8 +280,6 @@ static int get_groups (char *list)
gr_free ((struct group *)grp);
} while (NULL != list);
close_group_files ();
user_groups[ngroups] = (char *) 0;
/*
@@ -348,44 +292,6 @@ static int get_groups (char *list)
return 0;
}
/*
* get_local_group - checks if a given group name exists locally
*
* get_local_group() checks if a given group name exists locally.
* If the name exists the group information is returned, otherwise NULL is
* returned.
*/
static struct group * get_local_group(char * grp_name)
{
const struct group *grp;
struct group *result_grp = NULL;
long long int gid;
char *endptr;
gid = strtoll (grp_name, &endptr, 10);
if ( ('\0' != *grp_name)
&& ('\0' == *endptr)
&& (ERANGE != errno)
&& (gid == (gid_t)gid)) {
grp = gr_locate_gid ((gid_t) gid);
}
else {
grp = gr_locate(grp_name);
}
if (grp != NULL) {
result_grp = __gr_dup (grp);
if (NULL == result_grp) {
fprintf (stderr,
_("%s: Out of memory. Cannot find group '%s'.\n"),
Prog, grp_name);
fail_exit (E_GRP_UPDATE);
}
}
return result_grp;
}
#ifdef ENABLE_SUBIDS
struct ulong_range
{
@@ -418,7 +324,6 @@ static struct ulong_range getulong_range(const char *str)
result.last = (unsigned long int)last;
out:
return result;
}
struct ulong_range_list_entry {
@@ -473,6 +378,9 @@ static /*@noreturn@*/void usage (int status)
(void) fputs (_(" -a, --append append the user to the supplemental GROUPS\n"
" mentioned by the -G option without removing\n"
" the user from other groups\n"), usageout);
(void) fputs (_(" -r, --remove remove the user from only the supplemental GROUPS\n"
" mentioned by the -G option without removing\n"
" the user from other groups\n"), usageout);
(void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
(void) fputs (_(" -l, --login NEW_LOGIN new value of the login name\n"), usageout);
(void) fputs (_(" -L, --lock lock the user account\n"), usageout);
@@ -629,6 +537,12 @@ static void new_pwent (struct passwd *pwent)
SYSLOG ((LOG_INFO,
"change user '%s' home from '%s' to '%s'",
pwent->pw_name, pwent->pw_dir, user_newhome));
if (strlen(user_newhome) > 1
&& '/' == user_newhome[strlen(user_newhome)-1]) {
user_newhome[strlen(user_newhome)-1]='\0';
}
pwent->pw_dir = user_newhome;
}
if (sflg) {
@@ -676,10 +590,8 @@ static void new_spent (struct spwd *spent)
if (eflg) {
/* log dates rather than numbers of days. */
char new_exp[16], old_exp[16];
date_to_str (new_exp, sizeof(new_exp),
user_newexpire * DAY);
date_to_str (old_exp, sizeof(old_exp),
user_expire * DAY);
date_to_str (sizeof(new_exp), new_exp, user_newexpire * DAY);
date_to_str (sizeof(old_exp), old_exp, user_expire * DAY);
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
"changing expiration date",
@@ -800,6 +712,14 @@ static void update_group (void)
continue;
}
/*
* If rflg+Gflg is passed in AKA -rG invert is_member flag, which removes
* mentioned groups while leaving the others.
*/
if (Gflg && rflg && was_member) {
is_member = !is_member;
}
ngrp = __gr_dup (grp);
if (NULL == ngrp) {
fprintf (stderr,
@@ -915,6 +835,14 @@ static void update_gshadow (void)
continue;
}
/*
* If rflg+Gflg is passed in AKA -rG invert is_member, to remove targeted
* groups while leaving the user apart of groups not mentioned
*/
if (Gflg && rflg && was_member) {
is_member = !is_member;
}
nsgrp = __sgr_dup (sgrp);
if (NULL == nsgrp) {
fprintf (stderr,
@@ -997,7 +925,7 @@ static void update_gshadow (void)
changed = false;
/*
/*
* Update the group entry to reflect the changes.
*/
if (sgr_update (nsgrp) == 0) {
@@ -1063,6 +991,7 @@ static void process_flags (int argc, char **argv)
{"move-home", no_argument, NULL, 'm'},
{"non-unique", no_argument, NULL, 'o'},
{"password", required_argument, NULL, 'p'},
{"remove", no_argument, NULL, 'r'},
{"root", required_argument, NULL, 'R'},
{"prefix", required_argument, NULL, 'P'},
{"shell", required_argument, NULL, 's'},
@@ -1080,7 +1009,7 @@ static void process_flags (int argc, char **argv)
{NULL, 0, NULL, '\0'}
};
while ((c = getopt_long (argc, argv,
"abc:d:e:f:g:G:hl:Lmop:R:s:u:UP:"
"abc:d:e:f:g:G:hl:Lmop:rR:s:u:UP:"
#ifdef ENABLE_SUBIDS
"v:w:V:W:"
#endif /* ENABLE_SUBIDS */
@@ -1122,18 +1051,14 @@ static void process_flags (int argc, char **argv)
}
break;
case 'e':
if ('\0' != *optarg) {
user_newexpire = strtoday (optarg);
if (user_newexpire < -1) {
fprintf (stderr,
_("%s: invalid date '%s'\n"),
Prog, optarg);
exit (E_BAD_ARG);
}
user_newexpire *= DAY / SCALE;
} else {
user_newexpire = -1;
user_newexpire = strtoday (optarg);
if (user_newexpire < -1) {
fprintf (stderr,
_("%s: invalid date '%s'\n"),
Prog, optarg);
exit (E_BAD_ARG);
}
user_newexpire *= DAY / SCALE;
eflg = true;
break;
case 'f':
@@ -1190,6 +1115,9 @@ static void process_flags (int argc, char **argv)
user_pass = optarg;
pflg = true;
break;
case 'r':
rflg = true;
break;
case 'R': /* no-op, handled in process_root_flag () */
break;
case 'P': /* no-op, handled in process_prefix_flag () */
@@ -1329,7 +1257,7 @@ static void process_flags (int argc, char **argv)
if (!gflg) {
user_newgid = user_gid;
}
if(prefix[0]) {
if (prefix[0]) {
size_t len = strlen(prefix) + strlen(user_home) + 2;
int wlen;
prefix_user_home = xmalloc(len);
@@ -1391,6 +1319,20 @@ static void process_flags (int argc, char **argv)
usage (E_USAGE);
}
if (rflg && (!Gflg)) {
fprintf (stderr,
_("%s: %s flag is only allowed with the %s flag\n"),
Prog, "-r", "-G");
usage (E_USAGE);
}
if (rflg && aflg) {
fprintf (stderr,
_("%s: %s and %s are mutually exclusive flags\n"),
Prog, "-r", "-a");
usage (E_USAGE);
}
if ((Lflg && (pflg || Uflg)) || (pflg && Uflg)) {
fprintf (stderr,
_("%s: the -L, -p, and -U flags are exclusive\n"),
@@ -1523,7 +1465,50 @@ static void close_files (void)
}
if (Gflg || lflg) {
close_group_files ();
if (gr_close () == 0) {
fprintf (stderr,
_("%s: failure while writing changes to %s\n"),
Prog, gr_dbname ());
SYSLOG ((LOG_ERR,
"failure while writing changes to %s",
gr_dbname ()));
fail_exit (E_GRP_UPDATE);
}
#ifdef SHADOWGRP
if (is_shadow_grp) {
if (sgr_close () == 0) {
fprintf (stderr,
_("%s: failure while writing changes to %s\n"),
Prog, sgr_dbname ());
SYSLOG ((LOG_ERR,
"failure while writing changes to %s",
sgr_dbname ()));
fail_exit (E_GRP_UPDATE);
}
}
#endif
#ifdef SHADOWGRP
if (is_shadow_grp) {
if (sgr_unlock () == 0) {
fprintf (stderr,
_("%s: failed to unlock %s\n"),
Prog, sgr_dbname ());
SYSLOG ((LOG_ERR,
"failed to unlock %s",
sgr_dbname ()));
/* continue */
}
}
#endif
if (gr_unlock () == 0) {
fprintf (stderr,
_("%s: failed to unlock %s\n"),
Prog, gr_dbname ());
SYSLOG ((LOG_ERR,
"failed to unlock %s",
gr_dbname ()));
/* continue */
}
}
if (is_shadow_pwd) {
@@ -1592,60 +1577,6 @@ static void close_files (void)
#endif
}
/*
* close_group_files - close all of the files that were opened
*
* close_group_files() closes all of the files that were opened related
* with groups. This causes any modified entries to be written out.
*/
static void close_group_files (void)
{
if (gr_close () == 0) {
fprintf (stderr,
_("%s: failure while writing changes to %s\n"),
Prog, gr_dbname ());
SYSLOG ((LOG_ERR,
"failure while writing changes to %s",
gr_dbname ()));
fail_exit (E_GRP_UPDATE);
}
#ifdef SHADOWGRP
if (is_shadow_grp) {
if (sgr_close () == 0) {
fprintf (stderr,
_("%s: failure while writing changes to %s\n"),
Prog, sgr_dbname ());
SYSLOG ((LOG_ERR,
"failure while writing changes to %s",
sgr_dbname ()));
fail_exit (E_GRP_UPDATE);
}
}
#endif
#ifdef SHADOWGRP
if (is_shadow_grp) {
if (sgr_unlock () == 0) {
fprintf (stderr,
_("%s: failed to unlock %s\n"),
Prog, sgr_dbname ());
SYSLOG ((LOG_ERR,
"failed to unlock %s",
sgr_dbname ()));
/* continue */
}
}
#endif
if (gr_unlock () == 0) {
fprintf (stderr,
_("%s: failed to unlock %s\n"),
Prog, gr_dbname ());
SYSLOG ((LOG_ERR,
"failed to unlock %s",
gr_dbname ()));
/* continue */
}
}
/*
* open_files - lock and open the password files
*
@@ -1681,7 +1612,38 @@ static void open_files (void)
}
if (Gflg || lflg) {
open_group_files ();
/*
* Lock and open the group file. This will load all of the
* group entries.
*/
if (gr_lock () == 0) {
fprintf (stderr,
_("%s: cannot lock %s; try again later.\n"),
Prog, gr_dbname ());
fail_exit (E_GRP_UPDATE);
}
gr_locked = true;
if (gr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, gr_dbname ());
fail_exit (E_GRP_UPDATE);
}
#ifdef SHADOWGRP
if (is_shadow_grp && (sgr_lock () == 0)) {
fprintf (stderr,
_("%s: cannot lock %s; try again later.\n"),
Prog, sgr_dbname ());
fail_exit (E_GRP_UPDATE);
}
sgr_locked = true;
if (is_shadow_grp && (sgr_open (O_CREAT | O_RDWR) == 0)) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sgr_dbname ());
fail_exit (E_GRP_UPDATE);
}
#endif
}
#ifdef ENABLE_SUBIDS
if (vflg || Vflg) {
@@ -1717,44 +1679,6 @@ static void open_files (void)
#endif /* ENABLE_SUBIDS */
}
/*
* open_group_files - lock and open the group files
*
* open_group_files() loads all of the group entries.
*/
static void open_group_files (void)
{
if (gr_lock () == 0) {
fprintf (stderr,
_("%s: cannot lock %s; try again later.\n"),
Prog, gr_dbname ());
fail_exit (E_GRP_UPDATE);
}
gr_locked = true;
if (gr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, gr_dbname ());
fail_exit (E_GRP_UPDATE);
}
#ifdef SHADOWGRP
if (is_shadow_grp && (sgr_lock () == 0)) {
fprintf (stderr,
_("%s: cannot lock %s; try again later.\n"),
Prog, sgr_dbname ());
fail_exit (E_GRP_UPDATE);
}
sgr_locked = true;
if (is_shadow_grp && (sgr_open (O_CREAT | O_RDWR) == 0)) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sgr_dbname ());
fail_exit (E_GRP_UPDATE);
}
#endif
}
/*
* usr_update - create the user entries
*
@@ -2208,7 +2132,8 @@ int main (int argc, char **argv)
* Get my name so that I can use it to report errors.
*/
Prog = Basename (argv[0]);
shadow_logfd = stderr;
log_set_progname(Prog);
log_set_logfd(stderr);
(void) setlocale (LC_ALL, "");
(void) bindtextdomain (PACKAGE, LOCALEDIR);
@@ -2313,7 +2238,7 @@ int main (int argc, char **argv)
if (sub_uid_remove(user_name, ptr->range.first, count) == 0) {
fprintf (stderr,
_("%s: failed to remove uid range %lu-%lu from '%s'\n"),
Prog, ptr->range.first, ptr->range.last,
Prog, ptr->range.first, ptr->range.last,
sub_uid_dbname ());
fail_exit (E_SUB_UID_UPDATE);
}
@@ -2326,7 +2251,7 @@ int main (int argc, char **argv)
if (sub_uid_add(user_name, ptr->range.first, count) == 0) {
fprintf (stderr,
_("%s: failed to add uid range %lu-%lu to '%s'\n"),
Prog, ptr->range.first, ptr->range.last,
Prog, ptr->range.first, ptr->range.last,
sub_uid_dbname ());
fail_exit (E_SUB_UID_UPDATE);
}
@@ -2339,7 +2264,7 @@ int main (int argc, char **argv)
if (sub_gid_remove(user_name, ptr->range.first, count) == 0) {
fprintf (stderr,
_("%s: failed to remove gid range %lu-%lu from '%s'\n"),
Prog, ptr->range.first, ptr->range.last,
Prog, ptr->range.first, ptr->range.last,
sub_gid_dbname ());
fail_exit (E_SUB_GID_UPDATE);
}
@@ -2352,7 +2277,7 @@ int main (int argc, char **argv)
if (sub_gid_add(user_name, ptr->range.first, count) == 0) {
fprintf (stderr,
_("%s: failed to add gid range %lu-%lu to '%s'\n"),
Prog, ptr->range.first, ptr->range.last,
Prog, ptr->range.first, ptr->range.last,
sub_gid_dbname ());
fail_exit (E_SUB_GID_UPDATE);
}