~xnox/ubuntu/quantal/shadow/clear-locks

« back to all changes in this revision

Viewing changes to src/groupmems.c

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2009-05-05 09:45:21 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20090505094521-wpk2wn3q7957tlah
Tags: 1:4.1.3.1-1ubuntu1
* Merge from debian unstable, remaining changes:
  - Ubuntu specific:
    + debian/login.defs: use SHA512 by default for password crypt routine.
  - debian/patches/stdout-encrypted-password.patch: chpasswd can report
    password hashes on stdout (debian bug 505640).
  - debian/login.pam: Enable SELinux support (debian bug 527106).
  - debian/securetty.linux: support Freescale MX-series (debian bug 527095).
* Add debian/patches/300_lastlog_failure: fixed upstream (debian bug 524873).
* Drop debian/patches/593_omit_lastchange_field_if_clock_is_misset: fixed
  upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright 2000, International Business Machines
3
 
 * George Kraft IV, gk4@us.ibm.com, 03/23/2000
 
2
 * Copyright (c) 2000       , International Business Machines
 
3
 *                            George Kraft IV, gk4@us.ibm.com, 03/23/2000
 
4
 * Copyright (c) 2000 - 2006, Tomasz Kłoczko
 
5
 * Copyright (c) 2007 - 2008, Nicolas François
4
6
 * All rights reserved.
5
7
 *
6
8
 * Redistribution and use in source and binary forms, with or without
11
13
 * 2. Redistributions in binary form must reproduce the above copyright
12
14
 *    notice, this list of conditions and the following disclaimer in the
13
15
 *    documentation and/or other materials provided with the distribution.
14
 
 * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
15
 
 *    may be used to endorse or promote products derived from this software
16
 
 *    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
19
 *
18
 
 * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
19
 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 
 * ARE DISCLAIMED.  IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
22
 
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 
 * SUCH DAMAGE.
29
 
*/
 
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.
 
31
 */
30
32
 
31
33
#include <config.h>
32
34
 
40
42
#endif                          /* USE_PAM */
41
43
#include <pwd.h>
42
44
#include "defines.h"
 
45
#include "prototypes.h"
43
46
#include "groupio.h"
 
47
#ifdef SHADOWGRP
 
48
#include "sgroupio.h"
 
49
#endif
44
50
 
45
51
/* Exit Status Values */
46
52
 
52
58
#define EXIT_NOT_PRIMARY        5       /* not primary owner of group  */
53
59
#define EXIT_NOT_MEMBER         6       /* member of group does not exist */
54
60
#define EXIT_MEMBER_EXISTS      7       /* member of group already exists */
55
 
 
56
 
#define TRUE 1
57
 
#define FALSE 0
 
61
#define EXIT_INVALID_USER       8       /* specified user does not exist */
 
62
#define EXIT_INVALID_GROUP      9       /* specified group does not exist */
58
63
 
59
64
/*
60
65
 * Global variables
61
66
 */
 
67
char *Prog;
 
68
 
62
69
static char *adduser = NULL;
63
70
static char *deluser = NULL;
64
71
static char *thisgroup = NULL;
65
 
static int purge = FALSE;
66
 
static int list = FALSE;
 
72
static bool purge = false;
 
73
static bool list = false;
67
74
static int exclusive = 0;
68
 
 
69
 
static int isroot (void)
70
 
{
71
 
        return getuid ()? FALSE : TRUE;
72
 
}
73
 
 
74
 
static int isgroup (void)
75
 
{
76
 
        gid_t g = getgid ();
77
 
        struct group *grp = getgrgid (g); /* local, no need for xgetgrgid */
78
 
 
79
 
        return TRUE;
80
 
}
 
75
static bool gr_locked = false;
 
76
#ifdef SHADOWGRP
 
77
/* Indicate if shadow groups are enabled on the system
 
78
 * (/etc/gshadow present) */
 
79
static bool is_shadowgrp;
 
80
static bool sgr_locked = false;
 
81
#endif
 
