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 58static FILE *pwf; 59static const char *pwfile = "/etc/passwd"; 60static int pw_stayopen; 61 62static FILE *grf; 63static const char *grfile = "/etc/group"; 64static int gr_stayopen; 65 66void 67setpwfile(file) 68 const char *file; 69{ 70 pwfile = file; 71 if (pwf != NULL) 72 endpwent(); 73} 74 75void 76setpwent() 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 88void 89endpwent() 90{ 91 if (pwf != NULL) { 92 fclose(pwf); 93 pwf = NULL; 94 } 95 pw_stayopen = 0; 96} 97 98struct passwd * 99getpwent() 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 141struct passwd * 142getpwnam(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 165struct passwd * 166getpwuid(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 189void 190setgrfile(file) 191 const char *file; 192{ 193 grfile = file; 194 if (grf != NULL) 195 endgrent(); 196} 197 198void 199setgrent() 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 211void 212endgrent() 213{ 214 if (grf != NULL) { 215 fclose(grf); 216 grf = NULL; 217 } 218 gr_stayopen = 0; 219} 220 221struct group * 222getgrent() 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 262struct group * 263getgrnam(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 286struct group * 287getgrgid(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} 309