[svn-upgrade] Integrating new upstream version, shadow (4.0.1)
This commit is contained in:
+3
-4
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+276
-276
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 = ∅
|
||||
}
|
||||
/*
|
||||
* 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
@@ -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 */
|
||||
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+80
-84
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+170
-184
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+453
-510
File diff suppressed because it is too large
Load Diff
+665
-620
File diff suppressed because it is too large
Load Diff
+180
-163
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user