82
 
 
83
/* local function prototypes */
 
84
static char *whoami (void);
 
85
static void add_user (const char *user,
 
86
                      const struct group *grp);
 
87
static void remove_user (const char *user, 
 
88
                         const struct group *grp);
 
89
static void purge_members (const struct group *grp);
 
90
static void display_members (const char *const *members);
 
91
static void usage (void);
 
92
static void process_flags (int argc, char **argv);
 
93
static void check_perms (void);
 
94
static void fail_exit (int code);
 
95
#define isroot()                (getuid () == 0)
81
96
 
82
97
static char *whoami (void)
83
98
{
86
101
        /* local, no need for xgetpwuid */
87
102
        struct passwd *usr = getpwuid (getuid ());
88
103
 
89
 
        if (0 == strcmp (usr->pw_name, grp->gr_name)) {
90
 
                return (char *) strdup (usr->pw_name);
 
104
        if (   (NULL != usr)
 
105
            && (NULL != grp)
 
106
            && (0 == strcmp (usr->pw_name, grp->gr_name))) {
 
107
                return xstrdup (usr->pw_name);
91
108
        } else {
92
109
                return NULL;
93
110
        }
94
111
}
95
112
 
96
 
static void addtogroup (char *user, char **members)
97
 
{
98
 
        int i;
99
 
 
100
 
        for (i = 0; NULL != members[i]; i++) {
101
 
                if (0 == strcmp (user, members[i])) {
102
 
                        fputs (_("Member already exists\n"), stderr);
103
 
                        exit (EXIT_MEMBER_EXISTS);
104
 
                }
105
 
        }
106
 
 
107
 
        members = (char **) realloc (members, sizeof (char *) * (i+2));
108
 
        members[i] = user;
109
 
        members[i + 1] = NULL;
110
 
}
111
 
 
112
 
static void rmfromgroup (char *user, char **members)
113
 
{
114
 
        int i;
115
 
        int found = FALSE;
116
 
 
117
 
        i = 0;
118
 
        while (!found && NULL != members[i]) {
119
 
                if (0 == strcmp (user, members[i])) {
120
 
                        found = TRUE;
121
 
                } else {
122
 
                        i++;
123
 
                }
124
 
        }
125
 
 
126
 
        while (found && NULL != members[i]) {
127
 
                members[i] = members[i+1];
128
 
                i++;
129
 
        }
130
 
 
131
 
        if (!found) {
132
 
                fputs (_("Member to remove could not be found\n"), stderr);
133
 
                exit (EXIT_NOT_MEMBER);
134
 
        }
135
 
}
136
 
 
137
 
static void nomembers (char **members)
138
 
{
139
 
        int i;
140
 
 
141
 
        for (i = 0; NULL != members[i]; i++) {
142
 
                members[i] = NULL;
143
 
        }
144
 
}
145
 
 
146
 
static void members (char **members)
 
113
/*
 
114
 * add_user - Add an user to the specified group
 
115
 */
 
116
static void add_user (const char *user,
 
117
                      const struct group *grp)
 
118
{
 
119
        struct group *newgrp;
 
120
 
 
121
        /* Make sure the user is not already part of the group */
 
122
        if (is_on_list (grp->gr_mem, user)) {
 
123
                fprintf (stderr,
 
124
                         _("%s: user '%s' is already a member of '%s'\n"),
 
125
                         Prog, user, grp->gr_name);
 
126
                fail_exit (EXIT_MEMBER_EXISTS);
 
127
        }
 
128
 
 
129
        newgrp = __gr_dup(grp);
 
130
        if (NULL == newgrp) {
 
131
                fprintf (stderr,
 
132
                         _("%s: Out of memory. Cannot update %s.\n"),
 
133
                         Prog, gr_dbname ());
 
134
                fail_exit (13);
 
135
        }
 
136
 
 
137
        /* Add the user to the /etc/group group */
 
138
        newgrp->gr_mem = add_list (newgrp->gr_mem, user);
 
139
 
 
140
#ifdef SHADOWGRP
 
141
        if (is_shadowgrp) {
 
142
                const struct sgrp *sg = sgr_locate (newgrp->gr_name);
 
143
                struct sgrp *newsg;
 
144
 
 
145
                if (NULL == sg) {
 
146
                        /* Create a shadow group based on this group */
 
147
                        static struct sgrp sgrent;
 
148
                        sgrent.sg_name = xstrdup (newgrp->gr_name);
 
149
                        sgrent.sg_mem = dup_list (newgrp->gr_mem);
 
150
                        sgrent.sg_adm = (char **) xmalloc (sizeof (char *));
 
151
#ifdef FIRST_MEMBER_IS_ADMIN
 
152
                        if (sgrent.sg_mem[0]) {
 
153
                                sgrent.sg_adm[0] = xstrdup (sgrent.sg_mem[0]);
 
154
                                sgrent.sg_adm[1] = NULL;
 
155
                        } else
 
156
#endif
 
157
                        {
 
158
                                sgrent.sg_adm[0] = NULL;
 
159
                        }
 
160
 
 
161
                        /* Move any password to gshadow */
 
162
                        sgrent.sg_passwd = newgrp->gr_passwd;
 
163
                        newgrp->gr_passwd = SHADOW_PASSWD_STRING;
 
164
 
 
165
                        newsg = &sgrent;
 
166
                } else {
 
167
                        newsg = __sgr_dup (sg);
 
168
                        if (NULL == newsg) {
 
169
                                fprintf (stderr,
 
170
                                         _("%s: Out of memory. Cannot update %s.\n"),
 
171
                                         Prog, sgr_dbname ());
 
172
                                fail_exit (13);
 
173
                        }
 
174
                        /* Add the user to the members */
 
175
                        newsg->sg_mem = add_list (newsg->sg_mem, user);
 
176
                        /* Do not touch the administrators */
 
177
                }
 
178
 
 
179
                if (sgr_update (newsg) == 0) {
 
180
                        fprintf (stderr,
 
181
                                 _("%s: failed to prepare the new %s entry '%s'\n"),
 
182
                                 Prog, sgr_dbname (), newsg->sg_name);
 
183
                        fail_exit (13);
 
184
                }
 
185
        }
 
186
#endif
 
187
 
 
188
        if (gr_update (newgrp) == 0) {
 
189
                fprintf (stderr,
 
190
                         _("%s: failed to prepare the new %s entry '%s'\n"),
 
191
                         Prog, gr_dbname (), newgrp->gr_name);
 
192
                fail_exit (13);
 
193
        }
 
194
}
 
195
 
 
196
/*
 
197
 * remove_user - Remove an user from a given group
 
198
 */
 
199
static void remove_user (const char *user, 
 
200
                         const struct group *grp)
 
201
{
 
202
        struct group *newgrp;
 
203
 
 
204
        /* Check if the user is a member of the specified group */
 
205
        if (!is_on_list (grp->gr_mem, user)) {
 
206
                fprintf (stderr,
 
207
                         _("%s: user '%s' is not a member of '%s'\n"),
 
208
                         Prog, user, grp->gr_name);
 
209
                fail_exit (EXIT_NOT_MEMBER);
 
210
        }
 
211
 
 
212
        newgrp = __gr_dup (grp);
 
213
        if (NULL == newgrp) {
 
214
                fprintf (stderr,
 
215
                         _("%s: Out of memory. Cannot update %s.\n"),
 
216
                         Prog, gr_dbname ());
 
217
                fail_exit (13);
 
218
        }
 
219
 
 
220
        /* Remove the user from the /etc/group group */
 
221
        newgrp->gr_mem = del_list (newgrp->gr_mem, user);
 
222
 
 
223
#ifdef SHADOWGRP
 
224
        if (is_shadowgrp) {
 
225
                const struct sgrp *sg = sgr_locate (newgrp->gr_name);
 
226
                struct sgrp *newsg;
 
227
 
 
228
                if (NULL == sg) {
 
229
                        /* Create a shadow group based on this group */
 
230
                        static struct sgrp sgrent;
 
231
                        sgrent.sg_name = xstrdup (newgrp->gr_name);
 
232
                        sgrent.sg_mem = dup_list (newgrp->gr_mem);
 
233
                        sgrent.sg_adm = (char **) xmalloc (sizeof (char *));
 
234
#ifdef FIRST_MEMBER_IS_ADMIN
 
235
                        if (sgrent.sg_mem[0]) {
 
236
                                sgrent.sg_adm[0] = xstrdup (sgrent.sg_mem[0]);
 
237
                                sgrent.sg_adm[1] = NULL;
 
238
                        } else
 
239
#endif
 
240
                        {
 
241
                                sgrent.sg_adm[0] = NULL;
 
242
                        }
 
243
 
 
244
                        /* Move any password to gshadow */
 
245
                        sgrent.sg_passwd = newgrp->gr_passwd;
 
246
                        newgrp->gr_passwd = SHADOW_PASSWD_STRING;
 
247
 
 
248
                        newsg = &sgrent;
 
249
                } else {
 
250
                        newsg = __sgr_dup (sg);
 
251
                        if (NULL == newsg) {
 
252
                                fprintf (stderr,
 
253
                                         _("%s: Out of memory. Cannot update %s.\n"),
 
254
                                         Prog, sgr_dbname ());
 
255
                                fail_exit (13);
 
256
                        }
 
257
                        /* Remove the user from the members */
 
258
                        newsg->sg_mem = del_list (newsg->sg_mem, user);
 
259
                        /* Remove the user from the administrators */
 
260
                        newsg->sg_adm = del_list (newsg->sg_adm, user);
 
261
                }
 
262
 
 
263
                if (sgr_update (newsg) == 0) {
 
264
                        fprintf (stderr,
 
265
                                 _("%s: failed to prepare the new %s entry '%s'\n"),
 
266
                                 Prog, sgr_dbname (), newsg->sg_name);
 
267
                        fail_exit (13);
 
268
                }
 
269
        }
 
270
#endif
 
271
 
 
272
        if (gr_update (newgrp) == 0) {
 
273
                fprintf (stderr,
 
274
                         _("%s: failed to prepare the new %s entry '%s'\n"),
 
275
                         Prog, gr_dbname (), newgrp->gr_name);
 
276
                fail_exit (13);
 
277
        }
 
278
}
 
279
 
 
280
/*
 
281
 * purge_members - Rmeove every members of the specified group
 
282
 */
 
283
static void purge_members (const struct group *grp)
 
284
{
 
285
        struct group *newgrp = __gr_dup (grp);
 
286
 
 
287
        if (NULL == newgrp) {
 
288
                fprintf (stderr,
 
289
                         _("%s: Out of memory. Cannot update %s.\n"),
 
290
                         Prog, gr_dbname ());
 
291
                fail_exit (13);
 
292
        }
 
293
 
 
294
        /* Remove all the members of the /etc/group group */
 
295
        newgrp->gr_mem[0] = NULL;
 
296
 
 
297
#ifdef SHADOWGRP
 
298
        if (is_shadowgrp) {
 
299
                const struct sgrp *sg = sgr_locate (newgrp->gr_name);
 
300
                struct sgrp *newsg;
 
301
 
 
302
                if (NULL == sg) {
 
303
                        /* Create a shadow group based on this group */
 
304
                        static struct sgrp sgrent;
 
305
                        sgrent.sg_name = xstrdup (newgrp->gr_name);
 
306
                        sgrent.sg_mem = (char **) xmalloc (sizeof (char *));
 
307
                        sgrent.sg_mem[0] = NULL;
 
308
                        sgrent.sg_adm = (char **) xmalloc (sizeof (char *));
 
309
                        sgrent.sg_adm[0] = NULL;
 
310
 
 
311
                        /* Move any password to gshadow */
 
312
                        sgrent.sg_passwd = newgrp->gr_passwd;
 
313
                        newgrp->gr_passwd = xstrdup(SHADOW_PASSWD_STRING);
 
314
 
 
315
                        newsg = &sgrent;
 
316
                } else {
 
317
                        newsg = __sgr_dup (sg);
 
318
                        if (NULL == newsg) {
 
319
                                fprintf (stderr,
 
320
                                         _("%s: Out of memory. Cannot update %s.\n"),
 
321
                                         Prog, sgr_dbname ());
 
322
                                fail_exit (13);
 
323
                        }
 
324
                        /* Remove all the members of the /etc/gshadow
 
325
                         * group */
 
326
                        newsg->sg_mem[0] = NULL;
 
327
                        /* Remove all the administrators of the
 
328
                         * /etc/gshadow group */
 
329
                        newsg->sg_adm[0] = NULL;
 
330
                }
 
331
 
 
332
                if (sgr_update (newsg) == 0) {
 
333
                        fprintf (stderr,
 
334
                                 _("%s: failed to prepare the new %s entry '%s'\n"),
 
335
                                 Prog, sgr_dbname (), newsg->sg_name);
 
336
                        fail_exit (13);
 
337
                }
 
338
        }
 
339
#endif
 
340
 
 
341
        if (gr_update (newgrp) == 0) {
 
342
                fprintf (stderr,
 
343
                         _("%s: failed to prepare the new %s entry '%s'\n"),
 
344
                         Prog, gr_dbname (), newgrp->gr_name);
 
345
                fail_exit (13);
 
346
        }
 
347
}
 
348
 
 
349
static void display_members (const char *const *members)
147
350
{
148
351
        int i;
149
352
 
160
363
 
161
364
static void usage (void)
162
365
{
163
 
        fputs (_("Usage: groupmems -a username | -d username | -D | -l [-g groupname]\n"), stderr);
164
 
        exit (EXIT_USAGE);
 
366
        (void) fputs (_("Usage: groupmems [options] [action]\n"
 
367
                        "\n"
 
368
                        "Options:\n"
 
369
                        "  -g, --group groupname         change groupname instead of the user's group\n"
 
370
                        "                                (root only)\n"
 
371
                        "\n"
 
372
                        "Actions:\n"
 
373
                        "  -a, --add username            add username to the members of the group\n"
 
374
                        "  -d, --delete username         remove username from the members of the group\n"
 
375
                        "  -p, --purge                   purge all members from the group\n"
 
376
                        "  -l, --list                    list the members of the group\n"
 
377
                        "\n"), stderr);
 
378
        fail_exit (EXIT_USAGE);
165
379
}
166
380
 
167
 
int main (int argc, char **argv) 
 
381
/*
 
382
 * process_flags - perform command line argument setting
 
383
 */
 
384
static void process_flags (int argc, char **argv)
168
385
{
169
386
        int arg;
170
 
        char *name;
171
 
        struct group *grp;
172
 
 
173
 
#ifdef USE_PAM
174
 
        pam_handle_t *pamh = NULL;
175
 
        int retval;
176
 
#endif
177
 
 
178
 
        setlocale (LC_ALL, "");
179
 
        bindtextdomain (PACKAGE, LOCALEDIR);
180
 
        textdomain (PACKAGE);
181
 
 
182
387
        int option_index = 0;
183
388
        static struct option long_options[] = {
184
389
                {"add", required_argument, NULL, 'a'},
189
394
                {NULL, 0, NULL, '\0'}
190
395
        };
191
396
 
192
 
        while ((arg =
193
 
                getopt_long (argc, argv, "a:d:g:lp", long_options,
194
 
                             &option_index)) != EOF) {
 
397
        while ((arg = getopt_long (argc, argv, "a:d:g:lp", long_options,
 
398
                                   &option_index)) != EOF) {
195
399
                switch (arg) {
196
400
                case 'a':
197
 
                        adduser = strdup (optarg);
 
401
                        adduser = xstrdup (optarg);
198
402
                        ++exclusive;
199
403
                        break;
200
404
                case 'd':
201
 
                        deluser = strdup (optarg);
202
 
                        ++exclusive;
203
 
                        break;
204
 
                case 'p':
205
 
                        purge = TRUE;
 
405
                        deluser = xstrdup (optarg);
206
406
                        ++exclusive;
207
407
                        break;
208
408
                case 'g':
209
 
                        thisgroup = strdup (optarg);
 
409
                        thisgroup = xstrdup (optarg);
210
410
                        break;
211
411
                case 'l':
212
 
                        list = TRUE;
 
412
                        list = true;
 
413
                        ++exclusive;
 
414
                        break;
 
415
                case 'p':
 
416
                        purge = true;
213
417
                        ++exclusive;
214
418
                        break;
215
419
                default:
217
421
                }
218
422
        }
219
423
 
220
 
        if (exclusive > 1 || optind < argc) {
 
424
        if ((exclusive > 1) || (optind < argc)) {
221
425
                usage ();
222
426
        }
223
427
 
224
 
        if (!isroot () && NULL != thisgroup) {
225
 
                fputs (_("Only root can add members to different groups\n"),
226
 
                       stderr);
227
 
                exit (EXIT_NOT_ROOT);
228
 
        } else if (isroot () && NULL != thisgroup) {
229
 
                name = thisgroup;
230
 
        } else if (!isgroup ()) {
231
 
                fputs (_("Group access is required\n"), stderr);
232
 
                exit (EXIT_NOT_EROOT);
233
 
        } else if (NULL == (name = whoami ())) {
234
 
                fputs (_("Not primary owner of current group\n"), stderr);
235
 
                exit (EXIT_NOT_PRIMARY);
 
428
        /* local, no need for xgetpwnam */
 
429
        if (   (NULL != adduser)
 
430
            && (getpwnam (adduser) == NULL)) {
 
431
                fprintf (stderr, _("%s: user '%s' does not exist\n"),
 
432
                         Prog, adduser);
 
433
                fail_exit (EXIT_INVALID_USER);
236
434
        }
 
435
 
 
436
}
 
437
 
 
438
static void check_perms (void)
 
439
{
 
440
        if (!list) {
237
441
#ifdef USE_PAM
238
 
        retval = PAM_SUCCESS;
239
 
 
240
 
        {
 
442
                pam_handle_t *pamh = NULL;
 
443
                int retval;
241
444
                struct passwd *pampw;
 
445
 
242
446
                pampw = getpwuid (getuid ()); /* local, no need for xgetpwuid */
243
 
                if (pampw == NULL) {
244
 
                        retval = PAM_USER_UNKNOWN;
245
 
                }
246
 
 
247
 
                if (retval == PAM_SUCCESS) {
248
 
                        retval = pam_start ("groupmod", pampw->pw_name,
249
 
                                            &conv, &pamh);
250
 
                }
251
 
        }
252
 
 
253
 
        if (retval == PAM_SUCCESS) {
254
 
                retval = pam_authenticate (pamh, 0);
255
 
                if (retval != PAM_SUCCESS) {
256
 
                        pam_end (pamh, retval);
257
 
                }
258
 
        }
259
 
 
260
 
        if (retval == PAM_SUCCESS) {
261
 
                retval = pam_acct_mgmt (pamh, 0);
262
 
                if (retval != PAM_SUCCESS) {
263
 
                        pam_end (pamh, retval);
264
 
                }
265
 
        }
266
 
 
267
 
        if (retval != PAM_SUCCESS) {
268
 
                fputs (_("PAM authentication failed for\n"), stderr);
269
 
                exit (1);
270
 
        }
271
 
#endif
272
 
 
273
 
        if (!gr_lock ()) {
274
 
                fputs (_("Unable to lock group file\n"), stderr);
275
 
                exit (EXIT_GROUP_FILE);
276
 
        }
277
 
 
278
 
        if (!gr_open (O_RDWR)) {
279
 
                fputs (_("Unable to open group file\n"), stderr);
280
 
                exit (EXIT_GROUP_FILE);
281
 
        }
282
 
 
283
 
        grp = (struct group *) gr_locate (name);
284
 
 
285
 
        if (NULL != adduser) {
286
 
                addtogroup (adduser, grp->gr_mem);
287
 
                gr_update (grp);
 
447
                if (NULL == pampw) {
 
448
                        fprintf (stderr,
 
449
                                 _("%s: Cannot determine your user name.\n"),
 
450
                                 Prog);
 
451
                        fail_exit (1);
 
452
                }
 
453
 
 
454
                retval = pam_start ("groupmems", pampw->pw_name, &conv, &pamh);
 
455
 
 
456
                if (PAM_SUCCESS == retval) {
 
457
                        retval = pam_authenticate (pamh, 0);
 
458
                }
 
459
 
 
460
                if (PAM_SUCCESS == retval) {
 
461
                        retval = pam_acct_mgmt (pamh, 0);
 
462
                }
 
463
 
 
464
                if (NULL != pamh) {
 
465
                        (void) pam_end (pamh, retval);
 
466
                }
 
467
                if (PAM_SUCCESS != retval) {
 
468
                        fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
 
469
                        fail_exit (1);
 
470
                }
 
471
#endif
 
472
        }
 
473
}
 
474
 
 
475
static void fail_exit (int code)
 
476
{
 
477
        if (gr_locked) {
 
478
                if (gr_unlock () == 0) {
 
479
                        fprintf (stderr,
 
480
                                 _("%s: failed to unlock %s\n"),
 
481
                                 Prog, gr_dbname ());
 
482
                        SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ()));
 
483
                        /* continue */
 
484
                }
 
485
        }
 
486
 
 
487
#ifdef SHADOWGRP
 
488
        if (sgr_locked) {
 
489
                if (sgr_unlock () == 0) {
 
490
                        fprintf (stderr,
 
491
                                 _("%s: failed to unlock %s\n"),
 
492
                                 Prog, sgr_dbname ());
 
493
                        SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ()));
 
494
                        /* continue */
 
495
                }
 
496
        }
 
497
#endif
 
498
 
 
499
        exit (code);
 
500
}
 
501
 
 
502
static void open_files (void)
 
503
{
 
504
        if (!list) {
 
505
                if (gr_lock () == 0) {
 
506
                        fprintf (stderr,
 
507
                                 _("%s: cannot lock %s; try again later.\n"),
 
508
                                 Prog, gr_dbname ());
 
509
                        fail_exit (EXIT_GROUP_FILE);
 
510
                }
 
511
                gr_locked = true;
 
512
 
 
513
#ifdef SHADOWGRP
 
514
                if (is_shadowgrp) {
 
515
                        if (sgr_lock () == 0) {
 
516
                                fprintf (stderr,
 
517
                                         _("%s: cannot lock %s; try again later.\n"),
 
518
                                         Prog, sgr_dbname ());
 
519
                                fail_exit (EXIT_GROUP_FILE);
 
520
                        }
 
521
                        sgr_locked = true;
 
522
                }
 
523
#endif
 
524
        }
 
525
 
 
526
        if (gr_open (list ? O_RDONLY : O_RDWR) == 0) {
 
527
                fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ());
 
528
                fail_exit (EXIT_GROUP_FILE);
 
529
        }
 
530
 
 
531
#ifdef SHADOWGRP
 
532
        if (is_shadowgrp) {
 
533
                if (sgr_open (list ? O_RDONLY : O_RDWR) == 0) {
 
534
                        fprintf (stderr, _("%s: cannot open %s\n"), Prog, sgr_dbname ());
 
535
                        fail_exit (EXIT_GROUP_FILE);
 
536
                }
 
537
        }
 
538
#endif
 
539
}
 
540
 
 
541
static void close_files (void)
 
542
{
 
543
        if ((gr_close () == 0) && !list) {
 
544
                fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ());
 
545
                SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ()));
 
