2
* Copyright 1991 - 1994, Julianne Frances Haugh
2
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
3
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
4
* Copyright (c) 2000 - 2006, Tomasz Kłoczko
5
* Copyright (c) 2007 - 2008, Nicolas François
3
6
* All rights reserved.
5
8
* Redistribution and use in source and binary forms, with or without
10
13
* 2. Redistributions in binary form must reproduce the above copyright
11
14
* notice, this list of conditions and the following disclaimer in the
12
15
* documentation and/or other materials provided with the distribution.
13
* 3. Neither the name of Julianne F. Haugh nor the names of its contributors
14
* may be used to endorse or promote products derived from this software
15
* without specific prior written permission.
16
* 3. The name of the copyright holders or contributors may not be used to
17
* endorse or promote products derived from this software without
18
* specific prior written permission.
17
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
21
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
20
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
33
#include <config.h>
32
#ident "$Id: groupdel.c 1894 2008-03-08 23:52:50Z nekral-guest $"
35
#ident "$Id: groupdel.c 2473 2008-12-22 23:23:14Z nekral-guest $"
41
#ifdef ACCT_TOOLS_SETUID
39
43
#include "pam_defs.h"
40
44
#endif /* USE_PAM */
45
#endif /* ACCT_TOOLS_SETUID */
42
47
#include <sys/types.h>
43
48
#include "defines.h"
88
* fail_exit - exit with a failure code after unlocking the files
90
static void fail_exit (int code)
100
audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "deleting group",
108
93
* grp_update - update group file entries
110
95
* grp_update() writes the new records to the group files.
112
97
static void grp_update (void)
114
if (!gr_remove (group_name)) {
115
fprintf (stderr, _("%s: error removing group entry\n"), Prog);
116
fail_exit (E_GRP_UPDATE);
100
* To add the group, we need to update /etc/group.
101
* Make sure failures will be reported.
103
add_cleanup (cleanup_report_del_group_group, group_name);
106
/* We also need to update /etc/gshadow */
107
add_cleanup (cleanup_report_del_group_gshadow, group_name);
112
* Delete the group entry.
114
if (gr_remove (group_name) == 0) {
116
_("%s: cannot remove entry '%s' from %s\n"),
117
Prog, group_name, gr_dbname ());
120
123
* Delete the shadow group entries as well.
122
125
if (is_shadow_grp && (sgr_locate (group_name) != NULL)) {
123
if (!sgr_remove (group_name)) {
126
if (sgr_remove (group_name) == 0) {
125
_("%s: error removing shadow group entry\n"),
127
fail_exit (E_GRP_UPDATE);
128
_("%s: cannot remove entry '%s' from %s\n"),
129
Prog, group_name, sgr_dbname ());
130
133
#endif /* SHADOWGRP */
140
142
static void close_files (void)
144
/* First, write the changes in the regular group database */
145
if (gr_close () == 0) {
147
_("%s: failure while writing changes to %s\n"),
142
152
#ifdef WITH_AUDIT
143
audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "deleting group", group_name,
153
audit_logger (AUDIT_DEL_GROUP, Prog,
154
"removing group from /etc/group",
155
group_name, (unsigned int) group_id,
156
SHADOW_AUDIT_SUCCESS);
146
SYSLOG ((LOG_INFO, "remove group `%s'\n", group_name));
149
fprintf (stderr, _("%s: cannot rewrite group file\n"), Prog);
150
fail_exit (E_GRP_UPDATE);
159
"group '%s' removed from %s",
160
group_name, gr_dbname ()));
161
del_cleanup (cleanup_report_del_group_group);
163
cleanup_unlock_group (NULL);
164
del_cleanup (cleanup_unlock_group);
167
/* Then, write the changes in the shadow database */
154
if (is_shadow_grp && !sgr_close ()) {
156
_("%s: cannot rewrite shadow group file\n"), Prog);
157
fail_exit (E_GRP_UPDATE);
170
if (sgr_close () == 0) {
172
_("%s: failure while writing changes to %s\n"),
173
Prog, sgr_dbname ());
178
audit_logger (AUDIT_DEL_GROUP, Prog,
179
"removing group from /etc/gshadow",
180
group_name, (unsigned int) group_id,
181
SHADOW_AUDIT_SUCCESS);
184
"group '%s' removed from %s",
185
group_name, sgr_dbname ()));
186
del_cleanup (cleanup_report_del_group_gshadow);
188
cleanup_unlock_gshadow (NULL);
189
del_cleanup (cleanup_unlock_gshadow);
161
191
#endif /* SHADOWGRP */
193
/* Report success at the system level */
195
audit_logger (AUDIT_DEL_GROUP, Prog,
197
group_name, (unsigned int) group_id,
198
SHADOW_AUDIT_SUCCESS);
200
SYSLOG ((LOG_INFO, "group '%s' removed\n", group_name));
201
del_cleanup (cleanup_report_del_group);
169
209
static void open_files (void)
172
fprintf (stderr, _("%s: unable to lock group file\n"), Prog);
173
fail_exit (E_GRP_UPDATE);
175
if (!gr_open (O_RDWR)) {
176
fprintf (stderr, _("%s: unable to open group file\n"), Prog);
177
fail_exit (E_GRP_UPDATE);
180
if (is_shadow_grp && !sgr_lock ()) {
182
_("%s: unable to lock shadow group file\n"), Prog);
183
fail_exit (E_GRP_UPDATE);
185
if (is_shadow_grp && !sgr_open (O_RDWR)) {
187
_("%s: unable to open shadow group file\n"), Prog);
188
fail_exit (E_GRP_UPDATE);
211
/* First, lock the databases */
212
if (gr_lock () == 0) {
214
_("%s: cannot lock %s; try again later.\n"),
218
add_cleanup (cleanup_unlock_group, NULL);
221
if (sgr_lock () == 0) {
223
_("%s: cannot lock %s; try again later.\n"),
224
Prog, sgr_dbname ());
227
add_cleanup (cleanup_unlock_gshadow, NULL);
232
* Now, if the group is not removed, it's our fault.
233
* Make sure failures will be reported.
235
add_cleanup (cleanup_report_del_group, group_name);
237
/* An now open the databases */
238
if (gr_open (O_RDWR) == 0) {
240
_("%s: cannot open %s\n"),
242
SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ()));
247
if (sgr_open (O_RDWR) == 0) {
249
_("%s: cannot open %s\n"),
250
Prog, sgr_dbname ());
251
SYSLOG ((LOG_WARN, "cannot open %s", sgr_dbname ()));
190
255
#endif /* SHADOWGRP */
215
280
* If pwd isn't NULL, it stopped because the gid's matched.
218
if (pwd == (struct passwd *) 0)
283
if (pwd == (struct passwd *) 0) {
222
288
* Can't remove the group.
224
fprintf (stderr, _("%s: cannot remove user's primary group.\n"), Prog);
225
fail_exit (E_GROUP_BUSY);
291
_("%s: cannot remove the primary group of user '%s'\n"),
253
324
Prog = Basename (argv[0]);
255
setlocale (LC_ALL, "");
256
bindtextdomain (PACKAGE, LOCALEDIR);
257
textdomain (PACKAGE);
326
(void) setlocale (LC_ALL, "");
327
(void) bindtextdomain (PACKAGE, LOCALEDIR);
328
(void) textdomain (PACKAGE);
262
334
group_name = argv[1];
264
336
OPENLOG ("groupdel");
338
#ifdef ACCT_TOOLS_SETUID
267
retval = PAM_SUCCESS;
270
341
struct passwd *pampw;
271
342
pampw = getpwuid (getuid ()); /* local, no need for xgetpwuid */
272
343
if (pampw == NULL) {
273
retval = PAM_USER_UNKNOWN;
345
_("%s: Cannot determine your user name.\n"),
276
if (retval == PAM_SUCCESS) {
277
retval = pam_start ("groupdel", pampw->pw_name,
350
retval = pam_start ("groupdel", pampw->pw_name, &conv, &pamh);
282
if (retval == PAM_SUCCESS) {
353
if (PAM_SUCCESS == retval) {
283
354
retval = pam_authenticate (pamh, 0);
284
if (retval != PAM_SUCCESS) {
285
pam_end (pamh, retval);
289
if (retval == PAM_SUCCESS) {
357
if (PAM_SUCCESS == retval) {
290
358
retval = pam_acct_mgmt (pamh, 0);
291
if (retval != PAM_SUCCESS) {
292
pam_end (pamh, retval);
296
if (retval != PAM_SUCCESS) {
362
(void) pam_end (pamh, retval);
364
if (PAM_SUCCESS != retval) {
297
365
fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
300
368
#endif /* USE_PAM */
369
#endif /* ACCT_TOOLS_SETUID */
303
372
is_shadow_grp = sgr_file_present ();
309
378
* Start with a quick check to see if the group exists.
311
/* local, no need for xgetgrnam */
312
if (!(grp = getgrnam (group_name))) {
313
fprintf (stderr, _("%s: group %s does not exist\n"),
316
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
380
grp = getgrnam (group_name); /* local, no need for xgetgrnam */
383
_("%s: group '%s' does not exist\n"),
320
385
exit (E_NOTFOUND);
323
group_id = grp->gr_gid; /* LAUS */
388
group_id = grp->gr_gid;
331
396
char *nis_domain;
332
397
char *nis_master;
334
fprintf (stderr, _("%s: group %s is a NIS group\n"),
400
_("%s: group '%s' is a NIS group\n"),
338
audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "deleting group",
341
403
if (!yp_get_default_domain (&nis_domain) &&
342
404
!yp_master (nis_domain, "group.byname", &nis_master)) {
343
fprintf (stderr, _("%s: %s is the NIS master\n"),
406
_("%s: %s is the NIS master\n"),
346
409
exit (E_NOTFOUND);
351
* Now check to insure that this isn't the primary group of
414
* Make sure this isn't the primary group of anyone.
354
416
group_busy (group_id);