1 /*- 2 * Copyright (C) 1996 3 * David L. Nugent. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY DAVID L. NUGENT AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28 #ifndef lint 29 static const char rcsid[] = 30 "$FreeBSD$"; 31 #endif /* not lint */ 32 33 #include <stdio.h> 34 #include <string.h> 35 #include <stdlib.h> 36 #include <sys/param.h> 37 38 #include "pwupd.h" 39 40 static FILE * pwd_fp = NULL; 41 42 void 43 vendpwent(void) 44 { 45 if (pwd_fp != NULL) { 46 fclose(pwd_fp); 47 pwd_fp = NULL; 48 } 49 } 50 51 void 52 vsetpwent(void) 53 { 54 vendpwent(); 55 } 56 57 static struct passwd * 58 vnextpwent(char const * nam, uid_t uid, int doclose) 59 { 60 struct passwd * pw = NULL; 61 static char pwtmp[1024]; 62 63 strlcpy(pwtmp, getpwpath(_MASTERPASSWD), sizeof(pwtmp)); 64 65 if (pwd_fp != NULL || (pwd_fp = fopen(pwtmp, "r")) != NULL) { 66 int done = 0; 67 68 static struct passwd pwd; 69 70 while (!done && fgets(pwtmp, sizeof pwtmp, pwd_fp) != NULL) 71 { 72 int i, quickout = 0; 73 char * q; 74 char * p = strchr(pwtmp, '\n'); 75 76 if (p == NULL) { 77 while (fgets(pwtmp, sizeof pwtmp, pwd_fp) != NULL && strchr(pwtmp, '\n')==NULL) 78 ; /* Skip long lines */ 79 continue; 80 } 81 82 /* skip comments & empty lines */ 83 if (*pwtmp =='\n' || *pwtmp == '#') 84 continue; 85 86 i = 0; 87 q = p = pwtmp; 88 bzero(&pwd, sizeof pwd); 89 while (!quickout && (p = strsep(&q, ":\n")) != NULL) { 90 switch (i++) 91 { 92 case 0: /* username */ 93 pwd.pw_name = p; 94 if (nam) { 95 if (strcmp(nam, p) == 0) 96 done = 1; 97 else 98 quickout = 1; 99 } 100 break; 101 case 1: /* password */ 102 pwd.pw_passwd = p; 103 break; 104 case 2: /* uid */ 105 pwd.pw_uid = atoi(p); 106 if (uid != (uid_t)-1) { 107 if (uid == pwd.pw_uid) 108 done = 1; 109 else 110 quickout = 1; 111 } 112 break; 113 case 3: /* gid */ 114 pwd.pw_gid = atoi(p); 115 break; 116 case 4: /* class */ 117 if (nam == NULL && uid == (uid_t)-1) 118 done = 1; 119 pwd.pw_class = p; 120 break; 121 case 5: /* change */ 122 pwd.pw_change = (time_t)atol(p); 123 break; 124 case 6: /* expire */ 125 pwd.pw_expire = (time_t)atol(p); 126 break; 127 case 7: /* gecos */ 128 pwd.pw_gecos = p; 129 break; 130 case 8: /* directory */ 131 pwd.pw_dir = p; 132 break; 133 case 9: /* shell */ 134 pwd.pw_shell = p; 135 break; 136 } 137 } 138 } 139 if (doclose) 140 vendpwent(); 141 if (done && pwd.pw_name) { 142 pw = &pwd; 143 144 #define CKNULL(s) s = s ? s : "" 145 CKNULL(pwd.pw_passwd); 146 CKNULL(pwd.pw_class); 147 CKNULL(pwd.pw_gecos); 148 CKNULL(pwd.pw_dir); 149 CKNULL(pwd.pw_shell); 150 } 151 } 152 return pw; 153 } 154 155 struct passwd * 156 vgetpwent(void) 157 { 158 return vnextpwent(NULL, -1, 0); 159 } 160 161 struct passwd * 162 vgetpwuid(uid_t uid) 163 { 164 return vnextpwent(NULL, uid, 1); 165 } 166 167 struct passwd * 168 vgetpwnam(const char * nam) 169 { 170 return vnextpwent(nam, -1, 1); 171 } 172 173 174 static FILE * grp_fp = NULL; 175 176 void 177 vendgrent(void) 178 { 179 if (grp_fp != NULL) { 180 fclose(grp_fp); 181 grp_fp = NULL; 182 } 183 } 184 185 RET_SETGRENT 186 vsetgrent(void) 187 { 188 vendgrent(); 189 #if defined(__FreeBSD__) 190 return 0; 191 #endif 192 } 193 194 static struct group * 195 vnextgrent(char const * nam, gid_t gid, int doclose) 196 { 197 struct group * gr = NULL; 198 199 static char * grtmp = NULL; 200 static int grlen = 0; 201 static char ** mems = NULL; 202 static int memlen = 0; 203 204 extendline(&grtmp, &grlen, MAXPATHLEN); 205 strlcpy(grtmp, getgrpath(_GROUP), MAXPATHLEN); 206 207 if (grp_fp != NULL || (grp_fp = fopen(grtmp, "r")) != NULL) { 208 int done = 0; 209 210 static struct group grp; 211 212 while (!done && fgets(grtmp, grlen, grp_fp) != NULL) 213 { 214 int i, quickout = 0; 215 int mno = 0; 216 char * q, * p; 217 const char * sep = ":\n"; 218 219 if ((p = strchr(grtmp, '\n')) == NULL) { 220 int l; 221 extendline(&grtmp, &grlen, grlen + PWBUFSZ); 222 l = strlen(grtmp); 223 if (fgets(grtmp + l, grlen - l, grp_fp) == NULL) 224 break; /* No newline terminator on last line */ 225 } 226 /* Skip comments and empty lines */ 227 if (*grtmp == '\n' || *grtmp == '#') 228 continue; 229 i = 0; 230 q = p = grtmp; 231 bzero(&grp, sizeof grp); 232 extendarray(&mems, &memlen, 200); 233 while (!quickout && (p = strsep(&q, sep)) != NULL) { 234 switch (i++) 235 { 236 case 0: /* groupname */ 237 grp.gr_name = p; 238 if (nam) { 239 if (strcmp(nam, p) == 0) 240 done = 1; 241 else 242 quickout = 1; 243 } 244 break; 245 case 1: /* password */ 246 grp.gr_passwd = p; 247 break; 248 case 2: /* gid */ 249 grp.gr_gid = atoi(p); 250 if (gid != (gid_t)-1) { 251 if (gid == (gid_t)grp.gr_gid) 252 done = 1; 253 else 254 quickout = 1; 255 } else if (nam == NULL) 256 done = 1; 257 break; 258 case 3: 259 q = p; 260 sep = ",\n"; 261 break; 262 default: 263 if (*p) { 264 extendarray(&mems, &memlen, mno + 2); 265 mems[mno++] = p; 266 } 267 break; 268 } 269 } 270 grp.gr_mem = mems; 271 mems[mno] = NULL; 272 } 273 if (doclose) 274 vendgrent(); 275 if (done && grp.gr_name) { 276 gr = &grp; 277 278 CKNULL(grp.gr_passwd); 279 } 280 } 281 return gr; 282 } 283 284 struct group * 285 vgetgrent(void) 286 { 287 return vnextgrent(NULL, -1, 0); 288 } 289 290 291 struct group * 292 vgetgrgid(gid_t gid) 293 { 294 return vnextgrent(NULL, gid, 1); 295 } 296 297 struct group * 298 vgetgrnam(const char * nam) 299 { 300 return vnextgrent(nam, -1, 1); 301 } 302 303