]> granicus.if.org Git - shadow/blob - src/grpconv.c
* src/usermod.c (process_flags): Report usage if no options are
[shadow] / src / grpconv.c
1 /*
2  * Copyright (c) 1996 - 2000, Marek Michałkiewicz
3  * Copyright (c) 2002 - 2006, Tomasz Kłoczko
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the copyright holders or contributors may not be used to
15  *    endorse or promote products derived from this software without
16  *    specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
21  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
22  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 /*
32  * grpconv - create or update /etc/gshadow with information from
33  * /etc/group.
34  *
35  */
36
37 #include <config.h>
38 #ident "$Id$"
39
40 #include <errno.h>
41 #include <fcntl.h>
42 #include <grp.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <time.h>
47 #include <unistd.h>
48 #include "nscd.h"
49 #include "prototypes.h"
50 #ifdef SHADOWGRP
51 #include "groupio.h"
52 #include "sgroupio.h"
53 /*
54  * Global variables
55  */
56 const char *Prog;
57
58 static bool gr_locked  = false;
59 static bool sgr_locked = false;
60
61 /* local function prototypes */
62 static void fail_exit (int status);
63
64 static void fail_exit (int status)
65 {
66         if (gr_locked) {
67                 if (gr_unlock () == 0) {
68                         fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ());
69                         SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ()));
70                         /* continue */
71                 }
72         }
73
74         if (sgr_locked) {
75                 if (sgr_unlock () == 0) {
76                         fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ());
77                         SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ()));
78                         /* continue */
79                 }
80         }
81
82         exit (status);
83 }
84
85 int main (int argc, char **argv)
86 {
87         const struct group *gr;
88         struct group grent;
89         const struct sgrp *sg;
90         struct sgrp sgent;
91
92         if (1 != argc) {
93                 (void) fputs (_("Usage: grpconv\n"), stderr);
94         }
95         Prog = Basename (argv[0]);
96
97         (void) setlocale (LC_ALL, "");
98         (void) bindtextdomain (PACKAGE, LOCALEDIR);
99         (void) textdomain (PACKAGE);
100
101         OPENLOG ("grpconv");
102
103         if (gr_lock () == 0) {
104                 fprintf (stderr,
105                          _("%s: cannot lock %s; try again later.\n"),
106                          Prog, gr_dbname ());
107                 fail_exit (5);
108         }
109         gr_locked = true;
110         if (gr_open (O_RDWR) == 0) {
111                 fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ());
112                 fail_exit (1);
113         }
114
115         if (sgr_lock () == 0) {
116                 fprintf (stderr,
117                          _("%s: cannot lock %s; try again later.\n"),
118                          Prog, sgr_dbname ());
119                 fail_exit (5);
120         }
121         sgr_locked = true;
122         if (sgr_open (O_CREAT | O_RDWR) == 0) {
123                 fprintf (stderr, _("%s: cannot open %s\n"), Prog, sgr_dbname ());
124                 fail_exit (1);
125         }
126
127         /*
128          * Remove /etc/gshadow entries for groups not in /etc/group.
129          */
130         sgr_rewind ();
131         while ((sg = sgr_next ()) != NULL) {
132                 if (gr_locate (sg->sg_name) != NULL) {
133                         continue;
134                 }
135
136                 if (sgr_remove (sg->sg_name) == 0) {
137                         /*
138                          * This shouldn't happen (the entry exists) but...
139                          */
140                         fprintf (stderr,
141                                  _("%s: cannot remove entry '%s' from %s\n"),
142                                  Prog, sg->sg_name, sgr_dbname ());
143                         fail_exit (3);
144                 }
145         }
146
147         /*
148          * Update shadow group passwords if non-shadow password is not "x".
149          * Add any missing shadow group entries.
150          */
151         gr_rewind ();
152         while ((gr = gr_next ()) != NULL) {
153                 sg = sgr_locate (gr->gr_name);
154                 if (NULL != sg) {
155                         /* update existing shadow group entry */
156                         sgent = *sg;
157                         if (strcmp (gr->gr_passwd, SHADOW_PASSWD_STRING) != 0)
158                                 sgent.sg_passwd = gr->gr_passwd;
159                 } else {
160                         static char *empty = 0;
161
162                         /* add new shadow group entry */
163                         memset (&sgent, 0, sizeof sgent);
164                         sgent.sg_name = gr->gr_name;
165                         sgent.sg_passwd = gr->gr_passwd;
166                         sgent.sg_adm = &empty;
167                 }
168                 /*
169                  * XXX - sg_mem is redundant, it is currently always a copy
170                  * of gr_mem. Very few programs actually use sg_mem, and all
171                  * of them are in the shadow suite. Maybe this field could
172                  * be used for something else? Any suggestions?
173                  */
174                 sgent.sg_mem = gr->gr_mem;
175
176                 if (sgr_update (&sgent) == 0) {
177                         fprintf (stderr,
178                                  _("%s: failed to prepare the new %s entry '%s'\n"),
179                                  Prog, sgr_dbname (), sgent.sg_name);
180                         fail_exit (3);
181                 }
182                 /* remove password from /etc/group */
183                 grent = *gr;
184                 grent.gr_passwd = SHADOW_PASSWD_STRING; /* XXX warning: const */
185                 if (gr_update (&grent) == 0) {
186                         fprintf (stderr,
187                                  _("%s: failed to prepare the new %s entry '%s'\n"),
188                                  Prog, gr_dbname (), grent.gr_name);
189                         fail_exit (3);
190                 }
191         }
192
193         if (sgr_close () == 0) {
194                 fprintf (stderr,
195                          _("%s: failure while writing changes to %s\n"),
196                          Prog, sgr_dbname ());
197                 SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ()));
198                 fail_exit (3);
199         }
200         if (gr_close () == 0) {
201                 fprintf (stderr,
202                          _("%s: failure while writing changes to %s\n"),
203                          Prog, gr_dbname ());
204                 SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ()));
205                 fail_exit (3);
206         }
207         if (sgr_unlock () == 0) {
208                 fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ());
209                 SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ()));
210                 /* continue */
211         }
212         sgr_locked = false;
213         if (gr_unlock () == 0) {
214                 fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ());
215                 SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ()));
216                 /* continue */
217         }
218         gr_locked = false;
219
220         nscd_flush_cache ("group");
221
222         return 0;
223 }
224 #else                           /* !SHADOWGRP */
225 int main (int unused(argc), char **argv)
226 {
227         fprintf (stderr,
228                  "%s: not configured for shadow group support.\n", argv[0]);
229         exit (1);
230 }
231 #endif                          /* !SHADOWGRP */
232