add doc about interaction with RAMRUN to README.Debian in response to #581393
[debian/sudo] / tsgetgrpw.c
1 /*
2  * Copyright (c) 2005,2008 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 #else
42 # ifdef HAVE_STRINGS_H
43 #  include <strings.h>
44 # endif
45 #endif /* HAVE_STRING_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 ts_setgrfile __P((const char *));
68 void ts_setgrent __P((void));
69 void ts_endgrent __P((void));
70 struct group *ts_getgrent __P((void));
71 struct group *ts_getgrnam __P((const char *));
72 struct group *ts_getgrgid __P((gid_t));
73
74 void ts_setpwfile __P((const char *));
75 void ts_setpwent __P((void));
76 void ts_endpwent __P((void));
77 struct passwd *ts_getpwent __P((void));
78 struct passwd *ts_getpwnam __P((const char *));
79 struct passwd *ts_getpwuid __P((uid_t));
80
81 void
82 ts_setpwfile(file)
83     const char *file;
84 {
85     pwfile = file;
86     if (pwf != NULL)
87         ts_endpwent();
88 }
89
90 void
91 ts_setpwent()
92 {
93     if (pwf == NULL)
94         pwf = fopen(pwfile, "r");
95     else
96         rewind(pwf);
97     pw_stayopen = 1;
98 }
99
100 void
101 ts_endpwent()
102 {
103     if (pwf != NULL) {
104         fclose(pwf);
105         pwf = NULL;
106     }
107     pw_stayopen = 0;
108 }
109
110 struct passwd *
111 ts_getpwent()
112 {
113     static struct passwd pw;
114     static char pwbuf[LINE_MAX];
115     size_t len;
116     char *cp, *colon;
117
118     if ((colon = fgets(pwbuf, sizeof(pwbuf), pwf)) == NULL)
119         return(NULL);
120
121     zero_bytes(&pw, sizeof(pw));
122     if ((colon = strchr(cp = colon, ':')) == NULL)
123         return(NULL);
124     *colon++ = '\0';
125     pw.pw_name = cp;
126     if ((colon = strchr(cp = colon, ':')) == NULL)
127         return(NULL);
128     *colon++ = '\0';
129     pw.pw_passwd = cp;
130     if ((colon = strchr(cp = colon, ':')) == NULL)
131         return(NULL);
132     *colon++ = '\0';
133     pw.pw_uid = atoi(cp);
134     if ((colon = strchr(cp = colon, ':')) == NULL)
135         return(NULL);
136     *colon++ = '\0';
137     pw.pw_gid = atoi(cp);
138     if ((colon = strchr(cp = colon, ':')) == NULL)
139         return(NULL);
140     *colon++ = '\0';
141     pw.pw_gecos = cp;
142     if ((colon = strchr(cp = colon, ':')) == NULL)
143         return(NULL);
144     *colon++ = '\0';
145     pw.pw_dir = cp;
146     pw.pw_shell = colon;
147     len = strlen(colon);
148     if (len > 0 && colon[len - 1] == '\n')
149         colon[len - 1] = '\0';
150     return(&pw);
151 }
152
153 struct passwd *
154 ts_getpwnam(name)
155     const char *name;
156 {
157     struct passwd *pw;
158
159     if (pwf != NULL)
160         rewind(pwf);
161     else if ((pwf = fopen(pwfile, "r")) == NULL)
162         return(NULL);
163     while ((pw = ts_getpwent()) != NULL) {
164         if (strcmp(pw->pw_name, name) == 0)
165             break;
166     }
167     if (!pw_stayopen) {
168         fclose(pwf);
169         pwf = NULL;
170     }
171     return(pw);
172 }
173
174 struct passwd *
175 ts_getpwuid(uid)
176     uid_t uid;
177 {
178     struct passwd *pw;
179
180     if (pwf != NULL)
181         rewind(pwf);
182     else if ((pwf = fopen(pwfile, "r")) == NULL)
183         return(NULL);
184     while ((pw = ts_getpwent()) != NULL) {
185         if (pw->pw_uid == uid)
186             break;
187     }
188     if (!pw_stayopen) {
189         fclose(pwf);
190         pwf = NULL;
191     }
192     return(pw);
193 }
194
195 void
196 ts_setgrfile(file)
197     const char *file;
198 {
199     grfile = file;
200     if (grf != NULL)
201         ts_endgrent();
202 }
203
204 void
205 ts_setgrent()
206 {
207     if (grf == NULL)
208         grf = fopen(grfile, "r");
209     else
210         rewind(grf);
211     gr_stayopen = 1;
212 }
213
214 void
215 ts_endgrent()
216 {
217     if (grf != NULL) {
218         fclose(grf);
219         grf = NULL;
220     }
221     gr_stayopen = 0;
222 }
223
224 struct group *
225 ts_getgrent()
226 {
227     static struct group gr;
228     static char grbuf[LINE_MAX], *gr_mem[GRMEM_MAX+1];
229     size_t len;
230     char *cp, *colon;
231     int n;
232
233     if ((colon = fgets(grbuf, sizeof(grbuf), grf)) == NULL)
234         return(NULL);
235
236     zero_bytes(&gr, sizeof(gr));
237     if ((colon = strchr(cp = colon, ':')) == NULL)
238         return(NULL);
239     *colon++ = '\0';
240     gr.gr_name = cp;
241     if ((colon = strchr(cp = colon, ':')) == NULL)
242         return(NULL);
243     *colon++ = '\0';
244     gr.gr_passwd = cp;
245     if ((colon = strchr(cp = colon, ':')) == NULL)
246         return(NULL);
247     *colon++ = '\0';
248     gr.gr_gid = atoi(cp);
249     len = strlen(colon);
250     if (len > 0 && colon[len - 1] == '\n')
251         colon[len - 1] = '\0';
252     if (*colon != '\0') {
253         gr.gr_mem = gr_mem;
254         cp = strtok(colon, ",");
255         for (n = 0; cp != NULL && n < GRMEM_MAX; n++) {
256             gr.gr_mem[n] = cp;
257             cp = strtok(NULL, ",");
258         }
259         gr.gr_mem[n++] = NULL;
260     } else
261         gr.gr_mem = NULL;
262     return(&gr);
263 }
264
265 struct group *
266 ts_getgrnam(name)
267     const char *name;
268 {
269     struct group *gr;
270
271     if (grf != NULL)
272         rewind(grf);
273     else if ((grf = fopen(grfile, "r")) == NULL)
274         return(NULL);
275     while ((gr = ts_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 ts_getgrgid(gid)
288     gid_t gid;
289 {
290     struct group *gr;
291
292     if (grf != NULL)
293         rewind(grf);
294     else if ((grf = fopen(grfile, "r")) == NULL)
295         return(NULL);
296     while ((gr = ts_getgrent()) != NULL) {
297         if (gr->gr_gid == gid)
298             break;
299     }
300     if (!gr_stayopen) {
301         fclose(grf);
302         grf = NULL;
303     }
304     return(gr);
305 }