]> git.saurik.com Git - apple/system_cmds.git/blame - chkpasswd.tproj/file_passwd.c
system_cmds-175.tar.gz
[apple/system_cmds.git] / chkpasswd.tproj / file_passwd.c
CommitLineData
1815bff5
A
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 "stringops.h"
30
31#define TEMP_FILE "/tmp/.pwtmp"
32
33#define _PASSWD_FILE "/etc/master.passwd"
34#define _COMPAT_FILE "/etc/passwd"
35#define _PASSWD_FIELDS 10
36#define BUFSIZE 8192
37
38extern void checkpasswd(char *, char *);
39
40static int do_compat = 1;
41
42char *
43getline(FILE *fp)
44{
45 static char s[BUFSIZE];
46 int len;
47
48 s[0] = '\0';
49
50 fgets(s, BUFSIZE, fp);
51 if (s == NULL || s[0] == '\0') return NULL;
52
53 if (s[0] == '#') return s;
54
55 len = strlen(s) - 1;
56 s[len] = '\0';
57
58 return s;
59}
60
61struct passwd *
62parse_user(char *line)
63{
64 static struct passwd pw = {0};
65 char **tokens;
66 int i, len;
67
68 if (pw.pw_name != NULL) free(pw.pw_name);
69 pw.pw_name = NULL;
70 if (pw.pw_passwd != NULL) free(pw.pw_passwd);
71 pw.pw_passwd = NULL;
72 if (pw.pw_gecos != NULL) free(pw.pw_gecos);
73 pw.pw_gecos = NULL;
74 if (pw.pw_dir != NULL) free(pw.pw_dir);
75 pw.pw_dir = NULL;
76 if (pw.pw_shell != NULL) free(pw.pw_shell);
77 pw.pw_shell = NULL;
78
79 if (pw.pw_class != NULL) free(pw.pw_class);
80 pw.pw_class = NULL;
81
82 if (line == NULL) return (struct passwd *)NULL;
83 tokens = explode(line, ':');
84 len = listLength(tokens);
85
86 if (len != _PASSWD_FIELDS)
87 {
88 freeList(tokens);
89 return (struct passwd *)NULL;
90 }
91
92 i = 0;
93 pw.pw_name = tokens[i++];
94 pw.pw_passwd = tokens[i++];
95 pw.pw_uid = atoi(tokens[i]);
96 free(tokens[i++]);
97 pw.pw_gid = atoi(tokens[i]);
98 free(tokens[i++]);
99 pw.pw_class = tokens[i++];
100 pw.pw_change = atoi(tokens[i]);
101 free(tokens[i++]);
102 pw.pw_expire = atoi(tokens[i]);
103 free(tokens[i++]);
104 pw.pw_gecos = tokens[i++];
105 pw.pw_dir = tokens[i++];
106 pw.pw_shell = tokens[i++];
107
108 return &pw;
109}
110
111struct passwd *
112find_user(char *uname, FILE *fp)
113{
114 char *line;
115 struct passwd *pw;
116
117 rewind(fp);
118
119 while (NULL != (line = getline(fp)))
120 {
121 if (line[0] == '#') continue;
122 pw = parse_user(line);
123 if (pw == (struct passwd *)NULL) continue;
124 if (!strcmp(uname, pw->pw_name)) return pw;
125 }
126
127 pw = parse_user(NULL);
128 return (struct passwd *)NULL;
129}
130
131void
132rewrite_file(char *pwname, FILE *fp, struct passwd *newpw)
133{
134 char *line;
135 struct passwd *pw;
136 FILE *tfp, *cfp;
137 char fname[256];
138
139 sprintf(fname, "%s.%d", TEMP_FILE, getpid());
140
141 tfp = fopen(fname, "w+");
142 if (tfp == NULL)
143 {
144 fprintf(stderr, "can't write temporary file \"%s\": ", fname);
145 perror("");
146 exit(1);
147 }
148
149 cfp = NULL;
150 if (!strcmp(pwname, _PASSWD_FILE))
151 {
152 cfp = fopen(_COMPAT_FILE, "w");
153 if (cfp == NULL)
154 {
155 fprintf(stderr, "warning: can't write compatability file \"%s\": ",
156 _COMPAT_FILE);
157 perror("");
158 }
159 }
160
161 if (cfp != NULL)
162 {
163 fprintf(cfp, "#\n");
164 fprintf(cfp, "# 4.3BSD-compatable User Database\n");
165 fprintf(cfp, "#\n");
166 fprintf(cfp, "# Note that this file is not consulted for login.\n");
167 fprintf(cfp, "# It only exisits for compatability with 4.3BSD utilities.\n");
168 fprintf(cfp, "#\n");
169 fprintf(cfp, "# This file is automatically re-written by various system utilities.\n");
170 fprintf(cfp, "# Do not edit this file. Changes will be lost.\n");
171 fprintf(cfp, "#\n");
172 }
173
174 rewind(fp);
175
176 while (NULL != (line = getline(fp)))
177 {
178 if (line[0] == '#')
179 {
180 fprintf(tfp, "%s", line);
181 continue;
182 }
183
184 pw = parse_user(line);
185 if (pw == (struct passwd *)NULL)
186 {
187 fprintf(stderr, "warning: bad format for entry: \"%s\"\n", line);
188 fprintf(tfp, "%s\n", line);
189 if (cfp != NULL) fprintf(cfp, "%s\n", line);
190 continue;
191 }
192
193 if (strcmp(newpw->pw_name, pw->pw_name))
194 {
195 fprintf(tfp, "%s\n", line);
196 if (cfp != NULL) fprintf(cfp, "%s\n", line);
197 continue;
198 }
199
200 fprintf(tfp, "%s:%s:%d:%d:%s:%d:%d:%s:%s:%s\n",
201 newpw->pw_name, newpw->pw_passwd, newpw->pw_uid, newpw->pw_gid,
202 newpw->pw_class, newpw->pw_change, newpw->pw_expire,
203 newpw->pw_gecos, newpw->pw_dir, newpw->pw_shell);
204 if (cfp != NULL)
205 {
206 fprintf(cfp, "%s:",newpw->pw_name);
207 if ((newpw->pw_passwd == NULL) || (newpw->pw_passwd[0] == '\0'))
208 fprintf(cfp, ":");
209 else
210 fprintf(cfp, "*:");
211 fprintf(cfp, "%d:%d:%s:%s:%s\n",
212 newpw->pw_uid, newpw->pw_gid, newpw->pw_gecos,
213 newpw->pw_dir, newpw->pw_shell);
214 }
215 }
216
217 if (cfp != NULL) fclose(cfp);
218 fclose(fp);
219 if (unlink(pwname) < 0)
220 {
221 fprintf(stderr, "can't update \"%s\": ", pwname);
222 perror("");
223 }
224
225 rewind(tfp);
226
227 fp = fopen(pwname, "w");
228 if (fp == NULL)
229 {
230 fprintf(stderr, "ERROR: lost file \"%s\"\n", pwname);
231 fprintf(stderr, "new passwd file is \"%s\"\n", fname);
232 perror("open");
233 exit(1);
234 }
235
236 while (NULL != (line = getline(tfp)))
237 {
238 fprintf(fp, "%s", line);
239 if (line[0] != '#') fprintf(fp, "\n");
240 }
241 fclose(fp);
242 fclose(tfp);
243 unlink(fname);
244}
245
246int
247file_check_passwd(char *uname, char *locn)
248{
249 FILE *fp;
250 char *fname;
251 struct passwd *pw;
252
253 fname = _PASSWD_FILE;
254 if (locn != NULL) fname = locn;
255
256 fp = fopen(fname, "r");
257 if (fp == NULL)
258 {
259 fprintf(stderr, "can't read file \"%s\": ", fname);
260 perror("");
261 exit(1);
262 }
263
264
265 pw = find_user(uname, fp);
266 if (pw == (struct passwd *)NULL)
267 {
268 fprintf(stderr, "user %s not found in file %s\n", uname, fname);
269 exit(1);
270 }
271
272 checkpasswd(uname, pw->pw_passwd);
273 fclose(fp);
274
275 return 0;
276}