]> git.saurik.com Git - apple/system_cmds.git/blob - chkpasswd.tproj/file_passwd.c
system_cmds-496.tar.gz
[apple/system_cmds.git] / chkpasswd.tproj / file_passwd.c
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
39 extern void checkpasswd(char *, char *);
40
41 char *
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
60 struct passwd *
61 parse_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
110 struct passwd *
111 find_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
130 void
131 rewrite_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
245 int
246 file_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 }