* NEWS, src/groupmod.c: Make sure the passwd, group, and gshadow
files are unlocked on exit. Unlock locked files in fail_exit(). Prefer fail_exit() over exit(). * NEWS, src/groupmod.c: When the GID of a group is changed, update also the GID of the passwd entries of the users whose primary group is the group being modified.
This commit is contained in:
parent
b1a0769d3d
commit
a8a614c515
@ -1,3 +1,12 @@
|
|||||||
|
2008-03-08 Nicolas François <nicolas.francois@centraliens.net>
|
||||||
|
|
||||||
|
* NEWS, src/groupmod.c: Make sure the passwd, group, and gshadow
|
||||||
|
files are unlocked on exit. Unlock locked files in fail_exit().
|
||||||
|
Prefer fail_exit() over exit().
|
||||||
|
* NEWS, src/groupmod.c: When the GID of a group is changed, update
|
||||||
|
also the GID of the passwd entries of the users whose primary
|
||||||
|
group is the group being modified.
|
||||||
|
|
||||||
2008-03-08 Nicolas François <nicolas.francois@centraliens.net>
|
2008-03-08 Nicolas François <nicolas.francois@centraliens.net>
|
||||||
|
|
||||||
* lib/commonio.c (commonio_remove): Fail when the name to be
|
* lib/commonio.c (commonio_remove): Fail when the name to be
|
||||||
|
3
NEWS
3
NEWS
@ -42,6 +42,9 @@ shadow-4.1.0 -> shadow-4.1.1 UNRELEASED
|
|||||||
* Fix buffer overflow when adding an user to a group. Thanks to Peter Vrabec.
|
* Fix buffer overflow when adding an user to a group. Thanks to Peter Vrabec.
|
||||||
- groupmod
|
- groupmod
|
||||||
* New option -p/--password to specify an encrypted password.
|
* New option -p/--password to specify an encrypted password.
|
||||||
|
* Make sure the group and gshadow files are unlocked on exit.
|
||||||
|
* When the GID of a group is changed, update also the GID of the passwd
|
||||||
|
entries of the users whose primary group is the group being modified.
|
||||||
- grpck
|
- grpck
|
||||||
* Fix logging of changes to syslog when a group file is provided,
|
* Fix logging of changes to syslog when a group file is provided,
|
||||||
without a gshadow file.
|
without a gshadow file.
|
||||||
|
143
src/groupmod.c
143
src/groupmod.c
@ -44,6 +44,7 @@
|
|||||||
#include "chkname.h"
|
#include "chkname.h"
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#include "groupio.h"
|
#include "groupio.h"
|
||||||
|
#include "pwio.h"
|
||||||
#include "nscd.h"
|
#include "nscd.h"
|
||||||
#include "prototypes.h"
|
#include "prototypes.h"
|
||||||
#ifdef SHADOWGRP
|
#ifdef SHADOWGRP
|
||||||
@ -64,7 +65,10 @@
|
|||||||
*/
|
*/
|
||||||
#ifdef SHADOWGRP
|
#ifdef SHADOWGRP
|
||||||
static int is_shadow_grp;
|
static int is_shadow_grp;
|
||||||
|
static int gshadow_locked = 0;
|
||||||
#endif
|
#endif
|
||||||
|
static int group_locked = 0;
|
||||||
|
static int passwd_locked = 0;
|
||||||
static char *group_name;
|
static char *group_name;
|
||||||
static char *group_newname;
|
static char *group_newname;
|
||||||
static char *group_passwd;
|
static char *group_passwd;
|
||||||
@ -81,6 +85,7 @@ static int
|
|||||||
|
|
||||||
/* local function prototypes */
|
/* local function prototypes */
|
||||||
static void usage (void);
|
static void usage (void);
|
||||||
|
static void fail_exit (int);
|
||||||
static void new_grent (struct group *);
|
static void new_grent (struct group *);
|
||||||
|
|
||||||
#ifdef SHADOWGRP
|
#ifdef SHADOWGRP
|
||||||
@ -93,6 +98,7 @@ static void process_flags (int, char **);
|
|||||||
static void close_files (void);
|
static void close_files (void);
|
||||||
static void open_files (void);
|
static void open_files (void);
|
||||||
static gid_t get_gid (const char *gidstr);
|
static gid_t get_gid (const char *gidstr);
|
||||||
|
static void update_primary_groups (gid_t ogid, gid_t ngid);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* usage - display usage message and exit
|
* usage - display usage message and exit
|
||||||
@ -112,6 +118,20 @@ static void usage (void)
|
|||||||
exit (E_USAGE);
|
exit (E_USAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fail_exit (int status)
|
||||||
|
{
|
||||||
|
if (group_locked) {
|
||||||
|
gr_unlock ();
|
||||||
|
}
|
||||||
|
if (gshadow_locked) {
|
||||||
|
sgr_unlock ();
|
||||||
|
}
|
||||||
|
if (passwd_locked) {
|
||||||
|
pw_unlock();
|
||||||
|
}
|
||||||
|
exit (status);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* new_grent - updates the values in a group file entry
|
* new_grent - updates the values in a group file entry
|
||||||
*
|
*
|
||||||
@ -174,7 +194,7 @@ static void grp_update (void)
|
|||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "modifying group",
|
audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "modifying group",
|
||||||
group_name, -1, 0);
|
group_name, -1, 0);
|
||||||
#endif
|
#endif
|
||||||
exit (E_GRP_UPDATE);
|
fail_exit (E_GRP_UPDATE);
|
||||||
}
|
}
|
||||||
grp = *ogrp;
|
grp = *ogrp;
|
||||||
new_grent (&grp);
|
new_grent (&grp);
|
||||||
@ -187,6 +207,10 @@ static void grp_update (void)
|
|||||||
}
|
}
|
||||||
#endif /* SHADOWGRP */
|
#endif /* SHADOWGRP */
|
||||||
|
|
||||||
|
if (gflg) {
|
||||||
|
update_primary_groups (ogrp->gr_gid, group_newid);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write out the new group file entry.
|
* Write out the new group file entry.
|
||||||
*/
|
*/
|
||||||
@ -196,7 +220,7 @@ static void grp_update (void)
|
|||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "adding group",
|
audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "adding group",
|
||||||
group_name, -1, 0);
|
group_name, -1, 0);
|
||||||
#endif
|
#endif
|
||||||
exit (E_GRP_UPDATE);
|
fail_exit (E_GRP_UPDATE);
|
||||||
}
|
}
|
||||||
if (nflg && !gr_remove (group_name)) {
|
if (nflg && !gr_remove (group_name)) {
|
||||||
fprintf (stderr, _("%s: error removing group entry\n"), Prog);
|
fprintf (stderr, _("%s: error removing group entry\n"), Prog);
|
||||||
@ -204,7 +228,7 @@ static void grp_update (void)
|
|||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "deleting group",
|
audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "deleting group",
|
||||||
group_name, -1, 0);
|
group_name, -1, 0);
|
||||||
#endif
|
#endif
|
||||||
exit (E_GRP_UPDATE);
|
fail_exit (E_GRP_UPDATE);
|
||||||
}
|
}
|
||||||
#ifdef SHADOWGRP
|
#ifdef SHADOWGRP
|
||||||
|
|
||||||
@ -225,7 +249,7 @@ static void grp_update (void)
|
|||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "adding group",
|
audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "adding group",
|
||||||
group_name, -1, 0);
|
group_name, -1, 0);
|
||||||
#endif
|
#endif
|
||||||
exit (E_GRP_UPDATE);
|
fail_exit (E_GRP_UPDATE);
|
||||||
}
|
}
|
||||||
if (is_shadow_grp && nflg && !sgr_remove (group_name)) {
|
if (is_shadow_grp && nflg && !sgr_remove (group_name)) {
|
||||||
fprintf (stderr, _("%s: error removing group entry\n"), Prog);
|
fprintf (stderr, _("%s: error removing group entry\n"), Prog);
|
||||||
@ -233,7 +257,7 @@ static void grp_update (void)
|
|||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "deleting group",
|
audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "deleting group",
|
||||||
group_name, -1, 0);
|
group_name, -1, 0);
|
||||||
#endif
|
#endif
|
||||||
exit (E_GRP_UPDATE);
|
fail_exit (E_GRP_UPDATE);
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
#endif /* SHADOWGRP */
|
#endif /* SHADOWGRP */
|
||||||
@ -246,9 +270,10 @@ static void grp_update (void)
|
|||||||
SYSLOG ((LOG_INFO, "change group `%s' to `%s'",
|
SYSLOG ((LOG_INFO, "change group `%s' to `%s'",
|
||||||
group_name, group_newname));
|
group_name, group_newname));
|
||||||
|
|
||||||
if (gflg)
|
if (gflg) {
|
||||||
SYSLOG ((LOG_INFO, "change GID for `%s' to %u",
|
SYSLOG ((LOG_INFO, "change GID for `%s' to %u",
|
||||||
nflg ? group_newname : group_name, group_newid));
|
nflg ? group_newname : group_name, group_newid));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -279,7 +304,7 @@ static void check_new_gid (void)
|
|||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "modify gid", NULL,
|
audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "modify gid", NULL,
|
||||||
group_newid, 0);
|
group_newid, 0);
|
||||||
#endif
|
#endif
|
||||||
exit (E_GID_IN_USE);
|
fail_exit (E_GID_IN_USE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -312,7 +337,7 @@ static void check_new_name (void)
|
|||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
||||||
"modifying group", group_name, -1, 0);
|
"modifying group", group_name, -1, 0);
|
||||||
#endif
|
#endif
|
||||||
exit (E_NAME_IN_USE);
|
fail_exit (E_NAME_IN_USE);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -327,7 +352,7 @@ static void check_new_name (void)
|
|||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "modifying group", group_name,
|
audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "modifying group", group_name,
|
||||||
-1, 0);
|
-1, 0);
|
||||||
#endif
|
#endif
|
||||||
exit (E_BAD_ARG);
|
fail_exit (E_BAD_ARG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -342,7 +367,7 @@ static gid_t get_gid (const char *gidstr)
|
|||||||
if (*errptr || errno == ERANGE || val < 0) {
|
if (*errptr || errno == ERANGE || val < 0) {
|
||||||
fprintf (stderr, _("%s: invalid numeric argument '%s'\n"), Prog,
|
fprintf (stderr, _("%s: invalid numeric argument '%s'\n"), Prog,
|
||||||
gidstr);
|
gidstr);
|
||||||
exit (E_BAD_ARG);
|
fail_exit (E_BAD_ARG);
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
@ -417,18 +442,30 @@ static void close_files (void)
|
|||||||
{
|
{
|
||||||
if (!gr_close ()) {
|
if (!gr_close ()) {
|
||||||
fprintf (stderr, _("%s: cannot rewrite group file\n"), Prog);
|
fprintf (stderr, _("%s: cannot rewrite group file\n"), Prog);
|
||||||
exit (E_GRP_UPDATE);
|
fail_exit (E_GRP_UPDATE);
|
||||||
}
|
}
|
||||||
gr_unlock ();
|
gr_unlock ();
|
||||||
|
group_locked--;
|
||||||
#ifdef SHADOWGRP
|
#ifdef SHADOWGRP
|
||||||
if (is_shadow_grp && !sgr_close ()) {
|
if (is_shadow_grp && !sgr_close ()) {
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: cannot rewrite shadow group file\n"), Prog);
|
_("%s: cannot rewrite shadow group file\n"), Prog);
|
||||||
exit (E_GRP_UPDATE);
|
fail_exit (E_GRP_UPDATE);
|
||||||
}
|
}
|
||||||
if (is_shadow_grp)
|
if (is_shadow_grp) {
|
||||||
sgr_unlock ();
|
sgr_unlock ();
|
||||||
|
gshadow_locked--;
|
||||||
|
}
|
||||||
#endif /* SHADOWGRP */
|
#endif /* SHADOWGRP */
|
||||||
|
if (gflg) {
|
||||||
|
if (!pw_close ()) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: cannot rewrite passwd file\n"), Prog);
|
||||||
|
fail_exit (E_GRP_UPDATE);
|
||||||
|
}
|
||||||
|
pw_unlock();
|
||||||
|
passwd_locked--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -440,24 +477,74 @@ static void open_files (void)
|
|||||||
{
|
{
|
||||||
if (!gr_lock ()) {
|
if (!gr_lock ()) {
|
||||||
fprintf (stderr, _("%s: unable to lock group file\n"), Prog);
|
fprintf (stderr, _("%s: unable to lock group file\n"), Prog);
|
||||||
exit (E_GRP_UPDATE);
|
fail_exit (E_GRP_UPDATE);
|
||||||
}
|
}
|
||||||
|
group_locked++;
|
||||||
if (!gr_open (O_RDWR)) {
|
if (!gr_open (O_RDWR)) {
|
||||||
fprintf (stderr, _("%s: unable to open group file\n"), Prog);
|
fprintf (stderr, _("%s: unable to open group file\n"), Prog);
|
||||||
exit (E_GRP_UPDATE);
|
fail_exit (E_GRP_UPDATE);
|
||||||
}
|
}
|
||||||
#ifdef SHADOWGRP
|
#ifdef SHADOWGRP
|
||||||
if (is_shadow_grp && !sgr_lock ()) {
|
if (is_shadow_grp) {
|
||||||
fprintf (stderr,
|
if (!sgr_lock ()) {
|
||||||
_("%s: unable to lock shadow group file\n"), Prog);
|
fprintf (stderr,
|
||||||
exit (E_GRP_UPDATE);
|
_("%s: unable to lock shadow group file\n"),
|
||||||
}
|
Prog);
|
||||||
if (is_shadow_grp && !sgr_open (O_RDWR)) {
|
fail_exit (E_GRP_UPDATE);
|
||||||
fprintf (stderr,
|
}
|
||||||
_("%s: unable to open shadow group file\n"), Prog);
|
gshadow_locked++;
|
||||||
exit (E_GRP_UPDATE);
|
if (!sgr_open (O_RDWR)) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: unable to open shadow group file\n"),
|
||||||
|
Prog);
|
||||||
|
fail_exit (E_GRP_UPDATE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif /* SHADOWGRP */
|
#endif /* SHADOWGRP */
|
||||||
|
if (gflg) {
|
||||||
|
if (!pw_lock ()) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: unable to lock password file\n"),
|
||||||
|
Prog);
|
||||||
|
fail_exit (E_GRP_UPDATE);
|
||||||
|
}
|
||||||
|
passwd_locked++;
|
||||||
|
if (!pw_open (O_RDWR)) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: unable to open password file\n"),
|
||||||
|
Prog);
|
||||||
|
fail_exit (E_GRP_UPDATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_primary_groups (gid_t ogid, gid_t ngid)
|
||||||
|
{
|
||||||
|
struct passwd *pwd;
|
||||||
|
|
||||||
|
setpwent ();
|
||||||
|
while ((pwd = getpwent ()) != NULL) {
|
||||||
|
if (pwd->pw_gid == ogid) {
|
||||||
|
const struct passwd *lpwd;
|
||||||
|
struct passwd npwd;
|
||||||
|
lpwd = pw_locate (pwd->pw_name);
|
||||||
|
if (NULL == lpwd) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: cannot change the primary group of user '%s' from %u to %u, since it is not in the passwd file.\n"),
|
||||||
|
Prog, pwd->pw_name, ogid, ngid);
|
||||||
|
fail_exit (E_GRP_UPDATE);
|
||||||
|
} else {
|
||||||
|
npwd = *lpwd;
|
||||||
|
npwd.pw_gid = ngid;
|
||||||
|
if (!pw_update (&npwd)) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: cannot change the primary group of user '%s' from %u to %u.\n"),
|
||||||
|
Prog, pwd->pw_name, ogid, ngid);
|
||||||
|
fail_exit (E_GRP_UPDATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -528,7 +615,7 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
if (retval != PAM_SUCCESS) {
|
if (retval != PAM_SUCCESS) {
|
||||||
fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
|
fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
|
||||||
exit (1);
|
fail_exit (1);
|
||||||
}
|
}
|
||||||
#endif /* USE_PAM */
|
#endif /* USE_PAM */
|
||||||
|
|
||||||
@ -548,7 +635,7 @@ int main (int argc, char **argv)
|
|||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
||||||
"modifying group", group_name, -1, 0);
|
"modifying group", group_name, -1, 0);
|
||||||
#endif
|
#endif
|
||||||
exit (E_NOTFOUND);
|
fail_exit (E_NOTFOUND);
|
||||||
} else
|
} else
|
||||||
group_id = grp->gr_gid;
|
group_id = grp->gr_gid;
|
||||||
}
|
}
|
||||||
@ -581,7 +668,7 @@ int main (int argc, char **argv)
|
|||||||
fprintf (stderr, _("%s: %s is the NIS master\n"),
|
fprintf (stderr, _("%s: %s is the NIS master\n"),
|
||||||
Prog, nis_master);
|
Prog, nis_master);
|
||||||
}
|
}
|
||||||
exit (E_NOTFOUND);
|
fail_exit (E_NOTFOUND);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -598,6 +685,7 @@ int main (int argc, char **argv)
|
|||||||
open_files ();
|
open_files ();
|
||||||
|
|
||||||
grp_update ();
|
grp_update ();
|
||||||
|
|
||||||
close_files ();
|
close_files ();
|
||||||
|
|
||||||
nscd_flush_cache ("group");
|
nscd_flush_cache ("group");
|
||||||
@ -609,3 +697,4 @@ int main (int argc, char **argv)
|
|||||||
exit (E_SUCCESS);
|
exit (E_SUCCESS);
|
||||||
/* NOT REACHED */
|
/* NOT REACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user