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 * $FreeBSD: src/usr.sbin/pw/pw_vpw.c,v 1.4 2004/06/17 14:07:16 robert Exp $ 27 */ 28 29 #include <stdio.h> 30 #include <string.h> 31 #include <stdlib.h> 32 #include <sys/param.h> 33 34 #include "pwupd.h" 35 36 static FILE * pwd_fp = NULL; 37 38 void 39 vendpwent(void) 40 { 41 if (pwd_fp != NULL) { 42 fclose(pwd_fp); 43 pwd_fp = NULL; 44 } 45 } 46 47 void 48 vsetpwent(void) 49 { 50 vendpwent(); 51 } 52 53 static struct passwd * 54 vnextpwent(char const * nam, uid_t uid, int doclose) 55 { 56 struct passwd * pw = NULL; 57 static char pwtmp[1024]; 58 59 strlcpy(pwtmp, getpwpath(_MASTERPASSWD), sizeof(pwtmp)); 60 61 if (pwd_fp != NULL || (pwd_fp = fopen(pwtmp, "r")) != NULL) { 62 int done = 0; 63 64 static struct passwd pwd; 65 66 while (!done && fgets(pwtmp, sizeof pwtmp, pwd_fp) != NULL) 67 { 68 int i, quickout = 0; 69 char * q; 70 char * p = strchr(pwtmp, '\n'); 71 72 if (p == NULL) { 73 while (fgets(pwtmp, sizeof pwtmp, pwd_fp) != NULL && strchr(pwtmp, '\n')==NULL) 74 ; /* Skip long lines */ 75 continue; 76 } 77 78 /* skip comments & empty lines */ 79 if (*pwtmp =='\n' || *pwtmp == '#') 80 continue; 81 82 i = 0; 83 q = p = pwtmp; 84 bzero(&pwd, sizeof pwd); 85 while (!quickout && (p = strsep(&q, ":\n")) != NULL) { 86 switch (i++) 87 { 88 case 0: /* username */ 89 pwd.pw_name = p; 90 if (nam) { 91 if (strcmp(nam, p) == 0) 92 done = 1; 93 else 94 quickout = 1; 95 } 96 break; 97 case 1: /* password */ 98 pwd.pw_passwd = p; 99 break; 100 case 2: /* uid */ 101 pwd.pw_uid = atoi(p); 102 if (uid != (uid_t)-1) { 103 if (uid == pwd.pw_uid) 104 done = 1; 105 else 106 quickout = 1; 107 } 108 break; 109 case 3: /* gid */ 110 pwd.pw_gid = atoi(p); 111 break; 112 case 4: /* class */ 113 if (nam == NULL && uid == (uid_t)-1) 114 done = 1; 115 pwd.pw_class = p; 116 break; 117 case 5: /* change */ 118 pwd.pw_change = (time_t)atol(p); 119 break; 120 case 6: /* expire */ 121 pwd.pw_expire = (time_t)atol(p); 122 break; 123 case 7: /* gecos */ 124 pwd.pw_gecos = p; 125 break; 126 case 8: /* directory */ 127 pwd.pw_dir = p; 128 break; 129 case 9: /* shell */ 130 pwd.pw_shell = p; 131 break; 132 } 133 } 134 } 135 if (doclose) 136 vendpwent(); 137 if (done && pwd.pw_name) { 138 pw = &pwd; 139 140 #define CKNULL(s) s = s ? s : "" 141 CKNULL(pwd.pw_passwd); 142 CKNULL(pwd.pw_class); 143 CKNULL(pwd.pw_gecos); 144 CKNULL(pwd.pw_dir); 145 CKNULL(pwd.pw_shell); 146 } 147 } 148 return pw; 149 } 150 151 struct passwd * 152 vgetpwent(void) 153 { 154 return vnextpwent(NULL, -1, 0); 155 } 156 157 struct passwd * 158 vgetpwuid(uid_t uid) 159 { 160 return vnextpwent(NULL, uid, 1); 161 } 162 163 struct passwd * 164 vgetpwnam(const char * nam) 165 { 166 return vnextpwent(nam, -1, 1); 167 } 168 169 int 170 vpwdb(char *arg, ...) 171 { 172 arg=arg; 173 return 0; 174 } 175 176 177 178 static FILE * grp_fp = NULL; 179 180 void 181 vendgrent(void) 182 { 183 if (grp_fp != NULL) { 184 fclose(grp_fp); 185 grp_fp = NULL; 186 } 187 } 188 189 void 190 vsetgrent(void) 191 { 192 vendgrent(); 193 } 194 195 static struct group * 196 vnextgrent(char const * nam, gid_t gid, int doclose) 197 { 198 struct group * gr = NULL; 199 200 static char * grtmp = NULL; 201 static int grlen = 0; 202 static char ** mems = NULL; 203 static int memlen = 0; 204 205 extendline(&grtmp, &grlen, MAXPATHLEN); 206 strlcpy(grtmp, getgrpath(_GROUP), MAXPATHLEN); 207 208 if (grp_fp != NULL || (grp_fp = fopen(grtmp, "r")) != NULL) { 209 int done = 0; 210 211 static struct group grp; 212 213 while (!done && fgets(grtmp, grlen, grp_fp) != NULL) 214 { 215 int i, quickout = 0; 216 int mno = 0; 217 char * q, * p; 218 char * sep = ":\n"; 219 220 if ((p = strchr(grtmp, '\n')) == NULL) { 221 int l; 222 extendline(&grtmp, &grlen, grlen + PWBUFSZ); 223 l = strlen(grtmp); 224 if (fgets(grtmp + l, grlen - l, grp_fp) == NULL) 225 break; /* No newline terminator on last line */ 226 } 227 /* Skip comments and empty lines */ 228 if (*grtmp == '\n' || *grtmp == '#') 229 continue; 230 i = 0; 231 q = p = grtmp; 232 bzero(&grp, sizeof grp); 233 extendarray(&mems, &memlen, 200); 234 while (!quickout && (p = strsep(&q, sep)) != NULL) { 235 switch (i++) 236 { 237 case 0: /* groupname */ 238 grp.gr_name = p; 239 if (nam) { 240 if (strcmp(nam, p) == 0) 241 done = 1; 242 else 243 quickout = 1; 244 } 245 break; 246 case 1: /* password */ 247 grp.gr_passwd = p; 248 break; 249 case 2: /* gid */ 250 grp.gr_gid = atoi(p); 251 if (gid != (gid_t)-1) { 252 if (gid == (gid_t)grp.gr_gid) 253 done = 1; 254 else 255 quickout = 1; 256 } else if (nam == NULL) 257 done = 1; 258 break; 259 case 3: 260 q = p; 261 sep = ",\n"; 262 break; 263 default: 264 if (*p) { 265 extendarray(&mems, &memlen, mno + 2); 266 mems[mno++] = p; 267 } 268 break; 269 } 270 } 271 grp.gr_mem = mems; 272 mems[mno] = NULL; 273 } 274 if (doclose) 275 vendgrent(); 276 if (done && grp.gr_name) { 277 gr = &grp; 278 279 CKNULL(grp.gr_passwd); 280 } 281 } 282 return gr; 283 } 284 285 struct group * 286 vgetgrent(void) 287 { 288 return vnextgrent(NULL, -1, 0); 289 } 290 291 292 struct group * 293 vgetgrgid(gid_t gid) 294 { 295 return vnextgrent(NULL, gid, 1); 296 } 297 298 struct group * 299 vgetgrnam(const char * nam) 300 { 301 return vnextgrent(nam, -1, 1); 302 } 303 304 int 305 vgrdb(char *arg, ...) 306 { 307 arg=arg; 308 return 0; 309 } 310 311