546
                fail_exit (EXIT_GROUP_FILE);
 
547
        }
 
548
        if (gr_locked) {
 
549
                if (gr_unlock () == 0) {
 
550
                        fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ());
 
551
                        SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ()));
 
552
                        /* continue */
 
553
                }
 
554
                gr_locked = false;
 
555
        }
 
556
 
 
557
#ifdef SHADOWGRP
 
558
        if (is_shadowgrp) {
 
559
                if ((sgr_close () == 0) && !list) {
 
560
                        fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sgr_dbname ());
 
561
                        SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ()));
 
562
                        fail_exit (EXIT_GROUP_FILE);
 
563
                }
 
564
                if (sgr_locked) {
 
565
                        if (sgr_unlock () == 0) {
 
566
                                fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ());
 
567
                                SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ()));
 
568
                                /* continue */
 
569
                        }
 
570
                        sgr_locked = false;
 
571
                }
 
572
        }
 
573
#endif
 
574
}
 
575
 
 
576
int main (int argc, char **argv) 
 
577
{
 
578
        char *name;
 
579
        const struct group *grp;
 
580
 
 
581
        /*
 
582
         * Get my name so that I can use it to report errors.
 
583
         */
 
584
        Prog = Basename (argv[0]);
 
585
 
 
586
        OPENLOG ("groupmems");
 
587
 
 
588
        (void) setlocale (LC_ALL, "");
 
589
        (void) bindtextdomain (PACKAGE, LOCALEDIR);
 
590
        (void) textdomain (PACKAGE);
 
591
 
 
592
#ifdef SHADOWGRP
 
593
        is_shadowgrp = sgr_file_present ();
 
594
#endif
 
595
 
 
596
        process_flags (argc, argv);
 
597
 
 
598
        if (NULL == thisgroup) {
 
599
                name = whoami ();
 
600
                if (!list && (NULL == name)) {
 
601
                        fprintf (stderr, _("%s: your groupname does not match your username\n"), Prog);
 
602
                        fail_exit (EXIT_NOT_PRIMARY);
 
603
                }
 
604
        } else {
 
605
                name = thisgroup;
 
606
                if (!list && !isroot ()) {
 
607
                        fprintf (stderr, _("%s: only root can use the -g/--group option\n"), Prog);
 
608
                        fail_exit (EXIT_NOT_ROOT);
 
609
                }
 
610
        }
 
611
 
 
612
        check_perms ();
 
613
 
 
614
        open_files ();
 
615
 
 
616
        grp = gr_locate (name);
 
617
        if (NULL == grp) {
 
618
                fprintf (stderr, _("%s: group '%s' does not exist in %s\n"),
 
619
                         Prog, name, gr_dbname ());
 
620
                fail_exit (EXIT_INVALID_GROUP);
 
621
        }
 
622
 
 
623
        if (list) {
 
624
                display_members ((const char *const *)grp->gr_mem);
 
625
        } else if (NULL != adduser) {
 
626
                add_user (adduser, grp);
288
627
        } else if (NULL != deluser) {
289
 
                rmfromgroup (deluser, grp->gr_mem);
290
 
                gr_update (grp);
 
628
                remove_user (deluser, grp);
291
629
        } else if (purge) {
292
 
                nomembers (grp->gr_mem);
293
 
                gr_update (grp);
294
 
        } else if (list) {
295
 
                members (grp->gr_mem);
296
 
        }
297
 
 
298
 
        if (!gr_close ()) {
299
 
                fputs (_("Cannot close group file\n"), stderr);
300
 
                exit (EXIT_GROUP_FILE);
301
 
        }
302
 
 
303
 
        gr_unlock ();
304
 
 
305
 
#ifdef USE_PAM
306
 
        if (retval == PAM_SUCCESS) {
307
 
                pam_end (pamh, PAM_SUCCESS);
308
 
        }
309
 
#endif                          /* USE_PAM */
 
630
                purge_members (grp);
 
631
        }
 
632
 
 
633
        close_files ();
 
634
 
310
635
        exit (EXIT_SUCCESS);
311
636
}
 
637