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