7b9ad790e9038bc13a3fc9376ff9fc07f22773bb
[debian/sudo] / plugins / sudoers / tsgetgrpw.c
1 /*
2  * Copyright (c) 2005, 2008, 2010-2011 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
48 #include "tsgetgrpw.h"
49 #include "sudoers.h"
50
51 #ifndef LINE_MAX
52 # define LINE_MAX 2048
53 #endif
54
55 #undef GRMEM_MAX
56 #define GRMEM_MAX 200
57
58 static FILE *pwf;
59 static const char *pwfile = "/etc/passwd";
60 static int pw_stayopen;
61
62 static FILE *grf;
63 static const char *grfile = "/etc/group";
64 static int gr_stayopen;
65
66 void setgrfile(const char *);
67 void setgrent(void);
68 void endgrent(void);
69 struct group *getgrent(void);
70 struct group *getgrnam(const char *);
71 struct group *getgrgid(gid_t);
72
73 void setpwfile(const char *);
74 void setpwent(void);
75 void endpwent(void);
76 struct passwd *getpwent(void);
77 struct passwd *getpwnam(const char *);
78 struct passwd *getpwuid(uid_t);
79
80 void
81 setpwfile(const char *file)
82 {
83     pwfile = file;
84     if (pwf != NULL)
85         endpwent();
86 }
87
88 void
89 setpwent(void)
90 {
91     if (pwf == NULL) {
92         pwf = fopen(pwfile, "r");
93         if (pwf != NULL)
94             fcntl(fileno(pwf), F_SETFD, FD_CLOEXEC);
95     } else {
96         rewind(pwf);
97     }
98     pw_stayopen = 1;
99 }
100
101 void
102 endpwent(void)
103 {
104     if (pwf != NULL) {
105         fclose(pwf);
106         pwf = NULL;
107     }
108     pw_stayopen = 0;
109 }
110
111 struct passwd *
112 getpwent(void)
113 {
114     static struct passwd pw;
115     static char pwbuf[LINE_MAX];
116     size_t len;
117     char *cp, *colon;
118
119     if ((colon = fgets(pwbuf, sizeof(pwbuf), pwf)) == NULL)
120         return NULL;
121
122     zero_bytes(&pw, sizeof(pw));
123     if ((colon = strchr(cp = colon, ':')) == NULL)
124         return NULL;
125     *colon++ = '\0';
126     pw.pw_name = cp;
127     if ((colon = strchr(cp = colon, ':')) == NULL)
128         return NULL;
129     *colon++ = '\0';
130     pw.pw_passwd = cp;
131     if ((colon = strchr(cp = colon, ':')) == NULL)
132         return NULL;
133     *colon++ = '\0';
134     pw.pw_uid = atoi(cp);
135     if ((colon = strchr(cp = colon, ':')) == NULL)
136         return NULL;
137     *colon++ = '\0';
138     pw.pw_gid = atoi(cp);
139     if ((colon = strchr(cp = colon, ':')) == NULL)
140         return NULL;
141     *colon++ = '\0';
142     pw.pw_gecos = cp;
143     if ((colon = strchr(cp = colon, ':')) == NULL)
144         return NULL;
145     *colon++ = '\0';
146     pw.pw_dir = cp;
147     pw.pw_shell = colon;
148     len = strlen(colon);
149     if (len > 0 && colon[len - 1] == '\n')
150         colon[len - 1] = '\0';
151     return &pw;
152 }
153
154 struct passwd *
155 getpwnam(const char *name)
156 {
157     struct passwd *pw;
158
159     if (pwf == NULL) {
160         if ((pwf = fopen(pwfile, "r")) == NULL)
161             return NULL;
162         fcntl(fileno(pwf), F_SETFD, FD_CLOEXEC);
163     } else {
164         rewind(pwf);
165     }
166     while ((pw = getpwent()) != NULL) {
167         if (strcmp(pw->pw_name, name) == 0)
168             break;
169     }
170     if (!pw_stayopen) {
171         fclose(pwf);
172         pwf = NULL;
173     }
174     return pw;
175 }
176
177 struct passwd *
178 getpwuid(uid_t uid)
179 {
180     struct passwd *pw;
181
182     if (pwf == NULL) {
183         if ((pwf = fopen(pwfile, "r")) == NULL)
184             return NULL;
185         fcntl(fileno(pwf), F_SETFD, FD_CLOEXEC);
186     } else {
187         rewind(pwf);
188     }
189     while ((pw = getpwent()) != NULL) {
190         if (pw->pw_uid == uid)
191             break;
192     }
193     if (!pw_stayopen) {
194         fclose(pwf);
195         pwf = NULL;
196     }
197     return pw;
198 }
199
200 void
201 setgrfile(const char *file)
202 {
203     grfile = file;
204     if (grf != NULL)
205         endgrent();
206 }
207
208 void
209 setgrent(void)
210 {
211     if (grf == NULL) {
212         grf = fopen(grfile, "r");
213         if (grf != NULL)
214             fcntl(fileno(grf), F_SETFD, FD_CLOEXEC);
215     } else {
216         rewind(grf);
217     }
218     gr_stayopen = 1;
219 }
220
221 void
222 endgrent(void)
223 {
224     if (grf != NULL) {
225         fclose(grf);
226         grf = NULL;
227     }
228     gr_stayopen = 0;
229 }
230
231 struct group *
232 getgrent(void)
233 {
234     static struct group gr;
235     static char grbuf[LINE_MAX], *gr_mem[GRMEM_MAX+1];
236     size_t len;
237     char *cp, *colon;
238     int n;
239
240     if ((colon = fgets(grbuf, sizeof(grbuf), grf)) == NULL)
241         return NULL;
242
243     zero_bytes(&gr, sizeof(gr));
244     if ((colon = strchr(cp = colon, ':')) == NULL)
245         return NULL;
246     *colon++ = '\0';
247     gr.gr_name = cp;
248     if ((colon = strchr(cp = colon, ':')) == NULL)
249         return NULL;
250     *colon++ = '\0';
251     gr.gr_passwd = cp;
252     if ((colon = strchr(cp = colon, ':')) == NULL)
253         return NULL;
254     *colon++ = '\0';
255     gr.gr_gid = atoi(cp);
256     len = strlen(colon);
257     if (len > 0 && colon[len - 1] == '\n')
258         colon[len - 1] = '\0';
259     if (*colon != '\0') {
260         gr.gr_mem = gr_mem;
261         cp = strtok(colon, ",");
262         for (n = 0; cp != NULL && n < GRMEM_MAX; n++) {
263             gr.gr_mem[n] = cp;
264             cp = strtok(NULL, ",");
265         }
266         gr.gr_mem[n++] = NULL;
267     } else
268         gr.gr_mem = NULL;
269     return &gr;
270 }
271
272 struct group *
273 getgrnam(const char *name)
274 {
275     struct group *gr;
276
277     if (grf == NULL) {
278         if ((grf = fopen(grfile, "r")) == NULL)
279             return NULL;
280         fcntl(fileno(grf), F_SETFD, FD_CLOEXEC);
281     } else {
282         rewind(grf);
283     }
284     while ((gr = getgrent()) != NULL) {
285         if (strcmp(gr->gr_name, name) == 0)
286             break;
287     }
288     if (!gr_stayopen) {
289         fclose(grf);
290         grf = NULL;
291     }
292     return gr;
293 }
294
295 struct group *
296 getgrgid(gid_t gid)
297 {
298     struct group *gr;
299
300     if (grf == NULL) {
301         if ((grf = fopen(grfile, "r")) == NULL)
302             return NULL;
303         fcntl(fileno(grf), F_SETFD, FD_CLOEXEC);
304     } else {
305         rewind(grf);
306     }
307     while ((gr = getgrent()) != NULL) {
308         if (gr->gr_gid == gid)
309             break;
310     }
311     if (!gr_stayopen) {
312         fclose(grf);
313         grf = NULL;
314     }
315     return gr;
316 }