* libmisc/audit_help.c: Added audit_logger_message() to log
messages not related to an account. * lib/prototypes.h, libmisc/cleanup.c, libmisc/cleanup_group.c, libmisc/cleanup_user.c, libmisc/Makefile.am: Added stack of cleanup functions to be executed on exit. * NEWS, src/groupadd.c, src/groupdel.c, src/groupmod.c: Only report success to audit and syslog when the changes are committed to the system. Do not log failure for on-memory changes to audit or syslog. Make sure failures and inconsistencies will be reported in case of unexpected failures (e.g. malloc failures). Only specify an audit message if it is not implicitly implied by the type argument. Removed fail_exit (replaced by atexit(do_cleanups)).
This commit is contained in:
parent
a438c2f184
commit
5b8ff14caf
15
ChangeLog
15
ChangeLog
@ -1,3 +1,18 @@
|
|||||||
|
2008-12-22 Nicolas François <nicolas.francois@centraliens.net>
|
||||||
|
|
||||||
|
* libmisc/audit_help.c: Added audit_logger_message() to log
|
||||||
|
messages not related to an account.
|
||||||
|
* lib/prototypes.h, libmisc/cleanup.c, libmisc/cleanup_group.c,
|
||||||
|
libmisc/cleanup_user.c, libmisc/Makefile.am: Added stack of
|
||||||
|
cleanup functions to be executed on exit.
|
||||||
|
* NEWS, src/groupadd.c, src/groupdel.c, src/groupmod.c: Only
|
||||||
|
report success to audit and syslog when the changes are committed
|
||||||
|
to the system. Do not log failure for on-memory changes to audit
|
||||||
|
or syslog. Make sure failures and inconsistencies will be reported
|
||||||
|
in case of unexpected failures (e.g. malloc failures). Only
|
||||||
|
specify an audit message if it is not implicitly implied by the
|
||||||
|
type argument. Removed fail_exit (replaced by atexit(do_cleanups)).
|
||||||
|
|
||||||
2008-12-15 Nicolas François <nicolas.francois@centraliens.net>
|
2008-12-15 Nicolas François <nicolas.francois@centraliens.net>
|
||||||
|
|
||||||
* NEWS, src/gpasswd.c: Added support usernames with arbitrary
|
* NEWS, src/gpasswd.c: Added support usernames with arbitrary
|
||||||
|
12
NEWS
12
NEWS
@ -24,6 +24,13 @@ shadow-4.1.2.2 -> shadow-4.1.3 UNRELEASED
|
|||||||
* Speed improvement in case UID_MAX/SYS_UID_MAX/GID_MAX/SYS_GID_MAX is
|
* Speed improvement in case UID_MAX/SYS_UID_MAX/GID_MAX/SYS_GID_MAX is
|
||||||
used for an user/group. This should be noticeable in case of LDAP
|
used for an user/group. This should be noticeable in case of LDAP
|
||||||
configured systems. This should impact useradd, groupadd, and newusers
|
configured systems. This should impact useradd, groupadd, and newusers
|
||||||
|
- error handling improvement
|
||||||
|
* Make sure errors and incomplete changes are reported to syslog and
|
||||||
|
audit in case of unexpected failures.
|
||||||
|
* Report system inconsistencies to syslog and audit.
|
||||||
|
* Only report success to syslog and audit if the changes are really
|
||||||
|
performed in the system databases.
|
||||||
|
This is still not complete.
|
||||||
- /etc/login.defs
|
- /etc/login.defs
|
||||||
* New CREATE_HOME variable to tell useradd to create a home directory by
|
* New CREATE_HOME variable to tell useradd to create a home directory by
|
||||||
default.
|
default.
|
||||||
@ -35,9 +42,11 @@ shadow-4.1.2.2 -> shadow-4.1.3 UNRELEASED
|
|||||||
* Added support for usernames with arbitrary length.
|
* Added support for usernames with arbitrary length.
|
||||||
- groupadd
|
- groupadd
|
||||||
* audit logging improvements.
|
* audit logging improvements.
|
||||||
|
* error handling improvement (see above).
|
||||||
* Speedup (see "addition of users or groups" above).
|
* Speedup (see "addition of users or groups" above).
|
||||||
- groupdel
|
- groupdel
|
||||||
* audit logging improvements.
|
* audit logging improvements.
|
||||||
|
* error handling improvement (see above).
|
||||||
- groupmems
|
- groupmems
|
||||||
* Check if user exist before they are added to groups.
|
* Check if user exist before they are added to groups.
|
||||||
* Avoid segfault in case the specified group does not exist in /etc/group.
|
* Avoid segfault in case the specified group does not exist in /etc/group.
|
||||||
@ -50,6 +59,9 @@ shadow-4.1.2.2 -> shadow-4.1.3 UNRELEASED
|
|||||||
* Added support for shadow groups.
|
* Added support for shadow groups.
|
||||||
* Added support long options --add (-a), --delete (-d), --purge (-p),
|
* Added support long options --add (-a), --delete (-d), --purge (-p),
|
||||||
--list (-l), --group (-g).
|
--list (-l), --group (-g).
|
||||||
|
- groupmod
|
||||||
|
* audit logging improvements.
|
||||||
|
* error handling improvement (see above).
|
||||||
- newusers
|
- newusers
|
||||||
* Implement the -r, --system option.
|
* Implement the -r, --system option.
|
||||||
* Speedup (see "addition of users or groups" above).
|
* Speedup (see "addition of users or groups" above).
|
||||||
|
@ -78,6 +78,37 @@ extern int chown_tree (const char *, uid_t, uid_t, gid_t, gid_t);
|
|||||||
/* chowntty.c */
|
/* chowntty.c */
|
||||||
extern void chown_tty (const struct passwd *);
|
extern void chown_tty (const struct passwd *);
|
||||||
|
|
||||||
|
/* cleanup.c */
|
||||||
|
typedef void (*cleanup_function) (void *arg);
|
||||||
|
void add_cleanup (cleanup_function pcf, void *arg);
|
||||||
|
void del_cleanup (cleanup_function pcf);
|
||||||
|
void do_cleanups (void);
|
||||||
|
|
||||||
|
/* cleanup_group.c */
|
||||||
|
struct cleanup_info_mod {
|
||||||
|
char *audit_msg;
|
||||||
|
char *action;
|
||||||
|
char *name;
|
||||||
|
};
|
||||||
|
void cleanup_report_add_group (void *group_name);
|
||||||
|
void cleanup_report_add_group_group (void *group_name);
|
||||||
|
#ifdef SHADOWGRP
|
||||||
|
void cleanup_report_add_group_gshadow (void *group_name);
|
||||||
|
#endif
|
||||||
|
void cleanup_report_del_group (void *group_name);
|
||||||
|
void cleanup_report_del_group_group (void *group_name);
|
||||||
|
#ifdef SHADOWGRP
|
||||||
|
void cleanup_report_del_group_gshadow (void *group_name);
|
||||||
|
#endif
|
||||||
|
void cleanup_report_mod_passwd (void *cleanup_info);
|
||||||
|
void cleanup_report_mod_group (void *cleanup_info);
|
||||||
|
void cleanup_report_mod_gshadow (void *cleanup_info);
|
||||||
|
void cleanup_unlock_group (void *unused);
|
||||||
|
#ifdef SHADOWGRP
|
||||||
|
void cleanup_unlock_gshadow (void *unused);
|
||||||
|
#endif
|
||||||
|
void cleanup_unlock_passwd (void *unused);
|
||||||
|
|
||||||
/* console.c */
|
/* console.c */
|
||||||
extern bool console (const char *);
|
extern bool console (const char *);
|
||||||
|
|
||||||
@ -144,6 +175,7 @@ typedef enum {
|
|||||||
extern void audit_logger (int type, const char *pgname, const char *op,
|
extern void audit_logger (int type, const char *pgname, const char *op,
|
||||||
const char *name, unsigned int id,
|
const char *name, unsigned int id,
|
||||||
shadow_audit_result result);
|
shadow_audit_result result);
|
||||||
|
void audit_logger_message (const char *message, shadow_audit_result result);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* limits.c */
|
/* limits.c */
|
||||||
|
@ -14,6 +14,9 @@ libmisc_a_SOURCES = \
|
|||||||
chkname.h \
|
chkname.h \
|
||||||
chowndir.c \
|
chowndir.c \
|
||||||
chowntty.c \
|
chowntty.c \
|
||||||
|
cleanup.c \
|
||||||
|
cleanup_group.c \
|
||||||
|
cleanup_user.c \
|
||||||
console.c \
|
console.c \
|
||||||
copydir.c \
|
copydir.c \
|
||||||
entry.c \
|
entry.c \
|
||||||
|
@ -87,6 +87,21 @@ void audit_logger (int type, const char *pgname, const char *op,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void audit_logger_message (const char *message, shadow_audit_result result)
|
||||||
|
{
|
||||||
|
if (audit_fd < 0) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
audit_log_user_message (audit_fd,
|
||||||
|
AUDIT_USYS_CONFIG,
|
||||||
|
message,
|
||||||
|
NULL, /* hostname */
|
||||||
|
NULL, /* addr */
|
||||||
|
NULL, /* tty */
|
||||||
|
(int) result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#else /* WITH_AUDIT */
|
#else /* WITH_AUDIT */
|
||||||
extern int errno; /* warning: ANSI C forbids an empty source file */
|
extern int errno; /* warning: ANSI C forbids an empty source file */
|
||||||
#endif /* WITH_AUDIT */
|
#endif /* WITH_AUDIT */
|
||||||
|
126
libmisc/cleanup.c
Normal file
126
libmisc/cleanup.c
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2008 , Nicolas François
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the copyright holders or contributors may not be used to
|
||||||
|
* endorse or promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "prototypes.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The cleanup_functions stack.
|
||||||
|
*/
|
||||||
|
#define CLEANUP_FUNCTIONS 10
|
||||||
|
static cleanup_function cleanup_functions[CLEANUP_FUNCTIONS];
|
||||||
|
static const char * cleanup_function_args[CLEANUP_FUNCTIONS];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* - Cleanup functions shall not fail.
|
||||||
|
* - You should register do_cleanups with atexit.
|
||||||
|
* - You should add cleanup functions to the stack with add_cleanup when
|
||||||
|
* an operation is expected to be executed later, and remove it from the
|
||||||
|
* stack with del_cleanup when it has been executed.
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do_cleanups - perform the actions stored in the cleanup_functions stack.
|
||||||
|
*
|
||||||
|
* It is intended to be used as:
|
||||||
|
* atexit (do_cleanups);
|
||||||
|
*/
|
||||||
|
void do_cleanups (void)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
/* Make sure there were no overflow */
|
||||||
|
assert (NULL == cleanup_functions[CLEANUP_FUNCTIONS-1]);
|
||||||
|
|
||||||
|
i = CLEANUP_FUNCTIONS;
|
||||||
|
do {
|
||||||
|
i--;
|
||||||
|
if (cleanup_functions[i] != NULL) {
|
||||||
|
cleanup_functions[i] (cleanup_function_args[i]);
|
||||||
|
}
|
||||||
|
} while (i>0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* add_cleanup - Add a cleanup_function to the cleanup_functions stack.
|
||||||
|
*/
|
||||||
|
void add_cleanup (cleanup_function pcf, void *arg)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
assert (NULL != pcf);
|
||||||
|
|
||||||
|
assert (NULL == cleanup_functions[CLEANUP_FUNCTIONS-2]);
|
||||||
|
|
||||||
|
/* Add the cleanup_function at the end of the stack */
|
||||||
|
for (i=0; NULL != cleanup_functions[i]; i++);
|
||||||
|
cleanup_functions[i] = pcf;
|
||||||
|
cleanup_function_args[i] = arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* del_cleanup - Remove a cleanup_function from the cleanup_functions stack.
|
||||||
|
*/
|
||||||
|
void del_cleanup (cleanup_function pcf)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
assert (NULL != pcf);
|
||||||
|
|
||||||
|
/* Find the pcf cleanup function */
|
||||||
|
for (i=0; i<CLEANUP_FUNCTIONS; i++) {
|
||||||
|
if (cleanup_functions[i] == pcf) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure the cleanup function was found */
|
||||||
|
assert (i<CLEANUP_FUNCTIONS);
|
||||||
|
|
||||||
|
/* Move the rest of the cleanup functions */
|
||||||
|
for (; i<CLEANUP_FUNCTIONS; i++) {
|
||||||
|
/* Make sure the cleanup function was specified only once */
|
||||||
|
assert (cleanup_functions[i+1] != pcf);
|
||||||
|
|
||||||
|
if (i == (CLEANUP_FUNCTIONS -1)) {
|
||||||
|
cleanup_functions[i] = NULL;
|
||||||
|
} else {
|
||||||
|
cleanup_functions[i] = cleanup_functions[i+1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A NULL indicates the end of the stack */
|
||||||
|
if (NULL == cleanup_functions[i]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
235
libmisc/cleanup_group.c
Normal file
235
libmisc/cleanup_group.c
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2008 , Nicolas François
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the copyright holders or contributors may not be used to
|
||||||
|
* endorse or promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
#include "groupio.h"
|
||||||
|
#include "sgroupio.h"
|
||||||
|
#include "prototypes.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cleanup_report_add_group - Report failure to add a group to the system
|
||||||
|
*
|
||||||
|
* It should be registered when it is decided to add a group to the system.
|
||||||
|
*/
|
||||||
|
void cleanup_report_add_group (void *group_name)
|
||||||
|
{
|
||||||
|
const char *name = (const char *)group_name;
|
||||||
|
|
||||||
|
SYSLOG ((LOG_ERR, "failed to add group %s", name));
|
||||||
|
#ifdef WITH_AUDIT
|
||||||
|
audit_logger (AUDIT_ADD_GROUP, Prog,
|
||||||
|
"",
|
||||||
|
name, AUDIT_NO_ID,
|
||||||
|
SHADOW_AUDIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cleanup_report_del_group - Report failure to remove a group from the system
|
||||||
|
*
|
||||||
|
* It should be registered when it is decided to remove a group from the system.
|
||||||
|
*/
|
||||||
|
void cleanup_report_del_group (void *group_name)
|
||||||
|
{
|
||||||
|
const char *name = (const char *)group_name;
|
||||||
|
|
||||||
|
SYSLOG ((LOG_ERR, "failed to remove group %s", name));
|
||||||
|
#ifdef WITH_AUDIT
|
||||||
|
audit_logger (AUDIT_DEL_GROUP, Prog,
|
||||||
|
"",
|
||||||
|
name, AUDIT_NO_ID,
|
||||||
|
SHADOW_AUDIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup_report_mod_group (void *cleanup_info)
|
||||||
|
{
|
||||||
|
const struct cleanup_info_mod *info;
|
||||||
|
info = (const struct cleanup_info_mod *)cleanup_info;
|
||||||
|
|
||||||
|
SYSLOG ((LOG_ERR,
|
||||||
|
"failed to change %s (%s)",
|
||||||
|
gr_dbname (),
|
||||||
|
info->action));
|
||||||
|
#ifdef WITH_AUDIT
|
||||||
|
audit_logger (AUDIT_USER_ACCT, Prog,
|
||||||
|
info->audit_msg,
|
||||||
|
info->name, AUDIT_NO_ID,
|
||||||
|
SHADOW_AUDIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup_report_mod_gshadow (void *cleanup_info)
|
||||||
|
{
|
||||||
|
const struct cleanup_info_mod *info;
|
||||||
|
info = (const struct cleanup_info_mod *)cleanup_info;
|
||||||
|
|
||||||
|
SYSLOG ((LOG_ERR,
|
||||||
|
"failed to change %s (%s)",
|
||||||
|
sgr_dbname (),
|
||||||
|
info->action));
|
||||||
|
#ifdef WITH_AUDIT
|
||||||
|
audit_logger (AUDIT_USER_ACCT, Prog,
|
||||||
|
info->audit_msg,
|
||||||
|
info->name, AUDIT_NO_ID,
|
||||||
|
SHADOW_AUDIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cleanup_report_add_group_group - Report failure to add a group to group
|
||||||
|
*
|
||||||
|
* It should be registered when it is decided to add a group to the
|
||||||
|
* group database.
|
||||||
|
*/
|
||||||
|
void cleanup_report_add_group_group (void *group_name)
|
||||||
|
{
|
||||||
|
const char *name = (const char *)group_name;
|
||||||
|
|
||||||
|
SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, gr_dbname ()));
|
||||||
|
#ifdef WITH_AUDIT
|
||||||
|
audit_logger (AUDIT_ADD_GROUP, Prog,
|
||||||
|
"adding group to /etc/group",
|
||||||
|
name, AUDIT_NO_ID,
|
||||||
|
SHADOW_AUDIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SHADOWGRP
|
||||||
|
/*
|
||||||
|
* cleanup_report_add_group_gshadow - Report failure to add a group to gshadow
|
||||||
|
*
|
||||||
|
* It should be registered when it is decided to add a group to the
|
||||||
|
* gshadow database.
|
||||||
|
*/
|
||||||
|
void cleanup_report_add_group_gshadow (void *group_name)
|
||||||
|
{
|
||||||
|
const char *name = (const char *)group_name;
|
||||||
|
|
||||||
|
SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, sgr_dbname ()));
|
||||||
|
#ifdef WITH_AUDIT
|
||||||
|
audit_logger (AUDIT_ADD_GROUP, Prog,
|
||||||
|
"adding group to /etc/gshadow",
|
||||||
|
name, AUDIT_NO_ID,
|
||||||
|
SHADOW_AUDIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cleanup_report_del_group_group - Report failure to remove a group from the
|
||||||
|
* regular group database
|
||||||
|
*
|
||||||
|
* It should be registered when it is decided to remove a group from the
|
||||||
|
* regular group database.
|
||||||
|
*/
|
||||||
|
void cleanup_report_del_group_group (void *group_name)
|
||||||
|
{
|
||||||
|
const char *name = (const char *)group_name;
|
||||||
|
|
||||||
|
SYSLOG ((LOG_ERR,
|
||||||
|
"failed to remove group %s from %s",
|
||||||
|
name, gr_dbname ()));
|
||||||
|
#ifdef WITH_AUDIT
|
||||||
|
audit_logger (AUDIT_ADD_GROUP, Prog,
|
||||||
|
"removing group from /etc/group",
|
||||||
|
name, AUDIT_NO_ID,
|
||||||
|
SHADOW_AUDIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SHADOWGRP
|
||||||
|
/*
|
||||||
|
* cleanup_report_del_group_gshadow - Report failure to remove a group from
|
||||||
|
* gshadow
|
||||||
|
*
|
||||||
|
* It should be registered when it is decided to remove a group from the
|
||||||
|
* gshadow database.
|
||||||
|
*/
|
||||||
|
void cleanup_report_del_group_gshadow (void *group_name)
|
||||||
|
{
|
||||||
|
const char *name = (const char *)group_name;
|
||||||
|
|
||||||
|
SYSLOG ((LOG_ERR,
|
||||||
|
"failed to remove group %s from %s",
|
||||||
|
name, sgr_dbname ()));
|
||||||
|
#ifdef WITH_AUDIT
|
||||||
|
audit_logger (AUDIT_ADD_GROUP, Prog,
|
||||||
|
"removing group from /etc/gshadow",
|
||||||
|
name, AUDIT_NO_ID,
|
||||||
|
SHADOW_AUDIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cleanup_unlock_group - Unlock the group file
|
||||||
|
*
|
||||||
|
* It should be registered after the group file is successfully locked.
|
||||||
|
*/
|
||||||
|
void cleanup_unlock_group (unused void *arg)
|
||||||
|
{
|
||||||
|
if (gr_unlock () == 0) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: failed to unlock %s\n"),
|
||||||
|
Prog, gr_dbname ());
|
||||||
|
SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ()));
|
||||||
|
#ifdef WITH_AUDIT
|
||||||
|
audit_logger_message ("unlocking group file",
|
||||||
|
SHADOW_AUDIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SHADOWGRP
|
||||||
|
/*
|
||||||
|
* cleanup_unlock_gshadow - Unlock the gshadow file
|
||||||
|
*
|
||||||
|
* It should be registered after the gshadow file is successfully locked.
|
||||||
|
*/
|
||||||
|
void cleanup_unlock_gshadow (unused void *arg)
|
||||||
|
{
|
||||||
|
if (sgr_unlock () == 0) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: failed to unlock %s\n"),
|
||||||
|
Prog, sgr_dbname ());
|
||||||
|
SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ()));
|
||||||
|
#ifdef WITH_AUDIT
|
||||||
|
audit_logger_message ("unlocking gshadow file",
|
||||||
|
SHADOW_AUDIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
152
libmisc/cleanup_user.c
Normal file
152
libmisc/cleanup_user.c
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2008 , Nicolas François
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the copyright holders or contributors may not be used to
|
||||||
|
* endorse or promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
#include "pwio.h"
|
||||||
|
#include "shadowio.h"
|
||||||
|
#include "prototypes.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cleanup_report_add_user - Report failure to add an user to the system
|
||||||
|
*
|
||||||
|
* It should be registered when it is decided to add an user to the system.
|
||||||
|
*/
|
||||||
|
void cleanup_report_add_user (void *user_name)
|
||||||
|
{
|
||||||
|
const char *name = (const char *)user_name;
|
||||||
|
|
||||||
|
SYSLOG ((LOG_ERR, "failed to add user %s", name));
|
||||||
|
#ifdef WITH_AUDIT
|
||||||
|
audit_logger (AUDIT_ADD_USER, Prog,
|
||||||
|
"",
|
||||||
|
name, AUDIT_NO_ID,
|
||||||
|
SHADOW_AUDIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup_report_mod_passwd (void *cleanup_info)
|
||||||
|
{
|
||||||
|
const struct cleanup_info_mod *info;
|
||||||
|
info = (const struct cleanup_info_mod *)cleanup_info;
|
||||||
|
|
||||||
|
SYSLOG ((LOG_ERR,
|
||||||
|
"failed to change %s (%s)",
|
||||||
|
pw_dbname (),
|
||||||
|
info->action));
|
||||||
|
#ifdef WITH_AUDIT
|
||||||
|
audit_logger (AUDIT_USER_ACCT, Prog,
|
||||||
|
info->audit_msg,
|
||||||
|
info->name, AUDIT_NO_ID,
|
||||||
|
SHADOW_AUDIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cleanup_report_add_user_passwd - Report failure to add an user to
|
||||||
|
* /etc/passwd
|
||||||
|
*
|
||||||
|
* It should be registered when it is decided to add an user to the
|
||||||
|
* /etc/passwd database.
|
||||||
|
*/
|
||||||
|
void cleanup_report_add_user_passwd (void *user_name)
|
||||||
|
{
|
||||||
|
const char *name = (const char *)user_name;
|
||||||
|
|
||||||
|
SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, pw_dbname ()));
|
||||||
|
#ifdef WITH_AUDIT
|
||||||
|
audit_logger (AUDIT_ADD_USER, Prog,
|
||||||
|
"adding user to /etc/passwd",
|
||||||
|
name, AUDIT_NO_ID,
|
||||||
|
SHADOW_AUDIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cleanup_report_add_user_shadow - Report failure to add an user to
|
||||||
|
* /etc/shadow
|
||||||
|
*
|
||||||
|
* It should be registered when it is decided to add an user to the
|
||||||
|
* /etc/shadow database.
|
||||||
|
*/
|
||||||
|
void cleanup_report_add_user_shadow (void *user_name)
|
||||||
|
{
|
||||||
|
const char *name = (const char *)user_name;
|
||||||
|
|
||||||
|
SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, spw_dbname ()));
|
||||||
|
#ifdef WITH_AUDIT
|
||||||
|
audit_logger (AUDIT_ADD_USER, Prog,
|
||||||
|
"adding user to /etc/shadow",
|
||||||
|
name, AUDIT_NO_ID,
|
||||||
|
SHADOW_AUDIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cleanup_unlock_passwd - Unlock the /etc/passwd database
|
||||||
|
*
|
||||||
|
* It should be registered after the passwd database is successfully locked.
|
||||||
|
*/
|
||||||
|
void cleanup_unlock_passwd (unused void *arg)
|
||||||
|
{
|
||||||
|
if (pw_unlock () == 0) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: failed to unlock %s\n"),
|
||||||
|
Prog, pw_dbname ());
|
||||||
|
SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
|
||||||
|
#ifdef WITH_AUDIT
|
||||||
|
audit_logger_message ("unlocking passwd file",
|
||||||
|
SHADOW_AUDIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cleanup_unlock_shadow - Unlock the /etc/shadow database
|
||||||
|
*
|
||||||
|
* It should be registered after the shadow database is successfully locked.
|
||||||
|
*/
|
||||||
|
void cleanup_unlock_shadow (unused void *arg)
|
||||||
|
{
|
||||||
|
if (spw_unlock () == 0) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: failed to unlock %s\n"),
|
||||||
|
Prog, spw_dbname ());
|
||||||
|
SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ()));
|
||||||
|
#ifdef WITH_AUDIT
|
||||||
|
audit_logger_message ("unlocking shadow file",
|
||||||
|
SHADOW_AUDIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
213
src/groupadd.c
213
src/groupadd.c
@ -85,9 +85,7 @@ static bool pflg = false; /* new encrypted password */
|
|||||||
|
|
||||||
#ifdef SHADOWGRP
|
#ifdef SHADOWGRP
|
||||||
static bool is_shadow_grp;
|
static bool is_shadow_grp;
|
||||||
static bool sgr_locked = false;
|
|
||||||
#endif
|
#endif
|
||||||
static bool gr_locked = false;
|
|
||||||
|
|
||||||
/* local function prototypes */
|
/* local function prototypes */
|
||||||
static void usage (void);
|
static void usage (void);
|
||||||
@ -100,7 +98,6 @@ static void grp_update (void);
|
|||||||
static void check_new_name (void);
|
static void check_new_name (void);
|
||||||
static void close_files (void);
|
static void close_files (void);
|
||||||
static void open_files (void);
|
static void open_files (void);
|
||||||
static void fail_exit (int code);
|
|
||||||
static gid_t get_gid (const char *gidstr);
|
static gid_t get_gid (const char *gidstr);
|
||||||
static void process_flags (int argc, char **argv);
|
static void process_flags (int argc, char **argv);
|
||||||
static void check_flags (void);
|
static void check_flags (void);
|
||||||
@ -180,6 +177,18 @@ static void grp_update (void)
|
|||||||
struct sgrp sgrp;
|
struct sgrp sgrp;
|
||||||
#endif /* SHADOWGRP */
|
#endif /* SHADOWGRP */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To add the group, we need to update /etc/group.
|
||||||
|
* Make sure failures will be reported.
|
||||||
|
*/
|
||||||
|
add_cleanup (cleanup_report_add_group_group, group_name);
|
||||||
|
#ifdef SHADOWGRP
|
||||||
|
if (is_shadow_grp) {
|
||||||
|
/* We also need to update /etc/gshadow */
|
||||||
|
add_cleanup (cleanup_report_add_group_gshadow, group_name);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create the initial entries for this new group.
|
* Create the initial entries for this new group.
|
||||||
*/
|
*/
|
||||||
@ -198,7 +207,7 @@ static void grp_update (void)
|
|||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: failed to prepare the new %s entry '%s'\n"),
|
_("%s: failed to prepare the new %s entry '%s'\n"),
|
||||||
Prog, gr_dbname (), grp.gr_name);
|
Prog, gr_dbname (), grp.gr_name);
|
||||||
fail_exit (E_GRP_UPDATE);
|
exit (E_GRP_UPDATE);
|
||||||
}
|
}
|
||||||
#ifdef SHADOWGRP
|
#ifdef SHADOWGRP
|
||||||
/*
|
/*
|
||||||
@ -208,17 +217,9 @@ static void grp_update (void)
|
|||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: failed to prepare the new %s entry '%s'\n"),
|
_("%s: failed to prepare the new %s entry '%s'\n"),
|
||||||
Prog, sgr_dbname (), sgrp.sg_name);
|
Prog, sgr_dbname (), sgrp.sg_name);
|
||||||
fail_exit (E_GRP_UPDATE);
|
exit (E_GRP_UPDATE);
|
||||||
}
|
}
|
||||||
#endif /* SHADOWGRP */
|
#endif /* SHADOWGRP */
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_ADD_GROUP, Prog,
|
|
||||||
"adding group",
|
|
||||||
group_name, (unsigned int) group_id,
|
|
||||||
SHADOW_AUDIT_SUCCESS);
|
|
||||||
#endif
|
|
||||||
SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u",
|
|
||||||
group_name, (unsigned int) group_id));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -251,45 +252,60 @@ static void check_new_name (void)
|
|||||||
*/
|
*/
|
||||||
static void close_files (void)
|
static void close_files (void)
|
||||||
{
|
{
|
||||||
|
/* First, write the changes in the regular group database */
|
||||||
if (gr_close () == 0) {
|
if (gr_close () == 0) {
|
||||||
fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ());
|
fprintf (stderr,
|
||||||
SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ()));
|
_("%s: failure while writing changes to %s\n"),
|
||||||
fail_exit (E_GRP_UPDATE);
|
Prog, gr_dbname ());
|
||||||
|
exit (E_GRP_UPDATE);
|
||||||
}
|
}
|
||||||
if (gr_unlock () == 0) {
|
|
||||||
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ());
|
|
||||||
SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
#ifdef WITH_AUDIT
|
||||||
audit_logger (AUDIT_ADD_GROUP, Prog,
|
audit_logger (AUDIT_ADD_GROUP, Prog,
|
||||||
"unlocking group file",
|
"adding group to /etc/group",
|
||||||
group_name, AUDIT_NO_ID,
|
group_name, (unsigned int) group_id,
|
||||||
SHADOW_AUDIT_FAILURE);
|
SHADOW_AUDIT_SUCCESS);
|
||||||
#endif
|
#endif
|
||||||
/* continue */
|
SYSLOG ((LOG_INFO, "group added to %s: name=%s, GID=%u",
|
||||||
}
|
gr_dbname (), group_name, (unsigned int) group_id));
|
||||||
gr_locked = false;
|
del_cleanup (cleanup_report_add_group_group);
|
||||||
|
|
||||||
|
cleanup_unlock_group (NULL);
|
||||||
|
del_cleanup (cleanup_unlock_group);
|
||||||
|
|
||||||
|
/* Now, write the changes in the shadow database */
|
||||||
#ifdef SHADOWGRP
|
#ifdef SHADOWGRP
|
||||||
if (is_shadow_grp) {
|
if (is_shadow_grp) {
|
||||||
if (sgr_close () == 0) {
|
if (sgr_close () == 0) {
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: failure while writing changes to %s\n"), Prog, sgr_dbname ());
|
_("%s: failure while writing changes to %s\n"),
|
||||||
SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ()));
|
Prog, sgr_dbname ());
|
||||||
fail_exit (E_GRP_UPDATE);
|
exit (E_GRP_UPDATE);
|
||||||
}
|
}
|
||||||
if (sgr_unlock () == 0) {
|
|
||||||
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ());
|
|
||||||
SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
#ifdef WITH_AUDIT
|
||||||
audit_logger (AUDIT_ADD_GROUP, Prog,
|
audit_logger (AUDIT_ADD_GROUP, Prog,
|
||||||
"unlocking gshadow file",
|
"adding group to /etc/gshadow",
|
||||||
group_name, AUDIT_NO_ID,
|
group_name, (unsigned int) group_id,
|
||||||
SHADOW_AUDIT_FAILURE);
|
SHADOW_AUDIT_SUCCESS);
|
||||||
#endif
|
#endif
|
||||||
/* continue */
|
SYSLOG ((LOG_INFO, "group added to %s: name=%s",
|
||||||
}
|
sgr_dbname (), group_name));
|
||||||
sgr_locked = false;
|
del_cleanup (cleanup_report_add_group_gshadow);
|
||||||
|
|
||||||
|
cleanup_unlock_gshadow (NULL);
|
||||||
|
del_cleanup (cleanup_unlock_gshadow);
|
||||||
}
|
}
|
||||||
#endif /* SHADOWGRP */
|
#endif /* SHADOWGRP */
|
||||||
|
|
||||||
|
/* Report success at the system level */
|
||||||
|
#ifdef WITH_AUDIT
|
||||||
|
audit_logger (AUDIT_ADD_GROUP, Prog,
|
||||||
|
"",
|
||||||
|
group_name, (unsigned int) group_id,
|
||||||
|
SHADOW_AUDIT_SUCCESS);
|
||||||
|
#endif
|
||||||
|
SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u",
|
||||||
|
group_name, (unsigned int) group_id));
|
||||||
|
del_cleanup (cleanup_report_add_group);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -299,107 +315,53 @@ static void close_files (void)
|
|||||||
*/
|
*/
|
||||||
static void open_files (void)
|
static void open_files (void)
|
||||||
{
|
{
|
||||||
|
/* First, lock the databases */
|
||||||
if (gr_lock () == 0) {
|
if (gr_lock () == 0) {
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: cannot lock %s; try again later.\n"),
|
_("%s: cannot lock %s; try again later.\n"),
|
||||||
Prog, gr_dbname ());
|
Prog, gr_dbname ());
|
||||||
#ifdef WITH_AUDIT
|
exit (E_GRP_UPDATE);
|
||||||
audit_logger (AUDIT_ADD_GROUP, Prog,
|
|
||||||
"locking group file",
|
|
||||||
group_name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
fail_exit (E_GRP_UPDATE);
|
|
||||||
}
|
|
||||||
gr_locked = true;
|
|
||||||
if (gr_open (O_RDWR) == 0) {
|
|
||||||
fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ());
|
|
||||||
SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_ADD_GROUP, Prog,
|
|
||||||
"opening group file",
|
|
||||||
group_name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
fail_exit (E_GRP_UPDATE);
|
|
||||||
}
|
}
|
||||||
|
add_cleanup (cleanup_unlock_group, NULL);
|
||||||
|
|
||||||
#ifdef SHADOWGRP
|
#ifdef SHADOWGRP
|
||||||
if (is_shadow_grp) {
|
if (is_shadow_grp) {
|
||||||
if (sgr_lock () == 0) {
|
if (sgr_lock () == 0) {
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: cannot lock %s; try again later.\n"),
|
_("%s: cannot lock %s; try again later.\n"),
|
||||||
Prog, sgr_dbname ());
|
Prog, sgr_dbname ());
|
||||||
#ifdef WITH_AUDIT
|
exit (E_GRP_UPDATE);
|
||||||
audit_logger (AUDIT_ADD_GROUP, Prog,
|
|
||||||
"locking gshadow file",
|
|
||||||
group_name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
fail_exit (E_GRP_UPDATE);
|
|
||||||
}
|
}
|
||||||
sgr_locked = true;
|
add_cleanup (cleanup_unlock_gshadow, NULL);
|
||||||
|
}
|
||||||
|
#endif /* SHADOWGRP */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now if the group is not added, it's our fault.
|
||||||
|
* Make sure failures will be reported.
|
||||||
|
*/
|
||||||
|
add_cleanup (cleanup_report_add_group, group_name);
|
||||||
|
|
||||||
|
/* An now open the databases */
|
||||||
|
if (gr_open (O_RDWR) == 0) {
|
||||||
|
fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ());
|
||||||
|
SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ()));
|
||||||
|
exit (E_GRP_UPDATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SHADOWGRP
|
||||||
|
if (is_shadow_grp) {
|
||||||
if (sgr_open (O_RDWR) == 0) {
|
if (sgr_open (O_RDWR) == 0) {
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: cannot open %s\n"), Prog, sgr_dbname ());
|
_("%s: cannot open %s\n"),
|
||||||
|
Prog, sgr_dbname ());
|
||||||
SYSLOG ((LOG_WARN, "cannot open %s", sgr_dbname ()));
|
SYSLOG ((LOG_WARN, "cannot open %s", sgr_dbname ()));
|
||||||
#ifdef WITH_AUDIT
|
exit (E_GRP_UPDATE);
|
||||||
audit_logger (AUDIT_ADD_GROUP, Prog,
|
|
||||||
"opening gshadow file",
|
|
||||||
group_name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (gr_locked) {
|
|
||||||
if (gr_unlock () == 0) {
|
|
||||||
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ());
|
|
||||||
SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_ADD_GROUP, Prog,
|
|
||||||
"unlocking group file",
|
|
||||||
group_name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
/* continue */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef SHADOWGRP
|
|
||||||
if (sgr_locked) {
|
|
||||||
if (sgr_unlock () == 0) {
|
|
||||||
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ());
|
|
||||||
SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_ADD_GROUP, Prog,
|
|
||||||
"unlocking gshadow file",
|
|
||||||
group_name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
/* continue */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
if (code != E_SUCCESS) {
|
|
||||||
audit_logger (AUDIT_ADD_GROUP, Prog,
|
|
||||||
"adding group",
|
|
||||||
group_name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
exit (code);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_id - validate and get group ID
|
* get_id - validate and get group ID
|
||||||
*/
|
*/
|
||||||
@ -529,10 +491,10 @@ static void check_flags (void)
|
|||||||
/* The group already exist */
|
/* The group already exist */
|
||||||
if (fflg) {
|
if (fflg) {
|
||||||
/* OK, no need to do anything */
|
/* OK, no need to do anything */
|
||||||
fail_exit (E_SUCCESS);
|
exit (E_SUCCESS);
|
||||||
}
|
}
|
||||||
fprintf (stderr, _("%s: group '%s' already exists\n"), Prog, group_name);
|
fprintf (stderr, _("%s: group '%s' already exists\n"), Prog, group_name);
|
||||||
fail_exit (E_NAME_IN_USE);
|
exit (E_NAME_IN_USE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gflg && (getgrgid (group_id) != NULL)) {
|
if (gflg && (getgrgid (group_id) != NULL)) {
|
||||||
@ -550,7 +512,7 @@ static void check_flags (void)
|
|||||||
} else {
|
} else {
|
||||||
fprintf (stderr, _("%s: GID '%lu' already exists\n"),
|
fprintf (stderr, _("%s: GID '%lu' already exists\n"),
|
||||||
Prog, (unsigned long int) group_id);
|
Prog, (unsigned long int) group_id);
|
||||||
fail_exit (E_GID_IN_USE);
|
exit (E_GID_IN_USE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -610,6 +572,8 @@ int main (int argc, char **argv)
|
|||||||
#ifdef WITH_AUDIT
|
#ifdef WITH_AUDIT
|
||||||
audit_help_open ();
|
audit_help_open ();
|
||||||
#endif
|
#endif
|
||||||
|
atexit (do_cleanups);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get my name so that I can use it to report errors.
|
* Get my name so that I can use it to report errors.
|
||||||
*/
|
*/
|
||||||
@ -640,8 +604,7 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
if (!gflg) {
|
if (!gflg) {
|
||||||
if (find_new_gid (rflg, &group_id, NULL) < 0) {
|
if (find_new_gid (rflg, &group_id, NULL) < 0) {
|
||||||
fprintf (stderr, _("%s: can't create group\n"), Prog);
|
exit (E_GID_IN_USE);
|
||||||
fail_exit (E_GID_IN_USE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
200
src/groupdel.c
200
src/groupdel.c
@ -62,9 +62,7 @@ static gid_t group_id = -1;
|
|||||||
|
|
||||||
#ifdef SHADOWGRP
|
#ifdef SHADOWGRP
|
||||||
static bool is_shadow_grp;
|
static bool is_shadow_grp;
|
||||||
static bool sgr_locked = false;
|
|
||||||
#endif
|
#endif
|
||||||
static bool gr_locked = false;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* exit status values
|
* exit status values
|
||||||
@ -92,50 +90,6 @@ static void usage (void)
|
|||||||
exit (E_USAGE);
|
exit (E_USAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* fail_exit - exit with a failure code after unlocking the files
|
|
||||||
*/
|
|
||||||
static void fail_exit (int code)
|
|
||||||
{
|
|
||||||
if (gr_locked) {
|
|
||||||
if (gr_unlock () == 0) {
|
|
||||||
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ());
|
|
||||||
SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_DEL_GROUP, Prog,
|
|
||||||
"unlocking group file",
|
|
||||||
group_name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
/* continue */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef SHADOWGRP
|
|
||||||
if (sgr_locked) {
|
|
||||||
if (sgr_unlock () == 0) {
|
|
||||||
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ());
|
|
||||||
SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_DEL_GROUP, Prog,
|
|
||||||
"unlocking gshadow file",
|
|
||||||
group_name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
/* continue */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_DEL_GROUP, Prog,
|
|
||||||
"deleting group",
|
|
||||||
group_name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
exit (code);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* grp_update - update group file entries
|
* grp_update - update group file entries
|
||||||
*
|
*
|
||||||
@ -143,12 +97,28 @@ static void fail_exit (int code)
|
|||||||
*/
|
*/
|
||||||
static void grp_update (void)
|
static void grp_update (void)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* To add the group, we need to update /etc/group.
|
||||||
|
* Make sure failures will be reported.
|
||||||
|
*/
|
||||||
|
add_cleanup (cleanup_report_del_group_group, group_name);
|
||||||
|
#ifdef SHADOWGRP
|
||||||
|
if (is_shadow_grp) {
|
||||||
|
/* We also need to update /etc/gshadow */
|
||||||
|
add_cleanup (cleanup_report_del_group_gshadow, group_name);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delete the group entry.
|
||||||
|
*/
|
||||||
if (gr_remove (group_name) == 0) {
|
if (gr_remove (group_name) == 0) {
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: cannot remove entry '%s' from %s\n"),
|
_("%s: cannot remove entry '%s' from %s\n"),
|
||||||
Prog, group_name, gr_dbname ());
|
Prog, group_name, gr_dbname ());
|
||||||
fail_exit (E_GRP_UPDATE);
|
exit (E_GRP_UPDATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SHADOWGRP
|
#ifdef SHADOWGRP
|
||||||
/*
|
/*
|
||||||
* Delete the shadow group entries as well.
|
* Delete the shadow group entries as well.
|
||||||
@ -158,11 +128,10 @@ static void grp_update (void)
|
|||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: cannot remove entry '%s' from %s\n"),
|
_("%s: cannot remove entry '%s' from %s\n"),
|
||||||
Prog, group_name, sgr_dbname ());
|
Prog, group_name, sgr_dbname ());
|
||||||
fail_exit (E_GRP_UPDATE);
|
exit (E_GRP_UPDATE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* SHADOWGRP */
|
#endif /* SHADOWGRP */
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -173,54 +142,64 @@ static void grp_update (void)
|
|||||||
*/
|
*/
|
||||||
static void close_files (void)
|
static void close_files (void)
|
||||||
{
|
{
|
||||||
|
/* First, write the changes in the regular group database */
|
||||||
|
if (gr_close () == 0) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: failure while writing changes to %s\n"),
|
||||||
|
Prog, gr_dbname ());
|
||||||
|
exit (E_GRP_UPDATE);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef WITH_AUDIT
|
#ifdef WITH_AUDIT
|
||||||
audit_logger (AUDIT_DEL_GROUP, Prog,
|
audit_logger (AUDIT_DEL_GROUP, Prog,
|
||||||
"deleting group",
|
"removing group from /etc/group",
|
||||||
group_name, (unsigned int) group_id,
|
group_name, (unsigned int) group_id,
|
||||||
SHADOW_AUDIT_SUCCESS);
|
SHADOW_AUDIT_SUCCESS);
|
||||||
#endif
|
#endif
|
||||||
SYSLOG ((LOG_INFO, "remove group '%s'\n", group_name));
|
SYSLOG ((LOG_INFO,
|
||||||
|
"group '%s' removed from %s",
|
||||||
|
group_name, gr_dbname ()));
|
||||||
|
del_cleanup (cleanup_report_del_group_group);
|
||||||
|
|
||||||
if (gr_close () == 0) {
|
cleanup_unlock_group (NULL);
|
||||||
fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ());
|
del_cleanup (cleanup_unlock_group);
|
||||||
SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ()));
|
|
||||||
fail_exit (E_GRP_UPDATE);
|
|
||||||
}
|
/* Then, write the changes in the shadow database */
|
||||||
if (gr_unlock () == 0) {
|
|
||||||
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ());
|
|
||||||
SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_DEL_GROUP, Prog,
|
|
||||||
"unlocking group file",
|
|
||||||
group_name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
/* continue */
|
|
||||||
}
|
|
||||||
gr_locked = false;
|
|
||||||
#ifdef SHADOWGRP
|
#ifdef SHADOWGRP
|
||||||
if (is_shadow_grp) {
|
if (is_shadow_grp) {
|
||||||
if (sgr_close () == 0) {
|
if (sgr_close () == 0) {
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: failure while writing changes to %s\n"),
|
_("%s: failure while writing changes to %s\n"),
|
||||||
Prog, sgr_dbname ());
|
Prog, sgr_dbname ());
|
||||||
SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ()));
|
exit (E_GRP_UPDATE);
|
||||||
fail_exit (E_GRP_UPDATE);
|
|
||||||
}
|
}
|
||||||
if (sgr_unlock () == 0) {
|
|
||||||
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ());
|
|
||||||
SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
#ifdef WITH_AUDIT
|
||||||
audit_logger (AUDIT_DEL_GROUP, Prog,
|
audit_logger (AUDIT_DEL_GROUP, Prog,
|
||||||
"unlocking gshadow file",
|
"removing group from /etc/gshadow",
|
||||||
group_name, AUDIT_NO_ID,
|
group_name, (unsigned int) group_id,
|
||||||
SHADOW_AUDIT_FAILURE);
|
SHADOW_AUDIT_SUCCESS);
|
||||||
#endif
|
#endif
|
||||||
/* continue */
|
SYSLOG ((LOG_INFO,
|
||||||
}
|
"group '%s' removed from %s",
|
||||||
sgr_locked = false;
|
group_name, sgr_dbname ()));
|
||||||
|
del_cleanup (cleanup_report_del_group_gshadow);
|
||||||
|
|
||||||
|
cleanup_unlock_gshadow (NULL);
|
||||||
|
del_cleanup (cleanup_unlock_gshadow);
|
||||||
}
|
}
|
||||||
#endif /* SHADOWGRP */
|
#endif /* SHADOWGRP */
|
||||||
|
|
||||||
|
/* Report success at the system level */
|
||||||
|
#ifdef WITH_AUDIT
|
||||||
|
audit_logger (AUDIT_DEL_GROUP, Prog,
|
||||||
|
"",
|
||||||
|
group_name, (unsigned int) group_id,
|
||||||
|
SHADOW_AUDIT_SUCCESS);
|
||||||
|
#endif
|
||||||
|
SYSLOG ((LOG_INFO, "group '%s' removed\n", group_name));
|
||||||
|
del_cleanup (cleanup_report_del_group);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -230,34 +209,47 @@ static void close_files (void)
|
|||||||
*/
|
*/
|
||||||
static void open_files (void)
|
static void open_files (void)
|
||||||
{
|
{
|
||||||
|
/* First, lock the databases */
|
||||||
if (gr_lock () == 0) {
|
if (gr_lock () == 0) {
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: cannot lock %s; try again later.\n"),
|
_("%s: cannot lock %s; try again later.\n"),
|
||||||
Prog, gr_dbname ());
|
Prog, gr_dbname ());
|
||||||
fail_exit (E_GRP_UPDATE);
|
exit (E_GRP_UPDATE);
|
||||||
}
|
|
||||||
gr_locked = true;
|
|
||||||
if (gr_open (O_RDWR) == 0) {
|
|
||||||
fprintf (stderr,
|
|
||||||
_("%s: cannot open %s\n"), Prog, gr_dbname ());
|
|
||||||
SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ()));
|
|
||||||
fail_exit (E_GRP_UPDATE);
|
|
||||||
}
|
}
|
||||||
|
add_cleanup (cleanup_unlock_group, NULL);
|
||||||
#ifdef SHADOWGRP
|
#ifdef SHADOWGRP
|
||||||
if (is_shadow_grp) {
|
if (is_shadow_grp) {
|
||||||
if (sgr_lock () == 0) {
|
if (sgr_lock () == 0) {
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: cannot lock %s; try again later.\n"),
|
_("%s: cannot lock %s; try again later.\n"),
|
||||||
Prog, sgr_dbname ());
|
Prog, sgr_dbname ());
|
||||||
fail_exit (E_GRP_UPDATE);
|
exit (E_GRP_UPDATE);
|
||||||
}
|
}
|
||||||
sgr_locked = true;
|
add_cleanup (cleanup_unlock_gshadow, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now, if the group is not removed, it's our fault.
|
||||||
|
* Make sure failures will be reported.
|
||||||
|
*/
|
||||||
|
add_cleanup (cleanup_report_del_group, group_name);
|
||||||
|
|
||||||
|
/* An now open the databases */
|
||||||
|
if (gr_open (O_RDWR) == 0) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: cannot open %s\n"), Prog, gr_dbname ());
|
||||||
|
SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ()));
|
||||||
|
exit (E_GRP_UPDATE);
|
||||||
|
}
|
||||||
|
#ifdef SHADOWGRP
|
||||||
|
if (is_shadow_grp) {
|
||||||
if (sgr_open (O_RDWR) == 0) {
|
if (sgr_open (O_RDWR) == 0) {
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: cannot open %s\n"),
|
_("%s: cannot open %s\n"),
|
||||||
Prog, sgr_dbname ());
|
Prog, sgr_dbname ());
|
||||||
SYSLOG ((LOG_WARN, "cannot open %s", sgr_dbname ()));
|
SYSLOG ((LOG_WARN, "cannot open %s", sgr_dbname ()));
|
||||||
fail_exit (E_GRP_UPDATE);
|
exit (E_GRP_UPDATE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* SHADOWGRP */
|
#endif /* SHADOWGRP */
|
||||||
@ -295,8 +287,10 @@ static void group_busy (gid_t gid)
|
|||||||
/*
|
/*
|
||||||
* Can't remove the group.
|
* Can't remove the group.
|
||||||
*/
|
*/
|
||||||
fprintf (stderr, _("%s: cannot remove the primary group of user '%s'\n"), Prog, pwd->pw_name);
|
fprintf (stderr,
|
||||||
fail_exit (E_GROUP_BUSY);
|
_("%s: cannot remove the primary group of user '%s'\n"),
|
||||||
|
Prog, pwd->pw_name);
|
||||||
|
exit (E_GROUP_BUSY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -321,6 +315,7 @@ int main (int argc, char **argv)
|
|||||||
#ifdef WITH_AUDIT
|
#ifdef WITH_AUDIT
|
||||||
audit_help_open ();
|
audit_help_open ();
|
||||||
#endif
|
#endif
|
||||||
|
atexit (do_cleanups);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get my name so that I can use it to report errors.
|
* Get my name so that I can use it to report errors.
|
||||||
@ -384,18 +379,13 @@ int main (int argc, char **argv)
|
|||||||
*/
|
*/
|
||||||
grp = getgrnam (group_name); /* local, no need for xgetgrnam */
|
grp = getgrnam (group_name); /* local, no need for xgetgrnam */
|
||||||
if (NULL == grp) {
|
if (NULL == grp) {
|
||||||
fprintf (stderr, _("%s: group '%s' does not exist\n"),
|
fprintf (stderr,
|
||||||
Prog, group_name);
|
_("%s: group '%s' does not exist\n"),
|
||||||
#ifdef WITH_AUDIT
|
Prog, group_name);
|
||||||
audit_logger (AUDIT_DEL_GROUP, Prog,
|
|
||||||
"deleting group",
|
|
||||||
group_name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
exit (E_NOTFOUND);
|
exit (E_NOTFOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
group_id = grp->gr_gid; /* LAUS */
|
group_id = grp->gr_gid;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_NIS
|
#ifdef USE_NIS
|
||||||
@ -409,12 +399,6 @@ int main (int argc, char **argv)
|
|||||||
fprintf (stderr, _("%s: group '%s' is a NIS group\n"),
|
fprintf (stderr, _("%s: group '%s' is a NIS group\n"),
|
||||||
Prog, group_name);
|
Prog, group_name);
|
||||||
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_DEL_GROUP, Prog,
|
|
||||||
"deleting group",
|
|
||||||
group_name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_FAILURE);
|
|
||||||
#endif
|
|
||||||
if (!yp_get_default_domain (&nis_domain) &&
|
if (!yp_get_default_domain (&nis_domain) &&
|
||||||
!yp_master (nis_domain, "group.byname", &nis_master)) {
|
!yp_master (nis_domain, "group.byname", &nis_master)) {
|
||||||
fprintf (stderr, _("%s: %s is the NIS master\n"),
|
fprintf (stderr, _("%s: %s is the NIS master\n"),
|
||||||
|
481
src/groupmod.c
481
src/groupmod.c
@ -72,16 +72,17 @@ char *Prog;
|
|||||||
|
|
||||||
#ifdef SHADOWGRP
|
#ifdef SHADOWGRP
|
||||||
static bool is_shadow_grp;
|
static bool is_shadow_grp;
|
||||||
static bool sgr_locked = false;
|
|
||||||
#endif /* SHADOWGRP */
|
#endif /* SHADOWGRP */
|
||||||
static bool gr_locked = false;
|
|
||||||
static bool pw_locked = false;
|
|
||||||
static char *group_name;
|
static char *group_name;
|
||||||
static char *group_newname;
|
static char *group_newname;
|
||||||
static char *group_passwd;
|
static char *group_passwd;
|
||||||
static gid_t group_id;
|
static gid_t group_id;
|
||||||
static gid_t group_newid;
|
static gid_t group_newid;
|
||||||
|
|
||||||
|
struct cleanup_info_mod info_passwd;
|
||||||
|
struct cleanup_info_mod info_group;
|
||||||
|
struct cleanup_info_mod info_gshadow;
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
oflg = false, /* permit non-unique group ID to be specified with -g */
|
oflg = false, /* permit non-unique group ID to be specified with -g */
|
||||||
gflg = false, /* new ID value for the group */
|
gflg = false, /* new ID value for the group */
|
||||||
@ -90,7 +91,6 @@ static bool
|
|||||||
|
|
||||||
/* 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
|
||||||
@ -100,8 +100,10 @@ static void grp_update (void);
|
|||||||
static void check_new_gid (void);
|
static void check_new_gid (void);
|
||||||
static void check_new_name (void);
|
static void check_new_name (void);
|
||||||
static void process_flags (int, char **);
|
static void process_flags (int, char **);
|
||||||
static void close_files (void);
|
static void lock_files (void);
|
||||||
|
static void prepare_failure_reports (void);
|
||||||
static void open_files (void);
|
static void open_files (void);
|
||||||
|
static void close_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);
|
static void update_primary_groups (gid_t ogid, gid_t ngid);
|
||||||
|
|
||||||
@ -123,49 +125,6 @@ static void usage (void)
|
|||||||
exit (E_USAGE);
|
exit (E_USAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fail_exit (int status)
|
|
||||||
{
|
|
||||||
if (gr_locked) {
|
|
||||||
if (gr_unlock () == 0) {
|
|
||||||
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ());
|
|
||||||
SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
|
||||||
"unlocking group file",
|
|
||||||
group_name, AUDIT_NO_ID, 0);
|
|
||||||
#endif
|
|
||||||
/* continue */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef SHADOWGRP
|
|
||||||
if (sgr_locked) {
|
|
||||||
if (sgr_unlock () == 0) {
|
|
||||||
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ());
|
|
||||||
SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
|
||||||
"unlocking gshadow file",
|
|
||||||
group_name, AUDIT_NO_ID, 0);
|
|
||||||
#endif
|
|
||||||
/* continue */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* SHADOWGRP */
|
|
||||||
if (pw_locked) {
|
|
||||||
if (pw_unlock () == 0) {
|
|
||||||
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
|
|
||||||
SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
|
||||||
"unlocking passwd file",
|
|
||||||
group_name, AUDIT_NO_ID, 0);
|
|
||||||
#endif
|
|
||||||
/* continue */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exit (status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* new_grent - updates the values in a group file entry
|
* new_grent - updates the values in a group file entry
|
||||||
*
|
*
|
||||||
@ -209,7 +168,7 @@ static void new_sgent (struct sgrp *sgent)
|
|||||||
/*
|
/*
|
||||||
* grp_update - update group file entries
|
* grp_update - update group file entries
|
||||||
*
|
*
|
||||||
* grp_update() writes the new records to the group files.
|
* grp_update() updates the new records in the memory databases.
|
||||||
*/
|
*/
|
||||||
static void grp_update (void)
|
static void grp_update (void)
|
||||||
{
|
{
|
||||||
@ -229,17 +188,13 @@ static void grp_update (void)
|
|||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: group '%s' does not exist in %s\n"),
|
_("%s: group '%s' does not exist in %s\n"),
|
||||||
Prog, group_name, gr_dbname ());
|
Prog, group_name, gr_dbname ());
|
||||||
#ifdef WITH_AUDIT
|
exit (E_GRP_UPDATE);
|
||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
|
||||||
"modifying group",
|
|
||||||
group_name, AUDIT_NO_ID, 0);
|
|
||||||
#endif
|
|
||||||
fail_exit (E_GRP_UPDATE);
|
|
||||||
}
|
}
|
||||||
grp = *ogrp;
|
grp = *ogrp;
|
||||||
new_grent (&grp);
|
new_grent (&grp);
|
||||||
#ifdef SHADOWGRP
|
#ifdef SHADOWGRP
|
||||||
if (is_shadow_grp) {
|
if ( is_shadow_grp
|
||||||
|
&& (pflg || nflg)) {
|
||||||
osgrp = sgr_locate (group_name);
|
osgrp = sgr_locate (group_name);
|
||||||
if (NULL != osgrp) {
|
if (NULL != osgrp) {
|
||||||
sgrp = *osgrp;
|
sgrp = *osgrp;
|
||||||
@ -262,78 +217,38 @@ static void grp_update (void)
|
|||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: failed to prepare the new %s entry '%s'\n"),
|
_("%s: failed to prepare the new %s entry '%s'\n"),
|
||||||
Prog, gr_dbname (), grp.gr_name);
|
Prog, gr_dbname (), grp.gr_name);
|
||||||
#ifdef WITH_AUDIT
|
exit (E_GRP_UPDATE);
|
||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
|
||||||
"adding group",
|
|
||||||
group_name, AUDIT_NO_ID, 0);
|
|
||||||
#endif
|
|
||||||
fail_exit (E_GRP_UPDATE);
|
|
||||||
}
|
}
|
||||||
if (nflg && (gr_remove (group_name) == 0)) {
|
if (nflg && (gr_remove (group_name) == 0)) {
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: cannot remove entry '%s' from %s\n"),
|
_("%s: cannot remove entry '%s' from %s\n"),
|
||||||
Prog, grp.gr_name, gr_dbname ());
|
Prog, grp.gr_name, gr_dbname ());
|
||||||
#ifdef WITH_AUDIT
|
exit (E_GRP_UPDATE);
|
||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
|
||||||
"deleting group",
|
|
||||||
group_name, AUDIT_NO_ID, 0);
|
|
||||||
#endif
|
|
||||||
fail_exit (E_GRP_UPDATE);
|
|
||||||
}
|
}
|
||||||
#ifdef SHADOWGRP
|
#ifdef SHADOWGRP
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure there was a shadow entry to begin with. Skip down to
|
* Make sure there was a shadow entry to begin with.
|
||||||
* "out" if there wasn't. Can't just return because there might be
|
|
||||||
* some syslogging to do.
|
|
||||||
*/
|
*/
|
||||||
if (NULL == osgrp) {
|
if ( (NULL != osgrp)
|
||||||
goto out;
|
&& (pflg || nflg)) {
|
||||||
|
/*
|
||||||
|
* Write out the new shadow group entries as well.
|
||||||
|
*/
|
||||||
|
if (sgr_update (&sgrp) == 0) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: failed to prepare the new %s entry '%s'\n"),
|
||||||
|
Prog, sgr_dbname (), sgrp.sg_name);
|
||||||
|
exit (E_GRP_UPDATE);
|
||||||
|
}
|
||||||
|
if (nflg && (sgr_remove (group_name) == 0)) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: cannot remove entry '%s' from %s\n"),
|
||||||
|
Prog, group_name, sgr_dbname ());
|
||||||
|
exit (E_GRP_UPDATE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Write out the new shadow group entries as well.
|
|
||||||
*/
|
|
||||||
if (is_shadow_grp && (sgr_update (&sgrp) == 0)) {
|
|
||||||
fprintf (stderr,
|
|
||||||
_("%s: failed to prepare the new %s entry '%s'\n"),
|
|
||||||
Prog, sgr_dbname (), sgrp.sg_name);
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
|
||||||
"adding group",
|
|
||||||
group_name, AUDIT_NO_ID, 0);
|
|
||||||
#endif
|
|
||||||
fail_exit (E_GRP_UPDATE);
|
|
||||||
}
|
|
||||||
if (is_shadow_grp && nflg && (sgr_remove (group_name) == 0)) {
|
|
||||||
fprintf (stderr,
|
|
||||||
_("%s: cannot remove entry '%s' from %s\n"),
|
|
||||||
Prog, group_name, sgr_dbname ());
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
|
||||||
"deleting group",
|
|
||||||
group_name, AUDIT_NO_ID, 0);
|
|
||||||
#endif
|
|
||||||
fail_exit (E_GRP_UPDATE);
|
|
||||||
}
|
|
||||||
out:
|
|
||||||
#endif /* SHADOWGRP */
|
#endif /* SHADOWGRP */
|
||||||
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
|
||||||
"modifing group",
|
|
||||||
group_name, (unsigned int) group_id, 1);
|
|
||||||
#endif
|
|
||||||
if (nflg) {
|
|
||||||
SYSLOG ((LOG_INFO, "change group '%s' to '%s'",
|
|
||||||
group_name, group_newname));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gflg) {
|
|
||||||
SYSLOG ((LOG_INFO, "change GID for '%s' to %lu",
|
|
||||||
nflg ? group_newname : group_name,
|
|
||||||
(unsigned long) group_newid));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -364,12 +279,7 @@ static void check_new_gid (void)
|
|||||||
*/
|
*/
|
||||||
fprintf (stderr, _("%s: GID '%lu' already exists\n"),
|
fprintf (stderr, _("%s: GID '%lu' already exists\n"),
|
||||||
Prog, (unsigned long int) group_newid);
|
Prog, (unsigned long int) group_newid);
|
||||||
#ifdef WITH_AUDIT
|
exit (E_GID_IN_USE);
|
||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
|
||||||
"modify gid",
|
|
||||||
NULL, (unsigned int) group_newid, 0);
|
|
||||||
#endif
|
|
||||||
fail_exit (E_GID_IN_USE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -398,12 +308,7 @@ static void check_new_name (void)
|
|||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: group '%s' already exists\n"), Prog,
|
_("%s: group '%s' already exists\n"), Prog,
|
||||||
group_newname);
|
group_newname);
|
||||||
#ifdef WITH_AUDIT
|
exit (E_NAME_IN_USE);
|
||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
|
||||||
"modifying group",
|
|
||||||
group_name, AUDIT_NO_ID, 0);
|
|
||||||
#endif
|
|
||||||
fail_exit (E_NAME_IN_USE);
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -414,12 +319,7 @@ static void check_new_name (void)
|
|||||||
|
|
||||||
fprintf (stderr, _("%s: invalid group name '%s'\n"),
|
fprintf (stderr, _("%s: invalid group name '%s'\n"),
|
||||||
Prog, group_newname);
|
Prog, group_newname);
|
||||||
#ifdef WITH_AUDIT
|
exit (E_BAD_ARG);
|
||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
|
||||||
"modifying group",
|
|
||||||
group_name, AUDIT_NO_ID, 0);
|
|
||||||
#endif
|
|
||||||
fail_exit (E_BAD_ARG);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -434,7 +334,7 @@ static gid_t get_gid (const char *gidstr)
|
|||||||
if (('\0' != *errptr) || (ERANGE == errno) || (val < 0)) {
|
if (('\0' != *errptr) || (ERANGE == errno) || (val < 0)) {
|
||||||
fprintf (stderr, _("%s: invalid numeric argument '%s'\n"), Prog,
|
fprintf (stderr, _("%s: invalid numeric argument '%s'\n"), Prog,
|
||||||
gidstr);
|
gidstr);
|
||||||
fail_exit (E_BAD_ARG);
|
exit (E_BAD_ARG);
|
||||||
}
|
}
|
||||||
return (gid_t) val;
|
return (gid_t) val;
|
||||||
}
|
}
|
||||||
@ -467,11 +367,6 @@ static void process_flags (int argc, char **argv)
|
|||||||
case 'g':
|
case 'g':
|
||||||
gflg = true;
|
gflg = true;
|
||||||
group_newid = get_gid (optarg);
|
group_newid = get_gid (optarg);
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
|
||||||
"modifying group",
|
|
||||||
NULL, (unsigned int) group_newid, 0);
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
nflg = true;
|
nflg = true;
|
||||||
@ -510,129 +405,240 @@ static void process_flags (int argc, char **argv)
|
|||||||
static void close_files (void)
|
static void close_files (void)
|
||||||
{
|
{
|
||||||
if (gr_close () == 0) {
|
if (gr_close () == 0) {
|
||||||
fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ());
|
fprintf (stderr,
|
||||||
SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ()));
|
_("%s: failure while writing changes to %s\n"),
|
||||||
#ifdef WITH_AUDIT
|
Prog, gr_dbname ());
|
||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
exit (E_GRP_UPDATE);
|
||||||
"rewrite group file",
|
|
||||||
group_name, AUDIT_NO_ID, 0);
|
|
||||||
#endif
|
|
||||||
fail_exit (E_GRP_UPDATE);
|
|
||||||
}
|
}
|
||||||
if (gr_unlock () == 0) {
|
|
||||||
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ());
|
|
||||||
SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
#ifdef WITH_AUDIT
|
||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
audit_logger (AUDIT_USER_ACCT, Prog,
|
||||||
"unlocking group file",
|
info_group.audit_msg,
|
||||||
group_name, AUDIT_NO_ID, 0);
|
group_name, AUDIT_NO_ID,
|
||||||
|
SHADOW_AUDIT_SUCCESS);
|
||||||
#endif
|
#endif
|
||||||
/* continue */
|
SYSLOG ((LOG_INFO,
|
||||||
}
|
"group changed in %s (%s)",
|
||||||
gr_locked = false;
|
gr_dbname (), info_group.action));
|
||||||
|
del_cleanup (cleanup_report_mod_group);
|
||||||
|
|
||||||
|
cleanup_unlock_group (NULL);
|
||||||
|
del_cleanup (cleanup_unlock_group);
|
||||||
|
|
||||||
#ifdef SHADOWGRP
|
#ifdef SHADOWGRP
|
||||||
if (is_shadow_grp) {
|
if ( is_shadow_grp
|
||||||
|
&& (pflg || nflg)) {
|
||||||
if (sgr_close () == 0) {
|
if (sgr_close () == 0) {
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: failure while writing changes to %s\n"), Prog, sgr_dbname ());
|
_("%s: failure while writing changes to %s\n"),
|
||||||
SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ()));
|
Prog, sgr_dbname ());
|
||||||
#ifdef WITH_AUDIT
|
exit (E_GRP_UPDATE);
|
||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
|
||||||
"rewrite gshadow file",
|
|
||||||
group_name, AUDIT_NO_ID, 0);
|
|
||||||
#endif
|
|
||||||
fail_exit (E_GRP_UPDATE);
|
|
||||||
}
|
}
|
||||||
if (sgr_unlock () == 0) {
|
|
||||||
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ());
|
|
||||||
SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
#ifdef WITH_AUDIT
|
||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
audit_logger (AUDIT_USER_ACCT, Prog,
|
||||||
"unlocking gshadow file",
|
info_gshadow.audit_msg,
|
||||||
group_name, AUDIT_NO_ID, 0);
|
group_name, AUDIT_NO_ID,
|
||||||
|
SHADOW_AUDIT_SUCCESS);
|
||||||
#endif
|
#endif
|
||||||
/* continue */
|
SYSLOG ((LOG_INFO,
|
||||||
}
|
"group changed in %s (%s)",
|
||||||
sgr_locked = false;
|
sgr_dbname (), info_gshadow.action));
|
||||||
|
del_cleanup (cleanup_report_mod_gshadow);
|
||||||
|
|
||||||
|
cleanup_unlock_gshadow (NULL);
|
||||||
|
del_cleanup (cleanup_unlock_gshadow);
|
||||||
}
|
}
|
||||||
#endif /* SHADOWGRP */
|
#endif /* SHADOWGRP */
|
||||||
|
|
||||||
if (gflg) {
|
if (gflg) {
|
||||||
if (pw_close () == 0) {
|
if (pw_close () == 0) {
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: failure while writing changes to %s\n"), Prog, pw_dbname ());
|
_("%s: failure while writing changes to %s\n"),
|
||||||
SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ()));
|
Prog, pw_dbname ());
|
||||||
#ifdef WITH_AUDIT
|
exit (E_GRP_UPDATE);
|
||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
|
||||||
"rewrite passwd file",
|
|
||||||
group_name, AUDIT_NO_ID, 0);
|
|
||||||
#endif
|
|
||||||
fail_exit (E_GRP_UPDATE);
|
|
||||||
}
|
}
|
||||||
if (pw_unlock () == 0) {
|
|
||||||
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
|
|
||||||
SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
|
|
||||||
#ifdef WITH_AUDIT
|
#ifdef WITH_AUDIT
|
||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
audit_logger (AUDIT_USER_ACCT, Prog,
|
||||||
"unlocking passwd file",
|
info_passwd.audit_msg,
|
||||||
group_name, AUDIT_NO_ID, 0);
|
group_name, AUDIT_NO_ID,
|
||||||
|
SHADOW_AUDIT_SUCCESS);
|
||||||
#endif
|
#endif
|
||||||
/* continue */
|
SYSLOG ((LOG_INFO,
|
||||||
}
|
"group changed in %s (%s)",
|
||||||
pw_locked = false;
|
pw_dbname (), info_passwd.action));
|
||||||
|
del_cleanup (cleanup_report_mod_passwd);
|
||||||
|
|
||||||
|
cleanup_unlock_passwd (NULL);
|
||||||
|
del_cleanup (cleanup_unlock_passwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_AUDIT
|
||||||
|
audit_logger (AUDIT_USER_ACCT, Prog,
|
||||||
|
"modifying group",
|
||||||
|
group_name, AUDIT_NO_ID,
|
||||||
|
SHADOW_AUDIT_SUCCESS);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* open_files - lock and open the group files
|
* prepare_failure_reports - Prepare the cleanup_info structure for logging
|
||||||
*
|
* of success and failure to syslog or audit.
|
||||||
* open_files() opens the two group files.
|
|
||||||
*/
|
*/
|
||||||
static void open_files (void)
|
static void prepare_failure_reports (void)
|
||||||
|
{
|
||||||
|
info_group.name = group_name;
|
||||||
|
info_gshadow.name = group_name;
|
||||||
|
info_passwd.name = group_name;
|
||||||
|
|
||||||
|
info_group.audit_msg = xmalloc (512);
|
||||||
|
info_gshadow.audit_msg = xmalloc (512);
|
||||||
|
info_passwd.audit_msg = xmalloc (512);
|
||||||
|
|
||||||
|
snprintf (info_group.audit_msg, 511,
|
||||||
|
"changing %s; ", gr_dbname ());
|
||||||
|
snprintf (info_gshadow.audit_msg, 511,
|
||||||
|
"changing %s; ", sgr_dbname ());
|
||||||
|
snprintf (info_passwd.audit_msg, 511,
|
||||||
|
"changing %s; ", pw_dbname ());
|
||||||
|
|
||||||
|
info_group.action = info_group.audit_msg
|
||||||
|
+ strlen (info_group.audit_msg);
|
||||||
|
info_gshadow.action = info_gshadow.audit_msg
|
||||||
|
+ strlen (info_gshadow.audit_msg);
|
||||||
|
info_passwd.action = info_passwd.audit_msg
|
||||||
|
+ strlen (info_passwd.audit_msg);
|
||||||
|
|
||||||
|
snprintf (info_group.action, 511 - strlen (info_group.audit_msg),
|
||||||
|
"group %s/%d", group_name, group_id);
|
||||||
|
snprintf (info_gshadow.action, 511 - strlen (info_group.audit_msg),
|
||||||
|
"group %s", group_name);
|
||||||
|
snprintf (info_passwd.action, 511 - strlen (info_group.audit_msg),
|
||||||
|
"group %s/%d", group_name, group_id);
|
||||||
|
|
||||||
|
if (nflg) {
|
||||||
|
strncat (info_group.action, ", new name: ",
|
||||||
|
511 - strlen (info_group.audit_msg));
|
||||||
|
strncat (info_group.action, group_newname,
|
||||||
|
511 - strlen (info_group.audit_msg));
|
||||||
|
|
||||||
|
strncat (info_gshadow.action, ", new name: ",
|
||||||
|
511 - strlen (info_gshadow.audit_msg));
|
||||||
|
strncat (info_gshadow.action, group_newname,
|
||||||
|
511 - strlen (info_gshadow.audit_msg));
|
||||||
|
|
||||||
|
strncat (info_passwd.action, ", new name: ",
|
||||||
|
511 - strlen (info_passwd.audit_msg));
|
||||||
|
strncat (info_passwd.action, group_newname,
|
||||||
|
511 - strlen (info_passwd.audit_msg));
|
||||||
|
}
|
||||||
|
if (pflg) {
|
||||||
|
strncat (info_group.action, ", new password",
|
||||||
|
511 - strlen (info_group.audit_msg));
|
||||||
|
|
||||||
|
strncat (info_gshadow.action, ", new password",
|
||||||
|
511 - strlen (info_gshadow.audit_msg));
|
||||||
|
}
|
||||||
|
if (gflg) {
|
||||||
|
strncat (info_group.action, ", new gid: ",
|
||||||
|
511 - strlen (info_group.audit_msg));
|
||||||
|
snprintf (info_group.action+strlen (info_group.action),
|
||||||
|
511 - strlen (info_group.audit_msg),
|
||||||
|
"%d", group_newid);
|
||||||
|
|
||||||
|
strncat (info_passwd.action, ", new gid: ",
|
||||||
|
511 - strlen (info_passwd.audit_msg));
|
||||||
|
snprintf (info_passwd.action+strlen (info_passwd.action),
|
||||||
|
511 - strlen (info_passwd.audit_msg),
|
||||||
|
"%d", group_newid);
|
||||||
|
}
|
||||||
|
info_group.audit_msg[511] = '\0';
|
||||||
|
info_gshadow.audit_msg[511] = '\0';
|
||||||
|
info_passwd.audit_msg[511] = '\0';
|
||||||
|
|
||||||
|
// FIXME: add a system cleanup
|
||||||
|
add_cleanup (cleanup_report_mod_group, &info_group);
|
||||||
|
if ( is_shadow_grp
|
||||||
|
&& (pflg || nflg)) {
|
||||||
|
add_cleanup (cleanup_report_mod_gshadow, &info_gshadow);
|
||||||
|
}
|
||||||
|
if (gflg) {
|
||||||
|
add_cleanup (cleanup_report_mod_passwd, &info_passwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* lock_files - lock the accounts databases
|
||||||
|
*
|
||||||
|
* lock_files() locks the group, gshadow, and passwd databases.
|
||||||
|
*/
|
||||||
|
static void lock_files (void)
|
||||||
{
|
{
|
||||||
if (gr_lock () == 0) {
|
if (gr_lock () == 0) {
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: cannot lock %s; try again later.\n"),
|
_("%s: cannot lock %s; try again later.\n"),
|
||||||
Prog, gr_dbname ());
|
Prog, gr_dbname ());
|
||||||
fail_exit (E_GRP_UPDATE);
|
exit (E_GRP_UPDATE);
|
||||||
}
|
|
||||||
gr_locked = true;
|
|
||||||
if (gr_open (O_RDWR) == 0) {
|
|
||||||
fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ());
|
|
||||||
SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ()));
|
|
||||||
fail_exit (E_GRP_UPDATE);
|
|
||||||
}
|
}
|
||||||
|
add_cleanup (cleanup_unlock_group, NULL);
|
||||||
|
|
||||||
#ifdef SHADOWGRP
|
#ifdef SHADOWGRP
|
||||||
if (is_shadow_grp) {
|
if ( is_shadow_grp
|
||||||
|
&& (pflg || nflg)) {
|
||||||
if (sgr_lock () == 0) {
|
if (sgr_lock () == 0) {
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: cannot lock %s; try again later.\n"),
|
_("%s: cannot lock %s; try again later.\n"),
|
||||||
Prog, sgr_dbname ());
|
Prog, sgr_dbname ());
|
||||||
fail_exit (E_GRP_UPDATE);
|
exit (E_GRP_UPDATE);
|
||||||
}
|
|
||||||
sgr_locked = true;
|
|
||||||
if (sgr_open (O_RDWR) == 0) {
|
|
||||||
fprintf (stderr,
|
|
||||||
_("%s: cannot open %s\n"),
|
|
||||||
Prog, sgr_dbname ());
|
|
||||||
SYSLOG ((LOG_WARN, "cannot open %s", sgr_dbname ()));
|
|
||||||
fail_exit (E_GRP_UPDATE);
|
|
||||||
}
|
}
|
||||||
|
add_cleanup (cleanup_unlock_gshadow, NULL);
|
||||||
}
|
}
|
||||||
#endif /* SHADOWGRP */
|
#endif
|
||||||
|
|
||||||
if (gflg) {
|
if (gflg) {
|
||||||
if (pw_lock () == 0) {
|
if (pw_lock () == 0) {
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: cannot lock %s; try again later.\n"),
|
_("%s: cannot lock %s; try again later.\n"),
|
||||||
Prog, pw_dbname ());
|
Prog, pw_dbname ());
|
||||||
fail_exit (E_GRP_UPDATE);
|
exit (E_GRP_UPDATE);
|
||||||
}
|
}
|
||||||
pw_locked = true;
|
add_cleanup (cleanup_unlock_passwd, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* open_files - open the accounts databases
|
||||||
|
*
|
||||||
|
* open_files() opens the group, gshadow, and passwd databases.
|
||||||
|
*/
|
||||||
|
static void open_files (void)
|
||||||
|
{
|
||||||
|
if (gr_open (O_RDWR) == 0) {
|
||||||
|
fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ());
|
||||||
|
SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ()));
|
||||||
|
exit (E_GRP_UPDATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SHADOWGRP
|
||||||
|
if ( is_shadow_grp
|
||||||
|
&& (pflg || nflg)) {
|
||||||
|
if (sgr_open (O_RDWR) == 0) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: cannot open %s\n"),
|
||||||
|
Prog, sgr_dbname ());
|
||||||
|
SYSLOG ((LOG_WARN, "cannot open %s", sgr_dbname ()));
|
||||||
|
exit (E_GRP_UPDATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* SHADOWGRP */
|
||||||
|
|
||||||
|
if (gflg) {
|
||||||
if (pw_open (O_RDWR) == 0) {
|
if (pw_open (O_RDWR) == 0) {
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: cannot open %s\n"),
|
_("%s: cannot open %s\n"),
|
||||||
Prog, pw_dbname ());
|
Prog, pw_dbname ());
|
||||||
SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ()));
|
SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ()));
|
||||||
fail_exit (E_GRP_UPDATE);
|
exit (E_GRP_UPDATE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -651,7 +657,7 @@ void update_primary_groups (gid_t ogid, gid_t ngid)
|
|||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: user '%s' does not exist in %s\n"),
|
_("%s: user '%s' does not exist in %s\n"),
|
||||||
Prog, pwd->pw_name, pw_dbname ());
|
Prog, pwd->pw_name, pw_dbname ());
|
||||||
fail_exit (E_GRP_UPDATE);
|
exit (E_GRP_UPDATE);
|
||||||
} else {
|
} else {
|
||||||
npwd = *lpwd;
|
npwd = *lpwd;
|
||||||
npwd.pw_gid = ngid;
|
npwd.pw_gid = ngid;
|
||||||
@ -659,7 +665,7 @@ void update_primary_groups (gid_t ogid, gid_t ngid)
|
|||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: failed to prepare the new %s entry '%s'\n"),
|
_("%s: failed to prepare the new %s entry '%s'\n"),
|
||||||
Prog, pw_dbname (), npwd.pw_name);
|
Prog, pw_dbname (), npwd.pw_name);
|
||||||
fail_exit (E_GRP_UPDATE);
|
exit (E_GRP_UPDATE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -691,6 +697,7 @@ int main (int argc, char **argv)
|
|||||||
#ifdef WITH_AUDIT
|
#ifdef WITH_AUDIT
|
||||||
audit_help_open ();
|
audit_help_open ();
|
||||||
#endif
|
#endif
|
||||||
|
atexit (do_cleanups);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get my name so that I can use it to report errors.
|
* Get my name so that I can use it to report errors.
|
||||||
@ -714,7 +721,7 @@ int main (int argc, char **argv)
|
|||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
_("%s: Cannot determine your user name.\n"),
|
_("%s: Cannot determine your user name.\n"),
|
||||||
Prog);
|
Prog);
|
||||||
fail_exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = pam_start ("groupmod", pampw->pw_name, &conv, &pamh);
|
retval = pam_start ("groupmod", pampw->pw_name, &conv, &pamh);
|
||||||
@ -733,7 +740,7 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
if (PAM_SUCCESS != retval) {
|
if (PAM_SUCCESS != retval) {
|
||||||
fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
|
fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
|
||||||
fail_exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
#endif /* USE_PAM */
|
#endif /* USE_PAM */
|
||||||
#endif /* ACCT_TOOLS_SETUID */
|
#endif /* ACCT_TOOLS_SETUID */
|
||||||
@ -750,27 +757,12 @@ int main (int argc, char **argv)
|
|||||||
if (NULL == grp) {
|
if (NULL == grp) {
|
||||||
fprintf (stderr, _("%s: group '%s' does not exist\n"),
|
fprintf (stderr, _("%s: group '%s' does not exist\n"),
|
||||||
Prog, group_name);
|
Prog, group_name);
|
||||||
#ifdef WITH_AUDIT
|
exit (E_NOTFOUND);
|
||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
|
||||||
"modifying group",
|
|
||||||
group_name, AUDIT_NO_ID, 0);
|
|
||||||
#endif
|
|
||||||
fail_exit (E_NOTFOUND);
|
|
||||||
} else {
|
} else {
|
||||||
group_id = grp->gr_gid;
|
group_id = grp->gr_gid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
/* Set new name/id to original if not specified on command line */
|
|
||||||
if (!nflg) {
|
|
||||||
group_newname = group_name;
|
|
||||||
}
|
|
||||||
if (!gflg) {
|
|
||||||
group_newid = group_id;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_NIS
|
#ifdef USE_NIS
|
||||||
/*
|
/*
|
||||||
* Now make sure it isn't an NIS group.
|
* Now make sure it isn't an NIS group.
|
||||||
@ -782,17 +774,12 @@ int main (int argc, char **argv)
|
|||||||
fprintf (stderr, _("%s: group %s is a NIS group\n"),
|
fprintf (stderr, _("%s: group %s is a NIS group\n"),
|
||||||
Prog, group_name);
|
Prog, group_name);
|
||||||
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
|
|
||||||
"modifying group",
|
|
||||||
group_name, AUDIT_NO_ID, 0);
|
|
||||||
#endif
|
|
||||||
if (!yp_get_default_domain (&nis_domain) &&
|
if (!yp_get_default_domain (&nis_domain) &&
|
||||||
!yp_master (nis_domain, "group.byname", &nis_master)) {
|
!yp_master (nis_domain, "group.byname", &nis_master)) {
|
||||||
fprintf (stderr, _("%s: %s is the NIS master\n"),
|
fprintf (stderr, _("%s: %s is the NIS master\n"),
|
||||||
Prog, nis_master);
|
Prog, nis_master);
|
||||||
}
|
}
|
||||||
fail_exit (E_NOTFOUND);
|
exit (E_NOTFOUND);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -804,6 +791,14 @@ int main (int argc, char **argv)
|
|||||||
check_new_name ();
|
check_new_name ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lock_files ();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now if the group is not changed, it's our fault.
|
||||||
|
* Make sure failures will be reported.
|
||||||
|
*/
|
||||||
|
prepare_failure_reports ();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do the hard stuff - open the files, create the group entries,
|
* Do the hard stuff - open the files, create the group entries,
|
||||||
* then close and update the files.
|
* then close and update the files.
|
||||||
|
Loading…
Reference in New Issue
Block a user