[svn-upgrade] Integrating new upstream version, shadow (4.0.1)

This commit is contained in:
nekral-guest
2007-10-07 11:44:59 +00:00
parent 3bc4996775
commit 9db6abfa42
194 changed files with 20217 additions and 14460 deletions
+3 -4
View File
@@ -29,8 +29,7 @@ usbin_PROGRAMS = chpasswd dpasswd groupadd groupdel groupmod \
noinst_PROGRAMS = id sulogin
# id and groups are from gnu, sulogin from sysvinit,
# also suid programs are installed by hand.
# id and groups are from gnu, sulogin from sysvinit
suidbins = su
suidubins = chage chfn chsh expiry gpasswd newgrp passwd
@@ -54,6 +53,8 @@ userdel_LDADD = $(LDADD) $(LIBPAM)
usermod_LDADD = $(LDADD) $(LIBPAM)
install-exec-hook:
$(LN_S) newgrp $(DESTDIR)$(bindir)/sg
$(LN_S) vigr $(DESTDIR)$(bindir)/vipw
for i in $(suidbins); do \
chmod 4755 $(DESTDIR)$(bindir)/$$i; \
done
@@ -62,5 +63,3 @@ install-data-hook:
for i in $(suidubins); do \
chmod 4755 $(DESTDIR)$(ubindir)/$$i; \
done
rm -f $(DESTDIR)$(ubindir)/sg
ln -s newgrp $(DESTDIR)$(ubindir)/sg
+3 -4
View File
@@ -140,8 +140,7 @@ usbin_PROGRAMS = chpasswd dpasswd groupadd groupdel groupmod \
noinst_PROGRAMS = id sulogin
# id and groups are from gnu, sulogin from sysvinit,
# also suid programs are installed by hand.
# id and groups are from gnu, sulogin from sysvinit
suidbins = su
suidubins = chage chfn chsh expiry gpasswd newgrp passwd
@@ -795,6 +794,8 @@ uninstall-am: uninstall-binPROGRAMS uninstall-info-am \
install-exec-hook:
$(LN_S) newgrp $(DESTDIR)$(bindir)/sg
$(LN_S) vigr $(DESTDIR)$(bindir)/vipw
for i in $(suidbins); do \
chmod 4755 $(DESTDIR)$(bindir)/$$i; \
done
@@ -803,8 +804,6 @@ install-data-hook:
for i in $(suidubins); do \
chmod 4755 $(DESTDIR)$(ubindir)/$$i; \
done
rm -f $(DESTDIR)$(ubindir)/sg
ln -s newgrp $(DESTDIR)$(ubindir)/sg
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
+417 -436
View File
File diff suppressed because it is too large Load Diff
+276 -276
View File
@@ -17,7 +17,7 @@
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH 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)
@@ -30,32 +30,26 @@
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: chfn.c,v 1.17 2000/09/02 18:40:43 marekm Exp $")
RCSID (PKG_VER "$Id: chfn.c,v 1.20 2002/01/05 15:41:43 kloczek Exp $")
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include "prototypes.h"
#include "defines.h"
#include <pwd.h>
#include "pwio.h"
#include "getdef.h"
#include "pwauth.h"
#ifdef HAVE_SHADOW_H
#include <shadow.h>
#endif
#ifdef USE_PAM
#include "pam_defs.h"
#endif
/*
* Global variables.
*/
static char *Prog;
static char fullnm[BUFSIZ];
static char roomno[BUFSIZ];
@@ -68,84 +62,66 @@ static int amroot;
* External identifiers
*/
extern int optind;
extern char *optarg;
#ifdef NDBM
extern int pw_dbm_mode;
extern int pw_dbm_mode;
#endif
/*
* #defines for messages. This facilitates foreign language conversion
* since all messages are defined right here.
*/
#define WRONGPWD2 "incorrect password for `%s'"
#define PWDBUSY2 "can't lock /etc/passwd\n"
#define OPNERROR2 "can't open /etc/passwd\n"
#define UPDERROR2 "error updating passwd entry\n"
#define DBMERROR2 "error updating DBM passwd entry.\n"
#define NOTROOT2 "can't setuid(0).\n"
#define CLSERROR2 "can't rewrite /etc/passwd.\n"
#define UNLKERROR2 "can't unlock /etc/passwd.\n"
#define CHGGECOS "changed user `%s' information.\n"
/* local function prototypes */
static void usage(void);
static int may_change_field(int);
static void new_fields(void);
static char *copy_field(char *, char *, char *);
static void usage (void);
static int may_change_field (int);
static void new_fields (void);
static char *copy_field (char *, char *, char *);
/*
* usage - print command line syntax and exit
*/
static void
usage(void)
static void usage (void)
{
if (amroot)
fprintf(stderr,
_("Usage: %s [ -f full_name ] [ -r room_no ] [ -w work_ph ]\n\t[ -h home_ph ] [ -o other ] [ user ]\n"),
Prog);
fprintf (stderr,
_("Usage: %s [-f full_name] [-r room_no] "
"[-w work_ph]\n"
"\t[-h home_ph] [-o other] [user]\n"), Prog);
else
fprintf(stderr,
_("Usage: %s [ -f full_name ] [ -r room_no ] [ -w work_ph ] [ -h home_ph ]\n"),
Prog);
exit(1);
fprintf (stderr,
_("Usage: %s [-f full_name] [-r room_no] "
"[-w work_ph] [-h home_ph]\n"), Prog);
exit (1);
}
static int
may_change_field(int field)
static int may_change_field (int field)
{
const char *cp;
/*
* CHFN_RESTRICT can now specify exactly which fields may be
* changed by regular users, by using any combination of the
* following letters:
* CHFN_RESTRICT can now specify exactly which fields may be changed
* by regular users, by using any combination of the following
* letters:
* f - full name
* r - room number
* w - work phone
* h - home phone
*
* This makes it possible to disallow changing the room number
* information, for example - this feature was suggested by
* Maciej 'Tycoon' Majchrowski.
* information, for example - this feature was suggested by Maciej
* 'Tycoon' Majchrowski.
*
* For backward compatibility, "yes" is equivalent to "rwh",
* "no" is equivalent to "frwh". Only root can change anything
* "no" is equivalent to "frwh". Only root can change anything
* if the string is empty or not defined at all.
*/
if (amroot)
return 1;
cp = getdef_str("CHFN_RESTRICT");
cp = getdef_str ("CHFN_RESTRICT");
if (!cp)
cp = "";
else if (strcmp(cp, "yes") == 0)
else if (strcmp (cp, "yes") == 0)
cp = "rwh";
else if (strcmp(cp, "no") == 0)
else if (strcmp (cp, "no") == 0)
cp = "frwh";
if (strchr(cp, field))
if (strchr (cp, field))
return 1;
return 0;
}
@@ -153,53 +129,51 @@ may_change_field(int field)
/*
* new_fields - change the user's GECOS information interactively
*
* prompt the user for each of the four fields and fill in the fields
* from the user's response, or leave alone if nothing was entered.
* prompt the user for each of the four fields and fill in the fields from
* the user's response, or leave alone if nothing was entered.
*/
static void
new_fields(void)
static void new_fields (void)
{
printf(_("Enter the new value, or press return for the default\n"));
printf (_
("Enter the new value, or press ENTER for the default\n"));
if (may_change_field('f'))
change_field(fullnm, sizeof fullnm, _("Full Name"));
if (may_change_field ('f'))
change_field (fullnm, sizeof fullnm, _("Full Name"));
else
printf(_("\tFull Name: %s\n"), fullnm);
printf (_("\tFull Name: %s\n"), fullnm);
if (may_change_field('r'))
change_field(roomno, sizeof roomno, _("Room Number"));
if (may_change_field ('r'))
change_field (roomno, sizeof roomno, _("Room Number"));
else
printf(_("\tRoom Number: %s\n"), roomno);
printf (_("\tRoom Number: %s\n"), roomno);
if (may_change_field('w'))
change_field(workph, sizeof workph, _("Work Phone"));
if (may_change_field ('w'))
change_field (workph, sizeof workph, _("Work Phone"));
else
printf(_("\tWork Phone: %s\n"), workph);
printf (_("\tWork Phone: %s\n"), workph);
if (may_change_field('h'))
change_field(homeph, sizeof homeph, _("Home Phone"));
if (may_change_field ('h'))
change_field (homeph, sizeof homeph, _("Home Phone"));
else
printf(_("\tHome Phone: %s\n"), homeph);
printf (_("\tHome Phone: %s\n"), homeph);
if (amroot)
change_field(slop, sizeof slop, _("Other"));
change_field (slop, sizeof slop, _("Other"));
}
/*
* copy_field - get the next field from the gecos field
*
* copy_field copies the next field from the gecos field, returning a
* pointer to the field which follows, or NULL if there are no more
* fields.
* pointer to the field which follows, or NULL if there are no more fields.
*
* in - the current GECOS field
* out - where to copy the field to
* extra - fields with '=' get copied here
*/
static char *
copy_field(char *in, char *out, char *extra)
static char *copy_field (char *in, char *out, char *extra)
{
char *cp = NULL;
@@ -207,7 +181,7 @@ copy_field(char *in, char *out, char *extra)
if ((cp = strchr (in, ',')))
*cp++ = '\0';
if (! strchr (in, '='))
if (!strchr (in, '='))
break;
if (extra) {
@@ -228,8 +202,8 @@ copy_field(char *in, char *out, char *extra)
/*
* chfn - change a user's password file information
*
* This command controls the GECOS field information in the
* password file entry.
* This command controls the GECOS field information in the password
* file entry.
*
* The valid options are
*
@@ -242,26 +216,25 @@ copy_field(char *in, char *out, char *extra)
* (*) requires root permission to execute.
*/
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
char *cp; /* temporary character pointer */
char *cp; /* temporary character pointer */
const struct passwd *pw; /* password file entry */
struct passwd pwent; /* modified password file entry */
char old_gecos[BUFSIZ]; /* buffer for old GECOS fields */
char new_gecos[BUFSIZ]; /* buffer for new GECOS fields */
int flag; /* flag currently being processed */
int fflg = 0; /* -f - set full name */
int rflg = 0; /* -r - set room number */
int wflg = 0; /* -w - set work phone number */
int hflg = 0; /* -h - set home phone number */
int oflg = 0; /* -o - set other information */
struct passwd pwent; /* modified password file entry */
char old_gecos[BUFSIZ]; /* buffer for old GECOS fields */
char new_gecos[BUFSIZ]; /* buffer for new GECOS fields */
int flag; /* flag currently being processed */
int fflg = 0; /* -f - set full name */
int rflg = 0; /* -r - set room number */
int wflg = 0; /* -w - set work phone number */
int hflg = 0; /* -h - set home phone number */
int oflg = 0; /* -o - set other information */
char *user;
sanitize_env();
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
sanitize_env ();
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
/*
* This command behaves different for root and non-root
@@ -274,164 +247,179 @@ main(int argc, char **argv)
#endif
/*
* Get the program name. The program name is used as a
* Get the program name. The program name is used as a
* prefix to most error messages.
*/
Prog = Basename(argv[0]);
Prog = Basename (argv[0]);
OPENLOG("chfn");
OPENLOG ("chfn");
/*
* The remaining arguments will be processed one by one and
* executed by this command. The name is the last argument
* if it does not begin with a "-", otherwise the name is
* determined from the environment and must agree with the
* real UID. Also, the UID will be checked for any commands
* which are restricted to root only.
* The remaining arguments will be processed one by one and executed
* by this command. The name is the last argument if it does not
* begin with a "-", otherwise the name is determined from the
* environment and must agree with the real UID. Also, the UID will
* be checked for any commands which are restricted to root only.
*/
while ((flag = getopt (argc, argv, "f:r:w:h:o:")) != EOF) {
switch (flag) {
case 'f':
if (!may_change_field('f')) {
fprintf(stderr, _("%s: Permission denied.\n"), Prog);
exit(1);
}
fflg++;
STRFCPY(fullnm, optarg);
break;
case 'r':
if (!may_change_field('r')) {
fprintf(stderr, _("%s: Permission denied.\n"), Prog);
exit(1);
}
rflg++;
STRFCPY(roomno, optarg);
break;
case 'w':
if (!may_change_field('w')) {
fprintf(stderr, _("%s: Permission denied.\n"), Prog);
exit(1);
}
wflg++;
STRFCPY(workph, optarg);
break;
case 'h':
if (!may_change_field('h')) {
fprintf(stderr, _("%s: Permission denied.\n"), Prog);
exit(1);
}
hflg++;
STRFCPY(homeph, optarg);
break;
case 'o':
if (!amroot) {
fprintf(stderr, _("%s: Permission denied.\n"), Prog);
exit(1);
}
oflg++;
STRFCPY(slop, optarg);
break;
default:
usage();
case 'f':
if (!may_change_field ('f')) {
fprintf (stderr,
_("%s: Permission denied.\n"),
Prog);
exit (1);
}
fflg++;
STRFCPY (fullnm, optarg);
break;
case 'r':
if (!may_change_field ('r')) {
fprintf (stderr,
_("%s: Permission denied.\n"),
Prog);
exit (1);
}
rflg++;
STRFCPY (roomno, optarg);
break;
case 'w':
if (!may_change_field ('w')) {
fprintf (stderr,
_("%s: Permission denied.\n"),
Prog);
exit (1);
}
wflg++;
STRFCPY (workph, optarg);
break;
case 'h':
if (!may_change_field ('h')) {
fprintf (stderr,
_("%s: Permission denied.\n"),
Prog);
exit (1);
}
hflg++;
STRFCPY (homeph, optarg);
break;
case 'o':
if (!amroot) {
fprintf (stderr,
_("%s: Permission denied.\n"),
Prog);
exit (1);
}
oflg++;
STRFCPY (slop, optarg);
break;
default:
usage ();
}
}
/*
* Get the name of the user to check. It is either
* the command line name, or the name getlogin()
* returns.
* Get the name of the user to check. It is either the command line
* name, or the name getlogin() returns.
*/
if (optind < argc) {
user = argv[optind];
pw = getpwnam(user);
pw = getpwnam (user);
if (!pw) {
fprintf(stderr, _("%s: Unknown user %s\n"), Prog, user);
exit(1);
fprintf (stderr, _("%s: Unknown user %s\n"), Prog,
user);
exit (1);
}
} else {
pw = get_my_pwent();
pw = get_my_pwent ();
if (!pw) {
fprintf(stderr, _("%s: Cannot determine your user name.\n"), Prog);
exit(1);
fprintf (stderr,
_
("%s: Cannot determine your user name.\n"),
Prog);
exit (1);
}
user = xstrdup(pw->pw_name);
user = xstrdup (pw->pw_name);
}
#ifdef USE_NIS
/*
* Now we make sure this is a LOCAL password entry for
* this user ...
* Now we make sure this is a LOCAL password entry for this user ...
*/
if (__ispwNIS ()) {
char *nis_domain;
char *nis_master;
char *nis_domain;
char *nis_master;
fprintf (stderr, _("%s: cannot change user `%s' on NIS client.\n"), Prog, user);
fprintf (stderr,
_("%s: cannot change user `%s' on NIS client.\n"),
Prog, user);
if (! yp_get_default_domain (&nis_domain) &&
! yp_master (nis_domain, "passwd.byname",
if (!yp_get_default_domain (&nis_domain) &&
!yp_master (nis_domain, "passwd.byname",
&nis_master)) {
fprintf (stderr, _("%s: `%s' is the NIS master for this client.\n"), Prog, nis_master);
fprintf (stderr,
_
("%s: `%s' is the NIS master for this client.\n"),
Prog, nis_master);
}
exit (1);
}
#endif
/*
* Non-privileged users are only allowed to change the
* gecos field if the UID of the user matches the current
* real UID.
* Non-privileged users are only allowed to change the gecos field
* if the UID of the user matches the current real UID.
*/
if (!amroot && pw->pw_uid != getuid()) {
if (!amroot && pw->pw_uid != getuid ()) {
fprintf (stderr, _("%s: Permission denied.\n"), Prog);
closelog();
exit(1);
closelog ();
exit (1);
}
/*
* Non-privileged users are optionally authenticated
* (must enter the password of the user whose information
* is being changed) before any changes can be made.
* Idea from util-linux chfn/chsh. --marekm
* Non-privileged users are optionally authenticated (must enter the
* password of the user whose information is being changed) before
* any changes can be made. Idea from util-linux chfn/chsh.
* --marekm
*/
if (!amroot && getdef_bool("CHFN_AUTH"))
passwd_check(pw->pw_name, pw->pw_passwd, "chfn");
if (!amroot && getdef_bool ("CHFN_AUTH"))
passwd_check (pw->pw_name, pw->pw_passwd, "chfn");
/*
* Now get the full name. It is the first comma separated field
* in the GECOS field.
* Now get the full name. It is the first comma separated field in
* the GECOS field.
*/
STRFCPY(old_gecos, pw->pw_gecos);
cp = copy_field (old_gecos, fflg ? (char *) 0:fullnm, slop);
STRFCPY (old_gecos, pw->pw_gecos);
cp = copy_field (old_gecos, fflg ? (char *) 0 : fullnm, slop);
/*
* Now get the room number. It is the next comma separated field,
* Now get the room number. It is the next comma separated field,
* if there is indeed one.
*/
if (cp)
cp = copy_field (cp, rflg ? (char *) 0:roomno, slop);
cp = copy_field (cp, rflg ? (char *) 0 : roomno, slop);
/*
* Now get the work phone number. It is the third field.
* Now get the work phone number. It is the third field.
*/
if (cp)
cp = copy_field (cp, wflg ? (char *) 0:workph, slop);
cp = copy_field (cp, wflg ? (char *) 0 : workph, slop);
/*
* Now get the home phone number. It is the fourth field.
* Now get the home phone number. It is the fourth field.
*/
if (cp)
cp = copy_field (cp, hflg ? (char *) 0:homeph, slop);
cp = copy_field (cp, hflg ? (char *) 0 : homeph, slop);
/*
* Anything left over is "slop".
@@ -445,43 +433,49 @@ main(int argc, char **argv)
}
/*
* If none of the fields were changed from the command line,
* let the user interactively change them.
* If none of the fields were changed from the command line, let the
* user interactively change them.
*/
if (!fflg && !rflg && !wflg && !hflg && !oflg) {
printf(_("Changing the user information for %s\n"), user);
new_fields();
printf (_("Changing the user information for %s\n"), user);
new_fields ();
}
/*
* Check all of the fields for valid information
*/
if (valid_field(fullnm, ":,=")) {
fprintf(stderr, _("%s: invalid name: \"%s\"\n"), Prog, fullnm);
closelog();
exit(1);
if (valid_field (fullnm, ":,=")) {
fprintf (stderr, _("%s: invalid name: \"%s\"\n"), Prog,
fullnm);
closelog ();
exit (1);
}
if (valid_field(roomno, ":,=")) {
fprintf(stderr, _("%s: invalid room number: \"%s\"\n"), Prog, roomno);
closelog();
exit(1);
if (valid_field (roomno, ":,=")) {
fprintf (stderr, _("%s: invalid room number: \"%s\"\n"),
Prog, roomno);
closelog ();
exit (1);
}
if (valid_field(workph, ":,=")) {
fprintf(stderr, _("%s: invalid work phone: \"%s\"\n"), Prog, workph);
closelog();
exit(1);
if (valid_field (workph, ":,=")) {
fprintf (stderr, _("%s: invalid work phone: \"%s\"\n"),
Prog, workph);
closelog ();
exit (1);
}
if (valid_field (homeph, ":,=")) {
fprintf(stderr, _("%s: invalid home phone: \"%s\"\n"), Prog, homeph);
closelog();
exit(1);
fprintf (stderr, _("%s: invalid home phone: \"%s\"\n"),
Prog, homeph);
closelog ();
exit (1);
}
if (valid_field(slop, ":")) {
fprintf(stderr, _("%s: \"%s\" contains illegal characters\n"), Prog, slop);
closelog();
exit(1);
if (valid_field (slop, ":")) {
fprintf (stderr,
_("%s: \"%s\" contains illegal characters\n"),
Prog, slop);
closelog ();
exit (1);
}
/*
@@ -489,112 +483,118 @@ main(int argc, char **argv)
* if they will fit ...
*/
if (strlen(fullnm) + strlen(roomno) + strlen(workph) +
strlen(homeph) + strlen(slop) > (unsigned int) 80) {
fprintf(stderr, _("%s: fields too long\n"), Prog);
closelog();
exit(1);
if (strlen (fullnm) + strlen (roomno) + strlen (workph) +
strlen (homeph) + strlen (slop) > (unsigned int) 80) {
fprintf (stderr, _("%s: fields too long\n"), Prog);
closelog ();
exit (1);
}
snprintf(new_gecos, sizeof new_gecos, "%s,%s,%s,%s%s%s",
fullnm, roomno, workph, homeph, slop[0] ? "," : "", slop);
snprintf (new_gecos, sizeof new_gecos, "%s,%s,%s,%s%s%s",
fullnm, roomno, workph, homeph, slop[0] ? "," : "",
slop);
/*
* Before going any further, raise the ulimit to prevent
* colliding into a lowered ulimit, and set the real UID
* to root to protect against unexpected signals. Any
* keyboard signals are set to be ignored.
* Before going any further, raise the ulimit to prevent colliding
* into a lowered ulimit, and set the real UID to root to protect
* against unexpected signals. Any keyboard signals are set to be
* ignored.
*/
if (setuid(0)) {
fprintf(stderr, _("Cannot change ID to root.\n"));
SYSLOG((LOG_ERR, NOTROOT2));
closelog();
exit(1);
if (setuid (0)) {
fprintf (stderr, _("Cannot change ID to root.\n"));
SYSLOG ((LOG_ERR, "can't setuid(0)"));
closelog ();
exit (1);
}
pwd_init();
pwd_init ();
/*
* The passwd entry is now ready to be committed back to
* the password file. Get a lock on the file and open it.
* The passwd entry is now ready to be committed back to the
* password file. Get a lock on the file and open it.
*/
if (!pw_lock()) {
fprintf(stderr, _("Cannot lock the password file; try again later.\n"));
SYSLOG((LOG_WARN, PWDBUSY2));
closelog();
exit(1);
if (!pw_lock ()) {
fprintf (stderr,
_
("Cannot lock the password file; try again later.\n"));
SYSLOG ((LOG_WARN, "can't lock /etc/passwd"));
closelog ();
exit (1);
}
if (!pw_open(O_RDWR)) {
fprintf(stderr, _("Cannot open the password file.\n"));
pw_unlock();
SYSLOG((LOG_ERR, OPNERROR2));
closelog();
exit(1);
if (!pw_open (O_RDWR)) {
fprintf (stderr, _("Cannot open the password file.\n"));
pw_unlock ();
SYSLOG ((LOG_ERR, "can't open /etc/passwd"));
closelog ();
exit (1);
}
/*
* Get the entry to update using pw_locate() - we want the real
* one from /etc/passwd, not the one from getpwnam() which could
* contain the shadow password if (despite the warnings) someone
* enables AUTOSHADOW (or SHADOW_COMPAT in libc). --marekm
* Get the entry to update using pw_locate() - we want the real one
* from /etc/passwd, not the one from getpwnam() which could contain
* the shadow password if (despite the warnings) someone enables
* AUTOSHADOW (or SHADOW_COMPAT in libc). --marekm
*/
pw = pw_locate(user);
pw = pw_locate (user);
if (!pw) {
pw_unlock();
fprintf(stderr,
_("%s: %s not found in /etc/passwd\n"), Prog, user);
exit(1);
pw_unlock ();
fprintf (stderr,
_("%s: %s not found in /etc/passwd\n"), Prog,
user);
exit (1);
}
/*
* Make a copy of the entry, then change the gecos field. The other
* Make a copy of the entry, then change the gecos field. The other
* fields remain unchanged.
*/
pwent = *pw;
pwent.pw_gecos = new_gecos;
/*
* Update the passwd file entry. If there is a DBM file,
* update that entry as well.
* Update the passwd file entry. If there is a DBM file, update that
* entry as well.
*/
if (!pw_update(&pwent)) {
fprintf(stderr, _("Error updating the password entry.\n"));
pw_unlock();
SYSLOG((LOG_ERR, UPDERROR2));
closelog();
exit(1);
if (!pw_update (&pwent)) {
fprintf (stderr,
_("Error updating the password entry.\n"));
pw_unlock ();
SYSLOG ((LOG_ERR, "error updating passwd entry"));
closelog ();
exit (1);
}
#ifdef NDBM
if (pw_dbm_present() && !pw_dbm_update(&pwent)) {
fprintf(stderr, _("Error updating the DBM password entry.\n"));
if (pw_dbm_present () && !pw_dbm_update (&pwent)) {
fprintf (stderr,
_("Error updating the DBM password entry.\n"));
pw_unlock ();
SYSLOG((LOG_ERR, DBMERROR2));
closelog();
exit(1);
SYSLOG ((LOG_ERR, "error updating DBM passwd entry"));
closelog ();
exit (1);
}
endpwent();
endpwent ();
#endif
/*
* Changes have all been made, so commit them and unlock the
* file.
* Changes have all been made, so commit them and unlock the file.
*/
if (!pw_close()) {
fprintf(stderr, _("Cannot commit password file changes.\n"));
pw_unlock();
SYSLOG((LOG_ERR, CLSERROR2));
closelog();
exit(1);
if (!pw_close ()) {
fprintf (stderr,
_("Cannot commit password file changes.\n"));
pw_unlock ();
SYSLOG ((LOG_ERR, "can't rewrite /etc/passwd"));
closelog ();
exit (1);
}
if (!pw_unlock()) {
fprintf(stderr, _("Cannot unlock the password file.\n"));
SYSLOG((LOG_ERR, UNLKERROR2));
closelog();
exit(1);
if (!pw_unlock ()) {
fprintf (stderr, _("Cannot unlock the password file.\n"));
SYSLOG ((LOG_ERR, "can't unlock /etc/passwd"));
closelog ();
exit (1);
}
SYSLOG((LOG_INFO, CHGGECOS, user));
closelog();
SYSLOG ((LOG_INFO, "changed user `%s' information", user));
closelog ();
exit (0);
}
+130 -120
View File
@@ -17,7 +17,7 @@
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH 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)
@@ -30,8 +30,7 @@
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: chpasswd.c,v 1.13 2001/01/25 10:36:07 kloczek Exp $")
RCSID (PKG_VER "$Id: chpasswd.c,v 1.14 2002/01/05 15:41:43 kloczek Exp $")
#include <stdio.h>
#include "prototypes.h"
#include "defines.h"
@@ -41,151 +40,156 @@ RCSID(PKG_VER "$Id: chpasswd.c,v 1.13 2001/01/25 10:36:07 kloczek Exp $")
#ifdef SHADOWPWD
#include "shadowio.h"
#endif
#ifdef USE_PAM
#include <security/pam_appl.h>
#include <security/pam_misc.h>
#include <pwd.h>
#endif /* USE_PAM */
#endif /* USE_PAM */
static char *Prog;
static int eflg = 0;
#ifdef SHADOWPWD
static int is_shadow_pwd;
#endif
extern char *l64a();
extern char *l64a ();
/* local function prototypes */
static void usage(void);
static void usage (void);
/*
* usage - display usage message and exit
*/
static void
usage(void)
static void usage (void)
{
fprintf(stderr, _("usage: %s [-e]\n"), Prog);
exit(1);
fprintf (stderr, _("usage: %s [-e]\n"), Prog);
exit (1);
}
#ifdef USE_PAM
static struct pam_conv conv = {
misc_conv,
NULL
misc_conv,
NULL
};
#endif /* USE_PAM */
#endif /* USE_PAM */
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
char buf[BUFSIZ];
char *name;
char *newpwd;
char *cp;
char buf[BUFSIZ];
char *name;
char *newpwd;
char *cp;
#ifdef SHADOWPWD
const struct spwd *sp;
struct spwd newsp;
struct spwd newsp;
#endif
const struct passwd *pw;
struct passwd newpw;
struct passwd newpw;
#ifdef ATT_AGE
char newage[5];
char newage[5];
#endif
int errors = 0;
int line = 0;
long now = time ((long *) 0) / (24L*3600L);
int errors = 0;
int line = 0;
long now = time ((long *) 0) / (24L * 3600L);
int ok;
#ifdef USE_PAM
pam_handle_t *pamh = NULL;
struct passwd *pampw;
int retval;
#endif
Prog = Basename(argv[0]);
Prog = Basename (argv[0]);
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
#ifdef USE_PAM
retval = PAM_SUCCESS;
pampw = getpwuid(getuid());
pampw = getpwuid (getuid ());
if (pampw == NULL) {
retval = PAM_USER_UNKNOWN;
}
if (retval == PAM_SUCCESS) {
retval = pam_start("shadow", pampw->pw_name, &conv, &pamh);
retval =
pam_start ("shadow", pampw->pw_name, &conv, &pamh);
}
if (retval == PAM_SUCCESS) {
retval = pam_authenticate(pamh, 0);
retval = pam_authenticate (pamh, 0);
if (retval != PAM_SUCCESS) {
pam_end(pamh, retval);
pam_end (pamh, retval);
}
}
if (retval == PAM_SUCCESS) {
retval = pam_acct_mgmt(pamh, 0);
retval = pam_acct_mgmt (pamh, 0);
if (retval != PAM_SUCCESS) {
pam_end(pamh, retval);
pam_end (pamh, retval);
}
}
if (retval != PAM_SUCCESS) {
fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
fprintf (stderr, _("%s: PAM authentication failed\n"),
Prog);
exit (1);
}
#endif /* USE_PAM */
#endif /* USE_PAM */
/* XXX - use getopt() */
if (!(argc == 1 || (argc == 2 && !strcmp(argv[1], "-e"))))
usage();
if (!(argc == 1 || (argc == 2 && !strcmp (argv[1], "-e"))))
usage ();
if (argc == 2)
eflg = 1;
/*
* Lock the password file and open it for reading. This will
* bring all of the entries into memory where they may be
* updated.
* Lock the password file and open it for reading. This will bring
* all of the entries into memory where they may be updated.
*/
if (!pw_lock()) {
fprintf(stderr, _("%s: can't lock password file\n"), Prog);
exit(1);
if (!pw_lock ()) {
fprintf (stderr, _("%s: can't lock password file\n"),
Prog);
exit (1);
}
if (! pw_open (O_RDWR)) {
fprintf(stderr, _("%s: can't open password file\n"), Prog);
pw_unlock();
exit(1);
if (!pw_open (O_RDWR)) {
fprintf (stderr, _("%s: can't open password file\n"),
Prog);
pw_unlock ();
exit (1);
}
#ifdef SHADOWPWD
is_shadow_pwd = spw_file_present();
is_shadow_pwd = spw_file_present ();
if (is_shadow_pwd) {
if (!spw_lock()) {
fprintf(stderr, _("%s: can't lock shadow file\n"), Prog);
pw_unlock();
exit(1);
if (!spw_lock ()) {
fprintf (stderr, _("%s: can't lock shadow file\n"),
Prog);
pw_unlock ();
exit (1);
}
if (!spw_open(O_RDWR)) {
fprintf(stderr, _("%s: can't open shadow file\n"), Prog);
pw_unlock();
spw_unlock();
exit(1);
if (!spw_open (O_RDWR)) {
fprintf (stderr, _("%s: can't open shadow file\n"),
Prog);
pw_unlock ();
spw_unlock ();
exit (1);
}
}
#endif
/*
* Read each line, separating the user name from the password.
* The password entry for each user will be looked up in the
* appropriate file (shadow or passwd) and the password changed.
* For shadow files the last change date is set directly, for
* passwd files the last change date is set in the age only if
* aging information is present.
* Read each line, separating the user name from the password. The
* password entry for each user will be looked up in the appropriate
* file (shadow or passwd) and the password changed. For shadow
* files the last change date is set directly, for passwd files the
* last change date is set in the age only if aging information is
* present.
*/
while (fgets (buf, sizeof buf, stdin) != (char *) 0) {
@@ -193,59 +197,59 @@ main(int argc, char **argv)
if ((cp = strrchr (buf, '\n'))) {
*cp = '\0';
} else {
fprintf(stderr, _("%s: line %d: line too long\n"),
Prog, line);
fprintf (stderr, _("%s: line %d: line too long\n"),
Prog, line);
errors++;
continue;
}
/*
* The username is the first field. It is separated
* from the password with a ":" character which is
* replaced with a NUL to give the new password. The
* new password will then be encrypted in the normal
* fashion with a new salt generated, unless the '-e'
* is given, in which case it is assumed to already be
* encrypted.
* The username is the first field. It is separated from the
* password with a ":" character which is replaced with a
* NUL to give the new password. The new password will then
* be encrypted in the normal fashion with a new salt
* generated, unless the '-e' is given, in which case it is
* assumed to already be encrypted.
*/
name = buf;
if ((cp = strchr (name, ':'))) {
*cp++ = '\0';
} else {
fprintf(stderr, _("%s: line %d: missing new password\n"),
Prog, line);
fprintf (stderr,
_("%s: line %d: missing new password\n"),
Prog, line);
errors++;
continue;
}
newpwd = cp;
if (!eflg)
cp = pw_encrypt(newpwd, crypt_make_salt());
cp = pw_encrypt (newpwd, crypt_make_salt ());
/*
* Get the password file entry for this user. The user
* must already exist.
* Get the password file entry for this user. The user must
* already exist.
*/
pw = pw_locate(name);
pw = pw_locate (name);
if (!pw) {
fprintf (stderr, _("%s: line %d: unknown user %s\n"),
Prog, line, name);
fprintf (stderr,
_("%s: line %d: unknown user %s\n"), Prog,
line, name);
errors++;
continue;
}
#ifdef SHADOWPWD
if (is_shadow_pwd)
sp = spw_locate(name);
sp = spw_locate (name);
else
sp = NULL;
#endif
/*
* The freshly encrypted new password is merged into
* the user's password file entry and the last password
* change date is set to the current date.
* The freshly encrypted new password is merged into the
* user's password file entry and the last password change
* date is set to the current date.
*/
#ifdef SHADOWPWD
@@ -260,72 +264,78 @@ main(int argc, char **argv)
newpw.pw_passwd = cp;
#ifdef ATT_AGE
if (newpw.pw_age[0]) {
strcpy(newage, newpw.pw_age);
strcpy(newage + 2, l64a(now / 7));
strcpy (newage, newpw.pw_age);
strcpy (newage + 2, l64a (now / 7));
newpw.pw_age = newage;
}
#endif
}
/*
* The updated password file entry is then put back
* and will be written to the password file later, after
* all the other entries have been updated as well.
* The updated password file entry is then put back and will
* be written to the password file later, after all the
* other entries have been updated as well.
*/
#ifdef SHADOWPWD
if (sp)
ok = spw_update(&newsp);
ok = spw_update (&newsp);
else
#endif
ok = pw_update(&newpw);
ok = pw_update (&newpw);
if (!ok) {
fprintf(stderr, _("%s: line %d: cannot update password entry\n"),
Prog, line);
fprintf (stderr,
_
("%s: line %d: cannot update password entry\n"),
Prog, line);
errors++;
continue;
}
}
/*
* Any detected errors will cause the entire set of changes
* to be aborted. Unlocking the password file will cause
* all of the changes to be ignored. Otherwise the file is
* closed, causing the changes to be written out all at
* once, and then unlocked afterwards.
* Any detected errors will cause the entire set of changes to be
* aborted. Unlocking the password file will cause all of the
* changes to be ignored. Otherwise the file is closed, causing the
* changes to be written out all at once, and then unlocked
* afterwards.
*/
if (errors) {
fprintf(stderr, _("%s: error detected, changes ignored\n"), Prog);
fprintf (stderr,
_("%s: error detected, changes ignored\n"), Prog);
#ifdef SHADOWPWD
if (is_shadow_pwd)
spw_unlock();
spw_unlock ();
#endif
pw_unlock();
exit(1);
pw_unlock ();
exit (1);
}
#ifdef SHADOWPWD
if (is_shadow_pwd) {
if (!spw_close()) {
fprintf(stderr, _("%s: error updating shadow file\n"), Prog);
pw_unlock();
exit(1);
if (!spw_close ()) {
fprintf (stderr,
_("%s: error updating shadow file\n"),
Prog);
pw_unlock ();
exit (1);
}
spw_unlock();
spw_unlock ();
}
#endif
if (!pw_close()) {
fprintf(stderr, _("%s: error updating password file\n"), Prog);
exit(1);
if (!pw_close ()) {
fprintf (stderr, _("%s: error updating password file\n"),
Prog);
exit (1);
}
pw_unlock();
pw_unlock ();
#ifdef USE_PAM
if (retval == PAM_SUCCESS) {
retval = pam_chauthtok(pamh, 0);
retval = pam_chauthtok (pamh, 0);
if (retval != PAM_SUCCESS) {
pam_end(pamh, retval);
pam_end (pamh, retval);
}
}
@@ -335,8 +345,8 @@ main(int argc, char **argv)
}
if (retval == PAM_SUCCESS)
pam_end(pamh, PAM_SUCCESS);
#endif /* USE_PAM */
pam_end (pamh, PAM_SUCCESS);
#endif /* USE_PAM */
return (0);
}
+178 -204
View File
@@ -17,7 +17,7 @@
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH 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)
@@ -30,80 +30,50 @@
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: chsh.c,v 1.17 2000/09/02 18:40:43 marekm Exp $")
RCSID (PKG_VER "$Id: chsh.c,v 1.20 2002/01/05 15:41:43 kloczek Exp $")
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include "prototypes.h"
#include "defines.h"
#include <pwd.h>
#include "pwio.h"
#include "getdef.h"
#include "pwauth.h"
#ifdef HAVE_SHADOW_H
#include <shadow.h>
#endif
#ifdef USE_PAM
#include "pam_defs.h"
#endif
#ifndef SHELLS_FILE
#define SHELLS_FILE "/etc/shells"
#endif
/* global variables */
static char *Prog; /* Program name */
static int amroot; /* Real UID is root */
static char loginsh[BUFSIZ]; /* Name of new login shell */
/*
* Global variables.
*/
/* external identifiers */
static char *Prog; /* Program name */
static int amroot; /* Real UID is root */
static char loginsh[BUFSIZ]; /* Name of new login shell */
/*
* External identifiers
*/
extern int optind;
extern char *optarg;
#ifdef NDBM
extern int pw_dbm_mode;
extern int pw_dbm_mode;
#endif
/*
* #defines for messages. This facilitates foreign language conversion
* since all messages are defined right here.
*/
#define WRONGPWD2 "incorrect password for `%s'"
#define NOPERM2 "can't change shell for `%s'\n"
#define PWDBUSY2 "can't lock /etc/passwd\n"
#define OPNERROR2 "can't open /etc/passwd\n"
#define UPDERROR2 "error updating passwd entry\n"
#define DBMERROR2 "error updating DBM passwd entry.\n"
#define NOTROOT2 "can't setuid(0).\n"
#define CLSERROR2 "can't rewrite /etc/passwd.\n"
#define UNLKERROR2 "can't unlock /etc/passwd.\n"
#define CHGSHELL "changed user `%s' shell to `%s'\n"
/* local function prototypes */
static void usage(void);
static void new_fields(void);
static int restricted_shell(const char *);
static void usage (void);
static void new_fields (void);
static int restricted_shell (const char *);
/*
* usage - print command line syntax and exit
*/
static void
usage(void)
static void usage (void)
{
fprintf(stderr, _("Usage: %s [ -s shell ] [ name ]\n"), Prog);
exit(1);
fprintf (stderr, _("Usage: %s [-s shell] [name]\n"), Prog);
exit (1);
}
/*
@@ -113,11 +83,11 @@ usage(void)
* response, or leave it alone if nothing was entered.
*/
static void
new_fields(void)
static void new_fields (void)
{
printf(_("Enter the new value, or press return for the default\n"));
change_field(loginsh, sizeof loginsh, _("Login Shell"));
printf (_
("Enter the new value, or press return for the default\n"));
change_field (loginsh, sizeof loginsh, _("Login Shell"));
}
/*
@@ -127,20 +97,19 @@ new_fields(void)
* considered to be restricted.
*/
static int
restricted_shell(const char *sh)
static int restricted_shell (const char *sh)
{
#if 0
char *cp = Basename((char *) sh);
char *cp = Basename ((char *) sh);
return *cp == 'r' || *cp == 'R';
#else
/*
* Shells not listed in /etc/shells are considered to be
* restricted. Changed this to avoid confusion with "rc"
* (the plan9 shell - not restricted despite the name
* starting with 'r'). --marekm
* Shells not listed in /etc/shells are considered to be restricted.
* Changed this to avoid confusion with "rc" (the plan9 shell - not
* restricted despite the name starting with 'r'). --marekm
*/
return !check_shell(sh);
return !check_shell (sh);
#endif
}
@@ -148,28 +117,26 @@ restricted_shell(const char *sh)
/*
* chsh - this command controls changes to the user's shell
*
* The only supported option is -s which permits the
* the login shell to be set from the command line.
* The only supported option is -s which permits the the login shell to
* be set from the command line.
*/
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
char *user; /* User name */
int flag; /* Current command line flag */
int sflg = 0; /* -s - set shell from command line */
char *user; /* User name */
int flag; /* Current command line flag */
int sflg = 0; /* -s - set shell from command line */
const struct passwd *pw; /* Password entry from /etc/passwd */
struct passwd pwent; /* New password entry */
struct passwd pwent; /* New password entry */
sanitize_env();
sanitize_env ();
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
/*
* This command behaves different for root and non-root
* users.
* This command behaves different for root and non-root users.
*/
amroot = getuid () == 0;
@@ -178,13 +145,13 @@ main(int argc, char **argv)
#endif
/*
* Get the program name. The program name is used as a
* prefix to most error messages.
* Get the program name. The program name is used as a prefix to
* most error messages.
*/
Prog = Basename(argv[0]);
Prog = Basename (argv[0]);
OPENLOG("chsh");
OPENLOG ("chsh");
/*
* There is only one option, but use getopt() anyway to
@@ -193,180 +160,183 @@ main(int argc, char **argv)
while ((flag = getopt (argc, argv, "s:")) != EOF) {
switch (flag) {
case 's':
sflg++;
STRFCPY(loginsh, optarg);
break;
default:
usage ();
case 's':
sflg++;
STRFCPY (loginsh, optarg);
break;
default:
usage ();
}
}
/*
* There should be only one remaining argument at most
* and it should be the user's name.
* There should be only one remaining argument at most and it should
* be the user's name.
*/
if (argc > optind + 1)
usage ();
/*
* Get the name of the user to check. It is either
* the command line name, or the name getlogin()
* returns.
* Get the name of the user to check. It is either the command line
* name, or the name getlogin() returns.
*/
if (optind < argc) {
user = argv[optind];
pw = getpwnam(user);
pw = getpwnam (user);
if (!pw) {
fprintf(stderr,
_("%s: Unknown user %s\n"),
Prog, user);
exit(1);
fprintf (stderr,
_("%s: Unknown user %s\n"), Prog, user);
exit (1);
}
} else {
pw = get_my_pwent();
pw = get_my_pwent ();
if (!pw) {
fprintf(stderr,
_("%s: Cannot determine your user name.\n"),
Prog);
exit(1);
fprintf (stderr,
_
("%s: Cannot determine your user name.\n"),
Prog);
exit (1);
}
user = xstrdup(pw->pw_name);
user = xstrdup (pw->pw_name);
}
#ifdef USE_NIS
/*
* Now we make sure this is a LOCAL password entry for
* this user ...
* Now we make sure this is a LOCAL password entry for this user ...
*/
if (__ispwNIS ()) {
char *nis_domain;
char *nis_master;
char *nis_domain;
char *nis_master;
fprintf(stderr,
_("%s: cannot change user `%s' on NIS client.\n"),
Prog, user);
fprintf (stderr,
_("%s: cannot change user `%s' on NIS client.\n"),
Prog, user);
if (! yp_get_default_domain (&nis_domain) &&
! yp_master (nis_domain, "passwd.byname",
if (!yp_get_default_domain (&nis_domain) &&
!yp_master (nis_domain, "passwd.byname",
&nis_master)) {
fprintf(stderr,
_("%s: `%s' is the NIS master for this client.\n"),
Prog, nis_master);
fprintf (stderr,
_
("%s: `%s' is the NIS master for this client.\n"),
Prog, nis_master);
}
exit (1);
}
#endif
/*
* Non-privileged users are only allowed to change the
* shell if the UID of the user matches the current
* real UID.
* Non-privileged users are only allowed to change the shell if the
* UID of the user matches the current real UID.
*/
if (! amroot && pw->pw_uid != getuid()) {
SYSLOG((LOG_WARN, NOPERM2, user));
closelog();
fprintf(stderr, _("You may not change the shell for %s.\n"),
user);
exit(1);
if (!amroot && pw->pw_uid != getuid ()) {
SYSLOG ((LOG_WARN, "can't change shell for `%s'", user));
closelog ();
fprintf (stderr,
_("You may not change the shell for %s.\n"),
user);
exit (1);
}
/*
* Non-privileged users are only allowed to change the
* shell if it is not a restricted one.
* Non-privileged users are only allowed to change the shell if it
* is not a restricted one.
*/
if (! amroot && restricted_shell(pw->pw_shell)) {
SYSLOG((LOG_WARN, NOPERM2, user));
closelog();
fprintf(stderr, _("You may not change the shell for %s.\n"),
user);
exit(1);
if (!amroot && restricted_shell (pw->pw_shell)) {
SYSLOG ((LOG_WARN, "can't change shell for `%s'", user));
closelog ();
fprintf (stderr,
_("You may not change the shell for %s.\n"),
user);
exit (1);
}
/*
* Non-privileged users are optionally authenticated
* (must enter the password of the user whose information
* is being changed) before any changes can be made.
* Idea from util-linux chfn/chsh. --marekm
*/
* Non-privileged users are optionally authenticated (must enter
* the password of the user whose information is being changed)
* before any changes can be made. Idea from util-linux
* chfn/chsh. --marekm
*/
if (!amroot && getdef_bool("CHFN_AUTH"))
passwd_check(pw->pw_name, pw->pw_passwd, "chsh");
if (!amroot && getdef_bool ("CHFN_AUTH"))
passwd_check (pw->pw_name, pw->pw_passwd, "chsh");
/*
* Now get the login shell. Either get it from the password
* Now get the login shell. Either get it from the password
* file, or use the value from the command line.
*/
if (! sflg)
STRFCPY(loginsh, pw->pw_shell);
if (!sflg)
STRFCPY (loginsh, pw->pw_shell);
/*
* If the login shell was not set on the command line,
* let the user interactively change it.
* If the login shell was not set on the command line, let the user
* interactively change it.
*/
if (! sflg) {
printf(_("Changing the login shell for %s\n"), user);
new_fields();
if (!sflg) {
printf (_("Changing the login shell for %s\n"), user);
new_fields ();
}
/*
* Check all of the fields for valid information. The shell
* field may not contain any illegal characters. Non-privileged
* Check all of the fields for valid information. The shell
* field may not contain any illegal characters. Non-privileged
* users are restricted to using the shells in /etc/shells.
* The shell must be executable by the user.
*/
if (valid_field (loginsh, ":,=")) {
fprintf(stderr, _("%s: Invalid entry: %s\n"), Prog, loginsh);
closelog();
exit(1);
fprintf (stderr, _("%s: Invalid entry: %s\n"), Prog,
loginsh);
closelog ();
exit (1);
}
if (!amroot && (!check_shell(loginsh) || access(loginsh, X_OK) != 0)) {
fprintf(stderr, _("%s is an invalid shell.\n"), loginsh);
closelog();
exit(1);
if (!amroot
&& (!check_shell (loginsh) || access (loginsh, X_OK) != 0)) {
fprintf (stderr, _("%s is an invalid shell.\n"), loginsh);
closelog ();
exit (1);
}
/*
* Before going any further, raise the ulimit to prevent
* colliding into a lowered ulimit, and set the real UID
* to root to protect against unexpected signals. Any
* to root to protect against unexpected signals. Any
* keyboard signals are set to be ignored.
*/
if (setuid(0)) {
SYSLOG((LOG_ERR, NOTROOT2));
closelog();
if (setuid (0)) {
SYSLOG ((LOG_ERR, "can't setuid(0)"));
closelog ();
fprintf (stderr, _("Cannot change ID to root.\n"));
exit(1);
exit (1);
}
pwd_init();
pwd_init ();
/*
* The passwd entry is now ready to be committed back to
* the password file. Get a lock on the file and open it.
* the password file. Get a lock on the file and open it.
*/
if (!pw_lock()) {
SYSLOG((LOG_WARN, PWDBUSY2));
closelog();
fprintf(stderr,
_("Cannot lock the password file; try again later.\n"));
exit(1);
if (!pw_lock ()) {
SYSLOG ((LOG_WARN, "can't lock /etc/passwd"));
closelog ();
fprintf (stderr,
_
("Cannot lock the password file; try again later.\n"));
exit (1);
}
if (! pw_open (O_RDWR)) {
SYSLOG((LOG_ERR, OPNERROR2));
closelog();
fprintf(stderr, _("Cannot open the password file.\n"));
pw_unlock();
exit(1);
if (!pw_open (O_RDWR)) {
SYSLOG ((LOG_ERR, "can't open /etc/passwd"));
closelog ();
fprintf (stderr, _("Cannot open the password file.\n"));
pw_unlock ();
exit (1);
}
/*
@@ -375,63 +345,67 @@ main(int argc, char **argv)
* contain the shadow password if (despite the warnings) someone
* enables AUTOSHADOW (or SHADOW_COMPAT in libc). --marekm
*/
pw = pw_locate(user);
pw = pw_locate (user);
if (!pw) {
pw_unlock();
fprintf(stderr,
_("%s: %s not found in /etc/passwd\n"), Prog, user);
exit(1);
pw_unlock ();
fprintf (stderr,
_("%s: %s not found in /etc/passwd\n"), Prog,
user);
exit (1);
}
/*
* Make a copy of the entry, then change the shell field. The other
* Make a copy of the entry, then change the shell field. The other
* fields remain unchanged.
*/
pwent = *pw;
pwent.pw_shell = loginsh;
/*
* Update the passwd file entry. If there is a DBM file,
* update that entry as well.
* Update the passwd file entry. If there is a DBM file, update
* that entry as well.
*/
if (!pw_update(&pwent)) {
SYSLOG((LOG_ERR, UPDERROR2));
closelog();
fprintf(stderr, _("Error updating the password entry.\n"));
pw_unlock();
exit(1);
if (!pw_update (&pwent)) {
SYSLOG ((LOG_ERR, "error updating passwd entry"));
closelog ();
fprintf (stderr,
_("Error updating the password entry.\n"));
pw_unlock ();
exit (1);
}
#ifdef NDBM
if (pw_dbm_present() && ! pw_dbm_update (&pwent)) {
SYSLOG((LOG_ERR, DBMERROR2));
closelog();
fprintf (stderr, _("Error updating the DBM password entry.\n"));
pw_unlock();
exit(1);
if (pw_dbm_present () && !pw_dbm_update (&pwent)) {
SYSLOG ((LOG_ERR, "error updating DBM passwd entry"));
closelog ();
fprintf (stderr,
_("Error updating the DBM password entry.\n"));
pw_unlock ();
exit (1);
}
endpwent();
endpwent ();
#endif
/*
* Changes have all been made, so commit them and unlock the
* file.
* Changes have all been made, so commit them and unlock the file.
*/
if (!pw_close()) {
SYSLOG((LOG_ERR, CLSERROR2));
closelog();
fprintf(stderr, _("Cannot commit password file changes.\n"));
pw_unlock();
exit(1);
if (!pw_close ()) {
SYSLOG ((LOG_ERR, "can't rewrite /etc/passwd"));
closelog ();
fprintf (stderr,
_("Cannot commit password file changes.\n"));
pw_unlock ();
exit (1);
}
if (!pw_unlock()) {
SYSLOG((LOG_ERR, UNLKERROR2));
closelog();
fprintf(stderr, _("Cannot unlock the password file.\n"));
exit(1);
if (!pw_unlock ()) {
SYSLOG ((LOG_ERR, "can't unlock /etc/passwd"));
closelog ();
fprintf (stderr, _("Cannot unlock the password file.\n"));
exit (1);
}
SYSLOG((LOG_INFO, CHGSHELL, user, loginsh));
closelog();
SYSLOG ((LOG_INFO, "changed user `%s' shell to `%s'", user,
loginsh));
closelog ();
exit (0);
}
+82 -100
View File
@@ -17,7 +17,7 @@
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH 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)
@@ -30,8 +30,7 @@
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: dpasswd.c,v 1.12 2000/09/02 18:40:43 marekm Exp $")
RCSID (PKG_VER "$Id: dpasswd.c,v 1.15 2002/01/05 15:41:43 kloczek Exp $")
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
@@ -40,76 +39,59 @@ RCSID(PKG_VER "$Id: dpasswd.c,v 1.12 2000/09/02 18:40:43 marekm Exp $")
#include "prototypes.h"
#include "defines.h"
#include "dialup.h"
#define DTMP "/etc/d_passwd.tmp"
/*
* Prompts and messages go here.
*/
#define DIALCHG "changed password for %s\n"
#define DIALADD "added password for %s\n"
#define DIALREM "removed password for %s\n"
static int aflg = 0;
static int dflg = 0;
static char *Prog;
extern int optind;
extern char *optarg;
extern char *getpass();
/* local function prototypes */
static void usage(void);
static void usage (void);
static void
usage(void)
static void usage (void)
{
fprintf(stderr, _("Usage: %s [ -(a|d) ] shell\n"), Prog);
exit(1);
fprintf (stderr, _("Usage: %s [-(a|d)] shell\n"), Prog);
exit (1);
}
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
struct dialup *dial;
struct dialup dent;
struct stat sb;
FILE *fp;
char *sh = 0;
char *cp;
char pass[BUFSIZ];
int fd;
int found = 0;
int opt;
struct dialup *dial;
struct dialup dent;
struct stat sb;
FILE *fp;
char *sh = 0;
char *cp;
char pass[BUFSIZ];
int fd;
int found = 0;
int opt;
Prog = Basename(argv[0]);
Prog = Basename (argv[0]);
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
OPENLOG(Prog);
OPENLOG (Prog);
while ((opt = getopt (argc, argv, "a:d:")) != EOF) {
switch (opt) {
case 'a':
aflg++;
sh = optarg;
break;
case 'd':
dflg++;
sh = optarg;
break;
default:
usage ();
case 'a':
aflg++;
sh = optarg;
break;
case 'd':
dflg++;
sh = optarg;
break;
default:
usage ();
}
}
if (! aflg && ! dflg)
if (!aflg && !dflg)
aflg++;
if (! sh) {
if (!sh) {
if (optind >= argc)
usage ();
else
@@ -120,65 +102,67 @@ main(int argc, char **argv)
/*
* Add a new shell to the password file, or update an existing
* entry. Begin by getting an encrypted password for this
* shell.
* entry. Begin by getting an encrypted password for this shell.
*/
if (aflg) {
int tries = 3;
int tries = 3;
dent.du_shell = sh;
dent.du_passwd = ""; /* XXX warning: const */
dent.du_passwd = ""; /* XXX warning: const */
again:
if (! (cp = getpass(_("Shell password: "))))
again:
if (!(cp = getpass (_("Shell password: "))))
exit (1);
STRFCPY(pass, cp);
strzero(cp);
STRFCPY (pass, cp);
strzero (cp);
if (! (cp = getpass(_("re-enter Shell password: "))))
if (!(cp = getpass (_("re-enter Shell password: "))))
exit (1);
if (strcmp (pass, cp)) {
strzero(pass);
strzero(cp);
fprintf(stderr,
_("%s: Passwords do not match, try again.\n"),
Prog);
strzero (pass);
strzero (cp);
fprintf (stderr,
_
("%s: Passwords do not match, try again.\n"),
Prog);
if (--tries)
goto again;
exit(1);
exit (1);
}
strzero(cp);
dent.du_passwd = pw_encrypt(pass, crypt_make_salt());
strzero(pass);
strzero (cp);
dent.du_passwd = pw_encrypt (pass, crypt_make_salt ());
strzero (pass);
}
/*
* Create the temporary file for the updated dialup password
* information to be placed into. Turn it into a (FILE *)
* for use by putduent().
* information to be placed into. Turn it into a (FILE *) for use by
* putduent().
*/
if ((fd = open (DTMP, O_CREAT|O_EXCL|O_RDWR, 0600)) < 0) {
snprintf(pass, sizeof pass, _("%s: can't create %s"), Prog, DTMP);
if ((fd = open (DTMP, O_CREAT | O_EXCL | O_RDWR, 0600)) < 0) {
snprintf (pass, sizeof pass, _("%s: can't create %s"),
Prog, DTMP);
perror (pass);
exit (1);
}
if (! (fp = fdopen (fd, "r+"))) {
snprintf(pass, sizeof pass, _("%s: can't open %s"), Prog, DTMP);
if (!(fp = fdopen (fd, "r+"))) {
snprintf (pass, sizeof pass, _("%s: can't open %s"), Prog,
DTMP);
perror (pass);
unlink (DTMP);
exit (1);
}
/*
* Scan the dialup password file for the named entry,
* copying out other entries along the way. Copying
* stops when a match is found or the file runs out.
* Scan the dialup password file for the named entry, copying out
* other entries along the way. Copying stops when a match is found
* or the file runs out.
*/
while ((dial = getduent ())) {
@@ -191,13 +175,12 @@ again:
}
/*
* To delete the entry, just don't copy it. To update
* the entry, output the modified version - works with
* new entries as well.
* To delete the entry, just don't copy it. To update the entry,
* output the modified version - works with new entries as well.
*/
if (dflg && ! found) {
fprintf(stderr, _("%s: Shell %s not found.\n"), Prog, sh);
if (dflg && !found) {
fprintf (stderr, _("%s: Shell %s not found.\n"), Prog, sh);
goto failure;
}
if (aflg)
@@ -205,9 +188,8 @@ again:
goto failure;
/*
* Now copy out the remaining entries. Flush and close the
* new file before doing anything nasty to the existing
* file.
* Now copy out the remaining entries. Flush and close the new file
* before doing anything nasty to the existing file.
*/
@@ -221,16 +203,16 @@ again:
fclose (fp);
/*
* If the original file did not exist, we must create a new
* file with owner "root" and mode 400. Otherwise we copy
* the modes from the existing file to the new file.
* If the original file did not exist, we must create a new file
* with owner "root" and mode 400. Otherwise we copy the modes from
* the existing file to the new file.
*
* After this is done the new file will replace the old file.
*/
pwd_init();
pwd_init ();
if (! stat (DIALPWD, &sb)) {
if (!stat (DIALPWD, &sb)) {
chown (DTMP, sb.st_uid, sb.st_gid);
chmod (DTMP, sb.st_mode);
unlink (DIALPWD);
@@ -238,22 +220,22 @@ again:
chown (DTMP, 0, 0);
chmod (DTMP, 0400);
}
if (! link (DTMP, DIALPWD))
if (!link (DTMP, DIALPWD))
unlink (DTMP);
if (aflg && ! found)
SYSLOG((LOG_INFO, DIALADD, sh));
if (aflg && !found)
SYSLOG ((LOG_INFO, "added password for %s", sh));
else if (aflg && found)
SYSLOG((LOG_INFO, DIALCHG, sh));
SYSLOG ((LOG_INFO, "changed password for %s", sh));
else if (dflg)
SYSLOG((LOG_INFO, DIALREM, sh));
SYSLOG ((LOG_INFO, "removed password for %s", sh));
closelog();
closelog ();
sync ();
exit (0);
failure:
failure:
unlink (DTMP);
closelog();
closelog ();
exit (1);
}
+36 -62
View File
@@ -17,7 +17,7 @@
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH 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)
@@ -30,46 +30,22 @@
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: expiry.c,v 1.9 2000/08/26 18:27:18 marekm Exp $")
RCSID (PKG_VER "$Id: expiry.c,v 1.12 2002/01/05 15:41:43 kloczek Exp $")
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include "prototypes.h"
#include "defines.h"
#include <pwd.h>
#ifndef AGING
#if defined(HAVE_USERSEC_H) || defined(SHADOWPWD)
#define AGING 1
#endif
#endif
#if !defined(SHADOWPWD) && !defined(AGING) /*{*/
/*
* Not much to do here ...
*/
int
main(int argc, char **argv)
{
exit (0);
}
#else /*} AGING || SHADOWPWD {*/
/* local function prototypes */
static RETSIGTYPE catch(int);
static void usage(void);
static RETSIGTYPE catch (int);
static void usage (void);
/*
* catch - signal catcher
*/
static RETSIGTYPE
catch(int sig)
static RETSIGTYPE catch (int sig)
{
exit (10);
}
@@ -78,31 +54,29 @@ catch(int sig)
* usage - print syntax message and exit
*/
static void
usage(void)
static void usage (void)
{
fprintf(stderr, _("Usage: expiry { -f | -c }\n"));
exit(10);
fprintf (stderr, _("Usage: expiry {-f|-c}\n"));
exit (10);
}
/*
* expiry - check and enforce password expiration policy
*
* expiry checks (-c) the current password expiraction and
* forces (-f) changes when required. It is callable as a
* normal user command.
* expiry checks (-c) the current password expiraction and forces (-f)
* changes when required. It is callable as a normal user command.
*/
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
struct passwd *pwd;
struct passwd *pwd;
#ifdef SHADOWPWD
struct spwd *spwd;
struct spwd *spwd;
#endif
char *Prog = argv[0];
sanitize_env();
sanitize_env ();
/*
* Start by disabling all of the keyboard signals.
@@ -116,27 +90,29 @@ main(int argc, char **argv)
#endif
/*
* expiry takes one of two arguments. The default action
* is to give the usage message.
* expiry takes one of two arguments. The default action is to give
* the usage message.
*/
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
if (argc != 2 || (strcmp (argv[1], "-f") && strcmp (argv[1], "-c")))
if (argc != 2
|| (strcmp (argv[1], "-f") && strcmp (argv[1], "-c")))
usage ();
#if 0 /* could be setgid shadow with /etc/shadow mode 0640 */
#if 0 /* could be setgid shadow with /etc/shadow mode 0640 */
/*
* Make sure I am root. Can't open /etc/shadow without root
* Make sure I am root. Can't open /etc/shadow without root
* authority.
*/
if (geteuid () != 0) {
fprintf(stderr, _("%s: WARNING! Must be set-UID root!\n"),
argv[0]);
exit(10);
fprintf (stderr,
_("%s: WARNING! Must be set-UID root!\n"),
argv[0]);
exit (10);
}
#endif
@@ -144,12 +120,12 @@ main(int argc, char **argv)
* Get user entries for /etc/passwd and /etc/shadow
*/
if (!(pwd = get_my_pwent())) {
fprintf(stderr, _("%s: unknown user\n"), Prog);
exit(10);
if (!(pwd = get_my_pwent ())) {
fprintf (stderr, _("%s: unknown user\n"), Prog);
exit (10);
}
#ifdef SHADOWPWD
spwd = getspnam(pwd->pw_name);
spwd = getspnam (pwd->pw_name);
#endif
/*
@@ -169,7 +145,7 @@ main(int argc, char **argv)
#endif
/*
* Exit with status indicating state of account --
* Exit with status indicating state of account.
*/
#ifdef SHADOWPWD
@@ -186,10 +162,9 @@ main(int argc, char **argv)
if (strcmp (argv[1], "-f") == 0) {
/*
* Just call expire(). It will force the change
* or give a message indicating what to do. And
* it doesn't return at all unless the account
* is unexpired.
* Just call expire(). It will force the change or give a
* message indicating what to do. And it doesn't return at
* all unless the account is unexpired.
*/
#ifdef SHADOWPWD
@@ -207,4 +182,3 @@ main(int argc, char **argv)
usage ();
exit (1);
}
#endif /*}*/
+175 -183
View File
@@ -17,7 +17,7 @@
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH 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)
@@ -30,8 +30,7 @@
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: faillog.c,v 1.10 2000/08/26 18:27:18 marekm Exp $")
RCSID (PKG_VER "$Id: faillog.c,v 1.11 2002/01/05 15:41:43 kloczek Exp $")
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
@@ -40,242 +39,239 @@ RCSID(PKG_VER "$Id: faillog.c,v 1.10 2000/08/26 18:27:18 marekm Exp $")
#include "prototypes.h"
#include "defines.h"
#include "faillog.h"
static char *Prog; /* program name */
static FILE *fail; /* failure file stream */
static uid_t user; /* one single user, specified on command line */
static int days; /* number of days to consider for print command */
static time_t seconds; /* that number of days in seconds */
static char *Prog; /* program name */
static FILE *fail; /* failure file stream */
static uid_t user; /* one single user, specified on command line */
static int days; /* number of days to consider for print command */
static time_t seconds; /* that number of days in seconds */
static int
aflg = 0, /* set if all users are to be printed always */
uflg = 0, /* set if user is a valid user id */
tflg = 0; /* print is restricted to most recent days */
aflg = 0, /* set if all users are to be printed always */
uflg = 0, /* set if user is a valid user id */
tflg = 0; /* print is restricted to most recent days */
static struct stat statbuf; /* fstat buffer for file size */
#if !defined(UNISTD_H) && !defined(STDLIB_H)
extern char *optarg;
extern char *optarg;
#endif
#define NOW (time((time_t *) 0))
/* local function prototypes */
static void usage(void);
static void print(void);
static void print_one(const struct faillog *, uid_t);
static void reset(void);
static int reset_one(uid_t);
static void setmax(int);
static void setmax_one(uid_t, int);
static void set_locktime(long);
static void set_locktime_one(uid_t, long);
static void usage (void);
static void print (void);
static void print_one (const struct faillog *, uid_t);
static void reset (void);
static int reset_one (uid_t);
static void setmax (int);
static void setmax_one (uid_t, int);
static void set_locktime (long);
static void set_locktime_one (uid_t, long);
static void
usage(void)
static void usage (void)
{
fprintf(stderr,
_("usage: %s [-a|-u user] [-m max] [-r] [-t days] [-l locksecs]\n"),
Prog);
exit(1);
fprintf (stderr,
_
("usage: %s [-a|-u user] [-m max] [-r] [-t days] [-l locksecs]\n"),
Prog);
exit (1);
}
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
int c, anyflag = 0;
struct passwd *pwent;
Prog = Basename(argv[0]);
Prog = Basename (argv[0]);
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
/* try to open for read/write, if that fails - read only */
fail = fopen(FAILLOG_FILE, "r+");
fail = fopen (FAILLOG_FILE, "r+");
if (!fail)
fail = fopen(FAILLOG_FILE, "r");
fail = fopen (FAILLOG_FILE, "r");
if (!fail) {
perror(FAILLOG_FILE);
exit(1);
perror (FAILLOG_FILE);
exit (1);
}
while ((c = getopt(argc, argv, "al:m:pru:t:")) != EOF) {
while ((c = getopt (argc, argv, "al:m:pru:t:")) != EOF) {
switch (c) {
case 'a':
aflg++;
if (uflg)
usage();
break;
case 'l':
set_locktime((long) atoi(optarg));
anyflag++;
break;
case 'm':
setmax(atoi(optarg));
anyflag++;
break;
case 'p':
print();
anyflag++;
break;
case 'r':
reset();
anyflag++;
break;
case 'u':
if (aflg)
usage();
case 'a':
aflg++;
if (uflg)
usage ();
break;
case 'l':
set_locktime ((long) atoi (optarg));
anyflag++;
break;
case 'm':
setmax (atoi (optarg));
anyflag++;
break;
case 'p':
print ();
anyflag++;
break;
case 'r':
reset ();
anyflag++;
break;
case 'u':
if (aflg)
usage ();
pwent = getpwnam(optarg);
if (!pwent) {
fprintf(stderr, _("Unknown User: %s\n"), optarg);
exit(1);
}
uflg++;
user = pwent->pw_uid;
break;
case 't':
days = atoi(optarg);
seconds = days * DAY;
tflg++;
break;
default:
usage();
pwent = getpwnam (optarg);
if (!pwent) {
fprintf (stderr, _("Unknown User: %s\n"),
optarg);
exit (1);
}
uflg++;
user = pwent->pw_uid;
break;
case 't':
days = atoi (optarg);
seconds = days * DAY;
tflg++;
break;
default:
usage ();
}
}
/* no flags implies -a -p (= print information for all users) */
if (!(anyflag || aflg || tflg || uflg))
aflg++;
/* (-a or -t days or -u user) and no other flags implies -p
(= print information for selected users) */
(= print information for selected users) */
if (!anyflag && (aflg || tflg || uflg))
print();
fclose(fail);
print ();
fclose (fail);
return 0;
/*NOTREACHED*/
}
/*NOTREACHED*/}
static void
print(void)
static void print (void)
{
uid_t uid;
off_t offset;
struct faillog faillog;
uid_t uid;
off_t offset;
struct faillog faillog;
if (uflg) {
offset = user * sizeof faillog;
if (fstat(fileno(fail), &statbuf)) {
perror(FAILLOG_FILE);
if (fstat (fileno (fail), &statbuf)) {
perror (FAILLOG_FILE);
return;
}
if (offset >= statbuf.st_size)
return;
fseek(fail, (off_t) user * sizeof faillog, SEEK_SET);
if (fread((char *) &faillog, sizeof faillog, 1, fail) == 1)
print_one(&faillog, user);
fseek (fail, (off_t) user * sizeof faillog, SEEK_SET);
if (fread ((char *) &faillog, sizeof faillog, 1, fail) ==
1)
print_one (&faillog, user);
else
perror(FAILLOG_FILE);
perror (FAILLOG_FILE);
} else {
for (uid = 0;
fread((char *) &faillog, sizeof faillog, 1, fail) == 1;
uid++) {
fread ((char *) &faillog, sizeof faillog, 1,
fail) == 1; uid++) {
if (aflg == 0 && faillog.fail_cnt == 0)
continue;
if (aflg == 0 && tflg &&
NOW - faillog.fail_time > seconds)
NOW - faillog.fail_time > seconds)
continue;
if (aflg && faillog.fail_time == 0)
continue;
print_one(&faillog, uid);
print_one (&faillog, uid);
}
}
}
static void
print_one(const struct faillog *fl, uid_t uid)
static void print_one (const struct faillog *fl, uid_t uid)
{
static int once;
char *cp;
struct tm *tm;
static int once;
char *cp;
struct tm *tm;
time_t now;
struct passwd *pwent;
struct passwd *pwent;
#ifdef HAVE_STRFTIME
char ptime[80];
#endif
if (!once) {
printf(_("Username Failures Maximum Latest\n"));
printf (_("Username Failures Maximum Latest\n"));
once++;
}
pwent = getpwuid(uid);
time(&now);
tm = localtime(&fl->fail_time);
pwent = getpwuid (uid);
time (&now);
tm = localtime (&fl->fail_time);
#ifdef HAVE_STRFTIME
strftime(ptime, sizeof(ptime), "%a %b %e %H:%M:%S %z %Y",tm);
strftime (ptime, sizeof (ptime), "%a %b %e %H:%M:%S %z %Y", tm);
cp = ptime;
#else
cp = asctime(tm);
cp = asctime (tm);
cp[24] = '\0';
#endif
if (pwent) {
printf("%-12s %4d %4d",
printf ("%-12s %4d %4d",
pwent->pw_name, fl->fail_cnt, fl->fail_max);
if (fl->fail_time) {
printf(_(" %s on %s"), cp, fl->fail_line);
if (fl->fail_locktime) {
if (fl->fail_time + fl->fail_locktime > now
&& fl->fail_cnt)
printf(_(" [%lds left]"),
fl->fail_time + fl->fail_locktime - now);
else
printf(_(" [%lds lock]"), fl->fail_locktime);
}
printf (_(" %s on %s"), cp, fl->fail_line);
if (fl->fail_locktime) {
if (fl->fail_time + fl->fail_locktime > now
&& fl->fail_cnt)
printf (_(" [%lds left]"),
fl->fail_time +
fl->fail_locktime - now);
else
printf (_(" [%lds lock]"),
fl->fail_locktime);
}
}
putchar('\n');
putchar ('\n');
}
}
static void
reset(void)
static void reset (void)
{
uid_t uid;
if (uflg)
reset_one(user);
reset_one (user);
else
for (uid = 0; reset_one(uid); uid++)
;
for (uid = 0; reset_one (uid); uid++);
}
static int
reset_one(uid_t uid)
static int reset_one (uid_t uid)
{
off_t offset;
struct faillog faillog;
off_t offset;
struct faillog faillog;
offset = uid * sizeof faillog;
if (fstat(fileno(fail), &statbuf)) {
perror(FAILLOG_FILE);
if (fstat (fileno (fail), &statbuf)) {
perror (FAILLOG_FILE);
return 0;
}
if (offset >= statbuf.st_size)
return 0;
if (fseek(fail, offset, SEEK_SET) != 0) {
perror(FAILLOG_FILE);
if (fseek (fail, offset, SEEK_SET) != 0) {
perror (FAILLOG_FILE);
return 0;
}
if (fread((char *) &faillog, sizeof faillog, 1, fail) != 1) {
if (!feof(fail))
perror(FAILLOG_FILE);
if (fread ((char *) &faillog, sizeof faillog, 1, fail) != 1) {
if (!feof (fail))
perror (FAILLOG_FILE);
return 0;
}
@@ -284,96 +280,92 @@ reset_one(uid_t uid)
faillog.fail_cnt = 0;
if (fseek(fail, offset, SEEK_SET) == 0
&& fwrite((char *) &faillog, sizeof faillog, 1, fail) == 1) {
fflush(fail);
if (fseek (fail, offset, SEEK_SET) == 0
&& fwrite ((char *) &faillog, sizeof faillog, 1, fail) == 1) {
fflush (fail);
return 1;
} else {
perror(FAILLOG_FILE);
perror (FAILLOG_FILE);
}
return 0;
}
static void
setmax(int max)
static void setmax (int max)
{
struct passwd *pwent;
struct passwd *pwent;
if (uflg) {
setmax_one(user, max);
setmax_one (user, max);
} else {
setpwent();
while ((pwent = getpwent()))
setmax_one(pwent->pw_uid, max);
setpwent ();
while ((pwent = getpwent ()))
setmax_one (pwent->pw_uid, max);
}
}
static void
setmax_one(uid_t uid, int max)
static void setmax_one (uid_t uid, int max)
{
off_t offset;
struct faillog faillog;
off_t offset;
struct faillog faillog;
offset = uid * sizeof faillog;
if (fseek(fail, offset, SEEK_SET) != 0) {
perror(FAILLOG_FILE);
if (fseek (fail, offset, SEEK_SET) != 0) {
perror (FAILLOG_FILE);
return;
}
if (fread((char *) &faillog, sizeof faillog, 1, fail) != 1) {
if (!feof(fail))
perror(FAILLOG_FILE);
memzero(&faillog, sizeof faillog);
if (fread ((char *) &faillog, sizeof faillog, 1, fail) != 1) {
if (!feof (fail))
perror (FAILLOG_FILE);
memzero (&faillog, sizeof faillog);
}
faillog.fail_max = max;
if (fseek(fail, offset, SEEK_SET) == 0
&& fwrite((char *) &faillog, sizeof faillog, 1, fail) == 1)
fflush(fail);
if (fseek (fail, offset, SEEK_SET) == 0
&& fwrite ((char *) &faillog, sizeof faillog, 1, fail) == 1)
fflush (fail);
else
perror(FAILLOG_FILE);
perror (FAILLOG_FILE);
}
/*
* XXX - this needs to be written properly some day, right now it is
* a quick cut-and-paste hack from the above two functions. --marekm
*/
static void
set_locktime(long locktime)
static void set_locktime (long locktime)
{
struct passwd *pwent;
struct passwd *pwent;
if (uflg) {
set_locktime_one(user, locktime);
set_locktime_one (user, locktime);
} else {
setpwent();
while ((pwent = getpwent()))
set_locktime_one(pwent->pw_uid, locktime);
setpwent ();
while ((pwent = getpwent ()))
set_locktime_one (pwent->pw_uid, locktime);
}
}
static void
set_locktime_one(uid_t uid, long locktime)
static void set_locktime_one (uid_t uid, long locktime)
{
off_t offset;
struct faillog faillog;
off_t offset;
struct faillog faillog;
offset = uid * sizeof faillog;
if (fseek(fail, offset, SEEK_SET) != 0) {
perror(FAILLOG_FILE);
if (fseek (fail, offset, SEEK_SET) != 0) {
perror (FAILLOG_FILE);
return;
}
if (fread((char *) &faillog, sizeof faillog, 1, fail) != 1) {
if (!feof(fail))
perror(FAILLOG_FILE);
memzero(&faillog, sizeof faillog);
if (fread ((char *) &faillog, sizeof faillog, 1, fail) != 1) {
if (!feof (fail))
perror (FAILLOG_FILE);
memzero (&faillog, sizeof faillog);
}
faillog.fail_locktime = locktime;
if (fseek(fail, offset, SEEK_SET) == 0
&& fwrite((char *) &faillog, sizeof faillog, 1, fail) == 1)
fflush(fail);
if (fseek (fail, offset, SEEK_SET) == 0
&& fwrite ((char *) &faillog, sizeof faillog, 1, fail) == 1)
fflush (fail);
else
perror(FAILLOG_FILE);
perror (FAILLOG_FILE);
}
+238 -247
View File
@@ -17,7 +17,7 @@
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH 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)
@@ -30,8 +30,7 @@
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: gpasswd.c,v 1.17 2000/09/02 18:40:43 marekm Exp $")
RCSID (PKG_VER "$Id: gpasswd.c,v 1.19 2002/01/05 15:41:43 kloczek Exp $")
#include <sys/types.h>
#include <stdio.h>
#include <pwd.h>
@@ -39,61 +38,51 @@ RCSID(PKG_VER "$Id: gpasswd.c,v 1.17 2000/09/02 18:40:43 marekm Exp $")
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include "prototypes.h"
#include "defines.h"
#include "groupio.h"
#ifdef SHADOWGRP
#include "sgroupio.h"
#endif
static char *Prog;
#ifdef SHADOWGRP
static int is_shadowgrp;
#endif
static int
aflg = 0,
Aflg = 0,
dflg = 0,
Mflg = 0,
rflg = 0,
Rflg = 0;
aflg = 0, Aflg = 0, dflg = 0, Mflg = 0, rflg = 0, Rflg = 0;
#ifndef RETRIES
#define RETRIES 3
#endif
extern int optind;
extern char *optarg;
#ifdef NDBM
#ifdef SHADOWGRP
extern int sg_dbm_mode;
extern int sg_dbm_mode;
#endif
extern int gr_dbm_mode;
extern int gr_dbm_mode;
#endif
/* local function prototypes */
static void usage(void);
static RETSIGTYPE die(int);
static int check_list(const char *);
static void usage (void);
static RETSIGTYPE die (int);
static int check_list (const char *);
/*
* usage - display usage message
*/
static void
usage(void)
static void usage (void)
{
fprintf(stderr, _("usage: %s [-r|-R] group\n"), Prog);
fprintf(stderr, _(" %s [-a user] group\n"), Prog);
fprintf(stderr, _(" %s [-d user] group\n"), Prog);
fprintf (stderr, _("usage: %s [-r|-R] group\n"), Prog);
fprintf (stderr, _(" %s [-a user] group\n"), Prog);
fprintf (stderr, _(" %s [-d user] group\n"), Prog);
#ifdef SHADOWGRP
fprintf(stderr, _(" %s [-A user,...] [-M user,...] group\n"),
Prog);
fprintf (stderr,
_(" %s [-A user,...] [-M user,...] group\n"), Prog);
#else
fprintf(stderr, _(" %s [-M user,...] group\n"), Prog);
fprintf (stderr, _(" %s [-M user,...] group\n"), Prog);
#endif
exit (1);
}
@@ -101,21 +90,19 @@ usage(void)
/*
* die - set or reset termio modes.
*
* die() is called before processing begins. signal() is then
* called with die() as the signal handler. If signal later
* calls die() with a signal number, the terminal modes are
* then reset.
* die() is called before processing begins. signal() is then called
* with die() as the signal handler. If signal later calls die() with a
* signal number, the terminal modes are then reset.
*/
static RETSIGTYPE
die(int killed)
static RETSIGTYPE die (int killed)
{
static TERMIO sgtty;
if (killed)
STTY(0, &sgtty);
STTY (0, &sgtty);
else
GTTY(0, &sgtty);
GTTY (0, &sgtty);
if (killed) {
putchar ('\n');
@@ -131,34 +118,33 @@ die(int killed)
* that each listed name exists.
*/
static int
check_list(const char *users)
static int check_list (const char *users)
{
const char *start, *end;
char username[32];
int errors = 0;
int len;
int errors = 0;
int len;
for (start = users; start && *start; start = end) {
if ((end = strchr (start, ','))) {
len = end - start;
end++;
} else {
len = strlen(start);
len = strlen (start);
}
if (len > sizeof(username) - 1)
len = sizeof(username) - 1;
strncpy(username, start, len);
if (len > sizeof (username) - 1)
len = sizeof (username) - 1;
strncpy (username, start, len);
username[len] = '\0';
/*
* This user must exist.
*/
if (!getpwnam(username)) {
fprintf(stderr, _("%s: unknown user %s\n"),
Prog, username);
if (!getpwnam (username)) {
fprintf (stderr, _("%s: unknown user %s\n"),
Prog, username);
errors++;
}
}
@@ -166,13 +152,11 @@ check_list(const char *users)
}
static void
failure(void)
static void failure (void)
{
fprintf(stderr, _("Permission denied.\n"));
exit(1);
/*NOTREACHED*/
}
fprintf (stderr, _("Permission denied.\n"));
exit (1);
/*NOTREACHED*/}
/*
@@ -186,19 +170,19 @@ failure(void)
* -M user,... make list of users the group members
*/
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
int flag;
char *cp;
int amroot;
int retries;
int flag;
char *cp;
int amroot;
int retries;
struct group *gr = NULL;
struct group grent;
struct group grent;
static char pass[BUFSIZ];
#ifdef SHADOWGRP
struct sgrp *sg = NULL;
struct sgrp sgent;
struct sgrp sgent;
char *admins = NULL;
#endif
struct passwd *pw = NULL;
@@ -207,17 +191,17 @@ main(int argc, char **argv)
char *group = NULL;
char *members = NULL;
sanitize_env();
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
sanitize_env ();
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
/*
* Make a note of whether or not this command was invoked
* by root. This will be used to bypass certain checks
* later on. Also, set the real user ID to match the
* effective user ID. This will prevent the invoker from
* issuing signals which would interfer with this command.
* Make a note of whether or not this command was invoked by root.
* This will be used to bypass certain checks later on. Also, set
* the real user ID to match the effective user ID. This will
* prevent the invoker from issuing signals which would interfer
* with this command.
*/
amroot = getuid () == 0;
@@ -228,39 +212,41 @@ main(int argc, char **argv)
gr_dbm_mode = O_RDWR;
#endif
Prog = Basename(argv[0]);
Prog = Basename (argv[0]);
OPENLOG("gpasswd");
setbuf(stdout, NULL);
setbuf(stderr, NULL);
OPENLOG ("gpasswd");
setbuf (stdout, NULL);
setbuf (stderr, NULL);
#ifdef SHADOWGRP
is_shadowgrp = sgr_file_present();
is_shadowgrp = sgr_file_present ();
#endif
while ((flag = getopt (argc, argv, "a:d:grRA:M:")) != EOF) {
switch (flag) {
case 'a': /* add a user */
user = optarg;
if (!getpwnam(user)) {
fprintf(stderr, _("%s: unknown user %s\n"),
Prog, user);
exit(1);
if (!getpwnam (user)) {
fprintf (stderr,
_("%s: unknown user %s\n"), Prog,
user);
exit (1);
}
aflg++;
break;
#ifdef SHADOWGRP
case 'A':
if (!amroot)
failure();
failure ();
if (!is_shadowgrp) {
fprintf(stderr,
_("%s: shadow group passwords required for -A\n"),
Prog);
exit(2);
fprintf (stderr,
_
("%s: shadow group passwords required for -A\n"),
Prog);
exit (2);
}
admins = optarg;
if (check_list(admins))
exit(1);
if (check_list (admins))
exit (1);
Aflg++;
break;
#endif
@@ -272,10 +258,10 @@ main(int argc, char **argv)
break;
case 'M':
if (!amroot)
failure();
failure ();
members = optarg;
if (check_list(members))
exit(1);
if (check_list (members))
exit (1);
Mflg++;
break;
case 'r': /* remove group password */
@@ -285,7 +271,7 @@ main(int argc, char **argv)
Rflg++;
break;
default:
usage();
usage ();
}
}
@@ -297,61 +283,60 @@ main(int argc, char **argv)
usage ();
/*
* Determine the name of the user that invoked this command.
* This is really hit or miss because there are so many ways
* that command can be executed and so many ways to trip up
* the routines that report the user name.
* Determine the name of the user that invoked this command. This
* is really hit or miss because there are so many ways that command
* can be executed and so many ways to trip up the routines that
* report the user name.
*/
pw = get_my_pwent();
pw = get_my_pwent ();
if (!pw) {
fprintf(stderr, _("Who are you?\n"));
exit(1);
fprintf (stderr, _("Who are you?\n"));
exit (1);
}
myname = xstrdup(pw->pw_name);
myname = xstrdup (pw->pw_name);
/*
* Get the name of the group that is being affected. The group
* entry will be completely replicated so it may be modified
* later on.
* Get the name of the group that is being affected. The group entry
* will be completely replicated so it may be modified later on.
*/
/*
* XXX - should get the entry using gr_locate() and modify
* that, getgrnam() could give us a NIS group. --marekm
* XXX - should get the entry using gr_locate() and modify that,
* getgrnam() could give us a NIS group. --marekm
*/
if (! (group = argv[optind]))
if (!(group = argv[optind]))
usage ();
if (! (gr = getgrnam (group))) {
if (!(gr = getgrnam (group))) {
fprintf (stderr, _("unknown group: %s\n"), group);
exit (1);
}
grent = *gr;
grent.gr_name = xstrdup(gr->gr_name);
grent.gr_passwd = xstrdup(gr->gr_passwd);
grent.gr_name = xstrdup (gr->gr_name);
grent.gr_passwd = xstrdup (gr->gr_passwd);
grent.gr_mem = dup_list(gr->gr_mem);
grent.gr_mem = dup_list (gr->gr_mem);
#ifdef SHADOWGRP
if ((sg = getsgnam (group))) {
sgent = *sg;
sgent.sg_name = xstrdup(sg->sg_name);
sgent.sg_passwd = xstrdup(sg->sg_passwd);
sgent.sg_name = xstrdup (sg->sg_name);
sgent.sg_passwd = xstrdup (sg->sg_passwd);
sgent.sg_mem = dup_list(sg->sg_mem);
sgent.sg_adm = dup_list(sg->sg_adm);
sgent.sg_mem = dup_list (sg->sg_mem);
sgent.sg_adm = dup_list (sg->sg_adm);
} else {
sgent.sg_name = xstrdup(group);
sgent.sg_name = xstrdup (group);
sgent.sg_passwd = grent.gr_passwd;
grent.gr_passwd = "!"; /* XXX warning: const */
grent.gr_passwd = "!"; /* XXX warning: const */
sgent.sg_mem = dup_list(grent.gr_mem);
sgent.sg_mem = dup_list (grent.gr_mem);
sgent.sg_adm = (char **) xmalloc(sizeof(char *) * 2);
sgent.sg_adm = (char **) xmalloc (sizeof (char *) * 2);
#ifdef FIRST_MEMBER_IS_ADMIN
if (sgent.sg_mem[0]) {
sgent.sg_adm[0] = xstrdup(sgent.sg_mem[0]);
sgent.sg_adm[0] = xstrdup (sgent.sg_mem[0]);
sgent.sg_adm[1] = 0;
} else
#endif
@@ -361,160 +346,163 @@ main(int argc, char **argv)
}
/*
* The policy here for changing a group is that 1) you must be
* root or 2). you must be listed as an administrative member.
* Administrative members can do anything to a group that the
* root user can.
* The policy here for changing a group is that 1) you must be root
* or 2). you must be listed as an administrative member.
* Administrative members can do anything to a group that the root
* user can.
*/
if (!amroot && !is_on_list(sgent.sg_adm, myname))
failure();
#else /* ! SHADOWGRP */
if (!amroot && !is_on_list (sgent.sg_adm, myname))
failure ();
#else /* ! SHADOWGRP */
#ifdef FIRST_MEMBER_IS_ADMIN
/*
* The policy here for changing a group is that 1) you must bes
* root or 2) you must be the first listed member of the group.
* The first listed member of a group can do anything to that
* group that the root user can. The rationale for this hack is
* that the FIRST user is probably the most important user in
* this entire group.
* The policy here for changing a group is that 1) you must bes root
* or 2) you must be the first listed member of the group. The
* first listed member of a group can do anything to that group that
* the root user can. The rationale for this hack is that the FIRST
* user is probably the most important user in this entire group.
*/
if (! amroot) {
if (!amroot) {
if (grent.gr_mem[0] == (char *) 0)
failure();
failure ();
if (strcmp(grent.gr_mem[0], myname) != 0)
failure();
if (strcmp (grent.gr_mem[0], myname) != 0)
failure ();
}
#else
/*
* This feature enabled by default could be a security problem
* when installed on existing systems where the first group
* member might be just a normal user... --marekm
* This feature enabled by default could be a security problem when
* installed on existing systems where the first group member might
* be just a normal user. --marekm
*/
if (!amroot)
failure();
failure ();
#endif
#endif /* SHADOWGRP */
#endif /* SHADOWGRP */
/*
* Removing a password is straight forward. Just set the
* password field to a "".
* Removing a password is straight forward. Just set the password
* field to a "".
*/
if (rflg) {
grent.gr_passwd = ""; /* XXX warning: const */
grent.gr_passwd = ""; /* XXX warning: const */
#ifdef SHADOWGRP
sgent.sg_passwd = ""; /* XXX warning: const */
sgent.sg_passwd = ""; /* XXX warning: const */
#endif
SYSLOG((LOG_INFO, "remove password from group %s by %s\n", group, myname));
SYSLOG ((LOG_INFO, "remove password from group %s by %s",
group, myname));
goto output;
} else if (Rflg) {
/*
* Same thing for restricting the group. Set the password
* Same thing for restricting the group. Set the password
* field to "!".
*/
grent.gr_passwd = "!"; /* XXX warning: const */
grent.gr_passwd = "!"; /* XXX warning: const */
#ifdef SHADOWGRP
sgent.sg_passwd = "!"; /* XXX warning: const */
sgent.sg_passwd = "!"; /* XXX warning: const */
#endif
SYSLOG((LOG_INFO, "restrict access to group %s by %s\n", group, myname));
SYSLOG ((LOG_INFO, "restrict access to group %s by %s",
group, myname));
goto output;
}
/*
* Adding a member to a member list is pretty straightforward
* as well. Call the appropriate routine and split.
* Adding a member to a member list is pretty straightforward as
* well. Call the appropriate routine and split.
*/
if (aflg) {
printf(_("Adding user %s to group %s\n"), user, group);
printf (_("Adding user %s to group %s\n"), user, group);
grent.gr_mem = add_list (grent.gr_mem, user);
#ifdef SHADOWGRP
sgent.sg_mem = add_list (sgent.sg_mem, user);
#endif
SYSLOG((LOG_INFO, "add member %s to group %s by %s\n", user, group, myname));
SYSLOG ((LOG_INFO, "add member %s to group %s by %s", user,
group, myname));
goto output;
}
/*
* Removing a member from the member list is the same deal
* as adding one, except the routine is different.
* Removing a member from the member list is the same deal as adding
* one, except the routine is different.
*/
if (dflg) {
int removed = 0;
int removed = 0;
printf(_("Removing user %s from group %s\n"), user, group);
printf (_("Removing user %s from group %s\n"), user,
group);
if (is_on_list(grent.gr_mem, user)) {
if (is_on_list (grent.gr_mem, user)) {
removed = 1;
grent.gr_mem = del_list (grent.gr_mem, user);
}
#ifdef SHADOWGRP
if (is_on_list(sgent.sg_mem, user)) {
if (is_on_list (sgent.sg_mem, user)) {
removed = 1;
sgent.sg_mem = del_list (sgent.sg_mem, user);
}
#endif
if (! removed) {
fprintf(stderr, _("%s: unknown member %s\n"),
Prog, user);
if (!removed) {
fprintf (stderr, _("%s: unknown member %s\n"),
Prog, user);
exit (1);
}
SYSLOG((LOG_INFO, "remove member %s from group %s by %s\n",
user, group, myname));
SYSLOG ((LOG_INFO, "remove member %s from group %s by %s",
user, group, myname));
goto output;
}
#ifdef SHADOWGRP
/*
* Replacing the entire list of administators is simple. Check the
* list to make sure everyone is a real user. Then slap the new
* list in place.
* Replacing the entire list of administators is simple. Check the
* list to make sure everyone is a real user. Then slap the new list
* in place.
*/
if (Aflg) {
SYSLOG((LOG_INFO, "set administrators of %s to %s\n",
group, admins));
sgent.sg_adm = comma_to_list(admins);
SYSLOG ((LOG_INFO, "set administrators of %s to %s",
group, admins));
sgent.sg_adm = comma_to_list (admins);
if (!Mflg)
goto output;
}
#endif
/*
* Replacing the entire list of members is simple. Check the list
* to make sure everyone is a real user. Then slap the new list
* in place.
* Replacing the entire list of members is simple. Check the list to
* make sure everyone is a real user. Then slap the new list in
* place.
*/
if (Mflg) {
SYSLOG((LOG_INFO,"set members of %s to %s\n",group,members));
SYSLOG ((LOG_INFO, "set members of %s to %s", group,
members));
#ifdef SHADOWGRP
sgent.sg_mem = comma_to_list(members);
sgent.sg_mem = comma_to_list (members);
#endif
grent.gr_mem = comma_to_list(members);
grent.gr_mem = comma_to_list (members);
goto output;
}
/*
* If the password is being changed, the input and output must
* both be a tty. The typical keyboard signals are caught
* so the termio modes can be restored.
* If the password is being changed, the input and output must both
* be a tty. The typical keyboard signals are caught so the termio
* modes can be restored.
*/
if (! isatty (0) || ! isatty (1)) {
fprintf(stderr, _("%s: Not a tty\n"), Prog);
if (!isatty (0) || !isatty (1)) {
fprintf (stderr, _("%s: Not a tty\n"), Prog);
exit (1);
}
die (0); /* save tty modes */
die (0); /* save tty modes */
signal (SIGHUP, die);
signal (SIGINT, die);
@@ -525,137 +513,140 @@ main(int argc, char **argv)
#endif
/*
* A new password is to be entered and it must be encrypted,
* etc. The password will be prompted for twice, and both
* entries must be identical. There is no need to validate
* the old password since the invoker is either the group
* owner, or root.
* A new password is to be entered and it must be encrypted, etc.
* The password will be prompted for twice, and both entries must be
* identical. There is no need to validate the old password since
* the invoker is either the group owner, or root.
*/
printf(_("Changing the password for group %s\n"), group);
printf (_("Changing the password for group %s\n"), group);
for (retries = 0; retries < RETRIES; retries++) {
if (! (cp = getpass(_("New Password: "))))
if (!(cp = getpass (_("New Password: "))))
exit (1);
STRFCPY(pass, cp);
strzero(cp);
if (! (cp = getpass (_("Re-enter new password: "))))
STRFCPY (pass, cp);
strzero (cp);
if (!(cp = getpass (_("Re-enter new password: "))))
exit (1);
if (strcmp(pass, cp) == 0) {
strzero(cp);
if (strcmp (pass, cp) == 0) {
strzero (cp);
break;
}
strzero(cp);
memzero(pass, sizeof pass);
strzero (cp);
memzero (pass, sizeof pass);
if (retries + 1 < RETRIES)
puts(_("They don't match; try again"));
puts (_("They don't match; try again"));
}
if (retries == RETRIES) {
fprintf(stderr, _("%s: Try again later\n"), Prog);
exit(1);
fprintf (stderr, _("%s: Try again later\n"), Prog);
exit (1);
}
cp = pw_encrypt(pass, crypt_make_salt());
memzero(pass, sizeof pass);
cp = pw_encrypt (pass, crypt_make_salt ());
memzero (pass, sizeof pass);
#ifdef SHADOWGRP
if (is_shadowgrp)
sgent.sg_passwd = cp;
else
#endif
grent.gr_passwd = cp;
SYSLOG((LOG_INFO, "change the password for group %s by %s\n", group, myname));
grent.gr_passwd = cp;
SYSLOG ((LOG_INFO, "change the password for group %s by %s", group,
myname));
/*
* This is the common arrival point to output the new group
* file. The freshly crafted entry is in allocated space.
* The group file will be locked and opened for writing. The
* new entry will be output, etc.
* This is the common arrival point to output the new group file.
* The freshly crafted entry is in allocated space. The group file
* will be locked and opened for writing. The new entry will be
* output, etc.
*/
output:
if (setuid(0)) {
fprintf(stderr, _("Cannot change ID to root.\n"));
SYSLOG((LOG_ERR, "can't setuid(0)"));
closelog();
exit(1);
output:
if (setuid (0)) {
fprintf (stderr, _("Cannot change ID to root.\n"));
SYSLOG ((LOG_ERR, "can't setuid(0)"));
closelog ();
exit (1);
}
pwd_init();
pwd_init ();
if (! gr_lock ()) {
fprintf(stderr, _("%s: can't get lock\n"), Prog);
SYSLOG((LOG_WARN, "failed to get lock for /etc/group\n"));
if (!gr_lock ()) {
fprintf (stderr, _("%s: can't get lock\n"), Prog);
SYSLOG ((LOG_WARN, "failed to get lock for /etc/group"));
exit (1);
}
#ifdef SHADOWGRP
if (is_shadowgrp && ! sgr_lock ()) {
fprintf(stderr, _("%s: can't get shadow lock\n"), Prog);
SYSLOG((LOG_WARN, "failed to get lock for /etc/gshadow\n"));
if (is_shadowgrp && !sgr_lock ()) {
fprintf (stderr, _("%s: can't get shadow lock\n"), Prog);
SYSLOG ((LOG_WARN, "failed to get lock for /etc/gshadow"));
exit (1);
}
#endif
if (! gr_open (O_RDWR)) {
fprintf(stderr, _("%s: can't open file\n"), Prog);
SYSLOG((LOG_WARN, "cannot open /etc/group\n"));
if (!gr_open (O_RDWR)) {
fprintf (stderr, _("%s: can't open file\n"), Prog);
SYSLOG ((LOG_WARN, "cannot open /etc/group"));
exit (1);
}
#ifdef SHADOWGRP
if (is_shadowgrp && ! sgr_open (O_RDWR)) {
fprintf(stderr, _("%s: can't open shadow file\n"), Prog);
SYSLOG((LOG_WARN, "cannot open /etc/gshadow\n"));
if (is_shadowgrp && !sgr_open (O_RDWR)) {
fprintf (stderr, _("%s: can't open shadow file\n"), Prog);
SYSLOG ((LOG_WARN, "cannot open /etc/gshadow"));
exit (1);
}
#endif
if (! gr_update (&grent)) {
fprintf(stderr, _("%s: can't update entry\n"), Prog);
SYSLOG((LOG_WARN, "cannot update /etc/group\n"));
if (!gr_update (&grent)) {
fprintf (stderr, _("%s: can't update entry\n"), Prog);
SYSLOG ((LOG_WARN, "cannot update /etc/group"));
exit (1);
}
#ifdef SHADOWGRP
if (is_shadowgrp && ! sgr_update (&sgent)) {
fprintf(stderr, _("%s: can't update shadow entry\n"), Prog);
SYSLOG((LOG_WARN, "cannot update /etc/gshadow\n"));
if (is_shadowgrp && !sgr_update (&sgent)) {
fprintf (stderr, _("%s: can't update shadow entry\n"),
Prog);
SYSLOG ((LOG_WARN, "cannot update /etc/gshadow"));
exit (1);
}
#endif
if (! gr_close ()) {
fprintf(stderr, _("%s: can't re-write file\n"), Prog);
SYSLOG((LOG_WARN, "cannot re-write /etc/group\n"));
if (!gr_close ()) {
fprintf (stderr, _("%s: can't re-write file\n"), Prog);
SYSLOG ((LOG_WARN, "cannot re-write /etc/group"));
exit (1);
}
#ifdef SHADOWGRP
if (is_shadowgrp && ! sgr_close ()) {
fprintf(stderr, _("%s: can't re-write shadow file\n"), Prog);
SYSLOG((LOG_WARN, "cannot re-write /etc/gshadow\n"));
if (is_shadowgrp && !sgr_close ()) {
fprintf (stderr, _("%s: can't re-write shadow file\n"),
Prog);
SYSLOG ((LOG_WARN, "cannot re-write /etc/gshadow"));
exit (1);
}
if (is_shadowgrp)
sgr_unlock ();
#endif
if (! gr_unlock ()) {
fprintf(stderr, _("%s: can't unlock file\n"), Prog);
if (!gr_unlock ()) {
fprintf (stderr, _("%s: can't unlock file\n"), Prog);
exit (1);
}
#ifdef NDBM
if (gr_dbm_present() && ! gr_dbm_update (&grent)) {
fprintf(stderr, _("%s: can't update DBM files\n"), Prog);
SYSLOG((LOG_WARN, "cannot update /etc/group DBM files\n"));
if (gr_dbm_present () && !gr_dbm_update (&grent)) {
fprintf (stderr, _("%s: can't update DBM files\n"), Prog);
SYSLOG ((LOG_WARN, "cannot update /etc/group DBM files"));
exit (1);
}
endgrent ();
#ifdef SHADOWGRP
if (is_shadowgrp && sg_dbm_present() && ! sg_dbm_update (&sgent)) {
fprintf(stderr, _("%s: can't update DBM shadow files\n"), Prog);
SYSLOG((LOG_WARN, "cannot update /etc/gshadow DBM files\n"));
if (is_shadowgrp && sg_dbm_present () && !sg_dbm_update (&sgent)) {
fprintf (stderr, _("%s: can't update DBM shadow files\n"),
Prog);
SYSLOG ((LOG_WARN,
"cannot update /etc/gshadow DBM files"));
exit (1);
}
endsgent ();
#endif
#endif
exit (0);
/*NOTREACHED*/
}
/*NOTREACHED*/}
+199 -205
View File
@@ -17,7 +17,7 @@
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH 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)
@@ -30,31 +30,24 @@
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: groupadd.c,v 1.18 2000/10/09 19:02:20 kloczek Exp $")
RCSID (PKG_VER "$Id: groupadd.c,v 1.22 2002/01/06 14:09:07 kloczek Exp $")
#include <sys/types.h>
#include <stdio.h>
#include <grp.h>
#include <ctype.h>
#include <fcntl.h>
#include "defines.h"
#include "prototypes.h"
#include "chkname.h"
#include "getdef.h"
#include "groupio.h"
#ifdef SHADOWGRP
#include "sgroupio.h"
#ifdef USE_PAM
#include <security/pam_appl.h>
#include <security/pam_misc.h>
#include <pwd.h>
#endif /* USE_PAM */
#endif /* USE_PAM */
static int is_shadow_grp;
#endif
@@ -69,62 +62,58 @@ static int is_shadow_grp;
#define E_NAME_IN_USE 9 /* group name nut unique */
#define E_GRP_UPDATE 10 /* can't update group file */
static char *group_name;
static gid_t group_id;
static char *group_name;
static gid_t group_id;
static char *empty_list = NULL;
static char *Prog;
static char *Prog;
static int oflg = 0; /* permit non-unique group ID to be specified with -g */
static int gflg = 0; /* ID value for the new group */
static int fflg = 0; /* if group already exists, do nothing and exit(0) */
static int oflg = 0; /* permit non-unique group ID to be specified with -g */
static int gflg = 0; /* ID value for the new group */
static int fflg = 0; /* if group already exists, do nothing and exit(0) */
#ifdef NDBM
extern int gr_dbm_mode;
extern int sg_dbm_mode;
extern int gr_dbm_mode;
extern int sg_dbm_mode;
#endif
extern int optind;
extern char *optarg;
/* local function prototypes */
static void usage(void);
static void new_grent(struct group *);
static void usage (void);
static void new_grent (struct group *);
#ifdef SHADOWGRP
static void new_sgent(struct sgrp *);
static void new_sgent (struct sgrp *);
#endif
static void grp_update(void);
static void find_new_gid(void);
static void check_new_name(void);
static void process_flags(int, char **);
static void close_files(void);
static void open_files(void);
static void fail_exit(int);
static void grp_update (void);
static void find_new_gid (void);
static void check_new_name (void);
static void process_flags (int, char **);
static void close_files (void);
static void open_files (void);
static void fail_exit (int);
/*
* usage - display usage message and exit
*/
static void
usage(void)
static void usage (void)
{
fprintf(stderr, _("usage: groupadd [-g gid [-o]] group\n"));
exit(E_USAGE);
fprintf (stderr, _("usage: groupadd [-g gid [-o]] group\n"));
exit (E_USAGE);
}
/*
* new_grent - initialize the values in a group file entry
*
* new_grent() takes all of the values that have been entered and
* fills in a (struct group) with them.
* new_grent() takes all of the values that have been entered and fills
* in a (struct group) with them.
*/
static void
new_grent(struct group *grent)
static void new_grent (struct group *grent)
{
memzero(grent, sizeof *grent);
memzero (grent, sizeof *grent);
grent->gr_name = group_name;
grent->gr_passwd = SHADOW_PASSWD_STRING; /* XXX warning: const */
grent->gr_passwd = SHADOW_PASSWD_STRING; /* XXX warning: const */
grent->gr_gid = group_id;
grent->gr_mem = &empty_list;
}
@@ -133,20 +122,19 @@ new_grent(struct group *grent)
/*
* new_sgent - initialize the values in a shadow group file entry
*
* new_sgent() takes all of the values that have been entered and
* fills in a (struct sgrp) with them.
* new_sgent() takes all of the values that have been entered and fills
* in a (struct sgrp) with them.
*/
static void
new_sgent(struct sgrp *sgent)
static void new_sgent (struct sgrp *sgent)
{
memzero(sgent, sizeof *sgent);
memzero (sgent, sizeof *sgent);
sgent->sg_name = group_name;
sgent->sg_passwd = "!"; /* XXX warning: const */
sgent->sg_passwd = "!"; /* XXX warning: const */
sgent->sg_adm = &empty_list;
sgent->sg_mem = &empty_list;
}
#endif /* SHADOWGRP */
#endif /* SHADOWGRP */
/*
* grp_update - add new group file entries
@@ -154,13 +142,13 @@ new_sgent(struct sgrp *sgent)
* grp_update() writes the new records to the group files.
*/
static void
grp_update(void)
static void grp_update (void)
{
struct group grp;
struct group grp;
#ifdef SHADOWGRP
struct sgrp sgrp;
#endif /* SHADOWGRP */
struct sgrp sgrp;
#endif /* SHADOWGRP */
/*
* Create the initial entries for this new group.
@@ -169,15 +157,16 @@ grp_update(void)
new_grent (&grp);
#ifdef SHADOWGRP
new_sgent (&sgrp);
#endif /* SHADOWGRP */
#endif /* SHADOWGRP */
/*
* Write out the new group file entry.
*/
if (! gr_update (&grp)) {
fprintf(stderr, _("%s: error adding new group entry\n"), Prog);
fail_exit(E_GRP_UPDATE);
if (!gr_update (&grp)) {
fprintf (stderr, _("%s: error adding new group entry\n"),
Prog);
fail_exit (E_GRP_UPDATE);
}
#ifdef NDBM
@@ -185,12 +174,13 @@ grp_update(void)
* Update the DBM group file with the new entry as well.
*/
if (gr_dbm_present() && ! gr_dbm_update (&grp)) {
fprintf(stderr, _("%s: cannot add new dbm group entry\n"), Prog);
fail_exit(E_GRP_UPDATE);
if (gr_dbm_present () && !gr_dbm_update (&grp)) {
fprintf (stderr, _("%s: cannot add new dbm group entry\n"),
Prog);
fail_exit (E_GRP_UPDATE);
}
endgrent ();
#endif /* NDBM */
#endif /* NDBM */
#ifdef SHADOWGRP
@@ -198,9 +188,10 @@ grp_update(void)
* Write out the new shadow group entries as well.
*/
if (is_shadow_grp && ! sgr_update (&sgrp)) {
fprintf(stderr, _("%s: error adding new group entry\n"), Prog);
fail_exit(E_GRP_UPDATE);
if (is_shadow_grp && !sgr_update (&sgrp)) {
fprintf (stderr, _("%s: error adding new group entry\n"),
Prog);
fail_exit (E_GRP_UPDATE);
}
#ifdef NDBM
@@ -208,15 +199,16 @@ grp_update(void)
* Update the DBM group file with the new entry as well.
*/
if (is_shadow_grp && sg_dbm_present() && ! sg_dbm_update (&sgrp)) {
fprintf(stderr, _("%s: cannot add new dbm group entry\n"), Prog);
fail_exit(E_GRP_UPDATE);
if (is_shadow_grp && sg_dbm_present () && !sg_dbm_update (&sgrp)) {
fprintf (stderr, _("%s: cannot add new dbm group entry\n"),
Prog);
fail_exit (E_GRP_UPDATE);
}
endsgent ();
#endif /* NDBM */
#endif /* SHADOWGRP */
SYSLOG((LOG_INFO, "new group: name=%s, gid=%d\n",
group_name, group_id));
#endif /* NDBM */
#endif /* SHADOWGRP */
SYSLOG ((LOG_INFO, "new group: name=%s, gid=%u",
group_name, (unsigned int)group_id));
}
/*
@@ -227,60 +219,59 @@ grp_update(void)
* uniqueness.
*/
static void
find_new_gid(void)
static void find_new_gid (void)
{
const struct group *grp;
gid_t gid_min, gid_max;
gid_min = getdef_num("GID_MIN", 100);
gid_max = getdef_num("GID_MAX", 60000);
gid_min = getdef_unum ("GID_MIN", 100);
gid_max = getdef_unum ("GID_MAX", 60000);
/*
* Start with some GID value if the user didn't provide us with
* one already.
*/
if (! gflg)
if (!gflg)
group_id = gid_min;
/*
* Search the entire group file, either looking for this
* GID (if the user specified one with -g) or looking for the
* largest unused value.
* Search the entire group file, either looking for this GID (if the
* user specified one with -g) or looking for the largest unused
* value.
*/
#ifdef NO_GETGRENT
gr_rewind();
while ((grp = gr_next())) {
gr_rewind ();
while ((grp = gr_next ())) {
#else
setgrent();
while ((grp = getgrent())) {
setgrent ();
while ((grp = getgrent ())) {
#endif
if (strcmp(group_name, grp->gr_name) == 0) {
if (strcmp (group_name, grp->gr_name) == 0) {
if (fflg) {
fail_exit(E_SUCCESS);
fail_exit (E_SUCCESS);
}
fprintf(stderr, _("%s: name %s is not unique\n"),
Prog, group_name);
fail_exit(E_NAME_IN_USE);
fprintf (stderr, _("%s: name %s is not unique\n"),
Prog, group_name);
fail_exit (E_NAME_IN_USE);
}
if (gflg && group_id == grp->gr_gid) {
if (fflg) {
/* turn off -g and search again */
gflg = 0;
#ifdef NO_GETGRENT
gr_rewind();
gr_rewind ();
#else
setgrent();
setgrent ();
#endif
continue;
}
fprintf(stderr, _("%s: gid %ld is not unique\n"),
Prog, (long) group_id);
fail_exit(E_GID_IN_USE);
fprintf (stderr, _("%s: gid %u is not unique\n"),
Prog, (unsigned int) group_id);
fail_exit (E_GID_IN_USE);
}
if (! gflg && grp->gr_gid >= group_id) {
if (!gflg && grp->gr_gid >= group_id) {
if (grp->gr_gid > gid_max)
continue;
group_id = grp->gr_gid + 1;
@@ -289,20 +280,20 @@ find_new_gid(void)
if (!gflg && group_id == gid_max + 1) {
for (group_id = gid_min; group_id < gid_max; group_id++) {
#ifdef NO_GETGRENT
gr_rewind();
while ((grp = gr_next()) && grp->gr_gid != group_id)
;
gr_rewind ();
while ((grp = gr_next ())
&& grp->gr_gid != group_id);
if (!grp)
break;
#else
if (!getgrgid(group_id))
if (!getgrgid (group_id))
break;
#endif
}
if (group_id == gid_max) {
fprintf(stderr, _("%s: can't get unique gid\n"),
Prog);
fail_exit(E_GID_IN_USE);
fprintf (stderr, _("%s: can't get unique gid\n"),
Prog);
fail_exit (E_GID_IN_USE);
}
}
}
@@ -310,52 +301,51 @@ find_new_gid(void)
/*
* check_new_name - check the new name for validity
*
* check_new_name() insures that the new name doesn't contain
* any illegal characters.
* check_new_name() insures that the new name doesn't contain any
* illegal characters.
*/
static void
check_new_name(void)
static void check_new_name (void)
{
if (check_group_name(group_name))
if (check_group_name (group_name))
return;
/*
* All invalid group names land here.
*/
fprintf(stderr, _("%s: %s is a not a valid group name\n"),
Prog, group_name);
fprintf (stderr, _("%s: %s is a not a valid group name\n"),
Prog, group_name);
exit(E_BAD_ARG);
exit (E_BAD_ARG);
}
/*
* process_flags - perform command line argument setting
*
* process_flags() interprets the command line arguments and sets
* the values that the user will be created with accordingly. The
* values are checked for sanity.
* process_flags() interprets the command line arguments and sets the
* values that the user will be created with accordingly. The values
* are checked for sanity.
*/
static void
process_flags(int argc, char **argv)
static void process_flags (int argc, char **argv)
{
char *cp;
int arg;
while ((arg = getopt(argc, argv, "og:O:f")) != EOF) {
while ((arg = getopt (argc, argv, "og:O:f")) != EOF) {
switch (arg) {
case 'g':
gflg++;
if (! isdigit (optarg[0]))
if (!isdigit (optarg[0]))
usage ();
group_id = strtol(optarg, &cp, 10);
group_id = strtoul (optarg, &cp, 10);
if (*cp != '\0') {
fprintf(stderr, _("%s: invalid group %s\n"),
Prog, optarg);
fail_exit(E_BAD_ARG);
fprintf (stderr,
_("%s: invalid group %s\n"), Prog,
optarg);
fail_exit (E_BAD_ARG);
}
break;
case 'o':
@@ -367,67 +357,68 @@ process_flags(int argc, char **argv)
* example: -O GID_MIN=100 -O GID_MAX=499
* note: -O GID_MIN=10,GID_MAX=499 doesn't work yet
*/
cp = strchr(optarg, '=');
cp = strchr (optarg, '=');
if (!cp) {
fprintf(stderr,
_("%s: -O requires NAME=VALUE\n"),
Prog);
exit(E_BAD_ARG);
fprintf (stderr,
_("%s: -O requires NAME=VALUE\n"),
Prog);
exit (E_BAD_ARG);
}
/* terminate name, point to value */
*cp++ = '\0';
if (putdef_str(optarg, cp) < 0)
exit(E_BAD_ARG);
if (putdef_str (optarg, cp) < 0)
exit (E_BAD_ARG);
break;
case 'f':
/*
* "force" - do nothing, just exit(0), if the
* specified group already exists. With -g, if
* specified group already exists. With -g, if
* specified gid already exists, choose another
* (unique) gid (turn off -g). Based on the
* RedHat's patch from shadow-utils-970616-9.
* (unique) gid (turn off -g). Based on the RedHat's
* patch from shadow-utils-970616-9.
*/
fflg++;
break;
default:
usage();
usage ();
}
}
if (oflg && !gflg)
usage();
usage ();
if (optind != argc - 1)
usage();
usage ();
group_name = argv[argc - 1];
check_new_name();
check_new_name ();
}
/*
* close_files - close all of the files that were opened
*
* close_files() closes all of the files that were opened for this
* new group. This causes any modified entries to be written out.
* close_files() closes all of the files that were opened for this new
* group. This causes any modified entries to be written out.
*/
static void
close_files(void)
static void close_files (void)
{
if (!gr_close()) {
fprintf(stderr, _("%s: cannot rewrite group file\n"), Prog);
fail_exit(E_GRP_UPDATE);
if (!gr_close ()) {
fprintf (stderr, _("%s: cannot rewrite group file\n"),
Prog);
fail_exit (E_GRP_UPDATE);
}
gr_unlock();
gr_unlock ();
#ifdef SHADOWGRP
if (is_shadow_grp && !sgr_close()) {
fprintf(stderr, _("%s: cannot rewrite shadow group file\n"),
Prog);
fail_exit(E_GRP_UPDATE);
if (is_shadow_grp && !sgr_close ()) {
fprintf (stderr,
_("%s: cannot rewrite shadow group file\n"),
Prog);
fail_exit (E_GRP_UPDATE);
}
if (is_shadow_grp)
sgr_unlock ();
#endif /* SHADOWGRP */
#endif /* SHADOWGRP */
}
/*
@@ -436,37 +427,39 @@ close_files(void)
* open_files() opens the two group files.
*/
static void
open_files(void)
static void open_files (void)
{
if (! gr_lock ()) {
fprintf(stderr, _("%s: unable to lock group file\n"), Prog);
exit(E_GRP_UPDATE);
if (!gr_lock ()) {
fprintf (stderr, _("%s: unable to lock group file\n"),
Prog);
exit (E_GRP_UPDATE);
}
if (! gr_open (O_RDWR)) {
fprintf(stderr, _("%s: unable to open group file\n"), Prog);
fail_exit(E_GRP_UPDATE);
if (!gr_open (O_RDWR)) {
fprintf (stderr, _("%s: unable to open group file\n"),
Prog);
fail_exit (E_GRP_UPDATE);
}
#ifdef SHADOWGRP
if (is_shadow_grp && ! sgr_lock ()) {
fprintf(stderr, _("%s: unable to lock shadow group file\n"),
Prog);
fail_exit(E_GRP_UPDATE);
if (is_shadow_grp && !sgr_lock ()) {
fprintf (stderr,
_("%s: unable to lock shadow group file\n"),
Prog);
fail_exit (E_GRP_UPDATE);
}
if (is_shadow_grp && ! sgr_open (O_RDWR)) {
fprintf(stderr, _("%s: unable to open shadow group file\n"),
Prog);
fail_exit(E_GRP_UPDATE);
if (is_shadow_grp && !sgr_open (O_RDWR)) {
fprintf (stderr,
_("%s: unable to open shadow group file\n"),
Prog);
fail_exit (E_GRP_UPDATE);
}
#endif /* SHADOWGRP */
#endif /* SHADOWGRP */
}
/*
* fail_exit - exit with an error code after unlocking files
*/
static void
fail_exit(int code)
static void fail_exit (int code)
{
(void) gr_unlock ();
#ifdef SHADOWGRP
@@ -478,17 +471,16 @@ fail_exit(int code)
#ifdef USE_PAM
static struct pam_conv conv = {
misc_conv,
NULL
misc_conv,
NULL
};
#endif /* USE_PAM */
#endif /* USE_PAM */
/*
* main - groupadd command
*/
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
#ifdef USE_PAM
pam_handle_t *pamh = NULL;
@@ -500,73 +492,76 @@ main(int argc, char **argv)
* Get my name so that I can use it to report errors.
*/
Prog = Basename(argv[0]);
Prog = Basename (argv[0]);
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
#ifdef USE_PAM
retval = PAM_SUCCESS;
pampw = getpwuid(getuid());
pampw = getpwuid (getuid ());
if (pampw == NULL) {
retval = PAM_USER_UNKNOWN;
}
if (retval == PAM_SUCCESS) {
retval = pam_start("shadow", pampw->pw_name, &conv, &pamh);
retval =
pam_start ("shadow", pampw->pw_name, &conv, &pamh);
}
if (retval == PAM_SUCCESS) {
retval = pam_authenticate(pamh, 0);
retval = pam_authenticate (pamh, 0);
if (retval != PAM_SUCCESS) {
pam_end(pamh, retval);
pam_end (pamh, retval);
}
}
if (retval == PAM_SUCCESS) {
retval = pam_acct_mgmt(pamh, 0);
retval = pam_acct_mgmt (pamh, 0);
if (retval != PAM_SUCCESS) {
pam_end(pamh, retval);
pam_end (pamh, retval);
}
}
if (retval != PAM_SUCCESS) {
fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
fprintf (stderr, _("%s: PAM authentication failed\n"),
Prog);
exit (1);
}
#endif /* USE_PAM */
#endif /* USE_PAM */
OPENLOG(Prog);
OPENLOG (Prog);
#ifdef SHADOWGRP
is_shadow_grp = sgr_file_present();
is_shadow_grp = sgr_file_present ();
#endif
/*
* The open routines for the DBM files don't use read-write
* as the mode, so we have to clue them in.
* The open routines for the DBM files don't use read-write as the
* mode, so we have to clue them in.
*/
#ifdef NDBM
gr_dbm_mode = O_RDWR;
#ifdef SHADOWGRP
sg_dbm_mode = O_RDWR;
#endif /* SHADOWGRP */
#endif /* NDBM */
process_flags(argc, argv);
#endif /* SHADOWGRP */
#endif /* NDBM */
process_flags (argc, argv);
/*
* Start with a quick check to see if the group exists.
*/
if (getgrnam(group_name)) {
if (getgrnam (group_name)) {
if (fflg) {
exit(E_SUCCESS);
exit (E_SUCCESS);
}
fprintf(stderr, _("%s: group %s exists\n"), Prog, group_name);
exit(E_NAME_IN_USE);
fprintf (stderr, _("%s: group %s exists\n"), Prog,
group_name);
exit (E_NAME_IN_USE);
}
/*
@@ -574,20 +569,20 @@ main(int argc, char **argv)
* then close and update the files.
*/
open_files();
open_files ();
if (!gflg || !oflg)
find_new_gid();
find_new_gid ();
grp_update();
grp_update ();
close_files();
close_files ();
#ifdef USE_PAM
if (retval == PAM_SUCCESS) {
retval = pam_chauthtok(pamh, 0);
retval = pam_chauthtok (pamh, 0);
if (retval != PAM_SUCCESS) {
pam_end(pamh, retval);
pam_end (pamh, retval);
}
}
@@ -597,8 +592,7 @@ main(int argc, char **argv)
}
if (retval == PAM_SUCCESS)
pam_end(pamh, PAM_SUCCESS);
#endif /* USE_PAM */
exit(E_SUCCESS);
/*NOTREACHED*/
}
pam_end (pamh, PAM_SUCCESS);
#endif /* USE_PAM */
exit (E_SUCCESS);
/*NOTREACHED*/}
+224 -227
View File
@@ -17,7 +17,7 @@
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH 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)
@@ -30,29 +30,23 @@
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: groupmod.c,v 1.16 2000/10/09 19:02:20 kloczek Exp $")
RCSID (PKG_VER "$Id: groupmod.c,v 1.19 2002/01/05 15:41:43 kloczek Exp $")
#include <sys/types.h>
#include <stdio.h>
#include <grp.h>
#include <ctype.h>
#include <fcntl.h>
#ifdef USE_PAM
#include <security/pam_appl.h>
#include <security/pam_misc.h>
#include <pwd.h>
#endif /* USE_PAM */
#endif /* USE_PAM */
#include "prototypes.h"
#include "chkname.h"
#include "defines.h"
#include "groupio.h"
#ifdef SHADOWGRP
#include "sgroupio.h"
static int is_shadow_grp;
#endif
@@ -68,59 +62,56 @@ static int is_shadow_grp;
#define E_NAME_IN_USE 9 /* group name already in use */
#define E_GRP_UPDATE 10 /* can't update group file */
static char *group_name;
static char *group_newname;
static gid_t group_id;
static gid_t group_newid;
static char *group_name;
static char *group_newname;
static gid_t group_id;
static gid_t group_newid;
static char *Prog;
static char *Prog;
static int
oflg = 0, /* permit non-unique group ID to be specified with -g */
gflg = 0, /* new ID value for the group */
nflg = 0; /* a new name has been specified for the group */
oflg = 0, /* permit non-unique group ID to be specified with -g */
gflg = 0, /* new ID value for the group */
nflg = 0; /* a new name has been specified for the group */
#ifdef NDBM
extern int gr_dbm_mode;
extern int sg_dbm_mode;
extern int gr_dbm_mode;
extern int sg_dbm_mode;
#endif
extern int optind;
extern char *optarg;
/* local function prototypes */
static void usage(void);
static void new_grent(struct group *);
static void usage (void);
static void new_grent (struct group *);
#ifdef SHADOWGRP
static void new_sgent(struct sgrp *);
static void new_sgent (struct sgrp *);
#endif
static void grp_update(void);
static void check_new_gid(void);
static void check_new_name(void);
static void process_flags(int, char **);
static void close_files(void);
static void open_files(void);
static void grp_update (void);
static void check_new_gid (void);
static void check_new_name (void);
static void process_flags (int, char **);
static void close_files (void);
static void open_files (void);
/*
* usage - display usage message and exit
*/
static void
usage(void)
static void usage (void)
{
fprintf(stderr, _("usage: groupmod [-g gid [-o]] [-n name] group\n"));
exit(E_USAGE);
fprintf (stderr,
_("usage: groupmod [-g gid [-o]] [-n name] group\n"));
exit (E_USAGE);
}
/*
* new_grent - updates the values in a group file entry
*
* new_grent() takes all of the values that have been entered and
* fills in a (struct group) with them.
* new_grent() takes all of the values that have been entered and fills
* in a (struct group) with them.
*/
static void
new_grent(struct group *grent)
static void new_grent (struct group *grent)
{
if (nflg)
grent->gr_name = xstrdup (group_newname);
@@ -133,17 +124,16 @@ new_grent(struct group *grent)
/*
* new_sgent - updates the values in a shadow group file entry
*
* new_sgent() takes all of the values that have been entered and
* fills in a (struct sgrp) with them.
* new_sgent() takes all of the values that have been entered and fills
* in a (struct sgrp) with them.
*/
static void
new_sgent(struct sgrp *sgent)
static void new_sgent (struct sgrp *sgent)
{
if (nflg)
sgent->sg_name = xstrdup (group_newname);
}
#endif /* SHADOWGRP */
#endif /* SHADOWGRP */
/*
* grp_update - update group file entries
@@ -151,47 +141,49 @@ new_sgent(struct sgrp *sgent)
* grp_update() writes the new records to the group files.
*/
static void
grp_update(void)
static void grp_update (void)
{
struct group grp;
const struct group *ogrp;
#ifdef SHADOWGRP
struct sgrp sgrp;
const struct sgrp *osgrp = NULL;
#endif /* SHADOWGRP */
#endif /* SHADOWGRP */
/*
* Get the current settings for this group.
*/
ogrp = gr_locate(group_name);
ogrp = gr_locate (group_name);
if (!ogrp) {
fprintf(stderr,
_("%s: %s not found in /etc/group\n"),
Prog, group_name);
exit(E_GRP_UPDATE);
fprintf (stderr,
_("%s: %s not found in /etc/group\n"),
Prog, group_name);
exit (E_GRP_UPDATE);
}
grp = *ogrp;
new_grent (&grp);
#ifdef SHADOWGRP
if (is_shadow_grp && (osgrp = sgr_locate(group_name))) {
if (is_shadow_grp && (osgrp = sgr_locate (group_name))) {
sgrp = *osgrp;
new_sgent (&sgrp);
}
#endif /* SHADOWGRP */
#endif /* SHADOWGRP */
/*
* Write out the new group file entry.
*/
if (!gr_update(&grp)) {
fprintf(stderr, _("%s: error adding new group entry\n"), Prog);
exit(E_GRP_UPDATE);
if (!gr_update (&grp)) {
fprintf (stderr, _("%s: error adding new group entry\n"),
Prog);
exit (E_GRP_UPDATE);
}
if (nflg && !gr_remove(group_name)) {
fprintf(stderr, _("%s: error removing group entry\n"), Prog);
exit(E_GRP_UPDATE);
if (nflg && !gr_remove (group_name)) {
fprintf (stderr, _("%s: error removing group entry\n"),
Prog);
exit (E_GRP_UPDATE);
}
#ifdef NDBM
@@ -199,46 +191,48 @@ grp_update(void)
* Update the DBM group file with the new entry as well.
*/
if (gr_dbm_present()) {
if (!gr_dbm_update(&grp)) {
fprintf(stderr,
_("%s: cannot add new dbm group entry\n"),
Prog);
exit(E_GRP_UPDATE);
if (gr_dbm_present ()) {
if (!gr_dbm_update (&grp)) {
fprintf (stderr,
_("%s: cannot add new dbm group entry\n"),
Prog);
exit (E_GRP_UPDATE);
}
if (nflg && (ogrp = getgrnam(group_name)) &&
!gr_dbm_remove(ogrp)) {
fprintf(stderr,
_("%s: error removing group dbm entry\n"),
Prog);
exit(E_GRP_UPDATE);
if (nflg && (ogrp = getgrnam (group_name)) &&
!gr_dbm_remove (ogrp)) {
fprintf (stderr,
_("%s: error removing group dbm entry\n"),
Prog);
exit (E_GRP_UPDATE);
}
endgrent ();
}
#endif /* NDBM */
#endif /* NDBM */
#ifdef SHADOWGRP
/*
* Make sure there was a shadow entry to begin with. Skip
* down to "out" if there wasn't. Can't just return because
* there might be some syslogging to do.
* Make sure there was a shadow entry to begin with. Skip down to
* "out" if there wasn't. Can't just return because there might be
* some syslogging to do.
*/
if (! osgrp)
if (!osgrp)
goto out;
/*
* Write out the new shadow group entries as well.
*/
if (!sgr_update(&sgrp)) {
fprintf(stderr, _("%s: error adding new group entry\n"), Prog);
exit(E_GRP_UPDATE);
if (!sgr_update (&sgrp)) {
fprintf (stderr, _("%s: error adding new group entry\n"),
Prog);
exit (E_GRP_UPDATE);
}
if (nflg && !sgr_remove(group_name)) {
fprintf(stderr, _("%s: error removing group entry\n"), Prog);
exit(E_GRP_UPDATE);
if (nflg && !sgr_remove (group_name)) {
fprintf (stderr, _("%s: error removing group entry\n"),
Prog);
exit (E_GRP_UPDATE);
}
#ifdef NDBM
@@ -246,32 +240,34 @@ grp_update(void)
* Update the DBM shadow group file with the new entry as well.
*/
if (sg_dbm_present()) {
if (!sg_dbm_update(&sgrp)) {
fprintf(stderr,
_("%s: cannot add new dbm shadow group entry\n"),
Prog);
exit(E_GRP_UPDATE);
}
if (nflg && ! sg_dbm_remove (group_name)) {
if (sg_dbm_present ()) {
if (!sg_dbm_update (&sgrp)) {
fprintf (stderr,
_("%s: error removing shadow group dbm entry\n"),
Prog);
exit(E_GRP_UPDATE);
_
("%s: cannot add new dbm shadow group entry\n"),
Prog);
exit (E_GRP_UPDATE);
}
if (nflg && !sg_dbm_remove (group_name)) {
fprintf (stderr,
_
("%s: error removing shadow group dbm entry\n"),
Prog);
exit (E_GRP_UPDATE);
}
endsgent ();
}
#endif /* NDBM */
out:
#endif /* SHADOWGRP */
#endif /* NDBM */
out:
#endif /* SHADOWGRP */
if (nflg)
SYSLOG((LOG_INFO, "change group `%s' to `%s'\n",
group_name, group_newname));
SYSLOG ((LOG_INFO, "change group `%s' to `%s'",
group_name, group_newname));
if (gflg)
SYSLOG((LOG_INFO, "change gid for `%s' to %d\n",
nflg ? group_newname:group_name, group_newid));
SYSLOG ((LOG_INFO, "change gid for `%s' to %u",
nflg ? group_newname : group_name, group_newid));
}
/*
@@ -280,13 +276,12 @@ out:
* check_new_gid() insures that the new GID value is unique.
*/
static void
check_new_gid(void)
static void check_new_gid (void)
{
/*
* First, the easy stuff. If the ID can be duplicated, or if
* the ID didn't really change, just return. If the ID didn't
* change, turn off those flags. No sense doing needless work.
* First, the easy stuff. If the ID can be duplicated, or if the ID
* didn't really change, just return. If the ID didn't change, turn
* off those flags. No sense doing needless work.
*/
if (group_id == group_newid) {
@@ -294,48 +289,47 @@ check_new_gid(void)
return;
}
if (oflg || ! getgrgid (group_newid))
if (oflg || !getgrgid (group_newid))
return;
/*
* Tell the user what they did wrong.
*/
fprintf(stderr,
_("%s: %ld is not a unique gid\n"),
Prog, (long) group_newid);
exit(E_GID_IN_USE);
fprintf (stderr,
_("%s: %u is not a unique gid\n"), Prog, group_newid);
exit (E_GID_IN_USE);
}
/*
* check_new_name - check the new name for uniqueness
*
* check_new_name() insures that the new name does not exist
* already. You can't have the same name twice, period.
* check_new_name() insures that the new name does not exist already.
* You can't have the same name twice, period.
*/
static void
check_new_name(void)
static void check_new_name (void)
{
/*
* Make sure they are actually changing the name.
*/
if (strcmp(group_name, group_newname) == 0) {
if (strcmp (group_name, group_newname) == 0) {
nflg = 0;
return;
}
if (check_group_name(group_newname)) {
if (check_group_name (group_newname)) {
/*
* If the entry is found, too bad.
*/
if (getgrnam(group_newname)) {
fprintf(stderr, _("%s: %s is not a unique name\n"),
Prog, group_newname);
exit(E_NAME_IN_USE);
if (getgrnam (group_newname)) {
fprintf (stderr,
_("%s: %s is not a unique name\n"), Prog,
group_newname);
exit (E_NAME_IN_USE);
}
return;
}
@@ -344,53 +338,52 @@ check_new_name(void)
* All invalid group names land here.
*/
fprintf(stderr, _("%s: %s is a not a valid group name\n"),
Prog, group_newname);
exit(E_BAD_ARG);
fprintf (stderr, _("%s: %s is a not a valid group name\n"),
Prog, group_newname);
exit (E_BAD_ARG);
}
/*
* process_flags - perform command line argument setting
*
* process_flags() interprets the command line arguments and sets
* the values that the user will be created with accordingly. The
* values are checked for sanity.
* process_flags() interprets the command line arguments and sets the
* values that the user will be created with accordingly. The values
* are checked for sanity.
*/
static void
process_flags(int argc, char **argv)
static void process_flags (int argc, char **argv)
{
char *end;
int arg;
char *end;
int arg;
while ((arg = getopt (argc, argv, "og:n:")) != EOF) {
switch (arg) {
case 'g':
gflg++;
group_newid = strtol(optarg, &end, 10);
if (*end != '\0') {
fprintf(stderr,
_("%s: invalid group %s\n"),
Prog, optarg);
exit(E_BAD_ARG);
}
break;
case 'n':
nflg++;
group_newname = optarg;
break;
case 'o':
oflg++;
break;
default:
usage ();
case 'g':
gflg++;
group_newid = strtoul (optarg, &end, 10);
if (*end != '\0') {
fprintf (stderr,
_("%s: invalid group %s\n"),
Prog, optarg);
exit (E_BAD_ARG);
}
break;
case 'n':
nflg++;
group_newname = optarg;
break;
case 'o':
oflg++;
break;
default:
usage ();
}
}
if (oflg && !gflg)
usage();
usage ();
if (optind != argc - 1)
usage();
usage ();
group_name = argv[argc - 1];
}
@@ -398,27 +391,28 @@ process_flags(int argc, char **argv)
/*
* close_files - close all of the files that were opened
*
* close_files() closes all of the files that were opened for this
* new group. This causes any modified entries to be written out.
* close_files() closes all of the files that were opened for this new
* group. This causes any modified entries to be written out.
*/
static void
close_files(void)
static void close_files (void)
{
if (!gr_close()) {
fprintf(stderr, _("%s: cannot rewrite group file\n"), Prog);
exit(E_GRP_UPDATE);
if (!gr_close ()) {
fprintf (stderr, _("%s: cannot rewrite group file\n"),
Prog);
exit (E_GRP_UPDATE);
}
gr_unlock();
gr_unlock ();
#ifdef SHADOWGRP
if (is_shadow_grp && !sgr_close()) {
fprintf(stderr, _("%s: cannot rewrite shadow group file\n"),
Prog);
exit(E_GRP_UPDATE);
if (is_shadow_grp && !sgr_close ()) {
fprintf (stderr,
_("%s: cannot rewrite shadow group file\n"),
Prog);
exit (E_GRP_UPDATE);
}
if (is_shadow_grp)
sgr_unlock ();
#endif /* SHADOWGRP */
#endif /* SHADOWGRP */
}
/*
@@ -427,37 +421,40 @@ close_files(void)
* open_files() opens the two group files.
*/
static void
open_files(void)
static void open_files (void)
{
if (!gr_lock()) {
fprintf(stderr, _("%s: unable to lock group file\n"), Prog);
exit(E_GRP_UPDATE);
if (!gr_lock ()) {
fprintf (stderr, _("%s: unable to lock group file\n"),
Prog);
exit (E_GRP_UPDATE);
}
if (!gr_open(O_RDWR)) {
fprintf(stderr, _("%s: unable to open group file\n"), Prog);
exit(E_GRP_UPDATE);
if (!gr_open (O_RDWR)) {
fprintf (stderr, _("%s: unable to open group file\n"),
Prog);
exit (E_GRP_UPDATE);
}
#ifdef SHADOWGRP
if (is_shadow_grp && !sgr_lock()) {
fprintf(stderr, _("%s: unable to lock shadow group file\n"),
Prog);
exit(E_GRP_UPDATE);
if (is_shadow_grp && !sgr_lock ()) {
fprintf (stderr,
_("%s: unable to lock shadow group file\n"),
Prog);
exit (E_GRP_UPDATE);
}
if (is_shadow_grp && !sgr_open(O_RDWR)) {
fprintf(stderr, _("%s: unable to open shadow group file\n"),
Prog);
exit(E_GRP_UPDATE);
if (is_shadow_grp && !sgr_open (O_RDWR)) {
fprintf (stderr,
_("%s: unable to open shadow group file\n"),
Prog);
exit (E_GRP_UPDATE);
}
#endif /* SHADOWGRP */
#endif /* SHADOWGRP */
}
#ifdef USE_PAM
static struct pam_conv conv = {
misc_conv,
NULL
misc_conv,
NULL
};
#endif /* USE_PAM */
#endif /* USE_PAM */
/*
* main - groupmod command
@@ -472,10 +469,10 @@ static struct pam_conv conv = {
* -n - specify a new group name
*/
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
struct group *grp;
struct group *grp;
#ifdef USE_PAM
pam_handle_t *pamh = NULL;
struct passwd *pampw;
@@ -486,71 +483,73 @@ main(int argc, char **argv)
* Get my name so that I can use it to report errors.
*/
Prog = Basename(argv[0]);
Prog = Basename (argv[0]);
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
#ifdef USE_PAM
retval = PAM_SUCCESS;
pampw = getpwuid(getuid());
pampw = getpwuid (getuid ());
if (pampw == NULL) {
retval = PAM_USER_UNKNOWN;
}
if (retval == PAM_SUCCESS) {
retval = pam_start("shadow", pampw->pw_name, &conv, &pamh);
retval =
pam_start ("shadow", pampw->pw_name, &conv, &pamh);
}
if (retval == PAM_SUCCESS) {
retval = pam_authenticate(pamh, 0);
retval = pam_authenticate (pamh, 0);
if (retval != PAM_SUCCESS) {
pam_end(pamh, retval);
pam_end (pamh, retval);
}
}
if (retval == PAM_SUCCESS) {
retval = pam_acct_mgmt(pamh, 0);
retval = pam_acct_mgmt (pamh, 0);
if (retval != PAM_SUCCESS) {
pam_end(pamh, retval);
pam_end (pamh, retval);
}
}
if (retval != PAM_SUCCESS) {
fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
fprintf (stderr, _("%s: PAM authentication failed\n"),
Prog);
exit (1);
}
#endif /* USE_PAM */
#endif /* USE_PAM */
OPENLOG(Prog);
OPENLOG (Prog);
#ifdef SHADOWGRP
is_shadow_grp = sgr_file_present();
is_shadow_grp = sgr_file_present ();
#endif
/*
* The open routines for the DBM files don't use read-write
* as the mode, so we have to clue them in.
* The open routines for the DBM files don't use read-write as the
* mode, so we have to clue them in.
*/
#ifdef NDBM
gr_dbm_mode = O_RDWR;
#ifdef SHADOWGRP
sg_dbm_mode = O_RDWR;
#endif /* SHADOWGRP */
#endif /* NDBM */
#endif /* SHADOWGRP */
#endif /* NDBM */
process_flags (argc, argv);
/*
* Start with a quick check to see if the group exists.
*/
if (!(grp = getgrnam(group_name))) {
fprintf(stderr, _("%s: group %s does not exist\n"),
Prog, group_name);
exit(E_NOTFOUND);
if (!(grp = getgrnam (group_name))) {
fprintf (stderr, _("%s: group %s does not exist\n"),
Prog, group_name);
exit (E_NOTFOUND);
} else
group_id = grp->gr_gid;
@@ -561,19 +560,18 @@ main(int argc, char **argv)
*/
if (__isgrNIS ()) {
char *nis_domain;
char *nis_master;
char *nis_domain;
char *nis_master;
fprintf(stderr, _("%s: group %s is a NIS group\n"),
Prog, group_name);
fprintf (stderr, _("%s: group %s is a NIS group\n"),
Prog, group_name);
if (! yp_get_default_domain (&nis_domain) &&
! yp_master (nis_domain, "group.byname",
&nis_master)) {
fprintf(stderr, _("%s: %s is the NIS master\n"),
Prog, nis_master);
if (!yp_get_default_domain (&nis_domain) &&
!yp_master (nis_domain, "group.byname", &nis_master)) {
fprintf (stderr, _("%s: %s is the NIS master\n"),
Prog, nis_master);
}
exit(E_NOTFOUND);
exit (E_NOTFOUND);
}
#endif
@@ -596,9 +594,9 @@ main(int argc, char **argv)
#ifdef USE_PAM
if (retval == PAM_SUCCESS) {
retval = pam_chauthtok(pamh, 0);
retval = pam_chauthtok (pamh, 0);
if (retval != PAM_SUCCESS) {
pam_end(pamh, retval);
pam_end (pamh, retval);
}
}
@@ -608,8 +606,7 @@ main(int argc, char **argv)
}
if (retval == PAM_SUCCESS)
pam_end(pamh, PAM_SUCCESS);
#endif /* USE_PAM */
exit(E_SUCCESS);
/*NOTREACHED*/
}
pam_end (pamh, PAM_SUCCESS);
#endif /* USE_PAM */
exit (E_SUCCESS);
/*NOTREACHED*/}
+45 -48
View File
@@ -17,7 +17,7 @@
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH 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)
@@ -30,40 +30,37 @@
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: groups.c,v 1.7 2001/09/01 04:19:16 kloczek Exp $")
RCSID (PKG_VER "$Id: groups.c,v 1.8 2002/01/05 15:41:43 kloczek Exp $")
#include <stdio.h>
#include <pwd.h>
#include <grp.h>
#include "prototypes.h"
#include "defines.h"
/* local function prototypes */
static void print_groups(const char *);
static void print_groups (const char *);
/*
* print_groups - print the groups which the named user is a member of
*
* print_groups() scans the groups file for the list of groups
* which the user is listed as being a member of.
* print_groups() scans the groups file for the list of groups which
* the user is listed as being a member of.
*/
static void
print_groups(const char *member)
static void print_groups (const char *member)
{
int groups = 0;
struct group *grp;
struct passwd *pwd;
int flag = 0;
int groups = 0;
struct group *grp;
struct passwd *pwd;
int flag = 0;
setgrent ();
if ((pwd = getpwnam(member)) == 0) {
fprintf(stderr, _("unknown user %s\n"), member);
exit(1);
if ((pwd = getpwnam (member)) == 0) {
fprintf (stderr, _("unknown user %s\n"), member);
exit (1);
}
while ((grp = getgrent ())) {
if (is_on_list(grp->gr_mem, member)) {
if (is_on_list (grp->gr_mem, member)) {
if (groups++)
putchar (' ');
@@ -72,7 +69,7 @@ print_groups(const char *member)
flag = 1;
}
}
if (! flag && (grp = getgrgid (pwd->pw_gid))) {
if (!flag && (grp = getgrgid (pwd->pw_gid))) {
if (groups++)
putchar (' ');
@@ -86,47 +83,47 @@ print_groups(const char *member)
* groups - print out the groups a process is a member of
*/
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
long sys_ngroups;
#ifdef HAVE_GETGROUPS
int ngroups;
int ngroups;
GETGROUPS_T *groups;
int pri_grp;
int i;
struct group *gr;
int pri_grp;
int i;
struct group *gr;
#else
char *logname;
char *getlogin();
char *logname;
char *getlogin ();
#endif
sys_ngroups=sysconf(_SC_NGROUPS_MAX);
sys_ngroups = sysconf (_SC_NGROUPS_MAX);
#ifdef HAVE_GETGROUPS
groups=malloc(sys_ngroups*sizeof(GETGROUPS_T));
groups = malloc (sys_ngroups * sizeof (GETGROUPS_T));
#endif
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
if (argc == 1) {
/*
* Called with no arguments - give the group set
* for the current user.
* Called with no arguments - give the group set for the
* current user.
*/
#ifdef HAVE_GETGROUPS
/*
* This system supports concurrent group sets, so
* I can ask the system to tell me which groups are
* currently set for this process.
* This system supports concurrent group sets, so I can ask
* the system to tell me which groups are currently set for
* this process.
*/
ngroups = getgroups(sys_ngroups, groups);
ngroups = getgroups (sys_ngroups, groups);
if (ngroups < 0) {
perror("getgroups");
exit(1);
perror ("getgroups");
exit (1);
}
/*
@@ -134,7 +131,7 @@ main(int argc, char **argv)
*/
pri_grp = getegid ();
for (i = 0;i < ngroups;i++)
for (i = 0; i < ngroups; i++)
if (pri_grp == (int) groups[i])
break;
@@ -142,9 +139,9 @@ main(int argc, char **argv)
pri_grp = -1;
/*
* Print out the name of every group in the current
* group set. Unknown groups are printed as their
* decimal group ID values.
* Print out the name of every group in the current group
* set. Unknown groups are printed as their decimal group ID
* values.
*/
if (pri_grp != -1) {
@@ -154,7 +151,7 @@ main(int argc, char **argv)
printf ("%d", pri_grp);
}
for (i = 0;i < ngroups;i++) {
for (i = 0; i < ngroups; i++) {
if (i || pri_grp != -1)
putchar (' ');
@@ -166,8 +163,8 @@ main(int argc, char **argv)
putchar ('\n');
#else
/*
* This system does not have the getgroups() system
* call, so I must check the groups file directly.
* This system does not have the getgroups() system call, so
* I must check the groups file directly.
*/
if ((logname = getlogin ()))
@@ -178,8 +175,8 @@ main(int argc, char **argv)
} else {
/*
* The invoker wanted to know about some other
* user. Use that name to look up the groups instead.
* The invoker wanted to know about some other user. Use
* that name to look up the groups instead.
*/
print_groups (argv[1]);
+182 -195
View File
@@ -17,7 +17,7 @@
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH 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)
@@ -30,27 +30,23 @@
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: grpck.c,v 1.16 2001/08/18 09:28:16 malekith Exp $")
RCSID (PKG_VER "$Id: grpck.c,v 1.20 2002/01/05 15:41:43 kloczek Exp $")
#include <stdio.h>
#include <fcntl.h>
#include <grp.h>
#include "prototypes.h"
#include "defines.h"
#include "chkname.h"
#include <pwd.h>
#include "commonio.h"
#include "groupio.h"
extern void __gr_del_entry(const struct commonio_entry *);
extern struct commonio_entry *__gr_get_head(void);
extern void __gr_del_entry (const struct commonio_entry *);
extern struct commonio_entry *__gr_get_head (void);
#ifdef SHADOWGRP
#include "sgroupio.h"
extern void __sgr_del_entry(const struct commonio_entry *);
extern struct commonio_entry *__sgr_get_head(void);
extern void __sgr_del_entry (const struct commonio_entry *);
extern struct commonio_entry *__sgr_get_head (void);
#endif
/*
@@ -64,59 +60,52 @@ extern struct commonio_entry *__sgr_get_head(void);
#define E_CANT_LOCK 4
#define E_CANT_UPDATE 5
/*
* Global variables
*/
extern int optind;
extern char *optarg;
/*
* Local variables
*/
static char *Prog;
static const char *grp_file = GROUP_FILE;
#ifdef SHADOWGRP
static const char *sgr_file = SGROUP_FILE;
#endif
static int read_only = 0;
/* local function prototypes */
static void usage(void);
static int yes_or_no(void);
static void delete_member(char **, const char *);
static void usage (void);
static int yes_or_no (void);
static void delete_member (char **, const char *);
/*
* usage - print syntax message and exit
*/
static void
usage(void)
static void usage (void)
{
#ifdef SHADOWGRP
fprintf(stderr, _("Usage: %s [ -sr ] [ group [ gshadow ] ]\n"), Prog);
fprintf (stderr, _("Usage: %s [-r] [-s] [group [gshadow]]\n"),
Prog);
#else
fprintf(stderr, _("Usage: %s [ -sr ] [ group ]\n"), Prog);
fprintf (stderr, _("Usage: %s [-r] [-s] [group]\n"), Prog);
#endif
exit(E_USAGE);
exit (E_USAGE);
}
/*
* yes_or_no - get answer to question from the user
*/
static int
yes_or_no(void)
static int yes_or_no (void)
{
char buf[80];
char buf[80];
/*
* In read-only mode all questions are answered "no".
*/
if (read_only) {
puts(_("No"));
puts (_("No"));
return 0;
}
@@ -124,7 +113,7 @@ yes_or_no(void)
* Get a line and see what the first character is.
*/
if (fgets(buf, sizeof buf, stdin))
if (fgets (buf, sizeof buf, stdin))
return buf[0] == 'y' || buf[0] == 'Y';
return 0;
@@ -134,8 +123,7 @@ yes_or_no(void)
* delete_member - delete an entry in a list of members
*/
static void
delete_member(char **list, const char *member)
static void delete_member (char **list, const char *member)
{
int i;
@@ -152,19 +140,19 @@ delete_member(char **list, const char *member)
* grpck - verify group file integrity
*/
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
int arg;
int errors = 0;
int deleted = 0;
int i;
struct commonio_entry *gre, *tgre;
struct group *grp;
int sort_mode = 0;
int arg;
int errors = 0;
int deleted = 0;
int i;
struct commonio_entry *gre, *tgre;
struct group *grp;
int sort_mode = 0;
#ifdef SHADOWGRP
struct commonio_entry *sge, *tsge;
struct sgrp *sgr;
struct commonio_entry *sge, *tsge;
struct sgrp *sgr;
int is_shadow = 0;
#endif
@@ -172,19 +160,19 @@ main(int argc, char **argv)
* Get my name so that I can use it to report errors.
*/
Prog = Basename(argv[0]);
Prog = Basename (argv[0]);
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
OPENLOG(Prog);
OPENLOG (Prog);
/*
* Parse the command line arguments
*/
while ((arg = getopt(argc, argv, "qrs")) != EOF) {
while ((arg = getopt (argc, argv, "qrs")) != EOF) {
switch (arg) {
case 'q':
/* quiet - ignored for now */
@@ -196,16 +184,16 @@ main(int argc, char **argv)
sort_mode = 1;
break;
default:
usage();
usage ();
}
}
if (sort_mode && read_only) {
fprintf(stderr, _("%s: -s and -r are incompatibile\n"),
Prog);
exit(E_USAGE);
fprintf (stderr, _("%s: -s and -r are incompatibile\n"),
Prog);
exit (E_USAGE);
}
/*
* Make certain we have the right number of arguments
*/
@@ -215,24 +203,24 @@ main(int argc, char **argv)
#else
if (optind != argc && optind + 1 != argc)
#endif
usage();
usage ();
/*
* If there are two left over filenames, use those as the
* group and group password filenames.
* If there are two left over filenames, use those as the group and
* group password filenames.
*/
if (optind != argc) {
grp_file = argv[optind];
gr_name(grp_file);
gr_name (grp_file);
}
#ifdef SHADOWGRP
if (optind + 2 == argc) {
sgr_file = argv[optind + 1];
sgr_name(sgr_file);
sgr_name (sgr_file);
is_shadow = 1;
} else if (optind == argc)
is_shadow = sgr_file_present();
is_shadow = sgr_file_present ();
#endif
/*
@@ -240,51 +228,57 @@ main(int argc, char **argv)
*/
if (!read_only) {
if (!gr_lock()) {
fprintf(stderr, _("%s: cannot lock file %s\n"), Prog, grp_file);
if (!gr_lock ()) {
fprintf (stderr, _("%s: cannot lock file %s\n"),
Prog, grp_file);
if (optind == argc)
SYSLOG((LOG_WARN,"cannot lock %s\n",grp_file));
closelog();
exit(E_CANT_LOCK);
SYSLOG ((LOG_WARN, "cannot lock %s",
grp_file));
closelog ();
exit (E_CANT_LOCK);
}
#ifdef SHADOWGRP
if (is_shadow && !sgr_lock()) {
fprintf(stderr, _("%s: cannot lock file %s\n"), Prog, sgr_file);
if (is_shadow && !sgr_lock ()) {
fprintf (stderr, _("%s: cannot lock file %s\n"),
Prog, sgr_file);
if (optind == argc)
SYSLOG((LOG_WARN,"cannot lock %s\n",sgr_file));
closelog();
exit(E_CANT_LOCK);
SYSLOG ((LOG_WARN, "cannot lock %s",
sgr_file));
closelog ();
exit (E_CANT_LOCK);
}
#endif
}
/*
* Open the files. Use O_RDONLY if we are in read_only mode,
* Open the files. Use O_RDONLY if we are in read_only mode,
* O_RDWR otherwise.
*/
if (!gr_open(read_only ? O_RDONLY : O_RDWR)) {
fprintf(stderr, _("%s: cannot open file %s\n"), Prog, grp_file);
if (!gr_open (read_only ? O_RDONLY : O_RDWR)) {
fprintf (stderr, _("%s: cannot open file %s\n"), Prog,
grp_file);
if (optind == argc)
SYSLOG((LOG_WARN, "cannot open %s\n", grp_file));
closelog();
exit(E_CANT_OPEN);
SYSLOG ((LOG_WARN, "cannot open %s", grp_file));
closelog ();
exit (E_CANT_OPEN);
}
#ifdef SHADOWGRP
if (is_shadow && !sgr_open(read_only ? O_RDONLY : O_RDWR)) {
fprintf(stderr, _("%s: cannot open file %s\n"), Prog, sgr_file);
if (is_shadow && !sgr_open (read_only ? O_RDONLY : O_RDWR)) {
fprintf (stderr, _("%s: cannot open file %s\n"), Prog,
sgr_file);
if (optind == argc)
SYSLOG((LOG_WARN, "cannot open %s\n", sgr_file));
closelog();
exit(E_CANT_OPEN);
SYSLOG ((LOG_WARN, "cannot open %s", sgr_file));
closelog ();
exit (E_CANT_OPEN);
}
#endif
if (sort_mode) {
gr_sort();
gr_sort ();
#ifdef SHADOWGRP
if (is_shadow)
sgr_sort();
sgr_sort ();
#endif
goto write_and_bye;
}
@@ -293,7 +287,7 @@ main(int argc, char **argv)
* Loop through the entire group file.
*/
for (gre = __gr_get_head(); gre; gre = gre->next) {
for (gre = __gr_get_head (); gre; gre = gre->next) {
/*
* Skip all NIS entries.
*/
@@ -302,42 +296,42 @@ main(int argc, char **argv)
continue;
/*
* Start with the entries that are completely corrupt.
* They have no (struct group) entry because they couldn't
* be parsed properly.
* Start with the entries that are completely corrupt. They
* have no (struct group) entry because they couldn't be
* parsed properly.
*/
if (!gre->eptr) {
/*
* Tell the user this entire line is bogus and
* ask them to delete it.
* Tell the user this entire line is bogus and ask
* them to delete it.
*/
printf(_("invalid group file entry\n"));
printf(_("delete line `%s'? "), gre->line);
printf (_("invalid group file entry\n"));
printf (_("delete line `%s'? "), gre->line);
errors++;
/*
* prompt the user to delete the entry or not
*/
if (!yes_or_no())
if (!yes_or_no ())
continue;
/*
* All group file deletions wind up here. This
* code removes the current entry from the linked
* list. When done, it skips back to the top of
* the loop to try out the next list element.
* All group file deletions wind up here. This code
* removes the current entry from the linked list.
* When done, it skips back to the top of the loop
* to try out the next list element.
*/
delete_gr:
SYSLOG((LOG_INFO, "delete group line `%s'\n",
gre->line));
delete_gr:
SYSLOG ((LOG_INFO, "delete group line `%s'",
gre->line));
deleted++;
__gr_del_entry(gre);
__gr_del_entry (gre);
continue;
}
@@ -351,7 +345,7 @@ delete_gr:
* Make sure this entry has a unique name.
*/
for (tgre = __gr_get_head(); tgre; tgre = tgre->next) {
for (tgre = __gr_get_head (); tgre; tgre = tgre->next) {
const struct group *ent = tgre->eptr;
@@ -369,7 +363,7 @@ delete_gr:
if (!ent)
continue;
if (strcmp(grp->gr_name, ent->gr_name) != 0)
if (strcmp (grp->gr_name, ent->gr_name) != 0)
continue;
/*
@@ -377,44 +371,35 @@ delete_gr:
* another and ask them to delete it.
*/
puts(_("duplicate group entry\n"));
printf(_("delete line `%s'? "), gre->line);
puts (_("duplicate group entry\n"));
printf (_("delete line `%s'? "), gre->line);
errors++;
/*
* prompt the user to delete the entry or not
*/
if (yes_or_no())
if (yes_or_no ())
goto delete_gr;
}
/*
* Check for invalid group names. --marekm
*/
if (!check_group_name(grp->gr_name)) {
if (!check_group_name (grp->gr_name)) {
errors++;
printf(_("invalid group name `%s'\n"), grp->gr_name);
}
/*
* Check for a Slackware bug. Make sure GID is not -1
* (it has special meaning for some syscalls). --marekm
*/
if (grp->gr_gid == (gid_t) -1) {
errors++;
printf(_("group %s: bad GID (%d)\n"),
grp->gr_name, (int) grp->gr_gid);
printf (_("invalid group name `%s'\n"),
grp->gr_name);
}
/*
* Workaround for a NYS libc 5.3.12 bug on RedHat 4.2 -
* groups with no members are returned as groups with
* one member "", causing grpck to fail. --marekm
* groups with no members are returned as groups with one
* member "", causing grpck to fail. --marekm
*/
if (grp->gr_mem[0] && !grp->gr_mem[1] && *(grp->gr_mem[0]) == '\0')
if (grp->gr_mem[0] && !grp->gr_mem[1]
&& *(grp->gr_mem[0]) == '\0')
grp->gr_mem[0] = (char *) 0;
/*
@@ -422,27 +407,27 @@ delete_gr:
*/
for (i = 0; grp->gr_mem[i]; i++) {
if (getpwnam(grp->gr_mem[i]))
if (getpwnam (grp->gr_mem[i]))
continue;
/*
* Can't find this user. Remove them
* Can't find this user. Remove them
* from the list.
*/
errors++;
printf(_("group %s: no user %s\n"),
printf (_("group %s: no user %s\n"),
grp->gr_name, grp->gr_mem[i]);
printf(_("delete member `%s'? "), grp->gr_mem[i]);
printf (_("delete member `%s'? "), grp->gr_mem[i]);
if (!yes_or_no())
if (!yes_or_no ())
continue;
SYSLOG((LOG_INFO, "delete member `%s' group `%s'\n",
grp->gr_mem[i], grp->gr_name));
SYSLOG ((LOG_INFO, "delete member `%s' group `%s'",
grp->gr_mem[i], grp->gr_name));
deleted++;
delete_member(grp->gr_mem, grp->gr_mem[i]);
delete_member (grp->gr_mem, grp->gr_mem[i]);
gre->changed = 1;
__gr_set_changed();
__gr_set_changed ();
}
}
@@ -454,45 +439,45 @@ delete_gr:
* Loop through the entire shadow group file.
*/
for (sge = __sgr_get_head(); sge; sge = sge->next) {
for (sge = __sgr_get_head (); sge; sge = sge->next) {
/*
* Start with the entries that are completely corrupt.
* They have no (struct sgrp) entry because they couldn't
* be parsed properly.
* Start with the entries that are completely corrupt. They
* have no (struct sgrp) entry because they couldn't be
* parsed properly.
*/
if (!sge->eptr) {
/*
* Tell the user this entire line is bogus and
* ask them to delete it.
* Tell the user this entire line is bogus and ask
* them to delete it.
*/
printf(_("invalid shadow group file entry\n"));
printf(_("delete line `%s'? "), sge->line);
printf (_("invalid shadow group file entry\n"));
printf (_("delete line `%s'? "), sge->line);
errors++;
/*
* prompt the user to delete the entry or not
*/
if (!yes_or_no())
if (!yes_or_no ())
continue;
/*
* All shadow group file deletions wind up here.
* All shadow group file deletions wind up here.
* This code removes the current entry from the
* linked list. When done, it skips back to the
* top of the loop to try out the next list element.
* linked list. When done, it skips back to the top
* of the loop to try out the next list element.
*/
delete_sg:
SYSLOG((LOG_INFO, "delete shadow line `%s'\n",
sge->line));
delete_sg:
SYSLOG ((LOG_INFO, "delete shadow line `%s'",
sge->line));
deleted++;
__sgr_del_entry(sge);
__sgr_del_entry (sge);
continue;
}
@@ -506,7 +491,7 @@ delete_sg:
* Make sure this entry has a unique name.
*/
for (tsge = __sgr_get_head(); tsge; tsge = tsge->next) {
for (tsge = __sgr_get_head (); tsge; tsge = tsge->next) {
const struct sgrp *ent = tsge->eptr;
@@ -524,7 +509,7 @@ delete_sg:
if (!ent)
continue;
if (strcmp(sgr->sg_name, ent->sg_name) != 0)
if (strcmp (sgr->sg_name, ent->sg_name) != 0)
continue;
/*
@@ -532,15 +517,15 @@ delete_sg:
* another and ask them to delete it.
*/
puts(_("duplicate shadow group entry\n"));
printf(_("delete line `%s'? "), sge->line);
puts (_("duplicate shadow group entry\n"));
printf (_("delete line `%s'? "), sge->line);
errors++;
/*
* prompt the user to delete the entry or not
*/
if (yes_or_no())
if (yes_or_no ())
goto delete_sg;
}
@@ -548,11 +533,11 @@ delete_sg:
* Make sure this entry exists in the /etc/group file.
*/
if (!gr_locate(sgr->sg_name)) {
puts(_("no matching group file entry\n"));
printf(_("delete line `%s'? "), sge->line);
if (!gr_locate (sgr->sg_name)) {
puts (_("no matching group file entry\n"));
printf (_("delete line `%s'? "), sge->line);
errors++;
if (yes_or_no())
if (yes_or_no ())
goto delete_sg;
}
@@ -561,28 +546,30 @@ delete_sg:
*/
for (i = 0; sgr->sg_adm[i]; i++) {
if (getpwnam(sgr->sg_adm[i]))
if (getpwnam (sgr->sg_adm[i]))
continue;
/*
* Can't find this user. Remove them
* Can't find this user. Remove them
* from the list.
*/
errors++;
printf(_("shadow group %s: no administrative user %s\n"),
printf (_
("shadow group %s: no administrative user %s\n"),
sgr->sg_name, sgr->sg_adm[i]);
printf(_("delete administrative member `%s'? "), sgr->sg_adm[i]);
printf (_("delete administrative member `%s'? "),
sgr->sg_adm[i]);
if (!yes_or_no())
if (!yes_or_no ())
continue;
SYSLOG((LOG_INFO,
"delete admin `%s' from shadow group `%s'\n",
sgr->sg_adm[i], sgr->sg_name));
SYSLOG ((LOG_INFO,
"delete admin `%s' from shadow group `%s'",
sgr->sg_adm[i], sgr->sg_name));
deleted++;
delete_member(sgr->sg_adm, sgr->sg_adm[i]);
delete_member (sgr->sg_adm, sgr->sg_adm[i]);
sge->changed = 1;
__sgr_set_changed();
__sgr_set_changed ();
}
/*
@@ -590,52 +577,51 @@ delete_sg:
*/
for (i = 0; sgr->sg_mem[i]; i++) {
if (getpwnam(sgr->sg_mem[i]))
if (getpwnam (sgr->sg_mem[i]))
continue;
/*
* Can't find this user. Remove them
* from the list.
* Can't find this user. Remove them from the list.
*/
errors++;
printf(_("shadow group %s: no user %s\n"),
printf (_("shadow group %s: no user %s\n"),
sgr->sg_name, sgr->sg_mem[i]);
printf(_("delete member `%s'? "), sgr->sg_mem[i]);
printf (_("delete member `%s'? "), sgr->sg_mem[i]);
if (!yes_or_no())
if (!yes_or_no ())
continue;
SYSLOG((LOG_INFO,
"delete member `%s' from shadow group `%s'\n",
sgr->sg_mem[i], sgr->sg_name));
SYSLOG ((LOG_INFO,
"delete member `%s' from shadow group `%s'",
sgr->sg_mem[i], sgr->sg_name));
deleted++;
delete_member(sgr->sg_mem, sgr->sg_mem[i]);
delete_member (sgr->sg_mem, sgr->sg_mem[i]);
sge->changed = 1;
__sgr_set_changed();
__sgr_set_changed ();
}
}
shadow_done:
#endif /* SHADOWGRP */
shadow_done:
#endif /* SHADOWGRP */
/*
* All done. If there were no deletions we can just abandon any
* All done. If there were no deletions we can just abandon any
* changes to the files.
*/
if (deleted) {
write_and_bye:
if (!gr_close()) {
fprintf(stderr, _("%s: cannot update file %s\n"),
Prog, grp_file);
exit(E_CANT_UPDATE);
write_and_bye:
if (!gr_close ()) {
fprintf (stderr, _("%s: cannot update file %s\n"),
Prog, grp_file);
exit (E_CANT_UPDATE);
}
#ifdef SHADOWGRP
if (is_shadow && !sgr_close()) {
fprintf(stderr, _("%s: cannot update file %s\n"),
Prog, sgr_file);
exit(E_CANT_UPDATE);
if (is_shadow && !sgr_close ()) {
fprintf (stderr, _("%s: cannot update file %s\n"),
Prog, sgr_file);
exit (E_CANT_UPDATE);
}
#endif
}
@@ -646,9 +632,9 @@ write_and_bye:
#ifdef SHADOWGRP
if (is_shadow)
sgr_unlock();
sgr_unlock ();
#endif
(void) gr_unlock();
(void) gr_unlock ();
/*
* Tell the user what we did and exit.
@@ -656,14 +642,15 @@ write_and_bye:
if (errors)
#ifdef NDBM
printf(deleted ?
_("%s: the files have been updated; run mkpasswd\n") :
_("%s: no changes\n"), Prog);
printf (deleted ?
_
("%s: the files have been updated; run mkpasswd\n")
: _("%s: no changes\n"), Prog);
#else
printf(deleted ?
printf (deleted ?
_("%s: the files have been updated\n") :
_("%s: no changes\n"), Prog);
#endif
exit(errors ? E_BAD_ENTRY : E_OKAY);
exit (errors ? E_BAD_ENTRY : E_OKAY);
}
+78 -72
View File
@@ -4,8 +4,8 @@
*
* Copyright (C) 1996, Marek Michalkiewicz
* <marekm@i17linuxb.ists.pwr.wroc.pl>
* This program may be freely used and distributed. If you improve
* it, please send me your changes. Thanks!
* This program may be freely used and distributed. If you improve
* it, please send me your changes. Thanks!
*/
#include <config.h>
@@ -27,26 +27,24 @@
#include "sgroupio.h"
#include "rcsid.h"
RCSID(PKG_VER "$Id: grpconv.c,v 1.11 2000/08/26 18:27:18 marekm Exp $")
RCSID (PKG_VER "$Id: grpconv.c,v 1.12 2002/01/05 15:41:43 kloczek Exp $")
static int group_locked = 0;
static int gshadow_locked = 0;
/* local function prototypes */
static void fail_exit(int);
static void fail_exit (int);
static void
fail_exit(int status)
static void fail_exit (int status)
{
if (group_locked)
gr_unlock();
gr_unlock ();
if (gshadow_locked)
sgr_unlock();
exit(status);
sgr_unlock ();
exit (status);
}
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
const struct group *gr;
struct group grent;
@@ -54,45 +52,48 @@ main(int argc, char **argv)
struct sgrp sgent;
char *Prog = argv[0];
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
if (!gr_lock()) {
fprintf(stderr, _("%s: can't lock group file\n"), Prog);
fail_exit(5);
if (!gr_lock ()) {
fprintf (stderr, _("%s: can't lock group file\n"), Prog);
fail_exit (5);
}
group_locked++;
if (!gr_open(O_RDWR)) {
fprintf(stderr, _("%s: can't open group file\n"), Prog);
fail_exit(1);
if (!gr_open (O_RDWR)) {
fprintf (stderr, _("%s: can't open group file\n"), Prog);
fail_exit (1);
}
if (!sgr_lock()) {
fprintf(stderr, _("%s: can't lock shadow group file\n"), Prog);
fail_exit(5);
if (!sgr_lock ()) {
fprintf (stderr, _("%s: can't lock shadow group file\n"),
Prog);
fail_exit (5);
}
gshadow_locked++;
if (!sgr_open(O_CREAT | O_RDWR)) {
fprintf(stderr, _("%s: can't open shadow group file\n"), Prog);
fail_exit(1);
if (!sgr_open (O_CREAT | O_RDWR)) {
fprintf (stderr, _("%s: can't open shadow group file\n"),
Prog);
fail_exit (1);
}
/*
* Remove /etc/gshadow entries for groups not in /etc/group.
*/
sgr_rewind();
while ((sg = sgr_next())) {
if (gr_locate(sg->sg_name))
sgr_rewind ();
while ((sg = sgr_next ())) {
if (gr_locate (sg->sg_name))
continue;
if (!sgr_remove(sg->sg_name)) {
if (!sgr_remove (sg->sg_name)) {
/*
* This shouldn't happen (the entry exists) but...
*/
fprintf(stderr, _("%s: can't remove shadow group %s\n"),
Prog, sg->sg_name);
fail_exit(3);
fprintf (stderr,
_("%s: can't remove shadow group %s\n"),
Prog, sg->sg_name);
fail_exit (3);
}
}
@@ -100,74 +101,79 @@ main(int argc, char **argv)
* Update shadow group passwords if non-shadow password is not "x".
* Add any missing shadow group entries.
*/
gr_rewind();
while ((gr = gr_next())) {
sg = sgr_locate(gr->gr_name);
gr_rewind ();
while ((gr = gr_next ())) {
sg = sgr_locate (gr->gr_name);
if (sg) {
#if 0 /* because of sg_mem, but see below */
if (strcmp(gr->gr_passwd, SHADOW_PASSWD_STRING) == 0)
#if 0 /* because of sg_mem, but see below */
if (strcmp (gr->gr_passwd, SHADOW_PASSWD_STRING) ==
0)
continue;
#endif
/* update existing shadow group entry */
sgent = *sg;
if (strcmp(gr->gr_passwd, SHADOW_PASSWD_STRING) != 0)
if (strcmp (gr->gr_passwd, SHADOW_PASSWD_STRING) !=
0)
sgent.sg_passwd = gr->gr_passwd;
} else {
static char *empty = 0;
/* add new shadow group entry */
memset(&sgent, 0, sizeof sgent);
memset (&sgent, 0, sizeof sgent);
sgent.sg_name = gr->gr_name;
sgent.sg_passwd = gr->gr_passwd;
sgent.sg_adm = &empty;
}
/*
* XXX - sg_mem is redundant, it is currently always a copy
* of gr_mem. Very few programs actually use sg_mem, and
* all of them are in the shadow suite... Maybe this field
* could be used for something else? Any suggestions?
* of gr_mem. Very few programs actually use sg_mem, and all
* of them are in the shadow suite. Maybe this field could
* be used for something else? Any suggestions?
*/
sgent.sg_mem = gr->gr_mem;
if (!sgr_update(&sgent)) {
fprintf(stderr,
_("%s: can't update shadow entry for %s\n"),
Prog, sgent.sg_name);
fail_exit(3);
if (!sgr_update (&sgent)) {
fprintf (stderr,
_
("%s: can't update shadow entry for %s\n"),
Prog, sgent.sg_name);
fail_exit (3);
}
/* remove password from /etc/group */
grent = *gr;
grent.gr_passwd = SHADOW_PASSWD_STRING; /* XXX warning: const */
if (!gr_update(&grent)) {
fprintf(stderr,
_("%s: can't update entry for group %s\n"),
Prog, grent.gr_name);
fail_exit(3);
grent.gr_passwd = SHADOW_PASSWD_STRING; /* XXX warning: const */
if (!gr_update (&grent)) {
fprintf (stderr,
_
("%s: can't update entry for group %s\n"),
Prog, grent.gr_name);
fail_exit (3);
}
}
if (!sgr_close()) {
fprintf(stderr, _("%s: can't update shadow group file\n"), Prog);
fail_exit(3);
if (!sgr_close ()) {
fprintf (stderr, _("%s: can't update shadow group file\n"),
Prog);
fail_exit (3);
}
if (!gr_close()) {
fprintf(stderr, _("%s: can't update group file\n"), Prog);
fail_exit(3);
if (!gr_close ()) {
fprintf (stderr, _("%s: can't update group file\n"), Prog);
fail_exit (3);
}
sgr_unlock();
gr_unlock();
sgr_unlock ();
gr_unlock ();
return 0;
}
#else /* !SHADOWGRP */
int
main(int argc, char **argv)
#else /* !SHADOWGRP */
int main (int argc, char **argv)
{
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
fprintf(stderr, _("%s: not configured for shadow group support.\n"),
argv[0]);
exit(1);
fprintf (stderr,
_("%s: not configured for shadow group support.\n"),
argv[0]);
exit (1);
}
#endif /* !SHADOWGRP */
#endif /* !SHADOWGRP */
+64 -64
View File
@@ -4,128 +4,128 @@
* Copyright (C) 1996, Michael Meskes <meskes@debian.org>
* using sources from Marek Michalkiewicz
* <marekm@i17linuxb.ists.pwr.wroc.pl>
* This program may be freely used and distributed. If you improve
* it, please send me your changes. Thanks!
* This program may be freely used and distributed. If you improve
* it, please send me your changes. Thanks!
*/
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: grpunconv.c,v 1.10 2000/08/26 18:27:18 marekm Exp $")
RCSID (PKG_VER "$Id: grpunconv.c,v 1.11 2002/01/05 15:41:43 kloczek Exp $")
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include <grp.h>
#include "prototypes.h"
#ifdef SHADOWGRP
#include "groupio.h"
#include "sgroupio.h"
static int group_locked = 0;
static int gshadow_locked = 0;
/* local function prototypes */
static void fail_exit(int);
static void fail_exit (int);
static void
fail_exit(int status)
static void fail_exit (int status)
{
if (group_locked)
gr_unlock();
gr_unlock ();
if (gshadow_locked)
sgr_unlock();
exit(status);
sgr_unlock ();
exit (status);
}
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
const struct group *gr;
struct group grent;
const struct sgrp *sg;
char *Prog = argv[0];
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
if (!sgr_file_present())
exit(0); /* no /etc/gshadow, nothing to do */
if (!sgr_file_present ())
exit (0); /* no /etc/gshadow, nothing to do */
if (!gr_lock()) {
fprintf(stderr, _("%s: can't lock group file\n"), Prog);
fail_exit(5);
if (!gr_lock ()) {
fprintf (stderr, _("%s: can't lock group file\n"), Prog);
fail_exit (5);
}
group_locked++;
if (!gr_open(O_RDWR)) {
fprintf(stderr, _("%s: can't open group file\n"), Prog);
fail_exit(1);
if (!gr_open (O_RDWR)) {
fprintf (stderr, _("%s: can't open group file\n"), Prog);
fail_exit (1);
}
if (!sgr_lock()) {
fprintf(stderr, _("%s: can't lock shadow group file\n"), Prog);
fail_exit(5);
if (!sgr_lock ()) {
fprintf (stderr, _("%s: can't lock shadow group file\n"),
Prog);
fail_exit (5);
}
gshadow_locked++;
if (!sgr_open(O_RDWR)) {
fprintf(stderr, _("%s: can't open shadow group file\n"), Prog);
fail_exit(1);
if (!sgr_open (O_RDWR)) {
fprintf (stderr, _("%s: can't open shadow group file\n"),
Prog);
fail_exit (1);
}
/*
* Update group passwords if non-shadow password is "x".
*/
gr_rewind();
while ((gr = gr_next())) {
sg = sgr_locate(gr->gr_name);
if (sg && strcmp(gr->gr_passwd, SHADOW_PASSWD_STRING) == 0) {
/* add password to /etc/group */
grent = *gr;
gr_rewind ();
while ((gr = gr_next ())) {
sg = sgr_locate (gr->gr_name);
if (sg
&& strcmp (gr->gr_passwd, SHADOW_PASSWD_STRING) == 0) {
/* add password to /etc/group */
grent = *gr;
grent.gr_passwd = sg->sg_passwd;
if (!gr_update(&grent)) {
fprintf(stderr,
_("%s: can't update entry for group %s\n"),
Prog, grent.gr_name);
fail_exit(3);
if (!gr_update (&grent)) {
fprintf (stderr,
_
("%s: can't update entry for group %s\n"),
Prog, grent.gr_name);
fail_exit (3);
}
}
}
if (!sgr_close()) {
fprintf(stderr, _("%s: can't update shadow group file\n"), Prog);
fail_exit(3);
if (!sgr_close ()) {
fprintf (stderr, _("%s: can't update shadow group file\n"),
Prog);
fail_exit (3);
}
if (!gr_close()) {
fprintf(stderr, _("%s: can't update group file\n"), Prog);
fail_exit(3);
if (!gr_close ()) {
fprintf (stderr, _("%s: can't update group file\n"), Prog);
fail_exit (3);
}
if (unlink(SGROUP_FILE) != 0) {
fprintf(stderr, _("%s: can't delete shadow group file\n"), Prog);
fail_exit(3);
if (unlink (SGROUP_FILE) != 0) {
fprintf (stderr, _("%s: can't delete shadow group file\n"),
Prog);
fail_exit (3);
}
sgr_unlock();
gr_unlock();
sgr_unlock ();
gr_unlock ();
return 0;
}
#else /* !SHADOWGRP */
int
main(int argc, char **argv)
#else /* !SHADOWGRP */
int main (int argc, char **argv)
{
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
fprintf(stderr, _("%s: not configured for shadow group support.\n"), argv[0]);
exit(1);
fprintf (stderr,
_("%s: not configured for shadow group support.\n"),
argv[0]);
exit (1);
}
#endif /* !SHADOWGRP */
#endif /* !SHADOWGRP */
+59 -66
View File
@@ -17,7 +17,7 @@
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH 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)
@@ -30,62 +30,58 @@
/*
* id - print current process user identification information
*
* Print the current process identifiers. This includes the
* UID, GID, effective-UID and effective-GID. Optionally print
* Print the current process identifiers. This includes the
* UID, GID, effective-UID and effective-GID. Optionally print
* the concurrent group set if the current system supports it.
*/
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: id.c,v 1.7 2001/09/01 04:19:16 kloczek Exp $")
RCSID (PKG_VER "$Id: id.c,v 1.10 2002/01/05 15:41:43 kloczek Exp $")
#include <sys/types.h>
#include <stdio.h>
#include <grp.h>
#include <pwd.h>
#include "defines.h"
/* local function prototypes */
static void usage(void);
static void usage (void);
static void
usage(void)
static void usage (void)
{
#ifdef HAVE_GETGROUPS
fprintf(stderr, _("usage: id [ -a ]\n"));
fprintf (stderr, _("usage: id [-a]\n"));
#else
fprintf(stderr, _("usage: id\n"));
fprintf (stderr, _("usage: id\n"));
#endif
exit(1);
exit (1);
}
/*ARGSUSED*/
int
main(int argc, char **argv)
/*ARGSUSED*/ int main (int argc, char **argv)
{
uid_t ruid, euid;
gid_t rgid, egid;
int i;
long sys_ngroups;
/*
* This block of declarations is particularly strained because of several
* different ways of doing concurrent groups. Old BSD systems used int
* for gid's, but short for the type passed to getgroups(). Newer systems
* use gid_t for everything. Some systems have a small and fixed NGROUPS,
* usually about 16 or 32. Others use bigger values.
* different ways of doing concurrent groups. Old BSD systems used int for
* gid's, but short for the type passed to getgroups(). Newer systems use
* gid_t for everything. Some systems have a small and fixed NGROUPS,
* usually about 16 or 32. Others use bigger values.
*/
#ifdef HAVE_GETGROUPS
GETGROUPS_T *groups;
int ngroups;
int aflg = 0;
int ngroups;
int aflg = 0;
#endif
struct passwd *pw;
struct group *gr;
struct passwd *pw;
struct group *gr;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
/*
* Dynamically get the maximum number of groups from system, instead
@@ -93,46 +89,46 @@ main(int argc, char **argv)
* group limit is not hard coded into the binary, so it will still
* work if the system library is recompiled.
*/
sys_ngroups=sysconf(_SC_NGROUPS_MAX);
sys_ngroups = sysconf (_SC_NGROUPS_MAX);
#ifdef HAVE_GETGROUPS
groups=malloc(sys_ngroups*sizeof(GETGROUPS_T));
groups = malloc (sys_ngroups * sizeof (GETGROUPS_T));
/*
* See if the -a flag has been given to print out the
* concurrent group set.
* See if the -a flag has been given to print out the concurrent
* group set.
*/
if (argc > 1) {
if (argc > 2 || strcmp (argv[1], "-a"))
usage();
usage ();
else
aflg = 1;
}
#else
if (argc > 1)
usage();
usage ();
#endif
ruid = getuid();
euid = geteuid();
rgid = getgid();
egid = getegid();
ruid = getuid ();
euid = geteuid ();
rgid = getgid ();
egid = getegid ();
/*
* Print out the real user ID and group ID. If the user or
* group does not exist, just give the numerical value.
* Print out the real user ID and group ID. If the user or group
* does not exist, just give the numerical value.
*/
pw = getpwuid(ruid);
pw = getpwuid (ruid);
if (pw)
printf(_("uid=%d(%s)"), (int) ruid, pw->pw_name);
printf (_("uid=%u(%s)"), ruid, pw->pw_name);
else
printf(_("uid=%d"), (int) ruid);
printf (_("uid=%u"), ruid);
gr = getgrgid(rgid);
gr = getgrgid (rgid);
if (gr)
printf(_(" gid=%d(%s)"), (int) rgid, gr->gr_name);
printf (_(" gid=%u(%s)"), rgid, gr->gr_name);
else
printf(_(" gid=%d"), (int) rgid);
printf (_(" gid=%u"), rgid);
/*
* Print out the effective user ID and group ID if they are
@@ -140,58 +136,55 @@ main(int argc, char **argv)
*/
if (ruid != euid) {
pw = getpwuid(euid);
pw = getpwuid (euid);
if (pw)
printf(_(" euid=%d(%s)"), (int) euid, pw->pw_name);
printf (_(" euid=%u(%s)"), euid, pw->pw_name);
else
printf(_(" euid=%d"), (int) euid);
printf (_(" euid=%u"), euid);
}
if (rgid != egid) {
gr = getgrgid(egid);
gr = getgrgid (egid);
if (gr)
printf(_(" egid=%d(%s)"), (int) egid, gr->gr_name);
printf (_(" egid=%u(%s)"), egid, gr->gr_name);
else
printf(_(" egid=%d"), (int) egid);
printf (_(" egid=%u"), egid);
}
#ifdef HAVE_GETGROUPS
/*
* Print out the concurrent group set if the user has requested
* it. The group numbers will be printed followed by their
* names.
* Print out the concurrent group set if the user has requested it.
* The group numbers will be printed followed by their names.
*/
if (aflg && (ngroups = getgroups (sys_ngroups, groups)) != -1) {
/*
* Start off the group message. It will be of the format
* Start off the group message. It will be of the format
*
* groups=###(aaa),###(aaa),###(aaa)
* groups=###(aaa),###(aaa),###(aaa)
*
* where "###" is a numerical value and "aaa" is the
* corresponding name for each respective numerical value.
*/
printf(_(" groups="));
printf (_(" groups="));
for (i = 0; i < ngroups; i++) {
if (i)
putchar(',');
putchar (',');
gr = getgrgid(groups[i]);
gr = getgrgid (groups[i]);
if (gr)
printf("%d(%s)", (int) groups[i], gr->gr_name);
printf ("%u(%s)", groups[i], gr->gr_name);
else
printf("%d", (int) groups[i]);
printf ("%u", groups[i]);
}
}
free(groups);
free (groups);
#endif
/*
* Finish off the line.
*/
putchar('\n');
exit(0);
/*NOTREACHED*/
}
putchar ('\n');
exit (0);
/*NOTREACHED*/}
+70 -74
View File
@@ -17,7 +17,7 @@
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH 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)
@@ -30,14 +30,12 @@
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: lastlog.c,v 1.9 2000/11/29 12:50:09 kloczek Exp $")
RCSID (PKG_VER "$Id: lastlog.c,v 1.11 2002/01/05 15:41:43 kloczek Exp $")
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <pwd.h>
#include <time.h>
#include "prototypes.h"
#include "defines.h"
#if HAVE_LASTLOG_H
@@ -45,17 +43,15 @@ RCSID(PKG_VER "$Id: lastlog.c,v 1.9 2000/11/29 12:50:09 kloczek Exp $")
#else
#include "lastlog_.h"
#endif
/*
* Needed for MkLinux DR1/2/2.1 - J.
*/
#ifndef LASTLOG_FILE
#define LASTLOG_FILE "/var/log/lastlog"
#endif
static FILE *lastlogfile; /* lastlog file stream */
static off_t user; /* one single user, specified on command line */
static int days; /* number of days to consider for print command */
static off_t user; /* one single user, specified on command line */
static int days; /* number of days to consider for print command */
static time_t seconds; /* that number of days in seconds */
static int uflg = 0; /* set if user is a valid user id */
@@ -64,79 +60,78 @@ static struct lastlog lastlog; /* scratch structure to play with ... */
static struct stat statbuf; /* fstat buffer for file size */
static struct passwd *pwent;
#include <getopt.h>
static struct option const longopts[] =
{
{"user", required_argument, 0, 'u'},
{"time", required_argument, 0, 't'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
#include <getopt.h>
static struct option const longopts[] = {
{"user", required_argument, 0, 'u'},
{"time", required_argument, 0, 't'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
extern char *optarg;
#define NOW (time ((time_t *) 0))
/* local function prototypes */
static void print(void);
static void print_one(const struct passwd *);
static void print (void);
static void print_one (const struct passwd *);
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
int c;
int c;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
if ((lastlogfile = fopen (LASTLOG_FILE,"r")) == (FILE *) 0) {
if ((lastlogfile = fopen (LASTLOG_FILE, "r")) == (FILE *) 0) {
perror (LASTLOG_FILE);
exit (1);
}
while ((c = getopt_long (argc, argv, "u:t:h", longopts, NULL)) != -1) {
while ((c =
getopt_long (argc, argv, "u:t:h", longopts, NULL)) != -1) {
switch (c) {
case 'u':
pwent = getpwnam (optarg);
if (!pwent) {
fprintf(stderr,
_("Unknown User: %s\n"),
optarg);
exit (1);
}
uflg++;
user = pwent->pw_uid;
break;
case 't':
days = atoi (optarg);
seconds = days * DAY;
tflg++;
break;
case 'h':
fprintf(stdout, _("Usage: %s [<-u|--login> login-name] [<-t|--time> days] [<-h|--help>]\n"),
argv[0]);
exit(0);
default:
fprintf(stdout, _("Usage: %s [<-u|--login> login-name] [<-t|--time> days] [<-h|--help>]\n"),
argv[0]);
exit(1);
case 'u':
pwent = getpwnam (optarg);
if (!pwent) {
fprintf (stderr,
_("Unknown User: %s\n"), optarg);
exit (1);
}
uflg++;
user = pwent->pw_uid;
break;
case 't':
days = atoi (optarg);
seconds = days * DAY;
tflg++;
break;
case 'h':
fprintf (stdout,
_
("Usage: %s [<-u|--login> login-name] [<-t|--time> days] [<-h|--help>]\n"),
argv[0]);
exit (0);
default:
fprintf (stdout,
_
("Usage: %s [<-u|--login> login-name] [<-t|--time> days] [<-h|--help>]\n"),
argv[0]);
exit (1);
}
}
print ();
fclose (lastlogfile);
exit (0);
/*NOTREACHED*/
}
/*NOTREACHED*/}
static void
print(void)
static void print (void)
{
off_t offset;
off_t offset;
if (uflg) {
offset = (unsigned long) user * sizeof lastlog;
offset = (unsigned long) user *sizeof lastlog;
if (fstat (fileno (lastlogfile), &statbuf)) {
perror(LASTLOG_FILE);
perror (LASTLOG_FILE);
return;
}
if (offset >= statbuf.st_size)
@@ -144,7 +139,7 @@ print(void)
fseek (lastlogfile, offset, SEEK_SET);
if (fread ((char *) &lastlog, sizeof lastlog, 1,
lastlogfile) == 1)
lastlogfile) == 1)
print_one (pwent);
else
perror (LASTLOG_FILE);
@@ -152,10 +147,11 @@ print(void)
setpwent ();
while ((pwent = getpwent ())) {
user = pwent->pw_uid;
offset = (unsigned long) user * sizeof lastlog;
offset = (unsigned long) user *sizeof lastlog;
fseek (lastlogfile, offset, SEEK_SET);
if (fread ((char *) &lastlog, sizeof lastlog, 1,
lastlogfile) != 1)
lastlogfile) != 1)
continue;
if (tflg && NOW - lastlog.ll_time > seconds)
@@ -166,44 +162,44 @@ print(void)
}
}
static void
print_one(const struct passwd *pw)
static void print_one (const struct passwd *pw)
{
static int once;
char *cp;
struct tm *tm;
static int once;
char *cp;
struct tm *tm;
#ifdef HAVE_STRFTIME
char ptime[80];
#endif
if (! pw)
if (!pw)
return;
if (! once) {
if (!once) {
#ifdef HAVE_LL_HOST
printf(_("Username Port From Latest\n"));
printf (_
("Username Port From Latest\n"));
#else
printf(_("Username Port Latest\n"));
printf (_("Username Port Latest\n"));
#endif
once++;
}
tm = localtime (&lastlog.ll_time);
#ifdef HAVE_STRFTIME
strftime(ptime, sizeof(ptime), "%a %b %e %H:%M:%S %z %Y", tm);
strftime (ptime, sizeof (ptime), "%a %b %e %H:%M:%S %z %Y", tm);
cp = ptime;
#else
cp = asctime (tm);
cp[24] = '\0';
#endif
if(lastlog.ll_time == (time_t) 0)
if (lastlog.ll_time == (time_t) 0)
cp = _("**Never logged in**\0");
#ifdef HAVE_LL_HOST
printf ("%-16s %-8.8s %-16.16s %s\n", pw->pw_name,
lastlog.ll_line, lastlog.ll_host, cp);
#else
printf ("%-16s\t%-8.8s %s\n", pw->pw_name,
lastlog.ll_line, cp);
printf ("%-16s\t%-8.8s %s\n", pw->pw_name, lastlog.ll_line, cp);
#endif
}
+660 -606
View File
File diff suppressed because it is too large Load Diff
+80 -84
View File
@@ -17,7 +17,7 @@
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH 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)
@@ -30,8 +30,7 @@
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: logoutd.c,v 1.17 2001/08/06 06:23:26 kloczek Exp $")
RCSID (PKG_VER "$Id: logoutd.c,v 1.18 2002/01/05 15:41:43 kloczek Exp $")
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
@@ -40,16 +39,13 @@ RCSID(PKG_VER "$Id: logoutd.c,v 1.17 2001/08/06 06:23:26 kloczek Exp $")
#include <fcntl.h>
#include "prototypes.h"
#include "defines.h"
#ifdef SVR4
#include <libgen.h>
#endif
#ifdef SVR4
#define signal sigset
#endif
static char *Prog;
static char *Prog;
#ifndef DEFAULT_HUP_MESG
#define DEFAULT_HUP_MESG "login time exceeded\r\n"
@@ -60,81 +56,80 @@ static char *Prog;
#endif
/* local function prototypes */
static int check_login(const struct utmp *);
static int check_login (const struct utmp *);
/*
* check_login - check if user (struct utmp) allowed to stay logged in
*/
static int
check_login(const struct utmp *ut)
static int check_login (const struct utmp *ut)
{
char user[sizeof(ut->ut_user) + 1];
char user[sizeof (ut->ut_user) + 1];
time_t now;
/*
* ut_user may not have the terminating NUL.
*/
strncpy(user, ut->ut_user, sizeof(ut->ut_user));
user[sizeof(ut->ut_user)] = '\0';
strncpy (user, ut->ut_user, sizeof (ut->ut_user));
user[sizeof (ut->ut_user)] = '\0';
time(&now);
time (&now);
/*
* Check if they are allowed to be logged in right now.
*/
if (!isttytime(user, ut->ut_line, now))
if (!isttytime (user, ut->ut_line, now))
return 0;
#if 0
/*
* Check for how long they are allowed to stay logged in.
* XXX - not implemented yet. Need to add a new field to
* XXX - not implemented yet. Need to add a new field to
* /etc/porttime (login time limit in minutes, or no limit,
* based on username, tty, and time of login).
*/
if (now - ut->ut_time > get_time_limit(user, ut->ut_line, ut->ut_time))
if (now - ut->ut_time >
get_time_limit (user, ut->ut_line, ut->ut_time))
return 0;
#endif
return 1;
}
static void
send_mesg_to_tty(int tty_fd)
static void send_mesg_to_tty (int tty_fd)
{
TERMIO oldt, newt;
FILE *mesg_file, *tty_file;
int c, is_tty;
tty_file = fdopen(tty_fd, "w");
tty_file = fdopen (tty_fd, "w");
if (!tty_file)
return;
is_tty = (GTTY(tty_fd, &oldt) == 0);
is_tty = (GTTY (tty_fd, &oldt) == 0);
if (is_tty) {
/* Suggested by Ivan Nejgebauar <ian@unsux.ns.ac.yu>:
set OPOST before writing the message. */
set OPOST before writing the message. */
newt = oldt;
newt.c_oflag |= OPOST;
STTY(tty_fd, &newt);
STTY (tty_fd, &newt);
}
mesg_file = fopen(HUP_MESG_FILE, "r");
mesg_file = fopen (HUP_MESG_FILE, "r");
if (mesg_file) {
while ((c = getc(mesg_file)) != EOF) {
while ((c = getc (mesg_file)) != EOF) {
if (c == '\n')
putc('\r', tty_file);
putc(c, tty_file);
putc ('\r', tty_file);
putc (c, tty_file);
}
fclose(mesg_file);
fclose (mesg_file);
} else {
fputs(DEFAULT_HUP_MESG, tty_file);
fputs (DEFAULT_HUP_MESG, tty_file);
}
fflush(tty_file);
fclose(tty_file);
fflush (tty_file);
fclose (tty_file);
if (is_tty) {
STTY(tty_fd, &oldt);
STTY (tty_fd, &oldt);
}
}
@@ -143,62 +138,60 @@ send_mesg_to_tty(int tty_fd)
* logoutd - logout daemon to enforce /etc/porttime file policy
*
* logoutd is started at system boot time and enforces the login
* time and port restrictions specified in /etc/porttime. The
* time and port restrictions specified in /etc/porttime. The
* utmp file is periodically scanned and offending users are logged
* off from the system.
*/
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
int i;
int status;
pid_t pid;
struct utmp *ut;
char user[sizeof(ut->ut_user) + 1]; /* terminating NUL */
char tty_name[sizeof(ut->ut_line) + 6]; /* /dev/ + NUL */
char user[sizeof (ut->ut_user) + 1]; /* terminating NUL */
char tty_name[sizeof (ut->ut_line) + 6]; /* /dev/ + NUL */
int tty_fd;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
#ifndef DEBUG
for (i = 0;close (i) == 0;i++)
;
for (i = 0; close (i) == 0; i++);
#ifdef HAVE_SETPGRP
#ifdef SETPGRP_VOID
setpgrp(); /* USG */
setpgrp (); /* USG */
#else
setpgrp(getpid(), getpid());
setpgrp (getpid (), getpid ());
#endif
#else /* !HAVE_SETPGRP */
setpgid(getpid(), getpid()); /* BSD || SUN || SUN4 */
#endif /* !HAVE_SETPGRP */
#else /* !HAVE_SETPGRP */
setpgid (getpid (), getpid ()); /* BSD || SUN || SUN4 */
#endif /* !HAVE_SETPGRP */
/*
* Put this process in the background.
*/
pid = fork();
pid = fork ();
if (pid > 0) {
/* parent */
exit(0);
exit (0);
} else if (pid < 0) {
/* error */
perror("fork");
exit(1);
perror ("fork");
exit (1);
}
#endif /* !DEBUG */
#endif /* !DEBUG */
/*
* Start syslogging everything
*/
Prog = Basename(argv[0]);
Prog = Basename (argv[0]);
OPENLOG(Prog);
OPENLOG (Prog);
/*
* Scan the UTMP file once per minute looking for users that
@@ -208,34 +201,34 @@ main(int argc, char **argv)
while (1) {
/*
* Attempt to re-open the utmp file. The file is only
* Attempt to re-open the utmp file. The file is only
* open while it is being used.
*/
setutent();
setutent ();
/*
* Read all of the entries in the utmp file. The entries
* Read all of the entries in the utmp file. The entries
* for login sessions will be checked to see if the user
* is permitted to be signed on at this time.
*/
while ((ut = getutent())) {
while ((ut = getutent ())) {
#ifdef USER_PROCESS
if (ut->ut_type != USER_PROCESS)
continue;
#endif
if (ut->ut_user[0] == '\0')
continue;
if (check_login(ut))
if (check_login (ut))
continue;
/*
* Put the rest of this in a child process. This
* Put the rest of this in a child process. This
* keeps the scan from waiting on other ports to die.
*/
pid = fork();
pid = fork ();
if (pid > 0) {
/* parent */
continue;
@@ -245,45 +238,49 @@ main(int argc, char **argv)
}
/* child */
if (strncmp(ut->ut_line, "/dev/", 5) != 0)
strcpy(tty_name, "/dev/");
if (strncmp (ut->ut_line, "/dev/", 5) != 0)
strcpy (tty_name, "/dev/");
else
tty_name[0] = '\0';
strcat(tty_name, ut->ut_line);
strcat (tty_name, ut->ut_line);
#ifndef O_NOCTTY
#define O_NOCTTY 0
#endif
tty_fd = open(tty_name, O_WRONLY|O_NDELAY|O_NOCTTY);
tty_fd =
open (tty_name,
O_WRONLY | O_NDELAY | O_NOCTTY);
if (tty_fd != -1) {
send_mesg_to_tty(tty_fd);
close(tty_fd);
sleep(10);
send_mesg_to_tty (tty_fd);
close (tty_fd);
sleep (10);
}
#ifdef USER_PROCESS /* USG_UTMP */
#ifdef USER_PROCESS /* USG_UTMP */
if (ut->ut_pid > 1) {
kill(- ut->ut_pid, SIGHUP);
sleep(10);
kill(- ut->ut_pid, SIGKILL);
kill (-ut->ut_pid, SIGHUP);
sleep (10);
kill (-ut->ut_pid, SIGKILL);
}
#else /* BSD || SUN || SUN4 */
#else /* BSD || SUN || SUN4 */
/*
* vhangup() the line to kill try and kill
* whatever is out there using it.
*/
if ((tty_fd = open (tty_name, O_RDONLY|O_NDELAY)) == -1)
if ((tty_fd =
open (tty_name, O_RDONLY | O_NDELAY)) == -1)
continue;
vhangup (tty_fd);
close (tty_fd);
#endif /* BSD || SUN || SUN4 */
#endif /* BSD || SUN || SUN4 */
strncpy(user, ut->ut_user, sizeof(user) - 1);
user[sizeof(user) - 1] = '\0';
strncpy (user, ut->ut_user, sizeof (user) - 1);
user[sizeof (user) - 1] = '\0';
SYSLOG((LOG_NOTICE, "logged off user `%s' on `%s'\n",
user, tty_name));
SYSLOG ((LOG_NOTICE,
"logged off user `%s' on `%s'", user,
tty_name));
/*
* This child has done all it can, drop dead.
@@ -292,17 +289,16 @@ main(int argc, char **argv)
exit (0);
}
endutent();
endutent ();
#ifndef DEBUG
sleep(60);
sleep (60);
#endif
/*
* Reap any dead babies ...
*/
while (wait (&status) != -1)
;
while (wait (&status) != -1);
}
return 1; /* not reached */
return 1; /* not reached */
}
+165 -156
View File
@@ -17,7 +17,7 @@
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH 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)
@@ -30,125 +30,111 @@
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: mkpasswd.c,v 1.7 2000/08/26 18:27:18 marekm Exp $")
RCSID (PKG_VER "$Id: mkpasswd.c,v 1.9 2002/01/05 15:41:43 kloczek Exp $")
#include <sys/stat.h>
#include "prototypes.h"
#include "defines.h"
#include <stdio.h>
#if !defined(NDBM) /*{*/
int
main(int argc, char **argv)
#if !defined(NDBM) /*{ */
int main (int argc, char **argv)
{
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
fprintf(stderr,
_("%s: no DBM database on system - no action performed\n"),
argv[0]);
fprintf (stderr,
_
("%s: no DBM database on system - no action performed\n"),
argv[0]);
return 0;
}
#else /*} defined(NDBM) {*/
#else /*} defined(NDBM) { */
#include <fcntl.h>
#include <pwd.h>
#include <ndbm.h>
#include <grp.h>
extern DBM *pw_dbm;
extern DBM *gr_dbm;
extern DBM *pw_dbm;
extern DBM *gr_dbm;
#ifdef SHADOWPWD
extern DBM *sp_dbm;
extern DBM *sp_dbm;
#endif
#ifdef SHADOWGRP
extern DBM *sg_dbm;
extern DBM *sg_dbm;
#endif
char *fgetsx();
char *fgetsx ();
char *Progname;
int vflg = 0;
int fflg = 0;
int gflg = 0;
int sflg = 0; /* -s flag -- leave in, makes code nicer */
int pflg = 0;
extern struct passwd *sgetpwent ();
extern int pw_dbm_update ();
extern struct group *sgetgrent ();
extern int gr_dbm_update ();
#ifdef SHADOWPWD
#ifdef SHADOWGRP
#define USAGE _("Usage: %s [ -vf ] [ -p|g|sp|sg ] file\n")
#else /* !SHADOWGRP */
#define USAGE _("Usage: %s [ -vf ] [ -p|g|sp ] file\n")
#endif /* SHADOWGRP */
#else /* !SHADOWPWD */
#define USAGE _("Usage: %s [ -vf ] [ -p|g ] file\n")
#endif /* SHADOWPWD */
char *Progname;
int vflg = 0;
int fflg = 0;
int gflg = 0;
int sflg = 0; /* -s flag -- leave in, makes code nicer */
int pflg = 0;
extern struct passwd *sgetpwent();
extern int pw_dbm_update();
extern struct group *sgetgrent();
extern int gr_dbm_update();
#ifdef SHADOWPWD
extern struct spwd *sgetspent();
extern int sp_dbm_update();
extern struct spwd *sgetspent ();
extern int sp_dbm_update ();
#endif
#ifdef SHADOWGRP
extern struct sgrp *sgetsgent();
extern int sg_dbm_update();
extern struct sgrp *sgetsgent ();
extern int sg_dbm_update ();
#endif
/* local function prototypes */
static void usage(void);
static void usage (void);
/*
* mkpasswd - create DBM files for /etc/passwd-like input file
*
* mkpasswd takes an an argument the name of a file in /etc/passwd format
* and creates a DBM file keyed by user ID and name. The output files have
* and creates a DBM file keyed by user ID and name. The output files have
* the same name as the input file, with .dir and .pag appended.
*
* this command will also create look-aside files for
* /etc/group, /etc/shadow, and /etc/gshadow.
*/
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
extern int optind;
extern char *optarg;
FILE *fp; /* File pointer for input file */
char *file; /* Name of input file */
char *dir; /* Name of .dir file */
char *pag; /* Name of .pag file */
char *cp; /* Temporary character pointer */
int flag; /* Flag for command line option */
int cnt = 0; /* Number of entries in database */
int longest = 0; /* Longest entry in database */
int len; /* Length of input line */
int errors = 0; /* Count of errors processing file */
char buf[BUFSIZ*8]; /* Input line from file */
struct passwd *passwd=NULL; /* Pointer to password file entry */
extern int optind;
extern char *optarg;
FILE *fp; /* File pointer for input file */
char *file; /* Name of input file */
char *dir; /* Name of .dir file */
char *pag; /* Name of .pag file */
char *cp; /* Temporary character pointer */
int flag; /* Flag for command line option */
int cnt = 0; /* Number of entries in database */
int longest = 0; /* Longest entry in database */
int len; /* Length of input line */
int errors = 0; /* Count of errors processing file */
char buf[BUFSIZ * 8]; /* Input line from file */
struct passwd *passwd = NULL; /* Pointer to password file entry */
struct group *group = NULL; /* Pointer to group file entry */
struct group *group=NULL; /* Pointer to group file entry */
#ifdef SHADOWPWD
struct spwd *shadow=NULL; /* Pointer to shadow passwd entry */
struct spwd *shadow = NULL; /* Pointer to shadow passwd entry */
#endif
#ifdef SHADOWGRP
struct sgrp *gshadow=NULL; /* Pointer to shadow group entry */
struct sgrp *gshadow = NULL; /* Pointer to shadow group entry */
#endif
DBM *dbm; /* Pointer to new NDBM files */
DBM *dbm_open(); /* Function to open NDBM files */
DBM *dbm; /* Pointer to new NDBM files */
DBM *dbm_open (); /* Function to open NDBM files */
/*
* Figure out what my name is. I will use this later ...
* Figure out what my name is. I will use this later ...
*/
Progname = Basename(argv[0]);
Progname = Basename (argv[0]);
/*
* Figure out what the flags might be ...
@@ -156,39 +142,39 @@ main(int argc, char **argv)
while ((flag = getopt (argc, argv, "fvpgs")) != EOF) {
switch (flag) {
case 'v':
vflg++;
break;
case 'f':
fflg++;
break;
case 'g':
gflg++;
case 'v':
vflg++;
break;
case 'f':
fflg++;
break;
case 'g':
gflg++;
#ifndef SHADOWGRP
if (sflg)
usage ();
if (sflg)
usage ();
#endif
if (pflg)
usage ();
if (pflg)
usage ();
break;
break;
#if defined(SHADOWPWD) || defined(SHADOWGRP)
case 's':
sflg++;
case 's':
sflg++;
#ifndef SHADOWGRP
if (gflg)
usage ();
if (gflg)
usage ();
#endif
break;
break;
#endif
case 'p':
pflg++;
if (gflg)
usage ();
case 'p':
pflg++;
if (gflg)
usage ();
break;
default:
usage();
break;
default:
usage ();
}
}
@@ -197,9 +183,9 @@ main(int argc, char **argv)
*/
#ifdef SHADOWPWD
if (! sflg && ! gflg)
if (!sflg && !gflg)
#else
if (! gflg)
if (!gflg)
#endif
pflg++;
@@ -212,8 +198,9 @@ main(int argc, char **argv)
file = argv[optind];
if (! (fp = fopen (file, "r"))) {
fprintf (stderr, _("%s: cannot open file %s\n"), Progname, file);
if (!(fp = fopen (file, "r"))) {
fprintf (stderr, _("%s: cannot open file %s\n"), Progname,
file);
exit (1);
}
@@ -241,26 +228,29 @@ main(int argc, char **argv)
* to have existed already.
*/
if (access(dir, F_OK) == 0) {
fprintf (stderr, _("%s: cannot overwrite file %s\n"), Progname, dir);
if (access (dir, F_OK) == 0) {
fprintf (stderr, _("%s: cannot overwrite file %s\n"),
Progname, dir);
exit (1);
}
if (access(pag, F_OK) == 0) {
fprintf (stderr, _("%s: cannot overwrite file %s\n"), Progname, pag);
if (access (pag, F_OK) == 0) {
fprintf (stderr, _("%s: cannot overwrite file %s\n"),
Progname, pag);
exit (1);
}
if (sflg)
umask(077);
umask (077);
else
umask(022);
umask (022);
/*
* Now the DBM database gets initialized
*/
if (! (dbm = dbm_open (file, O_RDWR|O_CREAT, 0644))) {
fprintf (stderr, _("%s: cannot open DBM files for %s\n"), Progname, file);
if (!(dbm = dbm_open (file, O_RDWR | O_CREAT, 0644))) {
fprintf (stderr, _("%s: cannot open DBM files for %s\n"),
Progname, file);
exit (1);
}
if (gflg) {
@@ -280,8 +270,8 @@ main(int argc, char **argv)
}
/*
* Read every line in the password file and convert it into a
* data structure to be put in the DBM database files.
* Read every line in the password file and convert it into a data
* structure to be put in the DBM database files.
*/
while (fgetsx (buf, BUFSIZ, fp) != NULL) {
@@ -292,8 +282,11 @@ main(int argc, char **argv)
*/
buf[sizeof buf - 1] = '\0';
if (! (cp = strchr (buf, '\n'))) {
fprintf (stderr, _("%s: the beginning with "%.16s ..." is too long\n"), Progname, buf);
if (!(cp = strchr (buf, '\n'))) {
fprintf (stderr,
_("%s: the beginning with " %
.16 s..." is too long\n"), Progname,
buf);
exit (1);
}
*cp = '\0';
@@ -301,54 +294,72 @@ main(int argc, char **argv)
#ifdef USE_NIS
/*
* Parse the password file line into a (struct passwd).
* Erroneous lines cause error messages, but that's
* all. YP lines are ignored completely.
* Parse the password file line into a (struct passwd).
* Erroneous lines cause error messages, but that's all. YP
* lines are ignored completely.
*/
if (buf[0] == '-' || buf[0] == '+')
continue;
#endif
if (! (((! sflg && pflg) && (passwd = sgetpwent (buf)))
if (!(((!sflg && pflg) && (passwd = sgetpwent (buf)))
#ifdef SHADOWPWD
|| ((sflg && pflg) && (shadow = sgetspent (buf)))
|| ((sflg && pflg) && (shadow = sgetspent (buf)))
#endif
|| ((! sflg && gflg) && (group = sgetgrent (buf)))
|| ((!sflg && gflg) && (group = sgetgrent (buf)))
#ifdef SHADOWGRP
|| ((sflg && gflg) && (gshadow = sgetsgent (buf)))
|| ((sflg && gflg) && (gshadow = sgetsgent (buf)))
#endif
)) {
fprintf (stderr, _("%s: error parsing line \"%s\"\n"), Progname, buf);
)) {
fprintf (stderr,
_("%s: error parsing line \"%s\"\n"),
Progname, buf);
errors++;
continue;
}
if (vflg) {
if (!sflg && pflg) printf (_("adding record for name "%s"\n"), passwd->pw_name);
if (!sflg && pflg)
printf (_
("adding record for name " %
s "\n"), passwd->pw_name);
#ifdef SHADOWPWD
if (sflg && pflg) printf (_("adding record for name "%s"\n"), shadow->sp_namp);
if (sflg && pflg)
printf (_
("adding record for name " %
s "\n"), shadow->sp_namp);
#endif
if (!sflg && gflg) printf (_("adding record for name "%s"\n"), group->gr_name);
if (!sflg && gflg)
printf (_
("adding record for name " %
s "\n"), group->gr_name);
#ifdef SHADOWGRP
if (sflg && gflg) printf (_("adding record for name "%s"\n"), gshadow->sg_name);
if (sflg && gflg)
printf (_
("adding record for name " %
s "\n"), gshadow->sg_name);
#endif
}
if (! sflg && pflg && ! pw_dbm_update (passwd))
fprintf (stderr, _("%s: error adding record for "%s"\n"),
Progname, passwd->pw_name);
if (!sflg && pflg && !pw_dbm_update (passwd))
fprintf (stderr,
_("%s: error adding record for " %
s "\n"), Progname, passwd->pw_name);
#ifdef SHADOWPWD
if (sflg && pflg && ! sp_dbm_update (shadow))
fprintf (stderr, _("%s: error adding record for "%s"\n"),
Progname, shadow->sp_namp);
if (sflg && pflg && !sp_dbm_update (shadow))
fprintf (stderr,
_("%s: error adding record for " %
s "\n"), Progname, shadow->sp_namp);
#endif
if (! sflg && gflg && ! gr_dbm_update (group))
fprintf (stderr, _("%s: error adding record for "%s"\n"),
Progname, group->gr_name);
if (!sflg && gflg && !gr_dbm_update (group))
fprintf (stderr,
_("%s: error adding record for " %
s "\n"), Progname, group->gr_name);
#ifdef SHADOWGRP
if (sflg && gflg && ! sg_dbm_update (gshadow))
fprintf (stderr, _("%s: error adding record for "%s"\n"),
Progname, gshadow->sg_name);
#endif /* SHADOWGRP */
if (sflg && gflg && !sg_dbm_update (gshadow))
fprintf (stderr,
_("%s: error adding record for " %
s "\n"), Progname, gshadow->sg_name);
#endif /* SHADOWGRP */
/*
* Update the longest record and record count
@@ -364,31 +375,29 @@ main(int argc, char **argv)
*/
if (vflg)
printf (_("added %d entries, longest was %d\n"), cnt, longest);
printf (_("added %d entries, longest was %d\n"), cnt,
longest);
exit (errors);
/*NOTREACHED*/
}
/*NOTREACHED*/}
/*
* usage - print error message and exit
*/
static void
usage(void)
static void usage (void)
{
#ifdef SHADOWPWD
#ifdef SHADOWGRP
fprintf (stderr, _("Usage: %s [ -vf ] [ -p|g|sp|sg ] file\n"), Progname);
#else /* !SHADOWGRP */
fprintf (stderr, _("Usage: %s [ -vf ] [ -p|g|sp ] file\n"), Progname);
#endif /* SHADOWGRP */
#else /* !SHADOWPWD */
fprintf (stderr, _("Usage: %s [ -vf ] [ -p|g ] file\n"), Progname);
#endif /* SHADOWPWD */
fprintf (stderr, _("Usage: %s [-vf] [-p|g|sp|sg] file\n"),
Progname);
#else /* !SHADOWGRP */
fprintf (stderr, _("Usage: %s [-vf] [-p|g|sp] file\n"), Progname);
#endif /* SHADOWGRP */
#else /* !SHADOWPWD */
fprintf (stderr, _("Usage: %s [-vf] [-p|g] file\n"), Progname);
#endif /* SHADOWPWD */
exit (1);
/*NOTREACHED*/
}
#endif /*} defined(NDBM) */
/*NOTREACHED*/}
#endif /*} defined(NDBM) */
+308 -202
View File
@@ -17,7 +17,7 @@
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH 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)
@@ -30,18 +30,14 @@
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: newgrp.c,v 1.17 2001/09/01 04:19:16 kloczek Exp $")
RCSID (PKG_VER "$Id: newgrp.c,v 1.21 2002/01/06 15:00:07 kloczek Exp $")
#include <stdio.h>
#include <errno.h>
#include <grp.h>
#include <pwd.h>
#include "prototypes.h"
#include "defines.h"
#include "getdef.h"
extern char **environ;
#ifdef HAVE_SETGROUPS
@@ -53,41 +49,39 @@ static char *Prog;
static int is_newgrp;
/* local function prototypes */
static void usage(void);
static void usage (void);
/*
* usage - print command usage message
*/
static void
usage(void)
static void usage (void)
{
if (is_newgrp)
fprintf (stderr, _("usage: newgrp [ - ] [ group ]\n"));
fprintf (stderr, _("usage: newgrp [-] [group]\n"));
else
fprintf (stderr, _("usage: sg group [[-c] command ]\n"));
fprintf (stderr, _("usage: sg group [[-c] command]\n"));
}
/*
* newgrp - change the invokers current real and effective group id
*/
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
int initflag = 0;
int needspasswd = 0;
int i;
int their_grp = 0;
int initflag = 0;
int needspasswd = 0;
int i;
int cflag = 0;
gid_t gid;
char *cp;
const char *cpasswd, *name, *prog;
char *group = NULL;
char *command=NULL;
char **envp = environ;
char *command = NULL;
char **envp = environ;
struct passwd *pwd;
struct group *grp;
#ifdef SHADOWPWD
struct spwd *spwd;
#endif
@@ -97,58 +91,77 @@ main(int argc, char **argv)
#if ENABLE_NLS
/* XXX - remove when gettext is safe to use in setuid programs */
sanitize_env();
sanitize_env ();
#endif
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
/*
* save my name for error messages and save my real gid incase
* of errors. if there is an error i have to exec a new login
* shell for the user since her old shell won't have fork'd to
* create the process. skip over the program name to the next
* command line argument.
* Save my name for error messages and save my real gid incase of
* errors. If there is an error i have to exec a new login shell for
* the user since her old shell won't have fork'd to create the
* process. Skip over the program name to the next command line
* argument.
*
* This historical comment, and the code itself, suggest that the
* behavior of the system/shell on which it was written differed
* significantly from the one I am using. If this process was
* started from a shell (including the login shell), it was fork'ed
* and exec'ed as a child by that shell. In order to get the user
* back to that shell, it is only necessary to exit from this
* process which terminates the child of the fork. The parent shell,
* which is blocked waiting for a signal, will then receive a
* SIGCHLD and will continue; any changes made to the process
* persona or the environment after the fork never occurred in the
* parent process.
*
* Bottom line: we want to save the name and real gid for messages,
* but we do not need to restore the previous process persona and we
* don't need to re-exec anything. -- JWP
*/
Prog = Basename(argv[0]);
is_newgrp = (strcmp(Prog, "newgrp") == 0);
OPENLOG(is_newgrp ? "newgrp" : "sg");
gid = getgid();
argc--; argv++;
Prog = Basename (argv[0]);
is_newgrp = (strcmp (Prog, "newgrp") == 0);
OPENLOG (is_newgrp ? "newgrp" : "sg");
gid = getgid ();
argc--;
argv++;
initenv();
initenv ();
pwd = get_my_pwent();
pwd = get_my_pwent ();
if (!pwd) {
fprintf (stderr, _("unknown uid: %d\n"), (int) getuid());
SYSLOG((LOG_WARN, "unknown uid %d\n", (int) getuid()));
closelog();
exit(1);
fprintf (stderr, _("unknown uid: %u\n"), getuid ());
SYSLOG ((LOG_WARN, "unknown uid %u", getuid ()));
closelog ();
exit (1);
}
name = pwd->pw_name;
/*
* Parse the command line. There are two accepted flags. The
* first is "-", which for newgrp means to re-create the entire
* environment as though a login had been performed, and "-c",
* which for sg causes a command string to be executed.
* Parse the command line. There are two accepted flags. The first
* is "-", which for newgrp means to re-create the entire
* environment as though a login had been performed, and "-c", which
* for sg causes a command string to be executed.
*
* The next argument, if present, must be the new group name.
* Any remaining remaining arguments will be used to execute a
* command as the named group. If the group name isn't present,
* I just use the login group ID of the current user.
* The next argument, if present, must be the new group name. Any
* remaining remaining arguments will be used to execute a command
* as the named group. If the group name isn't present, I just use
* the login group ID of the current user.
*
* The valid syntax are
* newgrp [ - ] [ groupid ]
* newgrp [ -l ] [ groupid ]
* sg [ - ]
* sg [ - ] groupid [ command ]
* newgrp [ - ] [ groupid ]
* newgrp [ -l ] [ groupid ]
* sg [ - ]
* sg [ - ] groupid [ command ]
*/
if (argc > 0 && (!strcmp(argv[0], "-") || !strcmp(argv[0], "-l"))) {
argc--; argv++;
if (argc > 0
&& (!strcmp (argv[0], "-") || !strcmp (argv[0], "-l"))) {
argc--;
argv++;
initflag = 1;
}
if (!is_newgrp) {
@@ -159,19 +172,22 @@ main(int argc, char **argv)
if (argc > 0 && argv[0][0] != '-') {
group = argv[0];
argc--; argv++;
argc--;
argv++;
} else {
usage ();
closelog();
closelog ();
exit (1);
}
if (argc > 0) {
/* skip -c if specified so both forms work:
"sg group -c command" (as in the man page) or
"sg group command" (as in the usage message). */
/*
* skip -c if specified so both forms work:
* "sg group -c command" (as in the man page) or
* "sg group command" (as in the usage message).
*/
if (argc > 1 && strcmp(argv[0], "-c") == 0)
if (argc > 1 && strcmp (argv[0], "-c") == 0)
command = argv[1];
else
command = argv[0];
@@ -180,9 +196,8 @@ main(int argc, char **argv)
} else {
/*
* Do the command line for "newgrp". It's just
* making sure there aren't any flags and getting
* the new group name.
* Do the command line for "newgrp". It's just making sure
* there aren't any flags and getting the new group name.
*/
if (argc > 0 && argv[0][0] == '-') {
@@ -193,61 +208,92 @@ main(int argc, char **argv)
} else {
/*
* get the group file entry for her login group id.
* get the group file entry for her login group id.
* the entry must exist, simply to be annoying.
*
* Perhaps in the past, but the default behavior now depends on the
* group entry, so it had better exist. -- JWP
*/
if (! (grp = getgrgid (pwd->pw_gid))) {
fprintf(stderr, _("unknown gid: %ld\n"),
(long) pwd->pw_gid);
SYSLOG((LOG_CRIT, "unknown gid: %ld\n",
(long) pwd->pw_gid));
if (!(grp = getgrgid (pwd->pw_gid))) {
fprintf (stderr, _("unknown gid: %lu\n"),
(unsigned long) pwd->pw_gid);
SYSLOG ((LOG_CRIT, "unknown gid: %lu",
(unsigned long) pwd->pw_gid));
goto failure;
}
} else
group = grp->gr_name;
}
}
#ifdef HAVE_SETGROUPS
/*
* get the current users groupset. the new group will be
* added to the concurrent groupset if there is room, otherwise
* you get a nasty message but at least your real and effective
* group id's are set.
* get the current users groupset. The new group will be added to
* the concurrent groupset if there is room, otherwise you get a
* nasty message but at least your real and effective group id's are
* set.
*/
/* don't use getgroups(0, 0) - it doesn't work on some systems */
i = 16;
for (;;) {
grouplist = (GETGROUPS_T *) xmalloc(i * sizeof(GETGROUPS_T));
ngroups = getgroups(i, grouplist);
grouplist =
(GETGROUPS_T *) xmalloc (i * sizeof (GETGROUPS_T));
ngroups = getgroups (i, grouplist);
if (i > ngroups && !(ngroups == -1 && errno == EINVAL))
break;
/* not enough room, so try allocating a larger buffer */
free(grouplist);
free (grouplist);
i *= 2;
}
if (ngroups < 0) {
perror("getgroups");
exit(1);
perror ("getgroups");
exit (1);
}
#endif /* HAVE_SETGROUPS */
#endif /* HAVE_SETGROUPS */
/*
* now we put her in the new group. the password file entry for
* her current user id has been gotten. if there was no optional
* group argument she will have her real and effective group id
* set to the value from her password file entry. otherwise
* we validate her access to the specified group.
* now we put her in the new group. The password file entry for her
* current user id has been gotten. If there was no optional group
* argument she will have her real and effective group id set to the
* set to the value from her password file entry.
*
* If run as newgrp, or as sg with no command, this process exec's
* an interactive subshell with the effective gid of the new group.
* If run as sg with a command, that command is exec'ed in this
* subshell. When this process terminates, either because the user
* exits, or the command completes, the parent of this process
* resumes with the current gid.
*
* If a group is explicitly specified on the command line, the
* interactive shell or command is run with that effective gid.
* Access will be denied if no entry for that group can be found in
* /etc/group. If the current user name appears in the members list
* for that group, access will be granted immediately; if not, the
* user will be challenged for that group's password. If the
* password response is incorrect, if the specified group does not
* have a password, or if that group has been locked by gpasswd -R,
* access will be denied. This is true even if the group specified
* has the user's login gid (as shown in /etc/passwd). If no group
* is explicitly specified on the command line, the effect is
* exactly the same as if a group name matching the user's login gid
* had been explicitly specified. Root, however, is never
* challenged for passwords, and is always allowed access.
*
* The previous behavior was to allow access to the login group if
* no explicit group was specified, irrespective of the group
* control file(s). This behavior is usually not desirable. A user
* wishing to return to the login group has only to exit back to the
* login shell. Generating yet more shell levels in order to
* provide a convenient "return" to the default group has the
* undesirable side effects of confusing the user, scrambling the
* history file, and consuming system resources. The default now is
* to lock out such behavior. A sys admin can allow it by explicitly
* including the user's name in the member list of the user's login
* group. -- JWP
*/
if (group == (char *) 0) {
if (! (grp = getgrgid (pwd->pw_gid))) {
fprintf (stderr, _("unknown gid: %d\n"), pwd->pw_gid);
goto failure;
}
group = grp->gr_name;
their_grp = 1;
} else if (! (grp = getgrnam (group))) {
if (!(grp = getgrnam (group))) {
fprintf (stderr, _("unknown group: %s\n"), group);
goto failure;
}
@@ -259,23 +305,19 @@ main(int argc, char **argv)
#endif
/*
* see if she is a member of this group.
* if she isn't a member, she needs to provide the
* group password. if there is no group password, she
* will be denied access anyway.
* see if she is a member of this group. If she isn't a member, she
* needs to provide the group password. If there is no group
* password, she will be denied access anyway.
*
* we also check if this is the users default group, eg.
* they aren't a member, but this is the group listed as
* the one they belong to in their pwd entry.
*/
if (!is_on_list(grp->gr_mem, name) && !their_grp)
if (!is_on_list (grp->gr_mem, name))
needspasswd = 1;
/*
* if she does not have either a shadowed password,
* or a regular password, and the group has a password,
* she needs to give the group password.
* If she does not have either a shadowed password, or a regular
* password, and the group has a password, she needs to give the
* group password.
*/
#ifdef SHADOWPWD
@@ -287,12 +329,13 @@ main(int argc, char **argv)
needspasswd = 1;
/*
* now i see about letting her into the group she requested.
* if she is the root user, i'll let her in without having to
* prompt for the password. otherwise i ask for a password
* if she flunked one of the tests above. note that she
* won't have to provide the password to her login group even
* if she isn't listed as a member.
* Now i see about letting her into the group she requested. If she
* is the root user, i'll let her in without having to prompt for
* the password. Otherwise i ask for a password if she flunked one
* of the tests above.
*
* Note that she now has to provide the password to her own group,
* unless she is listed as a member. -- JWP
*/
if (getuid () != 0 && needspasswd) {
@@ -302,116 +345,190 @@ main(int argc, char **argv)
* the decryption from the group file.
*/
if (! (cp = getpass (_("Password: "))))
if (!(cp = getpass (_("Password: "))))
goto failure;
/*
* encrypt the key she gave us using the salt from
* the password in the group file. the result of
* this encryption must match the previously
* encrypted value in the file.
* encrypt the key she gave us using the salt from the
* password in the group file. The result of this encryption
* must match the previously encrypted value in the file.
*/
cpasswd = pw_encrypt (cp, grp->gr_passwd);
strzero(cp);
strzero (cp);
if (grp->gr_passwd[0] == '\0') {
/*
* there is no password, print out "Sorry" and give up
*/
sleep(1);
/*
* there is no password, print out "Sorry" and give up
*/
sleep (1);
fputs (_("Sorry.\n"), stderr);
goto failure;
}
if (strcmp (cpasswd, grp->gr_passwd) != 0) {
SYSLOG((LOG_INFO,
"Invalid password for group `%s' from `%s'\n",
group, name));
sleep(1);
SYSLOG ((LOG_INFO,
"Invalid password for group `%s' from `%s'",
group, name));
sleep (1);
fputs (_("Sorry.\n"), stderr);
goto failure;
}
}
/*
* all successful validations pass through this point. the
* group id will be set, and the group added to the concurrent
* groupset.
* all successful validations pass through this point. The group id
* will be set, and the group added to the concurrent groupset.
*/
#ifdef USE_SYSLOG
if (getdef_bool ("SYSLOG_SG_ENAB"))
SYSLOG((LOG_INFO, "user `%s' switched to group `%s'\n",
name, group));
#endif
SYSLOG ((LOG_INFO, "user `%s' switched to group `%s'",
name, group));
if (getdef_bool ("SYSLOG_SG_ENAB")) {
char *loginname = xstrdup (getlogin ());
char *tty = xstrdup (ttyname (0));
if (loginname == NULL)
loginname = "???";
if (tty == NULL)
tty = "???";
else if (strncmp (tty, "/dev/", 5) == 0)
tty += 5;
SYSLOG ((LOG_INFO,
"user `%s' (login `%s' on %s) switched to group `%s'",
name, loginname, tty, group));
if (getdef_bool ("CLOSE_SESSIONS")) {
/*
* We want to fork and exec the new shell in the child, leaving the
* parent waiting to log the session close.
*
* The parent must ignore signals generated from the console
* (SIGINT, SIGQUIT, SIGHUP) which might make the parent terminate
* before its child. When bash is exec'ed as the subshell, it
* generates a new process group id for itself, and consequently
* only SIGHUP, which is sent to all process groups in the session,
* can reach the parent. However, since arbitrary programs can be
* specified as login shells, there is no such guarantee in general.
* For the same reason, we must also ignore stop signals generated
* from the console (SIGTSTP, SIGTTIN, and SIGTTOU) in order to
* avoid any possibility of the parent being stopped when it
* receives SIGCHLD from the terminating subshell. -- JWP
*/
pid_t child, pid;
signal (SIGINT, SIG_IGN);
signal (SIGQUIT, SIG_IGN);
signal (SIGHUP, SIG_IGN);
signal (SIGTSTP, SIG_IGN);
signal (SIGTTIN, SIG_IGN);
signal (SIGTTOU, SIG_IGN);
child = fork ();
if (child < 0) {
/* error in fork() */
fprintf (stderr, "%s: failure forking: %s",
is_newgrp ? "newgrp" : "sg",
strerror (errno));
exit (1);
} else if (child) {
/* parent - wait for child to finish, then log session close */
do {
pid = waitpid (child, NULL, 0);
} while (pid != child);
SYSLOG ((LOG_INFO,
"user `%s' (login `%s' on %s) returned to group `%s'",
name, loginname, tty,
getgrgid (gid)->gr_name));
closelog ();
exit (0);
}
/* child - restore signals to their default state */
signal (SIGINT, SIG_DFL);
signal (SIGQUIT, SIG_DFL);
signal (SIGHUP, SIG_DFL);
signal (SIGTSTP, SIG_DFL);
signal (SIGTTIN, SIG_DFL);
signal (SIGTTOU, SIG_DFL);
}
}
#endif /* USE_SYSLOG */
gid = grp->gr_gid;
#ifdef HAVE_SETGROUPS
/*
* i am going to try to add her new group id to her concurrent
* group set. if the group id is already present i'll just
* skip this part. if the group doesn't fit, i'll complain
* loudly and skip this part ...
* I am going to try to add her new group id to her concurrent group
* set. If the group id is already present i'll just skip this part.
* If the group doesn't fit, i'll complain loudly and skip this
* part.
*/
for (i = 0;i < ngroups;i++) {
for (i = 0; i < ngroups; i++) {
if (gid == grouplist[i])
break;
}
if (i == ngroups) {
if (ngroups >= sysconf(_SC_NGROUPS_MAX)) {
if (ngroups >= sysconf (_SC_NGROUPS_MAX)) {
fprintf (stderr, _("too many groups\n"));
} else {
grouplist[ngroups++] = gid;
if (setgroups(ngroups, grouplist)) {
perror("setgroups");
if (setgroups (ngroups, grouplist)) {
perror ("setgroups");
}
}
}
#endif
okay:
/*
* i set her group id either to the value she requested, or
* to the original value if the newgrp failed.
* Set the effective gid to the new group id and the effective uid
* to the real uid. For root, this also sets the real gid to the
* new group id.
*/
if (setgid(gid))
perror("setgid");
if (setgid (gid))
perror ("setgid");
if (setuid(getuid())) {
perror("setuid");
exit(1);
if (setuid (getuid ())) {
perror ("setuid");
exit (1);
}
/*
* see if the "-c" flag was used. if it was, i just create a
* shell command for her using the argument that followed the
* "-c" flag.
* See if the "-c" flag was used. If it was, i just create a shell
* command for her using the argument that followed the "-c" flag.
*/
if (cflag) {
closelog();
execl("/bin/sh", "sh", "-c", command, (char *) 0);
closelog ();
execl ("/bin/sh", "sh", "-c", command, (char *) 0);
if (errno == ENOENT) {
perror("/bin/sh");
exit(127);
perror ("/bin/sh");
exit (127);
} else {
perror("/bin/sh");
exit(126);
perror ("/bin/sh");
exit (126);
}
}
/*
* i have to get the pathname of her login shell. as a favor,
* i'll try her environment for a $SHELL value first, and
* then try the password file entry. obviously this shouldn't
* be in the restricted command directory since it could be
* used to leave the restricted environment.
* I have to get the pathname of her login shell. As a favor, i'll
* try her environment for a $SHELL value first, and then try the
* password file entry. Obviously this shouldn't be in the
* restricted command directory since it could be used to leave the
* restricted environment.
*
* Note that the following assumes this user's entry in /etc/passwd
* does not have a chroot * prefix. If it does, the * will be copied
* verbatim into the exec path. This is probably not an issue
* because if this user is operating in a chroot jail, her entry in
* the version of /etc/passwd that is accessible here should
* probably never have a chroot shell entry (but entries for other
* users might). If I have missed something, and this causes you a
* problem, try using $SHELL as a workaround; also please notify me
* at jparmele@wildbear.com -- JWP
*/
if (! initflag && (cp = getenv ("SHELL")))
if (!initflag && (cp = getenv ("SHELL")))
prog = cp;
else if (pwd->pw_shell && pwd->pw_shell[0])
prog = pwd->pw_shell;
@@ -419,11 +536,11 @@ okay:
prog = "/bin/sh";
/*
* now i try to find the basename of the login shell. this
* will become argv[0] of the spawned command.
* Now i try to find the basename of the login shell. This will
* become argv[0] of the spawned command.
*/
cp = Basename((char *) prog);
cp = Basename ((char *) prog);
#ifdef SHADOWPWD
endspent ();
@@ -435,65 +552,54 @@ okay:
endgrent ();
/*
* switch back to her home directory if i am doing login
* Switch back to her home directory if i am doing login
* initialization.
*/
if (initflag) {
if (chdir (pwd->pw_dir))
perror("chdir");
perror ("chdir");
while (*envp) {
if (strncmp (*envp, "PATH=", 5) == 0 ||
strncmp (*envp, "HOME=", 5) == 0 ||
strncmp (*envp, "SHELL=", 6) == 0 ||
strncmp (*envp, "TERM=", 5) == 0)
addenv(*envp, NULL);
strncmp (*envp, "HOME=", 5) == 0 ||
strncmp (*envp, "SHELL=", 6) == 0 ||
strncmp (*envp, "TERM=", 5) == 0)
addenv (*envp, NULL);
envp++;
}
} else {
while (*envp)
addenv(*envp++, NULL);
addenv (*envp++, NULL);
}
/* sanitize_env() removes $HOME from the environment (maybe it
shouldn't - please tell me if you are sure that $HOME can't
cause security problems) - add it from user's passwd entry.
*/
addenv("HOME", pwd->pw_dir);
/*
* Sanitize_env() removes $HOME from the environment (maybe it
* shouldn't - please tell me if you are sure that $HOME can't cause
* security problems) - add it from user's passwd entry.
*/
addenv ("HOME", pwd->pw_dir);
/*
* exec the login shell and go away. we are trying to get
* back to the previous environment which should be the
* user's login shell.
* Exec the login shell and go away. We are trying to get back to
* the previous environment which should be the user's login shell.
*/
shell(prog, initflag ? (char *)0 : cp);
/*NOTREACHED*/
failure:
/*
* this is where all failures land. the group id will not
* have been set, so the setgid() below will set me to the
* original group id i had when i was invoked.
*/
shell (prog, initflag ? (char *) 0 : cp);
/*NOTREACHED*/ failure:
/*
* only newgrp needs to re-exec the user's shell. that is
* because the shell doesn't recognize "sg", so it doesn't
* "exec" this command.
* The previous code, when run as newgrp, re-exec'ed the shell in
* the current process with the original gid on error conditions.
* See the comment above. This historical behavior now has the
* effect of creating unlogged extraneous shell layers when the
* command line has an error or there is an authentication failure.
* We now just want to exit with error status back to the parent
* process. The closelog is probably unnecessary, but it does no
* harm. -- JWP
*/
if (!is_newgrp) {
closelog();
exit (1);
}
/*
* The GID is still set to the old value, so now I can
* give the user back her shell.
*/
goto okay;
closelog ();
exit (1);
}
+217 -215
View File
@@ -17,7 +17,7 @@
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH 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)
@@ -36,8 +36,7 @@
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: newusers.c,v 1.13 2000/10/09 19:02:20 kloczek Exp $")
RCSID (PKG_VER "$Id: newusers.c,v 1.15 2002/01/05 15:41:43 kloczek Exp $")
#include <sys/types.h>
#include <sys/stat.h>
#include "prototypes.h"
@@ -46,13 +45,11 @@ RCSID(PKG_VER "$Id: newusers.c,v 1.13 2000/10/09 19:02:20 kloczek Exp $")
#include <pwd.h>
#include <grp.h>
#include <fcntl.h>
#ifdef USE_PAM
#include <security/pam_appl.h>
#include <security/pam_misc.h>
#include <pwd.h>
#endif /* USE_PAM */
#endif /* USE_PAM */
static char *Prog;
#include "getdef.h"
@@ -66,71 +63,71 @@ static int is_shadow;
#endif
/* local function prototypes */
static void usage(void);
static int add_group(const char *, const char *, gid_t *);
static int add_user(const char *, const char *, uid_t *, gid_t);
static void update_passwd(struct passwd *, const char *);
static int add_passwd(struct passwd *, const char *);
static void usage (void);
static int add_group (const char *, const char *, gid_t *);
static int add_user (const char *, const char *, uid_t *, gid_t);
static void update_passwd (struct passwd *, const char *);
static int add_passwd (struct passwd *, const char *);
/*
* usage - display usage message and exit
*/
static void
usage(void)
static void usage (void)
{
fprintf(stderr, _("Usage: %s [ input ]\n"), Prog);
exit(1);
fprintf (stderr, _("Usage: %s [input]\n"), Prog);
exit (1);
}
/*
* add_group - create a new group or add a user to an existing group
*/
static int
add_group(const char *name, const char *gid, gid_t *ngid)
static int add_group (const char *name, const char *gid, gid_t * ngid)
{
const struct passwd *pwd;
const struct group *grp;
struct group grent;
char *members[2];
int i;
struct group grent;
char *members[2];
int i;
/*
* Start by seeing if the named group already exists. This
* will be very easy to deal with if it does.
* Start by seeing if the named group already exists. This will be
* very easy to deal with if it does.
*/
if ((grp = gr_locate (gid))) {
add_member:
add_member:
grent = *grp;
*ngid = grent.gr_gid;
for (i = 0;grent.gr_mem[i] != (char *) 0;i++)
for (i = 0; grent.gr_mem[i] != (char *) 0; i++)
if (strcmp (grent.gr_mem[i], name) == 0)
return 0;
grent.gr_mem = (char **) xmalloc (sizeof (char *) * (i + 2));
memcpy (grent.gr_mem, grp->gr_mem, sizeof (char *) * (i + 2));
grent.gr_mem =
(char **) xmalloc (sizeof (char *) * (i + 2));
memcpy (grent.gr_mem, grp->gr_mem,
sizeof (char *) * (i + 2));
grent.gr_mem[i] = xstrdup (name);
grent.gr_mem[i + 1] = (char *) 0;
return ! gr_update (&grent);
return !gr_update (&grent);
}
/*
* The group did not exist, so I try to figure out what the
* GID is going to be. The gid parameter is probably "", meaning
* I figure out the GID from the password file. I want the UID
* and GID to match, unless the GID is already used.
* The group did not exist, so I try to figure out what the GID is
* going to be. The gid parameter is probably "", meaning I figure
* out the GID from the password file. I want the UID and GID to
* match, unless the GID is already used.
*/
if (gid[0] == '\0') {
i = 100;
for (pw_rewind ();(pwd = pw_next ());) {
for (pw_rewind (); (pwd = pw_next ());) {
if (pwd->pw_uid >= i)
i = pwd->pw_uid + 1;
}
for (gr_rewind ();(grp = gr_next ());) {
for (gr_rewind (); (grp = gr_next ());) {
if (grp->gr_gid == i) {
i = -1;
break;
@@ -138,55 +135,53 @@ add_member:
}
} else if (gid[0] >= '0' && gid[0] <= '9') {
/*
* The GID is a number, which means either this is a brand new
* group, or an existing group. For existing groups I just add
* myself as a member, just like I did earlier.
*/
/*
* The GID is a number, which means either this is a brand
* new group, or an existing group. For existing groups I
* just add myself as a member, just like I did earlier.
*/
i = atoi (gid);
for (gr_rewind ();(grp = gr_next ());)
for (gr_rewind (); (grp = gr_next ());)
if (grp->gr_gid == i)
goto add_member;
} else
/*
* The last alternative is that the GID is a name which is not
* already the name of an existing group, and I need to figure
* out what group ID that group name is going to have.
*/
/*
* The last alternative is that the GID is a name which is
* not already the name of an existing group, and I need to
* figure out what group ID that group name is going to
* have.
*/
i = -1;
/*
* If I don't have a group ID by now, I'll go get the
* next one.
* If I don't have a group ID by now, I'll go get the next one.
*/
if (i == -1) {
for (i = 100, gr_rewind ();(grp = gr_next ());)
for (i = 100, gr_rewind (); (grp = gr_next ());)
if (grp->gr_gid >= i)
i = grp->gr_gid + 1;
}
/*
* Now I have all of the fields required to create the new
* group.
* Now I have all of the fields required to create the new group.
*/
if (gid[0] && (gid[0] <= '0' || gid[0] >= '9'))
grent.gr_name = xstrdup(gid);
grent.gr_name = xstrdup (gid);
else
grent.gr_name = xstrdup(name);
grent.gr_name = xstrdup (name);
grent.gr_passwd = "x"; /* XXX warning: const */
grent.gr_passwd = "x"; /* XXX warning: const */
grent.gr_gid = i;
members[0] = xstrdup(name);
members[0] = xstrdup (name);
members[1] = (char *) 0;
grent.gr_mem = members;
*ngid = grent.gr_gid;
return ! gr_update (&grent);
return !gr_update (&grent);
}
/*
@@ -194,15 +189,15 @@ add_member:
*/
static int
add_user(const char *name, const char *uid, uid_t *nuid, gid_t gid)
add_user (const char *name, const char *uid, uid_t * nuid, gid_t gid)
{
const struct passwd *pwd;
struct passwd pwent;
uid_t i;
struct passwd pwent;
uid_t i;
/*
* The first guess for the UID is either the numerical UID
* that the caller provided, or the next available UID.
* The first guess for the UID is either the numerical UID that the
* caller provided, or the next available UID.
*/
if (uid[0] >= '0' && uid[0] <= '9') {
@@ -211,19 +206,19 @@ add_user(const char *name, const char *uid, uid_t *nuid, gid_t gid)
i = pwd->pw_uid;
} else {
i = 100;
for (pw_rewind ();(pwd = pw_next ());)
for (pw_rewind (); (pwd = pw_next ());)
if (pwd->pw_uid >= i)
i = pwd->pw_uid + 1;
}
/*
* I don't want to fill in the entire password structure
* members JUST YET, since there is still more data to be
* added. So, I fill in the parts that I have.
* I don't want to fill in the entire password structure members
* JUST YET, since there is still more data to be added. So, I fill
* in the parts that I have.
*/
pwent.pw_name = xstrdup(name);
pwent.pw_passwd = "x"; /* XXX warning: const */
pwent.pw_name = xstrdup (name);
pwent.pw_passwd = "x"; /* XXX warning: const */
#ifdef ATT_AGE
pwent.pw_age = "";
#endif
@@ -235,25 +230,24 @@ add_user(const char *name, const char *uid, uid_t *nuid, gid_t gid)
#endif
pwent.pw_uid = i;
pwent.pw_gid = gid;
pwent.pw_gecos = ""; /* XXX warning: const */
pwent.pw_dir = ""; /* XXX warning: const */
pwent.pw_shell = ""; /* XXX warning: const */
pwent.pw_gecos = ""; /* XXX warning: const */
pwent.pw_dir = ""; /* XXX warning: const */
pwent.pw_shell = ""; /* XXX warning: const */
*nuid = i;
return ! pw_update (&pwent);
return !pw_update (&pwent);
}
static void
update_passwd(struct passwd *pwd, const char *passwd)
static void update_passwd (struct passwd *pwd, const char *passwd)
{
pwd->pw_passwd = pw_encrypt(passwd, crypt_make_salt());
pwd->pw_passwd = pw_encrypt (passwd, crypt_make_salt ());
#ifdef ATT_AGE
if (strlen(pwd->pw_age) == 4) {
if (strlen (pwd->pw_age) == 4) {
static char newage[5];
extern char *l64a();
extern char *l64a ();
strcpy(newage, pwd->pw_age);
strcpy(newage + 2, l64a(time((time_t *) 0) / WEEK));
strcpy (newage, pwd->pw_age);
strcpy (newage + 2, l64a (time ((time_t *) 0) / WEEK));
pwd->pw_age = newage;
}
#endif
@@ -263,198 +257,199 @@ update_passwd(struct passwd *pwd, const char *passwd)
* add_passwd - add or update the encrypted password
*/
static int
add_passwd(struct passwd *pwd, const char *passwd)
static int add_passwd (struct passwd *pwd, const char *passwd)
{
#ifdef SHADOWPWD
const struct spwd *sp;
struct spwd spent;
struct spwd spent;
#endif
/*
* In the case of regular password files, this is real
* easy - pwd points to the entry in the password file.
* Shadow files are harder since there are zillions of
* things to do ...
* In the case of regular password files, this is real easy - pwd
* points to the entry in the password file. Shadow files are
* harder since there are zillions of things to do ...
*/
if (!is_shadow) {
update_passwd(pwd, passwd);
update_passwd (pwd, passwd);
return 0;
}
#ifdef SHADOWPWD
/*
* Do the first and easiest shadow file case. The user
* already exists in the shadow password file.
* Do the first and easiest shadow file case. The user already
* exists in the shadow password file.
*/
if ((sp = spw_locate (pwd->pw_name))) {
spent = *sp;
spent.sp_pwdp = pw_encrypt(passwd, crypt_make_salt());
return ! spw_update (&spent);
spent.sp_pwdp = pw_encrypt (passwd, crypt_make_salt ());
return !spw_update (&spent);
}
/*
* Pick the next easiest case - the user has an encrypted
* password which isn't equal to "x". The password was set
* to "x" earlier when the entry was created, so this user
* would have to have had the password set someplace else.
* Pick the next easiest case - the user has an encrypted password
* which isn't equal to "x". The password was set to "x" earlier
* when the entry was created, so this user would have to have had
* the password set someplace else.
*/
if (strcmp (pwd->pw_passwd, "x") != 0) {
update_passwd(pwd, passwd);
update_passwd (pwd, passwd);
return 0;
}
/*
* Now the really hard case - I need to create an entirely
* new shadow password file entry.
* Now the really hard case - I need to create an entirely new
* shadow password file entry.
*/
spent.sp_namp = pwd->pw_name;
spent.sp_pwdp = pw_encrypt(passwd, crypt_make_salt());
spent.sp_lstchg = time((time_t *) 0) / SCALE;
spent.sp_min = getdef_num("PASS_MIN_DAYS", 0);
/* 10000 is infinity this week */
spent.sp_max = getdef_num("PASS_MAX_DAYS", 10000);
spent.sp_warn = getdef_num("PASS_WARN_AGE", -1);
spent.sp_pwdp = pw_encrypt (passwd, crypt_make_salt ());
spent.sp_lstchg = time ((time_t *) 0) / SCALE;
spent.sp_min = getdef_num ("PASS_MIN_DAYS", 0);
/* 10000 is infinity this week */
spent.sp_max = getdef_num ("PASS_MAX_DAYS", 10000);
spent.sp_warn = getdef_num ("PASS_WARN_AGE", -1);
spent.sp_inact = -1;
spent.sp_expire = -1;
spent.sp_flag = -1;
return ! spw_update (&spent);
return !spw_update (&spent);
#endif
}
#ifdef USE_PAM
static struct pam_conv conv = {
misc_conv,
NULL
misc_conv,
NULL
};
#endif /* USE_PAM */
#endif /* USE_PAM */
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
char buf[BUFSIZ];
char *fields[8];
int nfields;
char *cp;
char buf[BUFSIZ];
char *fields[8];
int nfields;
char *cp;
const struct passwd *pw;
struct passwd newpw;
int errors = 0;
int line = 0;
uid_t uid;
gid_t gid;
struct passwd newpw;
int errors = 0;
int line = 0;
uid_t uid;
gid_t gid;
#ifdef USE_PAM
pam_handle_t *pamh = NULL;
struct passwd *pampw;
int retval;
#endif
Prog = Basename(argv[0]);
Prog = Basename (argv[0]);
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
#ifdef USE_PAM
retval = PAM_SUCCESS;
pampw = getpwuid(getuid());
pampw = getpwuid (getuid ());
if (pampw == NULL) {
retval = PAM_USER_UNKNOWN;
}
if (retval == PAM_SUCCESS) {
retval = pam_start("shadow", pampw->pw_name, &conv, &pamh);
retval =
pam_start ("shadow", pampw->pw_name, &conv, &pamh);
}
if (retval == PAM_SUCCESS) {
retval = pam_authenticate(pamh, 0);
retval = pam_authenticate (pamh, 0);
if (retval != PAM_SUCCESS) {
pam_end(pamh, retval);
pam_end (pamh, retval);
}
}
if (retval == PAM_SUCCESS) {
retval = pam_acct_mgmt(pamh, 0);
retval = pam_acct_mgmt (pamh, 0);
if (retval != PAM_SUCCESS) {
pam_end(pamh, retval);
pam_end (pamh, retval);
}
}
if (retval != PAM_SUCCESS) {
fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
fprintf (stderr, _("%s: PAM authentication failed\n"),
Prog);
exit (1);
}
#endif /* USE_PAM */
#endif /* USE_PAM */
if (argc > 1 && argv[1][0] == '-')
usage ();
if (argc == 2) {
if (! freopen (argv[1], "r", stdin)) {
snprintf(buf, sizeof buf, "%s: %s", Prog, argv[1]);
if (!freopen (argv[1], "r", stdin)) {
snprintf (buf, sizeof buf, "%s: %s", Prog,
argv[1]);
perror (buf);
exit (1);
}
}
/*
* Lock the password files and open them for update. This will
* bring all of the entries into memory where they may be
* searched for an modified, or new entries added. The password
* file is the key - if it gets locked, assume the others can
* be locked right away.
* Lock the password files and open them for update. This will bring
* all of the entries into memory where they may be searched for an
* modified, or new entries added. The password file is the key - if
* it gets locked, assume the others can be locked right away.
*/
if (!pw_lock()) {
if (!pw_lock ()) {
fprintf (stderr, _("%s: can't lock /etc/passwd.\n"), Prog);
exit (1);
}
#ifdef SHADOWPWD
is_shadow = spw_file_present();
is_shadow = spw_file_present ();
if ((is_shadow && !spw_lock()) || !gr_lock())
if ((is_shadow && !spw_lock ()) || !gr_lock ())
#else
if (!gr_lock())
if (!gr_lock ())
#endif
{
fprintf (stderr, _("%s: can't lock files, try again later\n"),
Prog);
fprintf (stderr,
_("%s: can't lock files, try again later\n"),
Prog);
(void) pw_unlock ();
#ifdef SHADOWPWD
if (is_shadow)
spw_unlock();
spw_unlock ();
#endif
exit (1);
}
#ifdef SHADOWPWD
if (!pw_open(O_RDWR) || (is_shadow && !spw_open(O_RDWR)) || !gr_open(O_RDWR))
if (!pw_open (O_RDWR) || (is_shadow && !spw_open (O_RDWR))
|| !gr_open (O_RDWR))
#else
if (!pw_open(O_RDWR) || !gr_open(O_RDWR))
if (!pw_open (O_RDWR) || !gr_open (O_RDWR))
#endif
{
fprintf (stderr, _("%s: can't open files\n"), Prog);
(void) pw_unlock ();
#ifdef SHADOWPWD
if (is_shadow)
spw_unlock();
spw_unlock ();
#endif
(void) gr_unlock ();
exit (1);
}
/*
* Read each line. The line has the same format as a password
* file entry, except that certain fields are not contrained to
* be numerical values. If a group ID is entered which does
* not already exist, an attempt is made to allocate the same
* group ID as the numerical user ID. Should that fail, the
* next available group ID over 100 is allocated. The pw_gid
* field will be updated with that value.
* Read each line. The line has the same format as a password file
* entry, except that certain fields are not contrained to be
* numerical values. If a group ID is entered which does not already
* exist, an attempt is made to allocate the same group ID as the
* numerical user ID. Should that fail, the next available group ID
* over 100 is allocated. The pw_gid field will be updated with that
* value.
*/
while (fgets (buf, sizeof buf, stdin) != (char *) 0) {
@@ -463,18 +458,18 @@ main(int argc, char **argv)
*cp = '\0';
} else {
fprintf (stderr, _("%s: line %d: line too long\n"),
Prog, line);
Prog, line);
errors++;
continue;
}
/*
* Break the string into fields and screw around with
* them. There MUST be 7 colon separated fields,
* although the values aren't that particular.
* Break the string into fields and screw around with them.
* There MUST be 7 colon separated fields, although the
* values aren't that particular.
*/
for (cp = buf, nfields = 0;nfields < 7;nfields++) {
for (cp = buf, nfields = 0; nfields < 7; nfields++) {
fields[nfields] = cp;
if ((cp = strchr (cp, ':')))
*cp++ = '\0';
@@ -483,41 +478,42 @@ main(int argc, char **argv)
}
if (nfields != 6) {
fprintf (stderr, _("%s: line %d: invalid line\n"),
Prog, line);
Prog, line);
continue;
}
/*
* Now the fields are processed one by one. The first
* field to be processed is the group name. A new
* group will be created if the group name is non-numeric
* and does not already exist. The named user will be
* the only member. If there is no named group to be a
* member of, the UID will be figured out and that value
* will be a candidate for a new group, if that group ID
* exists, a whole new group ID will be made up.
* Now the fields are processed one by one. The first field
* to be processed is the group name. A new group will be
* created if the group name is non-numeric and does not
* already exist. The named user will be the only member. If
* there is no named group to be a member of, the UID will
* be figured out and that value will be a candidate for a
* new group, if that group ID exists, a whole new group ID
* will be made up.
*/
if (! (pw = pw_locate (fields[0])) &&
add_group (fields[0], fields[3], &gid)) {
fprintf (stderr, _("%s: line %d: can't create GID\n"),
Prog, line);
if (!(pw = pw_locate (fields[0])) &&
add_group (fields[0], fields[3], &gid)) {
fprintf (stderr,
_("%s: line %d: can't create GID\n"),
Prog, line);
errors++;
continue;
}
/*
* Now we work on the user ID. It has to be specified
* either as a numerical value, or left blank. If it
* is a numerical value, that value will be used, otherwise
* the next available user ID is computed and used. After
* this there will at least be a (struct passwd) for the
* user.
* Now we work on the user ID. It has to be specified either
* as a numerical value, or left blank. If it is a numerical
* value, that value will be used, otherwise the next
* available user ID is computed and used. After this there
* will at least be a (struct passwd) for the user.
*/
if (! pw && add_user (fields[0], fields[2], &uid, gid)) {
fprintf (stderr, _("%s: line %d: can't create UID\n"),
Prog, line);
if (!pw && add_user (fields[0], fields[2], &uid, gid)) {
fprintf (stderr,
_("%s: line %d: can't create UID\n"),
Prog, line);
errors++;
continue;
}
@@ -527,17 +523,19 @@ main(int argc, char **argv)
* all come next.
*/
if (! (pw = pw_locate (fields[0]))) {
fprintf (stderr, _("%s: line %d: cannot find user %s\n"),
Prog, line, fields[0]);
if (!(pw = pw_locate (fields[0]))) {
fprintf (stderr,
_("%s: line %d: cannot find user %s\n"),
Prog, line, fields[0]);
errors++;
continue;
}
newpw = *pw;
if (add_passwd (&newpw, fields[1])) {
fprintf (stderr, _("%s: line %d: can't update password\n"),
Prog, line);
fprintf (stderr,
_("%s: line %d: can't update password\n"),
Prog, line);
errors++;
continue;
}
@@ -550,58 +548,63 @@ main(int argc, char **argv)
if (fields[6][0])
newpw.pw_shell = fields[6];
if (newpw.pw_dir[0] && access(newpw.pw_dir, F_OK)) {
if (newpw.pw_dir[0] && access (newpw.pw_dir, F_OK)) {
if (mkdir (newpw.pw_dir,
0777 & ~getdef_num("UMASK", 077)))
fprintf (stderr, _("%s: line %d: mkdir failed\n"),
Prog, line);
else if (chown (newpw.pw_dir,
newpw.pw_uid, newpw.pw_gid))
fprintf (stderr, _("%s: line %d: chown failed\n"),
Prog, line);
0777 & ~getdef_num ("UMASK", 077)))
fprintf (stderr,
_("%s: line %d: mkdir failed\n"),
Prog, line);
else if (chown
(newpw.pw_dir, newpw.pw_uid,
newpw.pw_gid))
fprintf (stderr,
_("%s: line %d: chown failed\n"),
Prog, line);
}
/*
* Update the password entry with the new changes made.
*/
if (! pw_update (&newpw)) {
fprintf (stderr, _("%s: line %d: can't update entry\n"),
Prog, line);
if (!pw_update (&newpw)) {
fprintf (stderr,
_("%s: line %d: can't update entry\n"),
Prog, line);
errors++;
continue;
}
}
/*
* Any detected errors will cause the entire set of changes
* to be aborted. Unlocking the password file will cause
* all of the changes to be ignored. Otherwise the file is
* closed, causing the changes to be written out all at
* once, and then unlocked afterwards.
* Any detected errors will cause the entire set of changes to be
* aborted. Unlocking the password file will cause all of the
* changes to be ignored. Otherwise the file is closed, causing the
* changes to be written out all at once, and then unlocked
* afterwards.
*/
if (errors) {
fprintf (stderr, _("%s: error detected, changes ignored\n"), Prog);
fprintf (stderr,
_("%s: error detected, changes ignored\n"), Prog);
(void) gr_unlock ();
#ifdef SHADOWPWD
if (is_shadow)
spw_unlock();
spw_unlock ();
#endif
(void) pw_unlock ();
exit (1);
}
#ifdef SHADOWPWD
if (!pw_close() || (is_shadow && !spw_close()) || !gr_close())
if (!pw_close () || (is_shadow && !spw_close ()) || !gr_close ())
#else
if (!pw_close() || ! gr_close())
if (!pw_close () || !gr_close ())
#endif
{
fprintf (stderr, _("%s: error updating files\n"), Prog);
(void) gr_unlock ();
#ifdef SHADOWPWD
if (is_shadow)
spw_unlock();
spw_unlock ();
#endif
(void) pw_unlock ();
exit (1);
@@ -609,15 +612,15 @@ main(int argc, char **argv)
(void) gr_unlock ();
#ifdef SHADOWPWD
if (is_shadow)
spw_unlock();
spw_unlock ();
#endif
(void) pw_unlock ();
#ifdef USE_PAM
if (retval == PAM_SUCCESS) {
retval = pam_chauthtok(pamh, 0);
retval = pam_chauthtok (pamh, 0);
if (retval != PAM_SUCCESS) {
pam_end(pamh, retval);
pam_end (pamh, retval);
}
}
@@ -627,9 +630,8 @@ main(int argc, char **argv)
}
if (retval == PAM_SUCCESS)
pam_end(pamh, PAM_SUCCESS);
#endif /* USE_PAM */
pam_end (pamh, PAM_SUCCESS);
#endif /* USE_PAM */
exit (0);
/*NOTREACHED*/
}
/*NOTREACHED*/}
+525 -641
View File
File diff suppressed because it is too large Load Diff
+170 -184
View File
@@ -17,7 +17,7 @@
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH 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)
@@ -30,27 +30,23 @@
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: pwck.c,v 1.16 2001/08/14 21:10:58 malekith Exp $")
RCSID (PKG_VER "$Id: pwck.c,v 1.22 2002/01/05 15:41:44 kloczek Exp $")
#include <stdio.h>
#include <fcntl.h>
#include <grp.h>
#include "prototypes.h"
#include "defines.h"
#include "chkname.h"
#include <pwd.h>
#include "commonio.h"
#include "pwio.h"
extern void __pw_del_entry(const struct commonio_entry *);
extern struct commonio_entry *__pw_get_head(void);
extern void __pw_del_entry (const struct commonio_entry *);
extern struct commonio_entry *__pw_get_head (void);
#ifdef SHADOWPWD
#include "shadowio.h"
extern void __spw_del_entry(const struct commonio_entry *);
extern struct commonio_entry *__spw_get_head(void);
extern void __spw_del_entry (const struct commonio_entry *);
extern struct commonio_entry *__spw_get_head (void);
#endif
/*
@@ -64,50 +60,43 @@ extern struct commonio_entry *__spw_get_head(void);
#define E_CANTLOCK 4
#define E_CANTUPDATE 5
/*
* Global variables
*/
extern int optind;
extern char *optarg;
/*
* Local variables
*/
static char *Prog;
static const char *pwd_file = PASSWD_FILE;
#ifdef SHADOWPWD
static const char *spw_file = SHADOW_FILE;
#endif
static int read_only = 0;
static int quiet = 0; /* don't report warnings, only errors */
static int quiet = 0; /* don't report warnings, only errors */
/* local function prototypes */
static void usage(void);
static int yes_or_no(void);
static void usage (void);
static int yes_or_no (void);
/*
* usage - print syntax message and exit
*/
static void
usage(void)
static void usage (void)
{
#ifdef SHADOWPWD
fprintf(stderr, _("Usage: %s [ -sqr ] [ passwd [ shadow ] ]\n"), Prog);
fprintf (stderr, _("Usage: %s [-q] [-r] [-s] [passwd [shadow]]\n"),
Prog);
#else
fprintf(stderr, _("Usage: %s [ -sqr ] [ passwd ]\n"), Prog);
fprintf (stderr, _("Usage: %s [-q] [-r] [-s] [passwd]\n"), Prog);
#endif
exit(E_USAGE);
exit (E_USAGE);
}
/*
* yes_or_no - get answer to question from the user
*/
static int
yes_or_no(void)
static int yes_or_no (void)
{
char buf[80];
@@ -116,7 +105,7 @@ yes_or_no(void)
*/
if (read_only) {
puts(_("No"));
puts (_("No"));
return 0;
}
@@ -124,7 +113,7 @@ yes_or_no(void)
* Get a line and see what the first character is.
*/
if (fgets(buf, sizeof buf, stdin))
if (fgets (buf, sizeof buf, stdin))
return buf[0] == 'y' || buf[0] == 'Y';
return 0;
@@ -134,40 +123,40 @@ yes_or_no(void)
* pwck - verify password file integrity
*/
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
int arg;
int errors = 0;
int deleted = 0;
struct commonio_entry *pfe, *tpfe;
struct passwd *pwd;
int sort_mode = 0;
int arg;
int errors = 0;
int deleted = 0;
struct commonio_entry *pfe, *tpfe;
struct passwd *pwd;
int sort_mode = 0;
#ifdef SHADOWPWD
struct commonio_entry *spe, *tspe;
struct spwd *spw;
int is_shadow = 0;
struct commonio_entry *spe, *tspe;
struct spwd *spw;
int is_shadow = 0;
#endif
/*
* Get my name so that I can use it to report errors.
*/
Prog = Basename(argv[0]);
Prog = Basename (argv[0]);
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
OPENLOG(Prog);
OPENLOG (Prog);
/*
* Parse the command line arguments
*/
while ((arg = getopt(argc, argv, "eqrs")) != EOF) {
while ((arg = getopt (argc, argv, "eqrs")) != EOF) {
switch (arg) {
case 'e': /* added for Debian shadow-961025-2 compatibility */
case 'e': /* added for Debian shadow-961025-2 compatibility */
case 'q':
quiet = 1;
break;
@@ -178,16 +167,16 @@ main(int argc, char **argv)
sort_mode = 1;
break;
default:
usage();
usage ();
}
}
if (sort_mode && read_only) {
fprintf(stderr, _("%s: -s and -r are incompatibile\n"),
Prog);
exit(E_USAGE);
fprintf (stderr, _("%s: -s and -r are incompatibile\n"),
Prog);
exit (E_USAGE);
}
/*
* Make certain we have the right number of arguments
*/
@@ -197,24 +186,24 @@ main(int argc, char **argv)
#else
if (optind != argc && optind + 1 != argc)
#endif
usage();
usage ();
/*
* If there are two left over filenames, use those as the
* password and shadow password filenames.
* If there are two left over filenames, use those as the password
* and shadow password filenames.
*/
if (optind != argc) {
pwd_file = argv[optind];
pw_name(pwd_file);
pw_name (pwd_file);
}
#ifdef SHADOWPWD
if (optind + 2 == argc) {
spw_file = argv[optind + 1];
spw_name(spw_file);
spw_name (spw_file);
is_shadow = 1;
} else if (optind == argc)
is_shadow = spw_file_present();
is_shadow = spw_file_present ();
#endif
/*
@@ -222,109 +211,111 @@ main(int argc, char **argv)
*/
if (!read_only) {
if (!pw_lock()) {
fprintf(stderr, _("%s: cannot lock file %s\n"),
Prog, pwd_file);
if (!pw_lock ()) {
fprintf (stderr, _("%s: cannot lock file %s\n"),
Prog, pwd_file);
if (optind == argc)
SYSLOG((LOG_WARN,"cannot lock %s\n",pwd_file));
closelog();
exit(E_CANTLOCK);
SYSLOG ((LOG_WARN, "cannot lock %s",
pwd_file));
closelog ();
exit (E_CANTLOCK);
}
#ifdef SHADOWPWD
if (is_shadow && !spw_lock()) {
fprintf(stderr, _("%s: cannot lock file %s\n"),
Prog, spw_file);
if (is_shadow && !spw_lock ()) {
fprintf (stderr, _("%s: cannot lock file %s\n"),
Prog, spw_file);
if (optind == argc)
SYSLOG((LOG_WARN,"cannot lock %s\n",spw_file));
closelog();
exit(E_CANTLOCK);
SYSLOG ((LOG_WARN, "cannot lock %s",
spw_file));
closelog ();
exit (E_CANTLOCK);
}
#endif
}
/*
* Open the files. Use O_RDONLY if we are in read_only mode,
* O_RDWR otherwise.
* Open the files. Use O_RDONLY if we are in read_only mode, O_RDWR
* otherwise.
*/
if (!pw_open(read_only ? O_RDONLY:O_RDWR)) {
fprintf(stderr, _("%s: cannot open file %s\n"),
Prog, pwd_file);
if (!pw_open (read_only ? O_RDONLY : O_RDWR)) {
fprintf (stderr, _("%s: cannot open file %s\n"),
Prog, pwd_file);
if (optind == argc)
SYSLOG((LOG_WARN, "cannot open %s\n", pwd_file));
closelog();
exit(E_CANTOPEN);
SYSLOG ((LOG_WARN, "cannot open %s", pwd_file));
closelog ();
exit (E_CANTOPEN);
}
#ifdef SHADOWPWD
if (is_shadow && !spw_open(read_only ? O_RDONLY : O_RDWR)) {
fprintf(stderr, _("%s: cannot open file %s\n"),
Prog, spw_file);
if (is_shadow && !spw_open (read_only ? O_RDONLY : O_RDWR)) {
fprintf (stderr, _("%s: cannot open file %s\n"),
Prog, spw_file);
if (optind == argc)
SYSLOG((LOG_WARN, "cannot open %s\n", spw_file));
closelog();
exit(E_CANTOPEN);
SYSLOG ((LOG_WARN, "cannot open %s", spw_file));
closelog ();
exit (E_CANTOPEN);
}
#endif
if (sort_mode) {
pw_sort();
pw_sort ();
#ifdef SHADOWPWD
if (is_shadow)
spw_sort();
spw_sort ();
#endif
goto write_and_bye;
}
/*
* Loop through the entire password file.
*/
for (pfe = __pw_get_head(); pfe; pfe = pfe->next) {
for (pfe = __pw_get_head (); pfe; pfe = pfe->next) {
/*
* If this is a NIS line, skip it. You can't "know" what
* NIS is going to do without directly asking NIS ...
* If this is a NIS line, skip it. You can't "know" what NIS
* is going to do without directly asking NIS ...
*/
if (pfe->line[0] == '+' || pfe->line[0] == '-')
continue;
/*
* Start with the entries that are completely corrupt.
* They have no (struct passwd) entry because they couldn't
* be parsed properly.
* Start with the entries that are completely corrupt. They
* have no (struct passwd) entry because they couldn't be
* parsed properly.
*/
if (!pfe->eptr) {
/*
* Tell the user this entire line is bogus and
* ask them to delete it.
* Tell the user this entire line is bogus and ask
* them to delete it.
*/
printf(_("invalid password file entry\n"));
printf(_("delete line `%s'? "), pfe->line);
printf (_("invalid password file entry\n"));
printf (_("delete line `%s'? "), pfe->line);
errors++;
/*
* prompt the user to delete the entry or not
*/
if (!yes_or_no())
if (!yes_or_no ())
continue;
/*
* All password file deletions wind up here. This
* All password file deletions wind up here. This
* code removes the current entry from the linked
* list. When done, it skips back to the top of
* the loop to try out the next list element.
* list. When done, it skips back to the top of the
* loop to try out the next list element.
*/
delete_pw:
SYSLOG((LOG_INFO, "delete passwd line `%s'\n",
pfe->line));
delete_pw:
SYSLOG ((LOG_INFO, "delete passwd line `%s'",
pfe->line));
deleted++;
__pw_del_entry(pfe);
__pw_del_entry (pfe);
continue;
}
@@ -338,7 +329,7 @@ delete_pw:
* Make sure this entry has a unique name.
*/
for (tpfe = __pw_get_head(); tpfe; tpfe = tpfe->next) {
for (tpfe = __pw_get_head (); tpfe; tpfe = tpfe->next) {
const struct passwd *ent = tpfe->eptr;
/*
@@ -355,7 +346,7 @@ delete_pw:
if (!ent)
continue;
if (strcmp(pwd->pw_name, ent->pw_name) != 0)
if (strcmp (pwd->pw_name, ent->pw_name) != 0)
continue;
/*
@@ -363,34 +354,24 @@ delete_pw:
* another and ask them to delete it.
*/
puts(_("duplicate password entry\n"));
printf(_("delete line `%s'? "), pfe->line);
puts (_("duplicate password entry\n"));
printf (_("delete line `%s'? "), pfe->line);
errors++;
/*
* prompt the user to delete the entry or not
*/
if (yes_or_no())
if (yes_or_no ())
goto delete_pw;
}
/*
* Check for invalid usernames. --marekm
*/
if (!check_user_name(pwd->pw_name)) {
printf(_("invalid user name `%s'\n"), pwd->pw_name);
errors++;
}
/*
* Check for a Slackware bug. Make sure UID is not -1
* (it has special meaning for some syscalls). --marekm
*/
if (pwd->pw_uid == (uid_t) -1) {
printf(_("user %s: bad UID (%d)\n"),
pwd->pw_name, (int) pwd->pw_uid);
if (!check_user_name (pwd->pw_name)) {
printf (_("invalid user name `%s'\n"),
pwd->pw_name);
errors++;
}
@@ -398,14 +379,14 @@ delete_pw:
* Make sure the primary group exists
*/
if (!quiet && !getgrgid(pwd->pw_gid)) {
if (!quiet && !getgrgid (pwd->pw_gid)) {
/*
* No primary group, just give a warning
*/
printf(_("user %s: no group %d\n"),
pwd->pw_name, (int) pwd->pw_gid);
printf (_("user %s: no group %u\n"),
pwd->pw_name, pwd->pw_gid);
errors++;
}
@@ -413,13 +394,14 @@ delete_pw:
* Make sure the home directory exists
*/
if (!quiet && access(pwd->pw_dir, F_OK)) {
if (!quiet && access (pwd->pw_dir, F_OK)) {
/*
* Home directory doesn't exist, give a warning
*/
printf(_("user %s: directory %s does not exist\n"),
printf (_
("user %s: directory %s does not exist\n"),
pwd->pw_name, pwd->pw_dir);
errors++;
}
@@ -428,13 +410,14 @@ delete_pw:
* Make sure the login shell is executable
*/
if (!quiet && pwd->pw_shell[0] && access(pwd->pw_shell, F_OK)) {
if (!quiet && pwd->pw_shell[0]
&& access (pwd->pw_shell, F_OK)) {
/*
* Login shell doesn't exist, give a warning
*/
printf(_("user %s: program %s does not exist\n"),
printf (_("user %s: program %s does not exist\n"),
pwd->pw_name, pwd->pw_shell);
errors++;
}
@@ -448,52 +431,52 @@ delete_pw:
* Loop through the entire shadow password file.
*/
for (spe = __spw_get_head(); spe; spe = spe->next) {
for (spe = __spw_get_head (); spe; spe = spe->next) {
/*
* If this is a NIS line, skip it. You can't "know" what
* NIS is going to do without directly asking NIS ...
* If this is a NIS line, skip it. You can't "know" what NIS
* is going to do without directly asking NIS ...
*/
if (spe->line[0] == '+' || spe->line[0] == '-')
continue;
/*
* Start with the entries that are completely corrupt.
* They have no (struct spwd) entry because they couldn't
* be parsed properly.
* Start with the entries that are completely corrupt. They
* have no (struct spwd) entry because they couldn't be
* parsed properly.
*/
if (!spe->eptr) {
/*
* Tell the user this entire line is bogus and
* ask them to delete it.
* Tell the user this entire line is bogus and ask
* them to delete it.
*/
printf(_("invalid shadow password file entry\n"));
printf(_("delete line `%s'? "), spe->line);
printf (_("invalid shadow password file entry\n"));
printf (_("delete line `%s'? "), spe->line);
errors++;
/*
* prompt the user to delete the entry or not
*/
if (!yes_or_no())
if (!yes_or_no ())
continue;
/*
* All shadow file deletions wind up here. This
* code removes the current entry from the linked
* list. When done, it skips back to the top of
* the loop to try out the next list element.
* All shadow file deletions wind up here. This code
* removes the current entry from the linked list.
* When done, it skips back to the top of the loop
* to try out the next list element.
*/
delete_spw:
SYSLOG((LOG_INFO, "delete shadow line `%s'\n",
spe->line));
delete_spw:
SYSLOG ((LOG_INFO, "delete shadow line `%s'",
spe->line));
deleted++;
__spw_del_entry(spe);
__spw_del_entry (spe);
continue;
}
@@ -507,7 +490,7 @@ delete_spw:
* Make sure this entry has a unique name.
*/
for (tspe = __spw_get_head(); tspe; tspe = tspe->next) {
for (tspe = __spw_get_head (); tspe; tspe = tspe->next) {
const struct spwd *ent = tspe->eptr;
/*
@@ -524,7 +507,7 @@ delete_spw:
if (!ent)
continue;
if (strcmp(spw->sp_namp, ent->sp_namp) != 0)
if (strcmp (spw->sp_namp, ent->sp_namp) != 0)
continue;
/*
@@ -532,15 +515,15 @@ delete_spw:
* another and ask them to delete it.
*/
puts(_("duplicate shadow password entry\n"));
printf(_("delete line `%s'? "), spe->line);
puts (_("duplicate shadow password entry\n"));
printf (_("delete line `%s'? "), spe->line);
errors++;
/*
* prompt the user to delete the entry or not
*/
if (yes_or_no())
if (yes_or_no ())
goto delete_spw;
}
@@ -549,22 +532,22 @@ delete_spw:
* file.
*/
if (!pw_locate(spw->sp_namp)) {
if (!pw_locate (spw->sp_namp)) {
/*
* Tell the user this entry has no matching
* /etc/passwd entry and ask them to delete it.
*/
puts(_("no matching password file entry\n"));
printf(_("delete line `%s'? "), spe->line);
puts (_("no matching password file entry\n"));
printf (_("delete line `%s'? "), spe->line);
errors++;
/*
* prompt the user to delete the entry or not
*/
if (yes_or_no())
if (yes_or_no ())
goto delete_spw;
}
@@ -572,36 +555,38 @@ delete_spw:
* Warn if last password change in the future. --marekm
*/
if (!quiet && spw->sp_lstchg > time((time_t *)0) / SCALE) {
printf(_("user %s: last password change in the future\n"), spw->sp_namp);
if (!quiet && spw->sp_lstchg > time ((time_t *) 0) / SCALE) {
printf (_
("user %s: last password change in the future\n"),
spw->sp_namp);
errors++;
}
}
shadow_done:
shadow_done:
#endif
/*
* All done. If there were no deletions we can just abandon any
* All done. If there were no deletions we can just abandon any
* changes to the files.
*/
if (deleted) {
write_and_bye:
if (!pw_close()) {
fprintf(stderr, _("%s: cannot update file %s\n"),
Prog, pwd_file);
SYSLOG((LOG_WARN, "cannot update %s\n", pwd_file));
closelog();
exit(E_CANTUPDATE);
write_and_bye:
if (!pw_close ()) {
fprintf (stderr, _("%s: cannot update file %s\n"),
Prog, pwd_file);
SYSLOG ((LOG_WARN, "cannot update %s", pwd_file));
closelog ();
exit (E_CANTUPDATE);
}
#ifdef SHADOWPWD
if (is_shadow && !spw_close()) {
fprintf(stderr, _("%s: cannot update file %s\n"),
Prog, spw_file);
SYSLOG((LOG_WARN, "cannot update %s\n", spw_file));
closelog();
exit(E_CANTUPDATE);
if (is_shadow && !spw_close ()) {
fprintf (stderr, _("%s: cannot update file %s\n"),
Prog, spw_file);
SYSLOG ((LOG_WARN, "cannot update %s", spw_file));
closelog ();
exit (E_CANTUPDATE);
}
#endif
}
@@ -612,9 +597,9 @@ write_and_bye:
#ifdef SHADOWPWD
if (is_shadow)
spw_unlock();
spw_unlock ();
#endif
(void) pw_unlock();
(void) pw_unlock ();
/*
* Tell the user what we did and exit.
@@ -622,15 +607,16 @@ write_and_bye:
if (errors)
#ifdef NDBM
printf(deleted ?
_("%s: the files have been updated; run mkpasswd\n") :
_("%s: no changes\n"), Prog);
printf (deleted ?
_
("%s: the files have been updated; run mkpasswd\n")
: _("%s: no changes\n"), Prog);
#else
printf(deleted ?
printf (deleted ?
_("%s: the files have been updated\n") :
_("%s: no changes\n"), Prog);
#endif
closelog();
exit(errors ? E_BADENTRY : E_OKAY);
closelog ();
exit (errors ? E_BADENTRY : E_OKAY);
}
+84 -88
View File
@@ -2,37 +2,34 @@
* pwconv - create or update /etc/shadow with information from
* /etc/passwd.
*
* It is more like SysV pwconv, slightly different from the
* original Shadow pwconv. Depends on "x" as password in
* /etc/passwd which means that the password has already been
* moved to /etc/shadow. There is no need to move /etc/npasswd
* to /etc/passwd, password files are updated using library
* It is more like SysV pwconv, slightly different from the original Shadow
* pwconv. Depends on "x" as password in /etc/passwd which means that the
* password has already been moved to /etc/shadow. There is no need to move
* /etc/npasswd to /etc/passwd, password files are updated using library
* routines with proper locking.
*
* Can be used to update /etc/shadow after adding/deleting users
* by editing /etc/passwd. There is no man page yet, but this
* program should be close to pwconv(1M) on Solaris 2.x.
* Can be used to update /etc/shadow after adding/deleting users by editing
* /etc/passwd. There is no man page yet, but this program should be close
* to pwconv(1M) on Solaris 2.x.
*
* Warning: make sure that all users have "x" as the password in
* /etc/passwd before running this program for the first time on
* a system which already has shadow passwords. Anything else
* (like "*" from old versions of the shadow suite) will replace
* the user's encrypted password in /etc/shadow.
* Warning: make sure that all users have "x" as the password in /etc/passwd
* before running this program for the first time on a system which already
* has shadow passwords. Anything else (like "*" from old versions of the
* shadow suite) will replace the user's encrypted password in /etc/shadow.
*
* Doesn't currently support pw_age information in /etc/passwd,
* and doesn't support DBM files. Add it if you need it...
* Doesn't currently support pw_age information in /etc/passwd, and doesn't
* support DBM files. Add it if you need it...
*
* Copyright (C) 1996-1997, Marek Michalkiewicz
* <marekm@i17linuxb.ists.pwr.wroc.pl>
* This program may be freely used and distributed for any purposes.
* If you improve it, please send me your changes. Thanks!
* This program may be freely used and distributed for any purposes. If you
* improve it, please send me your changes. Thanks!
*/
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: pwconv.c,v 1.11 2000/08/26 18:27:18 marekm Exp $")
RCSID (PKG_VER "$Id: pwconv.c,v 1.12 2002/01/05 15:41:44 kloczek Exp $")
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -40,18 +37,15 @@ RCSID(PKG_VER "$Id: pwconv.c,v 1.11 2000/08/26 18:27:18 marekm Exp $")
#include <time.h>
#include <unistd.h>
#include <errno.h>
#include <pwd.h>
#include "prototypes.h"
#include "defines.h"
#include "pwio.h"
#include "shadowio.h"
#include "getdef.h"
/*
* exit status values
*/
#define E_SUCCESS 0 /* success */
#define E_NOPERM 1 /* permission denied */
#define E_USAGE 2 /* bad command syntax */
@@ -59,26 +53,22 @@ RCSID(PKG_VER "$Id: pwconv.c,v 1.11 2000/08/26 18:27:18 marekm Exp $")
#define E_MISSING 4 /* unexpected failure, passwd file missing */
#define E_PWDBUSY 5 /* passwd file(s) busy */
#define E_BADENTRY 6 /* bad shadow entry */
static int
shadow_locked = 0,
passwd_locked = 0;
shadow_locked = 0, passwd_locked = 0;
/* local function prototypes */
static void fail_exit(int);
static void fail_exit (int);
static void
fail_exit(int status)
static void fail_exit (int status)
{
if (shadow_locked)
spw_unlock();
spw_unlock ();
if (passwd_locked)
pw_unlock();
exit(status);
pw_unlock ();
exit (status);
}
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
const struct passwd *pw;
struct passwd pwent;
@@ -86,102 +76,108 @@ main(int argc, char **argv)
struct spwd spent;
char *Prog = argv[0];
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
if (!pw_lock()) {
fprintf(stderr, _("%s: can't lock passwd file\n"), Prog);
fail_exit(E_PWDBUSY);
if (!pw_lock ()) {
fprintf (stderr, _("%s: can't lock passwd file\n"), Prog);
fail_exit (E_PWDBUSY);
}
passwd_locked++;
if (!pw_open(O_RDWR)) {
fprintf(stderr, _("%s: can't open passwd file\n"), Prog);
fail_exit(E_MISSING);
if (!pw_open (O_RDWR)) {
fprintf (stderr, _("%s: can't open passwd file\n"), Prog);
fail_exit (E_MISSING);
}
if (!spw_lock()) {
fprintf(stderr, _("%s: can't lock shadow file\n"), Prog);
fail_exit(E_PWDBUSY);
if (!spw_lock ()) {
fprintf (stderr, _("%s: can't lock shadow file\n"), Prog);
fail_exit (E_PWDBUSY);
}
shadow_locked++;
if (!spw_open(O_CREAT | O_RDWR)) {
fprintf(stderr, _("%s: can't open shadow file\n"), Prog);
fail_exit(E_FAILURE);
if (!spw_open (O_CREAT | O_RDWR)) {
fprintf (stderr, _("%s: can't open shadow file\n"), Prog);
fail_exit (E_FAILURE);
}
/*
* Remove /etc/shadow entries for users not in /etc/passwd.
*/
spw_rewind();
while ((sp = spw_next())) {
if (pw_locate(sp->sp_namp))
spw_rewind ();
while ((sp = spw_next ())) {
if (pw_locate (sp->sp_namp))
continue;
if (!spw_remove(sp->sp_namp)) {
if (!spw_remove (sp->sp_namp)) {
/*
* This shouldn't happen (the entry exists) but...
*/
fprintf(stderr,
_("%s: can't remove shadow entry for %s\n"),
Prog, sp->sp_namp);
fail_exit(E_FAILURE);
fprintf (stderr,
_
("%s: can't remove shadow entry for %s\n"),
Prog, sp->sp_namp);
fail_exit (E_FAILURE);
}
}
/*
* Update shadow entries which don't have "x" as pw_passwd.
* Add any missing shadow entries.
* Update shadow entries which don't have "x" as pw_passwd. Add any
* missing shadow entries.
*/
pw_rewind();
while ((pw = pw_next())) {
sp = spw_locate(pw->pw_name);
pw_rewind ();
while ((pw = pw_next ())) {
sp = spw_locate (pw->pw_name);
if (sp) {
/* do we need to update this entry? */
if (strcmp(pw->pw_passwd, SHADOW_PASSWD_STRING) == 0)
if (strcmp (pw->pw_passwd, SHADOW_PASSWD_STRING) ==
0)
continue;
/* update existing shadow entry */
spent = *sp;
} else {
/* add new shadow entry */
memset(&spent, 0, sizeof spent);
memset (&spent, 0, sizeof spent);
spent.sp_namp = pw->pw_name;
spent.sp_min = getdef_num("PASS_MIN_DAYS", -1);
spent.sp_max = getdef_num("PASS_MAX_DAYS", -1);
spent.sp_warn = getdef_num("PASS_WARN_AGE", -1);
spent.sp_min = getdef_num ("PASS_MIN_DAYS", -1);
spent.sp_max = getdef_num ("PASS_MAX_DAYS", -1);
spent.sp_warn = getdef_num ("PASS_WARN_AGE", -1);
spent.sp_inact = -1;
spent.sp_expire = -1;
spent.sp_flag = -1;
}
spent.sp_pwdp = pw->pw_passwd;
spent.sp_lstchg = time((time_t *) 0) / (24L*3600L);
if (!spw_update(&spent)) {
fprintf(stderr,
_("%s: can't update shadow entry for %s\n"),
Prog, spent.sp_namp);
fail_exit(E_FAILURE);
spent.sp_lstchg = time ((time_t *) 0) / (24L * 3600L);
if (!spw_update (&spent)) {
fprintf (stderr,
_
("%s: can't update shadow entry for %s\n"),
Prog, spent.sp_namp);
fail_exit (E_FAILURE);
}
/* remove password from /etc/passwd */
pwent = *pw;
pwent.pw_passwd = SHADOW_PASSWD_STRING; /* XXX warning: const */
if (!pw_update(&pwent)) {
fprintf(stderr,
_("%s: can't update passwd entry for %s\n"),
Prog, pwent.pw_name);
fail_exit(E_FAILURE);
pwent.pw_passwd = SHADOW_PASSWD_STRING; /* XXX warning: const */
if (!pw_update (&pwent)) {
fprintf (stderr,
_
("%s: can't update passwd entry for %s\n"),
Prog, pwent.pw_name);
fail_exit (E_FAILURE);
}
}
if (!spw_close()) {
fprintf(stderr, _("%s: can't update shadow file\n"), Prog);
fail_exit(E_FAILURE);
if (!spw_close ()) {
fprintf (stderr, _("%s: can't update shadow file\n"),
Prog);
fail_exit (E_FAILURE);
}
if (!pw_close()) {
fprintf(stderr, _("%s: can't update passwd file\n"), Prog);
fail_exit(E_FAILURE);
if (!pw_close ()) {
fprintf (stderr, _("%s: can't update passwd file\n"),
Prog);
fail_exit (E_FAILURE);
}
chmod(PASSWD_FILE "-", 0600); /* /etc/passwd- (backup file) */
spw_unlock();
pw_unlock();
exit(E_SUCCESS);
chmod (PASSWD_FILE "-", 0600); /* /etc/passwd- (backup file) */
spw_unlock ();
pw_unlock ();
exit (E_SUCCESS);
}
+80 -77
View File
@@ -17,7 +17,7 @@
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH 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)
@@ -30,8 +30,7 @@
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: pwunconv.c,v 1.10 2001/01/25 10:36:07 kloczek Exp $")
RCSID (PKG_VER "$Id: pwunconv.c,v 1.11 2002/01/05 15:41:44 kloczek Exp $")
#include "defines.h"
#include <sys/types.h>
#include <stdio.h>
@@ -41,49 +40,44 @@ RCSID(PKG_VER "$Id: pwunconv.c,v 1.10 2001/01/25 10:36:07 kloczek Exp $")
#include "prototypes.h"
#include "pwio.h"
#include "shadowio.h"
#ifndef SHADOWPWD
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
fprintf(stderr, _("%s: Shadow passwords are not configured.\n"),
argv[0]);
exit(1);
fprintf (stderr, _("%s: Shadow passwords are not configured.\n"),
argv[0]);
exit (1);
}
#else /*{*/
#else /*{ */
char *l64a ();
char *l64a ();
static int shadow_locked = 0,
passwd_locked = 0;
static int shadow_locked = 0, passwd_locked = 0;
/* local function prototypes */
static void fail_exit(int);
static void fail_exit (int);
static void
fail_exit(int status)
static void fail_exit (int status)
{
if (shadow_locked)
spw_unlock();
spw_unlock ();
if (passwd_locked)
pw_unlock();
exit(status);
pw_unlock ();
exit (status);
}
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
const struct passwd *pw;
struct passwd pwent;
const struct spwd *spwd;
#ifdef ATT_AGE
char newage[5];
char newage[5];
#endif
char *Prog = argv[0];
@@ -91,33 +85,33 @@ main(int argc, char **argv)
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
if (!spw_file_present())
if (!spw_file_present ())
/* shadow not installed, do nothing */
exit(0);
exit (0);
if (!pw_lock()) {
fprintf(stderr, _("%s: can't lock passwd file\n"), Prog);
fail_exit(5);
if (!pw_lock ()) {
fprintf (stderr, _("%s: can't lock passwd file\n"), Prog);
fail_exit (5);
}
passwd_locked++;
if (!pw_open(O_RDWR)) {
fprintf(stderr, _("%s: can't open passwd file\n"), Prog);
fail_exit(1);
if (!pw_open (O_RDWR)) {
fprintf (stderr, _("%s: can't open passwd file\n"), Prog);
fail_exit (1);
}
if (!spw_lock()) {
fprintf(stderr, _("%s: can't open shadow file\n"), Prog);
fail_exit(5);
if (!spw_lock ()) {
fprintf (stderr, _("%s: can't open shadow file\n"), Prog);
fail_exit (5);
}
shadow_locked++;
if (!spw_open(O_RDWR)) {
fprintf(stderr, _("%s: can't open shadow file\n"), Prog);
fail_exit(1);
if (!spw_open (O_RDWR)) {
fprintf (stderr, _("%s: can't open shadow file\n"), Prog);
fail_exit (1);
}
pw_rewind();
while ((pw = pw_next())) {
if (!(spwd = spw_locate(pw->pw_name)))
pw_rewind ();
while ((pw = pw_next ())) {
if (!(spwd = spw_locate (pw->pw_name)))
continue;
pwent = *pw;
@@ -125,63 +119,72 @@ main(int argc, char **argv)
/*
* Update password if non-shadow is "x".
*/
if (strcmp(pw->pw_passwd, SHADOW_PASSWD_STRING) == 0)
if (strcmp (pw->pw_passwd, SHADOW_PASSWD_STRING) == 0)
pwent.pw_passwd = spwd->sp_pwdp;
/*
* Password aging works differently in the two different systems.
* With shadow password files you apparently must have some aging
* information. The maxweeks or minweeks may not map exactly.
* In pwconv we set max == 10000, which is about 30 years. Here
* we have to undo that kludge. So, if maxdays == 10000, no aging
* information is put into the new file. Otherwise, the days are
* converted to weeks and so on.
* Password aging works differently in the two different
* systems. With shadow password files you apparently must
* have some aging information. The maxweeks or minweeks
* may not map exactly. In pwconv we set max == 10000,
* which is about 30 years. Here we have to undo that
* kludge. So, if maxdays == 10000, no aging information is
* put into the new file. Otherwise, the days are converted
* to weeks and so on.
*/
#ifdef ATT_AGE
if (spwd->sp_max > (63*WEEK/SCALE) && spwd->sp_max < 10000)
spwd->sp_max = (63*WEEK/SCALE); /* 10000 is infinity */
if (spwd->sp_max > (63 * WEEK / SCALE)
&& spwd->sp_max < 10000)
spwd->sp_max = (63 * WEEK / SCALE); /* 10000 is infinity */
if (spwd->sp_min >= 0 && spwd->sp_min <= 63*7 &&
spwd->sp_max >= 0 && spwd->sp_max <= 63*7) {
if (spwd->sp_min >= 0 && spwd->sp_min <= 63 * 7 &&
spwd->sp_max >= 0 && spwd->sp_max <= 63 * 7) {
if (spwd->sp_lstchg == -1)
spwd->sp_lstchg = 0;
spwd->sp_max /= WEEK/SCALE; /* turn it into weeks */
spwd->sp_min /= WEEK/SCALE;
spwd->sp_lstchg /= WEEK/SCALE;
spwd->sp_max /= WEEK / SCALE; /* turn it into weeks */
spwd->sp_min /= WEEK / SCALE;
spwd->sp_lstchg /= WEEK / SCALE;
strncpy (newage, l64a (spwd->sp_lstchg * (64L*64L) +
spwd->sp_min * (64L) + spwd->sp_max), 5);
strncpy (newage,
l64a (spwd->sp_lstchg * (64L * 64L) +
spwd->sp_min * (64L) +
spwd->sp_max), 5);
pwent.pw_age = newage;
} else
pwent.pw_age = "";
#endif /* ATT_AGE */
if (!pw_update(&pwent)) {
fprintf(stderr,
_("%s: can't update entry for user %s\n"),
Prog, pwent.pw_name);
fail_exit(3);
#endif /* ATT_AGE */
if (!pw_update (&pwent)) {
fprintf (stderr,
_("%s: can't update entry for user %s\n"),
Prog, pwent.pw_name);
fail_exit (3);
}
}
if (!spw_close()) {
fprintf(stderr, _("%s: can't update shadow password file\n"), Prog);
fail_exit(3);
if (!spw_close ()) {
fprintf (stderr,
_("%s: can't update shadow password file\n"),
Prog);
fail_exit (3);
}
if (!pw_close()) {
fprintf(stderr, _("%s: can't update password file\n"), Prog);
fail_exit(3);
if (!pw_close ()) {
fprintf (stderr, _("%s: can't update password file\n"),
Prog);
fail_exit (3);
}
if (unlink(SHADOW) != 0) {
fprintf(stderr, _("%s: can't delete shadow password file\n"), Prog);
fail_exit(3);
if (unlink (SHADOW) != 0) {
fprintf (stderr,
_("%s: can't delete shadow password file\n"),
Prog);
fail_exit (3);
}
spw_unlock();
pw_unlock();
spw_unlock ();
pw_unlock ();
return 0;
}
#endif
+283 -273
View File
@@ -17,7 +17,7 @@
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH 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)
@@ -30,17 +30,14 @@
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: su.c,v 1.18 2001/06/28 20:47:06 kloczek Exp $")
RCSID (PKG_VER "$Id: su.c,v 1.21 2002/01/05 15:41:44 kloczek Exp $")
#include <sys/types.h>
#include <stdio.h>
#ifdef USE_PAM
#include "pam_defs.h"
static const struct pam_conv conv = {
misc_conv,
NULL
misc_conv,
NULL
};
static pam_handle_t *pamh = NULL;
@@ -69,7 +66,7 @@ static char oldname[BUFSIZ];
static char *Prog;
struct passwd pwent;
struct passwd pwent;
/*
* External identifiers
@@ -84,144 +81,141 @@ extern char **environ;
#ifndef USE_PAM
static RETSIGTYPE die(int);
static int iswheel(const char *);
static RETSIGTYPE die (int);
static int iswheel (const char *);
/*
* die - set or reset termio modes.
*
* die() is called before processing begins. signal() is then
* called with die() as the signal handler. If signal later
* calls die() with a signal number, the terminal modes are
* then reset.
* die() is called before processing begins. signal() is then called
* with die() as the signal handler. If signal later calls die() with a
* signal number, the terminal modes are then reset.
*/
static RETSIGTYPE
die(int killed)
static RETSIGTYPE die (int killed)
{
static TERMIO sgtty;
if (killed)
STTY(0, &sgtty);
STTY (0, &sgtty);
else
GTTY(0, &sgtty);
GTTY (0, &sgtty);
if (killed) {
closelog();
exit(killed);
closelog ();
exit (killed);
}
}
static int
iswheel(const char *username)
static int iswheel (const char *username)
{
struct group *grp;
grp = getgrgid(0);
grp = getgrgid (0);
if (!grp || !grp->gr_mem)
return 0;
return is_on_list(grp->gr_mem, username);
return is_on_list (grp->gr_mem, username);
}
#endif /* !USE_PAM */
#endif /* !USE_PAM */
static void
su_failure(const char *tty)
static void su_failure (const char *tty)
{
sulog(tty, 0, oldname, name); /* log failed attempt */
sulog (tty, 0, oldname, name); /* log failed attempt */
#ifdef USE_SYSLOG
if (getdef_bool("SYSLOG_SU_ENAB"))
SYSLOG((pwent.pw_uid ? LOG_INFO:LOG_NOTICE,
"- %s %s-%s\n", tty,
oldname[0] ? oldname:"???",
name[0] ? name:"???"));
closelog();
if (getdef_bool ("SYSLOG_SU_ENAB"))
SYSLOG ((pwent.pw_uid ? LOG_INFO : LOG_NOTICE,
"- %s %s-%s", tty,
oldname[0] ? oldname : "???",
name[0] ? name : "???"));
closelog ();
#endif
puts(_("Sorry."));
exit(1);
puts (_("Sorry."));
exit (1);
}
/*
* su - switch user id
*
* su changes the user's ids to the values for the specified user.
* if no new user name is specified, "root" is used by default.
* su changes the user's ids to the values for the specified user. if
* no new user name is specified, "root" is used by default.
*
* The only valid option is a "-" character, which is interpreted
* as requiring a new login session to be simulated.
* The only valid option is a "-" character, which is interpreted as
* requiring a new login session to be simulated.
*
* Any additional arguments are passed to the user's shell. In
* particular, the argument "-c" will cause the next argument to
* be interpreted as a command by the common shell programs.
* Any additional arguments are passed to the user's shell. In
* particular, the argument "-c" will cause the next argument to be
* interpreted as a command by the common shell programs.
*/
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
char *cp;
const char *tty = 0; /* Name of tty SU is run from */
int doshell = 0;
int fakelogin = 0;
int amroot = 0;
char *cp;
const char *tty = 0; /* Name of tty SU is run from */
int doshell = 0;
int fakelogin = 0;
int amroot = 0;
uid_t my_uid;
struct passwd *pw = 0;
char **envp = environ;
struct passwd *pw = 0;
char **envp = environ;
#ifdef USE_PAM
int ret;
#else /* !USE_PAM */
RETSIGTYPE (*oldsig)();
#else /* !USE_PAM */
RETSIGTYPE (*oldsig) ();
int is_console = 0;
#ifdef SHADOWPWD
struct spwd *spwd = 0;
struct spwd *spwd = 0;
#endif
#ifdef SU_ACCESS
char *oldpass;
#endif
#endif /* !USE_PAM */
#endif /* !USE_PAM */
sanitize_env();
sanitize_env ();
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
/*
* Get the program name. The program name is used as a
* prefix to most error messages.
* Get the program name. The program name is used as a prefix to
* most error messages.
*/
Prog = Basename(argv[0]);
Prog = Basename (argv[0]);
OPENLOG("su");
OPENLOG ("su");
initenv();
initenv ();
my_uid = getuid();
my_uid = getuid ();
amroot = (my_uid == 0);
/*
* Get the tty name. Entries will be logged indicating that
* the user tried to change to the named new user from the
* current terminal.
* Get the tty name. Entries will be logged indicating that the user
* tried to change to the named new user from the current terminal.
*/
if (isatty(0) && (cp = ttyname(0))) {
if (isatty (0) && (cp = ttyname (0))) {
if (strncmp (cp, "/dev/", 5) == 0)
tty = cp + 5;
else
tty = cp;
#ifndef USE_PAM
is_console = console(tty);
is_console = console (tty);
#endif
} else {
/*
* Be more paranoid, like su from SimplePAMApps. --marekm
*/
if (!amroot) {
fprintf(stderr, _("%s: must be run from a terminal\n"),
Prog);
exit(1);
fprintf (stderr,
_("%s: must be run from a terminal\n"),
Prog);
exit (1);
}
tty = "???";
}
@@ -230,65 +224,67 @@ main(int argc, char **argv)
* Process the command line arguments.
*/
argc--; argv++; /* shift out command name */
argc--;
argv++; /* shift out command name */
if (argc > 0 && strcmp(argv[0], "-") == 0) {
if (argc > 0 && strcmp (argv[0], "-") == 0) {
fakelogin = 1;
argc--; argv++; /* shift ... */
argc--;
argv++; /* shift ... */
}
/*
* If a new login is being set up, the old environment will
* be ignored and a new one created later on.
* If a new login is being set up, the old environment will be
* ignored and a new one created later on.
*/
if (fakelogin) {
if ((cp=getdef_str("ENV_TZ")))
addenv(*cp == '/' ? tz(cp) : cp, NULL);
/*
* The clock frequency will be reset to the login value if required
*/
if ((cp=getdef_str("ENV_HZ")))
addenv(cp, NULL); /* set the default $HZ, if one */
/*
* The terminal type will be left alone if it is present in the
* environment already.
*/
if ((cp = getdef_str ("ENV_TZ")))
addenv (*cp == '/' ? tz (cp) : cp, NULL);
/*
* The clock frequency will be reset to the login value if required
*/
if ((cp = getdef_str ("ENV_HZ")))
addenv (cp, NULL); /* set the default $HZ, if one */
/*
* The terminal type will be left alone if it is present in
* the environment already.
*/
if ((cp = getenv ("TERM")))
addenv("TERM", cp);
addenv ("TERM", cp);
} else {
while (*envp)
addenv(*envp++, NULL);
addenv (*envp++, NULL);
}
/*
* The next argument must be either a user ID, or some flag to
* a subshell. Pretty sticky since you can't have an argument
* which doesn't start with a "-" unless you specify the new user
* name. Any remaining arguments will be passed to the user's
* login shell.
* The next argument must be either a user ID, or some flag to a
* subshell. Pretty sticky since you can't have an argument which
* doesn't start with a "-" unless you specify the new user name.
* Any remaining arguments will be passed to the user's login shell.
*/
if (argc > 0 && argv[0][0] != '-') {
STRFCPY(name, argv[0]); /* use this login id */
argc--; argv++; /* shift ... */
STRFCPY (name, argv[0]); /* use this login id */
argc--;
argv++; /* shift ... */
}
if (! name[0]) /* use default user ID */
if (!name[0]) /* use default user ID */
(void) strcpy (name, "root");
doshell = argc == 0; /* any arguments remaining? */
doshell = argc == 0; /* any arguments remaining? */
/*
* Get the user's real name. The current UID is used to determine
* who has executed su. That user ID must exist.
* Get the user's real name. The current UID is used to determine
* who has executed su. That user ID must exist.
*/
pw = get_my_pwent();
pw = get_my_pwent ();
if (!pw) {
SYSLOG((LOG_CRIT, "Unknown UID: %d\n", (int) my_uid));
su_failure(tty);
SYSLOG ((LOG_CRIT, "Unknown UID: %u", my_uid));
su_failure (tty);
}
STRFCPY(oldname, pw->pw_name);
STRFCPY (oldname, pw->pw_name);
#ifndef USE_PAM
#ifdef SU_ACCESS
@@ -297,129 +293,141 @@ main(int argc, char **argv)
* -- chris
*/
#ifdef SHADOWPWD
if ((spwd = getspnam(oldname)))
if ((spwd = getspnam (oldname)))
pw->pw_passwd = spwd->sp_pwdp;
#endif
oldpass = xstrdup(pw->pw_passwd);
#endif /* SU_ACCESS */
oldpass = xstrdup (pw->pw_passwd);
#endif /* SU_ACCESS */
#else /* USE_PAM */
ret = pam_start("su", name, &conv, &pamh);
#else /* USE_PAM */
ret = pam_start ("su", name, &conv, &pamh);
if (ret != PAM_SUCCESS) {
SYSLOG((LOG_ERR, "pam_start: error %d\n", ret);
fprintf(stderr, _("%s: pam_start: error %d\n"), Prog, ret));
exit(1);
SYSLOG ((LOG_ERR, "pam_start: error %d", ret);
fprintf (stderr, _("%s: pam_start: error %d\n"),
Prog, ret));
exit (1);
}
ret = pam_set_item(pamh, PAM_TTY, (const void *) tty);
ret = pam_set_item (pamh, PAM_TTY, (const void *) tty);
if (ret == PAM_SUCCESS)
ret = pam_set_item(pamh, PAM_RUSER, (const void *) oldname);
ret =
pam_set_item (pamh, PAM_RUSER, (const void *) oldname);
if (ret != PAM_SUCCESS) {
SYSLOG((LOG_ERR, "pam_set_item: %s\n", pam_strerror(pamh, ret)));
fprintf(stderr, "%s: %s\n", Prog, pam_strerror(pamh, ret));
pam_end(pamh, ret);
exit(1);
SYSLOG ((LOG_ERR, "pam_set_item: %s",
pam_strerror (pamh, ret)));
fprintf (stderr, "%s: %s\n", Prog,
pam_strerror (pamh, ret));
pam_end (pamh, ret);
exit (1);
}
#endif /* USE_PAM */
#endif /* USE_PAM */
top:
top:
/*
* This is the common point for validating a user whose name
* is known. It will be reached either by normal processing,
* or if the user is to be logged into a subsystem root.
* This is the common point for validating a user whose name is
* known. It will be reached either by normal processing, or if the
* user is to be logged into a subsystem root.
*
* The password file entries for the user is gotten and the
* account validated.
* The password file entries for the user is gotten and the account
* validated.
*/
if (!(pw = getpwnam(name))) {
if (!(pw = getpwnam (name))) {
(void) fprintf (stderr, _("Unknown id: %s\n"), name);
closelog();
exit(1);
closelog ();
exit (1);
}
#ifndef USE_PAM
#ifdef SHADOWPWD
spwd = NULL;
if (strcmp(pw->pw_passwd, SHADOW_PASSWD_STRING) == 0 && (spwd = getspnam(name)))
if (strcmp (pw->pw_passwd, SHADOW_PASSWD_STRING) == 0
&& (spwd = getspnam (name)))
pw->pw_passwd = spwd->sp_pwdp;
#endif
#endif /* !USE_PAM */
#endif /* !USE_PAM */
pwent = *pw;
#ifndef USE_PAM
/*
* BSD systems only allow "wheel" to SU to root. USG systems
* don't, so we make this a configurable option.
* BSD systems only allow "wheel" to SU to root. USG systems don't,
* so we make this a configurable option.
*/
/* The original Shadow 3.3.2 did this differently. Do it like BSD:
- check for uid 0 instead of name "root" - there are systems
with several root accounts under different names,
- check the contents of /etc/group instead of the current group
set (you must be listed as a member, GID 0 is not sufficient).
In addition to this traditional feature, we now have complete
su access control (allow, deny, no password, own password).
Thanks to Chris Evans <lady0110@sable.ox.ac.uk>. */
/* The original Shadow 3.3.2 did this differently. Do it like BSD:
*
* - check for uid 0 instead of name "root" - there are systems with
* several root accounts under different names,
*
* - check the contents of /etc/group instead of the current group
* set (you must be listed as a member, GID 0 is not sufficient).
*
* In addition to this traditional feature, we now have complete su
* access control (allow, deny, no password, own password). Thanks
* to Chris Evans <lady0110@sable.ox.ac.uk>.
*/
if (!amroot) {
if (pwent.pw_uid == 0 && getdef_bool("SU_WHEEL_ONLY")
&& !iswheel(oldname)) {
fprintf(stderr, _("You are not authorized to su %s\n"), name);
exit(1);
if (pwent.pw_uid == 0 && getdef_bool ("SU_WHEEL_ONLY")
&& !iswheel (oldname)) {
fprintf (stderr,
_("You are not authorized to su %s\n"),
name);
exit (1);
}
#ifdef SU_ACCESS
switch (check_su_auth(oldname, name)) {
case 0: /* normal su, require target user's password */
switch (check_su_auth (oldname, name)) {
case 0: /* normal su, require target user's password */
break;
case 1: /* require no password */
pwent.pw_passwd = ""; /* XXX warning: const */
case 1: /* require no password */
pwent.pw_passwd = ""; /* XXX warning: const */
break;
case 2: /* require own password */
puts(_("(Enter your own password.)"));
case 2: /* require own password */
puts (_("(Enter your own password.)"));
pwent.pw_passwd = oldpass;
break;
default: /* access denied (-1) or unexpected value */
fprintf(stderr, _("You are not authorized to su %s\n"), name);
exit(1);
default: /* access denied (-1) or unexpected value */
fprintf (stderr,
_("You are not authorized to su %s\n"),
name);
exit (1);
}
#endif /* SU_ACCESS */
#endif /* SU_ACCESS */
}
#endif /* !USE_PAM */
#endif /* !USE_PAM */
/*
* Set the default shell.
*/
if (pwent.pw_shell[0] == '\0')
pwent.pw_shell = "/bin/sh"; /* XXX warning: const */
pwent.pw_shell = "/bin/sh"; /* XXX warning: const */
#ifdef USE_PAM
ret = pam_authenticate(pamh, 0);
ret = pam_authenticate (pamh, 0);
if (ret != PAM_SUCCESS) {
SYSLOG((LOG_ERR, "pam_authenticate: %s\n",
pam_strerror(pamh, ret)));
fprintf(stderr, "%s: %s\n", Prog, pam_strerror(pamh, ret));
pam_end(pamh, ret);
su_failure(tty);
SYSLOG ((LOG_ERR, "pam_authenticate: %s",
pam_strerror (pamh, ret)));
fprintf (stderr, "%s: %s\n", Prog,
pam_strerror (pamh, ret));
pam_end (pamh, ret);
su_failure (tty);
}
ret = pam_acct_mgmt(pamh, 0);
ret = pam_acct_mgmt (pamh, 0);
if (ret != PAM_SUCCESS) {
if (amroot) {
fprintf(stderr, _("%s: %s\n(Ignored)\n"), Prog, pam_strerror(pamh, ret));
fprintf (stderr, _("%s: %s\n(Ignored)\n"), Prog,
pam_strerror (pamh, ret));
} else {
SYSLOG((LOG_ERR, "pam_acct_mgmt: %s\n",
pam_strerror(pamh, ret)));
fprintf(stderr, "%s: %s\n", Prog, pam_strerror(pamh, ret));
pam_end(pamh, ret);
su_failure(tty);
SYSLOG ((LOG_ERR, "pam_acct_mgmt: %s",
pam_strerror (pamh, ret)));
fprintf (stderr, "%s: %s\n", Prog,
pam_strerror (pamh, ret));
pam_end (pamh, ret);
su_failure (tty);
}
}
#else /* !USE_PAM */
#else /* !USE_PAM */
/*
* Set up a signal handler in case the user types QUIT.
*/
@@ -428,84 +436,83 @@ top:
oldsig = signal (SIGQUIT, die);
/*
* See if the system defined authentication method is being used.
* The first character of an administrator defined method is an
* '@' character.
* See if the system defined authentication method is being used.
* The first character of an administrator defined method is an '@'
* character.
*/
if (! amroot && pw_auth (pwent.pw_passwd, name, PW_SU, (char *) 0)) {
SYSLOG((pwent.pw_uid ? LOG_NOTICE:LOG_WARN,
"Authentication failed for %s\n", name));
su_failure(tty);
if (!amroot && pw_auth (pwent.pw_passwd, name, PW_SU, (char *) 0)) {
SYSLOG ((pwent.pw_uid ? LOG_NOTICE : LOG_WARN,
"Authentication failed for %s", name));
su_failure (tty);
}
signal (SIGQUIT, oldsig);
/*
* Check to see if the account is expired. root gets to
* ignore any expired accounts, but normal users can't become
* a user with an expired password.
* Check to see if the account is expired. root gets to ignore any
* expired accounts, but normal users can't become a user with an
* expired password.
*/
if (! amroot) {
if (!amroot) {
#ifdef SHADOWPWD
if (!spwd)
spwd = pwd_to_spwd(&pwent);
spwd = pwd_to_spwd (&pwent);
if (isexpired(&pwent, spwd)) {
SYSLOG((pwent.pw_uid ? LOG_WARN : LOG_CRIT,
"Expired account %s\n", name));
su_failure(tty);
if (isexpired (&pwent, spwd)) {
SYSLOG ((pwent.pw_uid ? LOG_WARN : LOG_CRIT,
"Expired account %s", name));
su_failure (tty);
}
#else
#if defined(ATT_AGE) && defined(AGING)
else if (pwent.pw_age[0] &&
isexpired (&pwent)) {
SYSLOG((pwent.pw_uid ? LOG_WARN:LOG_CRIT,
"Expired account %s\n", name));
su_failure(tty);
#if defined(ATT_AGE)
if (pwent.pw_age[0] && isexpired (&pwent)) {
SYSLOG ((pwent.pw_uid ? LOG_WARN : LOG_CRIT,
"Expired account %s", name));
su_failure (tty);
}
#endif /* ATT_AGE */
#endif /* ATT_AGE */
#endif
}
/*
* Check to see if the account permits "su". root gets to
* ignore any restricted accounts, but normal users can't become
* a user if there is a "SU" entry in the /etc/porttime file
* denying access to the account.
* Check to see if the account permits "su". root gets to ignore any
* restricted accounts, but normal users can't become a user if
* there is a "SU" entry in the /etc/porttime file denying access to
* the account.
*/
if (! amroot) {
if (! isttytime (pwent.pw_name, "SU", time ((time_t *) 0))) {
SYSLOG((pwent.pw_uid ? LOG_WARN : LOG_CRIT,
"SU by %s to restricted account %s\n",
oldname, name));
su_failure(tty);
if (!amroot) {
if (!isttytime (pwent.pw_name, "SU", time ((time_t *) 0))) {
SYSLOG ((pwent.pw_uid ? LOG_WARN : LOG_CRIT,
"SU by %s to restricted account %s",
oldname, name));
su_failure (tty);
}
}
#endif /* !USE_PAM */
#endif /* !USE_PAM */
signal(SIGINT, SIG_DFL);
cp = getdef_str((pwent.pw_uid == 0) ? "ENV_SUPATH" : "ENV_PATH");
signal (SIGINT, SIG_DFL);
cp = getdef_str ((pwent.pw_uid == 0) ? "ENV_SUPATH" : "ENV_PATH");
#if 0
addenv(cp ? cp : "PATH=/bin:/usr/bin", NULL);
addenv (cp ? cp : "PATH=/bin:/usr/bin", NULL);
#else
/* XXX very similar code duplicated in libmisc/setupenv.c */
if (!cp) {
addenv("PATH=/bin:/usr/bin", NULL);
} else if (strchr(cp, '=')) {
addenv(cp, NULL);
addenv ("PATH=/bin:/usr/bin", NULL);
} else if (strchr (cp, '=')) {
addenv (cp, NULL);
} else {
addenv("PATH", cp);
addenv ("PATH", cp);
}
#endif
environ = newenvp; /* make new environment active */
environ = newenvp; /* make new environment active */
if (getenv ("IFS")) /* don't export user IFS ... */
addenv("IFS= \t\n", NULL); /* ... instead, set a safe IFS */
if (getenv ("IFS")) /* don't export user IFS ... */
addenv ("IFS= \t\n", NULL); /* ... instead, set a safe IFS */
if (pwent.pw_shell[0] == '*') { /* subsystem root required */
if (pwent.pw_shell[0] == '*') { /* subsystem root required */
pwent.pw_shell++; /* skip the '*' */
subsystem (&pwent); /* figure out what to execute */
endpwent ();
@@ -515,110 +522,113 @@ top:
goto top;
}
sulog(tty, 1, oldname, name); /* save SU information */
sulog (tty, 1, oldname, name); /* save SU information */
endpwent ();
#ifdef SHADOWPWD
endspent ();
#endif
#ifdef USE_SYSLOG
if (getdef_bool("SYSLOG_SU_ENAB"))
SYSLOG((LOG_INFO, "+ %s %s-%s\n", tty,
oldname[0] ? oldname:"???", name[0] ? name:"???"));
if (getdef_bool ("SYSLOG_SU_ENAB"))
SYSLOG ((LOG_INFO, "+ %s %s-%s", tty,
oldname[0] ? oldname : "???",
name[0] ? name : "???"));
#endif
#ifdef USE_PAM
/* set primary group id and supplementary groups */
if (setup_groups(&pwent)) {
pam_end(pamh, PAM_ABORT);
exit(1);
if (setup_groups (&pwent)) {
pam_end (pamh, PAM_ABORT);
exit (1);
}
/* pam_setcred() may do things like resource limits, console groups,
and much more, depending on the configured modules */
ret = pam_setcred(pamh, PAM_ESTABLISH_CRED);
/*
* pam_setcred() may do things like resource limits, console groups,
* and much more, depending on the configured modules
*/
ret = pam_setcred (pamh, PAM_ESTABLISH_CRED);
if (ret != PAM_SUCCESS) {
SYSLOG((LOG_ERR, "pam_setcred: %s\n", pam_strerror(pamh, ret)));
fprintf(stderr, "%s: %s\n", Prog, pam_strerror(pamh, ret));
pam_end(pamh, ret);
exit(1);
SYSLOG ((LOG_ERR, "pam_setcred: %s",
pam_strerror (pamh, ret)));
fprintf (stderr, "%s: %s\n", Prog,
pam_strerror (pamh, ret));
pam_end (pamh, ret);
exit (1);
}
/* become the new user */
if (change_uid(&pwent)) {
pam_setcred(pamh, PAM_DELETE_CRED);
pam_end(pamh, PAM_ABORT);
exit(1);
if (change_uid (&pwent)) {
pam_setcred (pamh, PAM_DELETE_CRED);
pam_end (pamh, PAM_ABORT);
exit (1);
}
/* now we are done using PAM */
pam_end(pamh, PAM_SUCCESS);
pam_end (pamh, PAM_SUCCESS);
#else /* !USE_PAM */
if (!amroot) /* no limits if su from root */
setup_limits(&pwent);
#else /* !USE_PAM */
if (!amroot) /* no limits if su from root */
setup_limits (&pwent);
if (setup_uid_gid(&pwent, is_console))
exit(1);
#endif /* !USE_PAM */
if (setup_uid_gid (&pwent, is_console))
exit (1);
#endif /* !USE_PAM */
if (fakelogin)
setup_env(&pwent);
#if 1 /* Suggested by Joey Hess. XXX - is this right? */
setup_env (&pwent);
#if 1 /* Suggested by Joey Hess. XXX - is this right? */
else
addenv("HOME", pwent.pw_dir);
addenv ("HOME", pwent.pw_dir);
#endif
/*
* This is a workaround for Linux libc bug/feature (?) - the
* /dev/log file descriptor is open without the close-on-exec
* flag and used to be passed to the new shell. There is
* "fcntl(LogFile, F_SETFD, 1)" in libc/misc/syslog.c, but
* it is commented out (at least in 5.4.33). Why? --marekm
* /dev/log file descriptor is open without the close-on-exec flag
* and used to be passed to the new shell. There is "fcntl(LogFile,
* F_SETFD, 1)" in libc/misc/syslog.c, but it is commented out (at
* least in 5.4.33). Why? --marekm
*/
closelog();
closelog ();
/*
* See if the user has extra arguments on the command line. In
* that case they will be provided to the new user's shell as
* arguments.
* See if the user has extra arguments on the command line. In that
* case they will be provided to the new user's shell as arguments.
*/
if (fakelogin) {
char *arg0;
#if 0 /* XXX - GNU su doesn't do this. --marekm */
if (! hushed (&pwent)) {
#if 0 /* XXX - GNU su doesn't do this. --marekm */
if (!hushed (&pwent)) {
motd ();
mailcheck ();
}
#endif
cp = getdef_str("SU_NAME");
cp = getdef_str ("SU_NAME");
if (!cp)
cp = Basename(pwent.pw_shell);
cp = Basename (pwent.pw_shell);
arg0 = xmalloc(strlen(cp) + 2);
arg0 = xmalloc (strlen (cp) + 2);
arg0[0] = '-';
strcpy(arg0 + 1, cp);
strcpy (arg0 + 1, cp);
cp = arg0;
} else
cp = Basename(pwent.pw_shell);
cp = Basename (pwent.pw_shell);
if (! doshell) {
if (!doshell) {
/*
* Use new user's shell from /etc/passwd and create an
* argv with the rest of the command line included.
* Use new user's shell from /etc/passwd and create an argv
* with the rest of the command line included.
*/
argv[-1] = pwent.pw_shell;
(void) execv (pwent.pw_shell, &argv[-1]);
(void) fprintf (stderr, _("No shell\n"));
SYSLOG((LOG_WARN, "Cannot execute %s\n", pwent.pw_shell));
closelog();
SYSLOG ((LOG_WARN, "Cannot execute %s", pwent.pw_shell));
closelog ();
exit (1);
}
shell(pwent.pw_shell, cp);
/*NOTREACHED*/
exit(1);
shell (pwent.pw_shell, cp);
/*NOTREACHED*/ exit (1);
}
+84 -84
View File
@@ -17,7 +17,7 @@
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH 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 JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH 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)
@@ -30,28 +30,25 @@
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: sulogin.c,v 1.12 2000/09/02 18:40:44 marekm Exp $")
RCSID (PKG_VER "$Id: sulogin.c,v 1.13 2002/01/05 15:41:44 kloczek Exp $")
#include "prototypes.h"
#include "defines.h"
#include "getdef.h"
#if HAVE_UTMPX_H
#include <utmpx.h>
#else
#include <utmp.h>
#endif
#include <signal.h>
#include <stdio.h>
#include <pwd.h>
#include <fcntl.h>
#include "pwauth.h"
static char name[BUFSIZ];
static char pass[BUFSIZ];
static struct passwd pwent;
#if 0
#if HAVE_UTMPX_H
static struct utmpx utent;
@@ -64,58 +61,57 @@ static struct utmp utent;
extern char **newenvp;
extern size_t newenvc;
extern char **environ;
extern char **environ;
#ifndef ALARM
#define ALARM 60
#endif
/* local function prototypes */
static RETSIGTYPE catch(int);
static RETSIGTYPE catch (int);
static RETSIGTYPE
catch(int sig)
static RETSIGTYPE catch (int sig)
{
exit(1);
exit (1);
}
/* syslogd is usually not running at the time when sulogin is typically
called, cluttering the screen with unnecessary messages. Suggested
by Ivan Nejgebauer <ian@unsux.ns.ac.yu>. --marekm */
/*
* syslogd is usually not running at the time when sulogin is typically
* called, cluttering the screen with unnecessary messages. Suggested by
* Ivan Nejgebauer <ian@unsux.ns.ac.yu>. --marekm
*/
#undef USE_SYSLOG
/*ARGSUSED*/
int
main(int argc, char **argv)
/*ARGSUSED*/ int main (int argc, char **argv)
{
char *cp;
char **envp = environ;
TERMIO termio;
char *cp;
char **envp = environ;
TERMIO termio;
#ifdef USE_TERMIO
ioctl (0, TCGETA, &termio);
termio.c_iflag |= (ICRNL|IXON);
termio.c_oflag |= (OPOST|ONLCR);
termio.c_iflag |= (ICRNL | IXON);
termio.c_oflag |= (OPOST | ONLCR);
termio.c_cflag |= (CREAD);
termio.c_lflag |= (ISIG|ICANON|ECHO|ECHOE|ECHOK);
termio.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK);
ioctl (0, TCSETAF, &termio);
#endif
#ifdef USE_TERMIOS
tcgetattr (0, &termio);
termio.c_iflag |= (ICRNL|IXON);
termio.c_iflag |= (ICRNL | IXON);
termio.c_oflag |= (CREAD);
termio.c_lflag |= (ECHO|ECHOE|ECHOK|ICANON|ISIG);
termio.c_lflag |= (ECHO | ECHOE | ECHOK | ICANON | ISIG);
tcsetattr (0, TCSANOW, &termio);
#endif
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
#ifdef USE_SYSLOG
OPENLOG("sulogin");
OPENLOG ("sulogin");
#endif
initenv();
initenv ();
if (argc > 1) {
close (0);
close (1);
@@ -132,16 +128,16 @@ main(int argc, char **argv)
exit (1);
}
}
if (access(PASSWD_FILE, F_OK) == -1) { /* must be a password file! */
printf(_("No password file\n"));
if (access (PASSWD_FILE, F_OK) == -1) { /* must be a password file! */
printf (_("No password file\n"));
#ifdef USE_SYSLOG
syslog(LOG_WARN, "No password file\n");
syslog (LOG_WARN, "No password file\n");
closelog ();
#endif
exit (1);
}
#if !defined(DEBUG) && defined(SULOGIN_ONLY_INIT)
if (getppid () != 1) { /* parent must be INIT */
if (getppid () != 1) { /* parent must be INIT */
#ifdef USE_SYSLOG
syslog (LOG_WARN, "Pid == %d, not 1\n", getppid ());
closelog ();
@@ -149,69 +145,75 @@ main(int argc, char **argv)
exit (1);
}
#endif
if (! isatty (0) || ! isatty (1) || ! isatty (2)) {
if (!isatty (0) || !isatty (1) || !isatty (2)) {
#ifdef USE_SYSLOG
closelog ();
#endif
exit (1); /* must be a terminal */
exit (1); /* must be a terminal */
}
while (*envp) /* add inherited environment, */
addenv(*envp++, NULL); /* some variables change later */
while (*envp) /* add inherited environment, */
addenv (*envp++, NULL); /* some variables change later */
if ((cp = getdef_str("ENV_TZ")))
addenv(*cp == '/' ? tz(cp) : cp, NULL);
if ((cp = getdef_str("ENV_HZ")))
addenv(cp, NULL); /* set the default $HZ, if one */
if ((cp = getdef_str ("ENV_TZ")))
addenv (*cp == '/' ? tz (cp) : cp, NULL);
if ((cp = getdef_str ("ENV_HZ")))
addenv (cp, NULL); /* set the default $HZ, if one */
(void) strcpy (name, "root"); /* KLUDGE!!! */
signal (SIGALRM, catch); /* exit if the timer expires */
alarm (ALARM); /* only wait so long ... */
alarm (ALARM); /* only wait so long ... */
while (1) { /* repeatedly get login/password pairs */
pw_entry(name, &pwent); /* get entry from password file */
pw_entry (name, &pwent); /* get entry from password file */
if (pwent.pw_name == (char *) 0) {
/*
* Fail secure
*/
printf(_("No password entry for 'root'\n"));
printf (_("No password entry for 'root'\n"));
#ifdef USE_SYSLOG
syslog (LOG_WARN, "No password entry for 'root'\n");
syslog (LOG_WARN,
"No password entry for 'root'\n");
closelog ();
#endif
exit (1);
}
/*
* Here we prompt for the root password, or if no password is
* given we just exit.
*/
/*
* Here we prompt for the root password, or if no password
* is given we just exit.
*/
/* get a password for root */
cp = getpass(_("\nType control-d to proceed with normal startup,\n(or give root password for system maintenance):"));
/*
* XXX - can't enter single user mode if root password is empty.
* I think this doesn't happen very often :-). But it will work
* with standard getpass() (no NULL on EOF). --marekm
*/
/* get a password for root */
cp = getpass (_
("\nType control-d to proceed with normal startup,\n(or give root password for system maintenance):"));
/*
* XXX - can't enter single user mode if root password is
* empty. I think this doesn't happen very often :-). But
* it will work with standard getpass() (no NULL on EOF).
* --marekm
*/
if (!cp || !*cp) {
#ifdef USE_SYSLOG
syslog (LOG_INFO, "Normal startup\n");
closelog ();
#endif
puts("\n");
puts ("\n");
#ifdef TELINIT
execl (PATH_TELINIT, "telinit", RUNLEVEL, (char *) 0);
execl (PATH_TELINIT, "telinit", RUNLEVEL,
(char *) 0);
#endif
exit (0);
} else {
STRFCPY(pass, cp);
strzero(cp);
STRFCPY (pass, cp);
strzero (cp);
}
#ifdef AUTH_METHODS
if (pwent.pw_name && pwent.pw_passwd[0] == '@') {
if (pw_auth (pwent.pw_passwd + 1, name, PW_LOGIN, (char *) 0)) {
if (pw_auth
(pwent.pw_passwd + 1, name, PW_LOGIN,
(char *) 0)) {
#ifdef USE_SYSLOG
syslog (LOG_WARN,
"Incorrect root authentication");
@@ -221,53 +223,51 @@ main(int argc, char **argv)
goto auth_done;
}
#endif
if (valid (pass, &pwent)) /* check encrypted passwords ... */
break; /* ... encrypted passwords matched */
if (valid (pass, &pwent)) /* check encrypted passwords ... */
break; /* ... encrypted passwords matched */
#ifdef USE_SYSLOG
syslog (LOG_WARN, "Incorrect root password\n");
#endif
sleep(2);
sleep (2);
puts (_("Login incorrect"));
}
#ifdef AUTH_METHODS
auth_done:
auth_done:
#endif
strzero(pass);
strzero (pass);
alarm (0);
signal (SIGALRM, SIG_DFL);
environ = newenvp; /* make new environment active */
environ = newenvp; /* make new environment active */
puts(_("Entering System Maintenance Mode\n"));
puts (_("Entering System Maintenance Mode\n"));
#ifdef USE_SYSLOG
syslog (LOG_INFO, "System Maintenance Mode\n");
#endif
#if 0 /* do we need all this? we are logging in as root anyway... --marekm */
#if 0 /* do we need all this? we are logging in as root anyway... --marekm */
/*
* Normally there would be a utmp entry for login to mung on
* to get the tty name, date, etc. from. We don't need all that
* stuff because we won't update the utmp or wtmp files. BUT!,
* we do need the tty name so we can set the permissions and
* ownership.
* Normally there would be a utmp entry for login to mung on to get
* the tty name, date, etc. from. We don't need all that stuff
* because we won't update the utmp or wtmp files. BUT!, we do need
* the tty name so we can set the permissions and ownership.
*/
if ((cp = ttyname (0))) { /* found entry in /dev/ */
if (strncmp(cp, "/dev/", 5) == 0)
if ((cp = ttyname (0))) { /* found entry in /dev/ */
if (strncmp (cp, "/dev/", 5) == 0)
cp += 5;
strncpy(utent.ut_line, cp, sizeof utent.ut_line);
strncpy (utent.ut_line, cp, sizeof utent.ut_line);
}
if (getenv ("IFS")) /* don't export user IFS ... */
addenv("IFS= \t\n", NULL); /* ... instead, set a safe IFS */
if (getenv ("IFS")) /* don't export user IFS ... */
addenv ("IFS= \t\n", NULL); /* ... instead, set a safe IFS */
setup (&pwent, 0); /* set UID, GID, HOME, etc ... */
setup (&pwent, 0); /* set UID, GID, HOME, etc ... */
#endif
#ifdef USE_SYSLOG
closelog ();
#endif
shell (pwent.pw_shell, (char *) 0); /* exec the shell finally. */
/*NOTREACHED*/
return (0);
shell (pwent.pw_shell, (char *) 0); /* exec the shell finally. */
/*NOTREACHED*/ return (0);
}
+641 -603
View File
File diff suppressed because it is too large Load Diff
+453 -510
View File
File diff suppressed because it is too large Load Diff
+665 -620
View File
File diff suppressed because it is too large Load Diff
+180 -163
View File
@@ -11,7 +11,7 @@
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
@@ -23,10 +23,8 @@
#include <config.h>
#include "rcsid.h"
RCSID(PKG_VER "$Id: vipw.c,v 1.2 2000/08/26 18:27:19 marekm Exp $")
RCSID (PKG_VER "$Id: vipw.c,v 1.3 2002/01/05 15:41:44 kloczek Exp $")
#include "defines.h"
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -40,67 +38,71 @@ RCSID(PKG_VER "$Id: vipw.c,v 1.2 2000/08/26 18:27:19 marekm Exp $")
#include "shadowio.h"
#include "groupio.h"
#include "sgroupio.h"
static const char *progname, *filename, *fileeditname;
static int filelocked = 0, createedit = 0;
static int (*unlock)(void);
static int (*unlock) (void);
/* local function prototypes */
static int create_backup_file(FILE *, const char *, struct stat *);
static void vipwexit(const char *, int, int);
static void vipwedit(const char *, int (*)(void), int (*)(void));
static int create_backup_file (FILE *, const char *, struct stat *);
static void vipwexit (const char *, int, int);
static void vipwedit (const char *, int (*)(void), int (*)(void));
static int
create_backup_file(FILE *fp, const char *backup, struct stat *sb)
create_backup_file (FILE * fp, const char *backup, struct stat *sb)
{
struct utimbuf ub;
FILE *bkfp;
int c;
mode_t mask;
struct utimbuf ub;
FILE *bkfp;
int c;
mode_t mask;
mask = umask(077);
bkfp = fopen(backup, "w");
umask(mask);
if (!bkfp) return -1;
mask = umask (077);
bkfp = fopen (backup, "w");
umask (mask);
if (!bkfp)
return -1;
rewind(fp);
while ((c = getc(fp)) != EOF) {
if (putc(c, bkfp) == EOF) break;
}
rewind (fp);
while ((c = getc (fp)) != EOF) {
if (putc (c, bkfp) == EOF)
break;
}
if (c != EOF || fflush(bkfp)) {
fclose(bkfp);
unlink(backup);
return -1;
}
if (fclose(bkfp)) {
unlink(backup);
return -1;
}
if (c != EOF || fflush (bkfp)) {
fclose (bkfp);
unlink (backup);
return -1;
}
if (fclose (bkfp)) {
unlink (backup);
return -1;
}
ub.actime = sb->st_atime;
ub.modtime = sb->st_mtime;
if (utime(backup, &ub) ||
chmod(backup, sb->st_mode) ||
chown(backup, sb->st_uid, sb->st_gid)) {
unlink(backup);
return -1;
}
return 0;
ub.actime = sb->st_atime;
ub.modtime = sb->st_mtime;
if (utime (backup, &ub) ||
chmod (backup, sb->st_mode) ||
chown (backup, sb->st_uid, sb->st_gid)) {
unlink (backup);
return -1;
}
return 0;
}
static void
vipwexit(const char *msg, int syserr, int ret)
static void vipwexit (const char *msg, int syserr, int ret)
{
int err = errno;
if (filelocked) (*unlock)();
if (createedit) unlink(fileeditname);
if (msg) fprintf(stderr, "%s: %s", progname, msg);
if (syserr) fprintf(stderr, ": %s", strerror(err));
fprintf(stderr, _("\n%s: %s is unchanged\n"), progname, filename);
exit(ret);
int err = errno;
if (filelocked)
(*unlock) ();
if (createedit)
unlink (fileeditname);
if (msg)
fprintf (stderr, "%s: %s", progname, msg);
if (syserr)
fprintf (stderr, ": %s", strerror (err));
fprintf (stderr, _("\n%s: %s is unchanged\n"), progname, filename);
exit (ret);
}
#ifndef DEFAULT_EDITOR
@@ -108,145 +110,160 @@ vipwexit(const char *msg, int syserr, int ret)
#endif
static void
vipwedit(const char *file, int (*file_lock)(void), int (*file_unlock)(void))
vipwedit (const char *file, int (*file_lock) (void),
int (*file_unlock) (void))
{
const char *editor;
pid_t pid;
struct stat st1, st2;
int status;
FILE *f;
char filebackup[1024], fileedit[1024];
const char *editor;
pid_t pid;
struct stat st1, st2;
int status;
FILE *f;
char filebackup[1024], fileedit[1024];
snprintf(filebackup, sizeof filebackup, "%s-", file);
snprintf(fileedit, sizeof fileedit, "%s.edit", file);
unlock = file_unlock;
filename = file;
fileeditname = fileedit;
if (access(file, F_OK)) vipwexit(file, 1, 1);
if (!file_lock()) vipwexit(_("Couldn't lock file"), errno, 5);
filelocked = 1;
snprintf (filebackup, sizeof filebackup, "%s-", file);
snprintf (fileedit, sizeof fileedit, "%s.edit", file);
unlock = file_unlock;
filename = file;
fileeditname = fileedit;
/* edited copy has same owners, perm */
if (stat(file, &st1)) vipwexit(file, 1, 1);
if (!(f = fopen(file, "r"))) vipwexit(file, 1, 1);
if (create_backup_file(f, fileedit, &st1))
vipwexit(_("Couldn't make backup"), errno, 1);
createedit = 1;
editor = getenv("VISUAL");
if (!editor)
editor = getenv("EDITOR");
if (!editor)
editor = DEFAULT_EDITOR;
if ((pid = fork()) == -1) vipwexit("fork", 1, 1);
else if (!pid) {
if (access (file, F_OK))
vipwexit (file, 1, 1);
if (!file_lock ())
vipwexit (_("Couldn't lock file"), errno, 5);
filelocked = 1;
/* edited copy has same owners, perm */
if (stat (file, &st1))
vipwexit (file, 1, 1);
if (!(f = fopen (file, "r")))
vipwexit (file, 1, 1);
if (create_backup_file (f, fileedit, &st1))
vipwexit (_("Couldn't make backup"), errno, 1);
createedit = 1;
editor = getenv ("VISUAL");
if (!editor)
editor = getenv ("EDITOR");
if (!editor)
editor = DEFAULT_EDITOR;
if ((pid = fork ()) == -1)
vipwexit ("fork", 1, 1);
else if (!pid) {
#if 0
execlp(editor, editor, fileedit, (char *) 0);
fprintf(stderr, "%s: %s: %s\n", progname, editor, strerror(errno));
exit(1);
execlp (editor, editor, fileedit, (char *) 0);
fprintf (stderr, "%s: %s: %s\n", progname, editor,
strerror (errno));
exit (1);
#else
/* use the system() call to invoke the editor so that it accepts
command line args in the EDITOR and VISUAL environment vars */
char *buf;
buf = (char *) malloc (strlen(editor) + strlen(fileedit) + 2);
snprintf(buf, strlen(editor) + strlen(fileedit) + 2, "%s %s",
editor, fileedit);
if (system(buf) != 0) {
fprintf(stderr, "%s: %s: %s\n", progname, editor, strerror(errno));
exit(1);
} else
exit(0);
/* use the system() call to invoke the editor so that it accepts
command line args in the EDITOR and VISUAL environment vars */
char *buf;
buf =
(char *) malloc (strlen (editor) + strlen (fileedit) +
2);
snprintf (buf, strlen (editor) + strlen (fileedit) + 2,
"%s %s", editor, fileedit);
if (system (buf) != 0) {
fprintf (stderr, "%s: %s: %s\n", progname, editor,
strerror (errno));
exit (1);
} else
exit (0);
#endif
}
}
for (;;) {
pid = waitpid(pid, &status, WUNTRACED);
if (WIFSTOPPED(status)) {
kill(getpid(), SIGSTOP);
kill(getpid(), SIGCONT);
}
else break;
}
for (;;) {
pid = waitpid (pid, &status, WUNTRACED);
if (WIFSTOPPED (status)) {
kill (getpid (), SIGSTOP);
kill (getpid (), SIGCONT);
} else
break;
}
if (pid == -1 || !WIFEXITED(status) || WEXITSTATUS(status))
vipwexit(editor, 1, 1);
if (pid == -1 || !WIFEXITED (status) || WEXITSTATUS (status))
vipwexit (editor, 1, 1);
if (stat(fileedit, &st2)) vipwexit(fileedit, 1, 1);
if (st1.st_mtime == st2.st_mtime) vipwexit(0, 0, 0);
if (stat (fileedit, &st2))
vipwexit (fileedit, 1, 1);
if (st1.st_mtime == st2.st_mtime)
vipwexit (0, 0, 0);
/* XXX - here we should check fileedit for errors; if there are any,
ask the user what to do (edit again, save changes anyway, or quit
without saving). Use pwck or grpck to do the check. --marekm */
/*
* XXX - here we should check fileedit for errors; if there are any,
* ask the user what to do (edit again, save changes anyway, or quit
* without saving). Use pwck or grpck to do the check. --marekm
*/
createedit = 0;
unlink(filebackup);
link(file, filebackup);
if (rename(fileedit, file) == -1) {
fprintf(stderr, _("%s: can't restore %s: %s (your changes are in %s)\n"),
progname, file, strerror(errno), fileedit);
vipwexit(0,0,1);
}
createedit = 0;
unlink (filebackup);
link (file, filebackup);
if (rename (fileedit, file) == -1) {
fprintf (stderr,
_
("%s: can't restore %s: %s (your changes are in %s)\n"),
progname, file, strerror (errno), fileedit);
vipwexit (0, 0, 1);
}
(*file_unlock)();
(*file_unlock) ();
}
int
main(int argc, char **argv)
int main (int argc, char **argv)
{
int flag;
int editshadow = 0;
char *c;
int e = 1;
int do_vipw;
int flag;
int editshadow = 0;
char *c;
int e = 1;
int do_vipw;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
progname = ((c = strrchr(*argv, '/')) ? c+1 : *argv);
do_vipw = (strcmp(progname, "vigr") != 0);
progname = ((c = strrchr (*argv, '/')) ? c + 1 : *argv);
do_vipw = (strcmp (progname, "vigr") != 0);
while ((flag = getopt(argc, argv, "ghps")) != EOF) {
switch (flag) {
case 'p':
do_vipw = 1;
break;
case 'g':
do_vipw = 0;
break;
case 's':
editshadow = 1;
break;
case 'h':
e = 0;
default:
printf(_("Usage:\n\
while ((flag = getopt (argc, argv, "ghps")) != EOF) {
switch (flag) {
case 'p':
do_vipw = 1;
break;
case 'g':
do_vipw = 0;
break;
case 's':
editshadow = 1;
break;
case 'h':
e = 0;
default:
printf (_("Usage:\n\
`vipw' edits /etc/passwd `vipw -s' edits /etc/shadow\n\
`vigr' edits /etc/group `vigr -s' edits /etc/gshadow\n\
"));
exit(e);
}
}
exit (e);
}
}
if (do_vipw) {
if (do_vipw) {
#ifdef SHADOWPWD
if (editshadow)
vipwedit(SHADOW_FILE, spw_lock, spw_unlock);
else
if (editshadow)
vipwedit (SHADOW_FILE, spw_lock, spw_unlock);
else
#endif
vipwedit(PASSWD_FILE, pw_lock, pw_unlock);
}
else {
vipwedit (PASSWD_FILE, pw_lock, pw_unlock);
} else {
#ifdef SHADOWGRP
if (editshadow)
vipwedit(SGROUP_FILE, sgr_lock, sgr_unlock);
else
if (editshadow)
vipwedit (SGROUP_FILE, sgr_lock, sgr_unlock);
else
#endif
vipwedit(GROUP_FILE, gr_lock, gr_unlock);
}
vipwedit (GROUP_FILE, gr_lock, gr_unlock);
}
return 0;
return 0;
}