fix up changelog
[debian/sudo] / tsgetgrpw.c
1 /*
2  * Copyright (c) 2005, 2008, 2010 Todd C. Miller <Todd.Miller@courtesan.com>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 /*
18  * Trivial replacements for the libc get{gr,pw}{uid,nam}() routines
19  * for use by testsudoers in the sudo test harness.
20  * We need our own since many platforms don't provide set{pw,gr}file().
21  */
22
23 #include <config.h>
24
25 #include <sys/types.h>
26 #include <sys/param.h>
27 #include <stdio.h>
28 #ifdef STDC_HEADERS
29 # include <stdlib.h>
30 # include <stddef.h>
31 #else
32 # ifdef HAVE_STDLIB_H
33 #  include <stdlib.h>
34 # endif
35 #endif /* STDC_HEADERS */
36 #ifdef HAVE_STRING_H
37 # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
38 #  include <memory.h>
39 # endif
40 # include <string.h>
41 #endif /* HAVE_STRING_H */
42 #ifdef HAVE_STRINGS_H
43 # include <strings.h>
44 #endif /* HAVE_STRINGS_H */
45 #include <fcntl.h>
46 #include <limits.h>
47 #include <pwd.h>
48 #include <grp.h>
49
50 #include "sudo.h"
51
52 #ifndef LINE_MAX
53 # define LINE_MAX 2048
54 #endif
55
56 #undef GRMEM_MAX
57 #define GRMEM_MAX 200
58
59 static FILE *pwf;
60 static const char *pwfile = "/etc/passwd";
61 static int pw_stayopen;
62
63 static FILE *grf;
64 static const char *grfile = "/etc/group";
65 static int gr_stayopen;
66
67 void setgrfile __P((const char *));
68 void setgrent __P((void));
69 void endgrent __P((void));
70 struct group *getgrent __P((void));
71 struct group *getgrnam __P((const char *));
72 struct group *getgrgid __P((gid_t));
73
74 void setpwfile __P((const char *));
75 void setpwent __P((void));
76 void endpwent __P((void));
77 struct passwd *getpwent __P((void));
78 struct passwd *getpwnam __P((const char *));
79 struct passwd *getpwuid __P((uid_t));
80
81 void
82 setpwfile(file)
83     const char *file;
84 {
85     pwfile = file;
86     if (pwf != NULL)
87         endpwent();
88 }
89
90 void
91 setpwent()
92 {
93     if (pwf == NULL) {
94         pwf = fopen(pwfile, "r");
95         if (pwf != NULL)
96             fcntl(fileno(pwf), F_SETFD, FD_CLOEXEC);
97     } else {
98         rewind(pwf);
99     }
100     pw_stayopen = 1;
101 }
102
103 void
104 endpwent()
105 {
106     if (pwf != NULL) {
107         fclose(pwf);
108         pwf = NULL;
109     }
110     pw_stayopen = 0;
111 }
112
113 struct passwd *
114 getpwent()
115 {
116     static struct passwd pw;
117     static char pwbuf[LINE_MAX];
118     size_t len;
119     char *cp, *colon;
120
121     if ((colon = fgets(pwbuf, sizeof(pwbuf), pwf)) == NULL)
122         return(NULL);
123
124     zero_bytes(&pw, sizeof(pw));
125     if ((colon = strchr(cp = colon, ':')) == NULL)
126         return(NULL);
127     *colon++ = '\0';
128     pw.pw_name = cp;
129     if ((colon = strchr(cp = colon, ':')) == NULL)
130         return(NULL);
131     *colon++ = '\0';
132     pw.pw_passwd = cp;
133     if ((colon = strchr(cp = colon, ':')) == NULL)
134         return(NULL);
135     *colon++ = '\0';
136     pw.pw_uid = atoi(cp);
137     if ((colon = strchr(cp = colon, ':')) == NULL)
138         return(NULL);
139     *colon++ = '\0';
140     pw.pw_gid = atoi(cp);
141     if ((colon = strchr(cp = colon, ':')) == NULL)
142         return(NULL);
143     *colon++ = '\0';
144     pw.pw_gecos = cp;
145     if ((colon = strchr(cp = colon, ':')) == NULL)
146         return(NULL);
147     *colon++ = '\0';
148     pw.pw_dir = cp;
149     pw.pw_shell = colon;
150     len = strlen(colon);
151     if (len > 0 && colon[len - 1] == '\n')
152         colon[len - 1] = '\0';
153     return(&pw);
154 }
155
156 struct passwd *
157 getpwnam(name)
158     const char *name;
159 {
160     struct passwd *pw;
161
162     if (pwf == NULL) {
163         if ((pwf = fopen(pwfile, "r")) == NULL)
164             return(NULL);
165         fcntl(fileno(pwf), F_SETFD, FD_CLOEXEC);
166     } else {
167         rewind(pwf);
168     }
169     while ((pw = getpwent()) != NULL) {
170         if (strcmp(pw->pw_name, name) == 0)
171             break;
172     }
173     if (!pw_stayopen) {
174         fclose(pwf);
175         pwf = NULL;
176     }
177     return(pw);
178 }
179
180 struct passwd *
181 getpwuid(uid)
182     uid_t uid;
183 {
184     struct passwd *pw;
185
186     if (pwf == NULL) {
187         if ((pwf = fopen(pwfile, "r")) == NULL)
188             return(NULL);
189         fcntl(fileno(pwf), F_SETFD, FD_CLOEXEC);
190     } else {
191         rewind(pwf);
192     }
193     while ((pw = getpwent()) != NULL) {
194         if (pw->pw_uid == uid)
195             break;
196     }
197     if (!pw_stayopen) {
198         fclose(pwf);
199         pwf = NULL;
200     }
201     return(pw);
202 }
203
204 void
205 setgrfile(file)
206     const char *file;
207 {
208     grfile = file;
209     if (grf != NULL)
210         endgrent();
211 }
212
213 void
214 setgrent()
215 {
216     if (grf == NULL) {
217         grf = fopen(grfile, "r");
218         if (grf != NULL)
219             fcntl(fileno(grf), F_SETFD, FD_CLOEXEC);
220     } else {
221         rewind(grf);
222     }
223     gr_stayopen = 1;
224 }
225
226 void
227 endgrent()
228 {
229     if (grf != NULL) {
230         fclose(grf);
231         grf = NULL;
232     }
233     gr_stayopen = 0;
234 }
235
236 struct group *
237 getgrent()
238 {
239     static struct group gr;
240     static char grbuf[LINE_MAX], *gr_mem[GRMEM_MAX+1];
241     size_t len;
242     char *cp, *colon;
243     int n;
244
245     if ((colon = fgets(grbuf, sizeof(grbuf), grf)) == NULL)
246         return(NULL);
247
248     zero_bytes(&gr, sizeof(gr));
249     if ((colon = strchr(cp = colon, ':')) == NULL)
250         return(NULL);
251     *colon++ = '\0';
252     gr.gr_name = cp;
253     if ((colon = strchr(cp = colon, ':')) == NULL)
254         return(NULL);
255     *colon++ = '\0';
256     gr.gr_passwd = cp;
257     if ((colon = strchr(cp = colon, ':')) == NULL)
258         return(NULL);
259     *colon++ = '\0';
260     gr.gr_gid = atoi(cp);
261     len = strlen(colon);
262     if (len > 0 && colon[len - 1] == '\n')
263         colon[len - 1] = '\0';
264     if (*colon != '\0') {
265         gr.gr_mem = gr_mem;
266         cp = strtok(colon, ",");
267         for (n = 0; cp != NULL && n < GRMEM_MAX; n++) {
268             gr.gr_mem[n] = cp;
269             cp = strtok(NULL, ",");
270         }
271         gr.gr_mem[n++] = NULL;
272     } else
273         gr.gr_mem = NULL;
274     return(&gr);
275 }
276
277 struct group *
278 getgrnam(name)
279     const char *name;
280 {
281     struct group *gr;
282
283     if (grf == NULL) {
284         if ((grf = fopen(grfile, "r")) == NULL)
285             return(NULL);
286         fcntl(fileno(grf), F_SETFD, FD_CLOEXEC);
287     } else {
288         rewind(grf);
289     }
290     while ((gr = getgrent()) != NULL) {
291         if (strcmp(gr->gr_name, name) == 0)
292             break;
293     }
294     if (!gr_stayopen) {
295         fclose(grf);
296         grf = NULL;
297     }
298     return(gr);
299 }
300
301 struct group *
302 getgrgid(gid)
303     gid_t gid;
304 {
305     struct group *gr;
306
307     if (grf == NULL) {
308         if ((grf = fopen(grfile, "r")) == NULL)
309             return(NULL);
310         fcntl(fileno(grf), F_SETFD, FD_CLOEXEC);
311     } else {
312         rewind(grf);
313     }
314     while ((gr = getgrent()) != NULL) {
315         if (gr->gr_gid == gid)
316             break;
317     }
318     if (!gr_stayopen) {
319         fclose(grf);
320         grf = NULL;
321     }
322     return(gr);
323 }