1/* 2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights 7 * Reserved. This file contains Original Code and/or Modifications of 8 * Original Code as defined in and that are subject to the Apple Public 9 * Source License Version 1.0 (the 'License'). You may not use this file 10 * except in compliance with the License. Please obtain a copy of the 11 * License at http://www.apple.com/publicsource and read it before using 12 * this file. 13 * 14 * The Original Code and all software distributed under the License are 15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 19 * License for the specific language governing rights and limitations 20 * under the License." 21 * 22 * @APPLE_LICENSE_HEADER_END@ 23 */ 24#include <stdio.h> 25#include <stdlib.h> 26#include <unistd.h> 27#include <pwd.h> 28#include <errno.h> 29#include <string.h> 30#include "stringops.h" 31 32#define TEMP_FILE "/tmp/.pwtmp" 33 34#define _PASSWD_FILE "/etc/master.passwd" 35#define _COMPAT_FILE "/etc/passwd" 36#define _PASSWD_FIELDS 10 37#define BUFSIZE 8192 38 39extern void checkpasswd(char *, char *); 40 41char * 42_getline(FILE *fp) 43{ 44 static char s[BUFSIZE]; 45 int len; 46 47 s[0] = '\0'; 48 49 fgets(s, BUFSIZE, fp); 50 if (s == NULL || s[0] == '\0') return NULL; 51 52 if (s[0] == '#') return s; 53 54 len = strlen(s) - 1; 55 s[len] = '\0'; 56 57 return s; 58} 59 60struct passwd * 61parse_user(char *line) 62{ 63 static struct passwd pw = {0}; 64 char **tokens; 65 int i, len; 66 67 if (pw.pw_name != NULL) free(pw.pw_name); 68 pw.pw_name = NULL; 69 if (pw.pw_passwd != NULL) free(pw.pw_passwd); 70 pw.pw_passwd = NULL; 71 if (pw.pw_gecos != NULL) free(pw.pw_gecos); 72 pw.pw_gecos = NULL; 73 if (pw.pw_dir != NULL) free(pw.pw_dir); 74 pw.pw_dir = NULL; 75 if (pw.pw_shell != NULL) free(pw.pw_shell); 76 pw.pw_shell = NULL; 77 78 if (pw.pw_class != NULL) free(pw.pw_class); 79 pw.pw_class = NULL; 80 81 if (line == NULL) return (struct passwd *)NULL; 82 tokens = explode(line, ':'); 83 len = listLength(tokens); 84 85 if (len != _PASSWD_FIELDS) 86 { 87 freeList(tokens); 88 return (struct passwd *)NULL; 89 } 90 91 i = 0; 92 pw.pw_name = tokens[i++]; 93 pw.pw_passwd = tokens[i++]; 94 pw.pw_uid = atoi(tokens[i]); 95 free(tokens[i++]); 96 pw.pw_gid = atoi(tokens[i]); 97 free(tokens[i++]); 98 pw.pw_class = tokens[i++]; 99 pw.pw_change = atoi(tokens[i]); 100 free(tokens[i++]); 101 pw.pw_expire = atoi(tokens[i]); 102 free(tokens[i++]); 103 pw.pw_gecos = tokens[i++]; 104 pw.pw_dir = tokens[i++]; 105 pw.pw_shell = tokens[i++]; 106 107 return &pw; 108} 109 110struct passwd * 111find_user(char *uname, FILE *fp) 112{ 113 char *line; 114 struct passwd *pw; 115 116 rewind(fp); 117 118 while (NULL != (line = _getline(fp))) 119 { 120 if (line[0] == '#') continue; 121 pw = parse_user(line); 122 if (pw == (struct passwd *)NULL) continue; 123 if (!strcmp(uname, pw->pw_name)) return pw; 124 } 125 126 pw = parse_user(NULL); 127 return (struct passwd *)NULL; 128} 129 130void 131rewrite_file(char *pwname, FILE *fp, struct passwd *newpw) 132{ 133 char *line; 134 struct passwd *pw; 135 FILE *tfp, *cfp; 136 char fname[256]; 137 138 sprintf(fname, "%s.%d", TEMP_FILE, getpid()); 139 140 tfp = fopen(fname, "w+"); 141 if (tfp == NULL) 142 { 143 fprintf(stderr, "can't write temporary file \"%s\": ", fname); 144 perror(""); 145 exit(1); 146 } 147 148 cfp = NULL; 149 if (!strcmp(pwname, _PASSWD_FILE)) 150 { 151 cfp = fopen(_COMPAT_FILE, "w"); 152 if (cfp == NULL) 153 { 154 fprintf(stderr, "warning: can't write compatability file \"%s\": ", 155 _COMPAT_FILE); 156 perror(""); 157 } 158 } 159 160 if (cfp != NULL) 161 { 162 fprintf(cfp, "#\n"); 163 fprintf(cfp, "# 4.3BSD-compatable User Database\n"); 164 fprintf(cfp, "#\n"); 165 fprintf(cfp, "# Note that this file is not consulted for login.\n"); 166 fprintf(cfp, "# It only exisits for compatability with 4.3BSD utilities.\n"); 167 fprintf(cfp, "#\n"); 168 fprintf(cfp, "# This file is automatically re-written by various system utilities.\n"); 169 fprintf(cfp, "# Do not edit this file. Changes will be lost.\n"); 170 fprintf(cfp, "#\n"); 171 } 172 173 rewind(fp); 174 175 while (NULL != (line = _getline(fp))) 176 { 177 if (line[0] == '#') 178 { 179 fprintf(tfp, "%s", line); 180 continue; 181 } 182 183 pw = parse_user(line); 184 if (pw == (struct passwd *)NULL) 185 { 186 fprintf(stderr, "warning: bad format for entry: \"%s\"\n", line); 187 fprintf(tfp, "%s\n", line); 188 if (cfp != NULL) fprintf(cfp, "%s\n", line); 189 continue; 190 } 191 192 if (strcmp(newpw->pw_name, pw->pw_name)) 193 { 194 fprintf(tfp, "%s\n", line); 195 if (cfp != NULL) fprintf(cfp, "%s\n", line); 196 continue; 197 } 198 199 fprintf(tfp, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", 200 newpw->pw_name, newpw->pw_passwd, newpw->pw_uid, newpw->pw_gid, 201 newpw->pw_class, newpw->pw_change, newpw->pw_expire, 202 newpw->pw_gecos, newpw->pw_dir, newpw->pw_shell); 203 if (cfp != NULL) 204 { 205 fprintf(cfp, "%s:",newpw->pw_name); 206 if ((newpw->pw_passwd == NULL) || (newpw->pw_passwd[0] == '\0')) 207 fprintf(cfp, ":"); 208 else 209 fprintf(cfp, "*:"); 210 fprintf(cfp, "%d:%d:%s:%s:%s\n", 211 newpw->pw_uid, newpw->pw_gid, newpw->pw_gecos, 212 newpw->pw_dir, newpw->pw_shell); 213 } 214 } 215 216 if (cfp != NULL) fclose(cfp); 217 fclose(fp); 218 if (unlink(pwname) < 0) 219 { 220 fprintf(stderr, "can't update \"%s\": ", pwname); 221 perror(""); 222 } 223 224 rewind(tfp); 225 226 fp = fopen(pwname, "w"); 227 if (fp == NULL) 228 { 229 fprintf(stderr, "ERROR: lost file \"%s\"\n", pwname); 230 fprintf(stderr, "new passwd file is \"%s\"\n", fname); 231 perror("open"); 232 exit(1); 233 } 234 235 while (NULL != (line = _getline(tfp))) 236 { 237 fprintf(fp, "%s", line); 238 if (line[0] != '#') fprintf(fp, "\n"); 239 } 240 fclose(fp); 241 fclose(tfp); 242 unlink(fname); 243} 244 245int 246file_check_passwd(char *uname, char *locn) 247{ 248 FILE *fp; 249 char *fname; 250 struct passwd *pw; 251 252 fname = _PASSWD_FILE; 253 if (locn != NULL) fname = locn; 254 255 if (access(fname,R_OK) || (fp = fopen(fname, "r")) == NULL) 256 { 257 fprintf(stderr, "can't read file \"%s\": ", fname); 258 perror(""); 259 exit(1); 260 } 261 262 263 pw = find_user(uname, fp); 264 if (pw == (struct passwd *)NULL) 265 { 266 fprintf(stderr, "user %s not found in file %s\n", uname, fname); 267 exit(1); 268 } 269 270 checkpasswd(uname, pw->pw_passwd); 271 fclose(fp); 272 273 return 0; 274} 275