pwd_mkdb.c revision 1.17 1 1.11 fair /*
2 1.5 mycroft * Copyright (c) 1991, 1993, 1994
3 1.5 mycroft * The Regents of the University of California. All rights reserved.
4 1.6 phil * Portions Copyright(C) 1994, Jason Downs. All rights reserved.
5 1.1 cgd *
6 1.1 cgd * Redistribution and use in source and binary forms, with or without
7 1.1 cgd * modification, are permitted provided that the following conditions
8 1.1 cgd * are met:
9 1.1 cgd * 1. Redistributions of source code must retain the above copyright
10 1.1 cgd * notice, this list of conditions and the following disclaimer.
11 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
12 1.1 cgd * notice, this list of conditions and the following disclaimer in the
13 1.1 cgd * documentation and/or other materials provided with the distribution.
14 1.1 cgd * 3. All advertising materials mentioning features or use of this software
15 1.1 cgd * must display the following acknowledgement:
16 1.1 cgd * This product includes software developed by the University of
17 1.1 cgd * California, Berkeley and its contributors.
18 1.1 cgd * 4. Neither the name of the University nor the names of its contributors
19 1.1 cgd * may be used to endorse or promote products derived from this software
20 1.1 cgd * without specific prior written permission.
21 1.1 cgd *
22 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 1.1 cgd * SUCH DAMAGE.
33 1.1 cgd */
34 1.1 cgd
35 1.10 lukem #include <sys/cdefs.h>
36 1.1 cgd #ifndef lint
37 1.17 mycroft __COPYRIGHT("@(#) Copyright (c) 2000\n\
38 1.17 mycroft The NetBSD Foundation, Inc. All rights reserved.\n\
39 1.17 mycroft Copyright (c) 1991, 1993, 1994\n\
40 1.10 lukem The Regents of the University of California. All rights reserved.\n");
41 1.17 mycroft __SCCSID("from: @(#)pwd_mkdb.c 8.5 (Berkeley) 4/20/94");
42 1.17 mycroft __RCSID("$NetBSD: pwd_mkdb.c,v 1.17 2000/01/23 19:59:33 mycroft Exp $");
43 1.1 cgd #endif /* not lint */
44 1.1 cgd
45 1.1 cgd #include <sys/param.h>
46 1.1 cgd #include <sys/stat.h>
47 1.5 mycroft
48 1.1 cgd #include <db.h>
49 1.5 mycroft #include <err.h>
50 1.1 cgd #include <errno.h>
51 1.5 mycroft #include <fcntl.h>
52 1.1 cgd #include <limits.h>
53 1.5 mycroft #include <pwd.h>
54 1.5 mycroft #include <signal.h>
55 1.1 cgd #include <stdio.h>
56 1.5 mycroft #include <stdlib.h>
57 1.1 cgd #include <string.h>
58 1.5 mycroft #include <unistd.h>
59 1.7 jtc #include <util.h>
60 1.1 cgd
61 1.1 cgd #define INSECURE 1
62 1.1 cgd #define SECURE 2
63 1.1 cgd #define PERM_INSECURE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
64 1.1 cgd #define PERM_SECURE (S_IRUSR|S_IWUSR)
65 1.1 cgd
66 1.6 phil /* pull this out of the C library. */
67 1.6 phil extern const char __yp_token[];
68 1.6 phil
69 1.5 mycroft HASHINFO openinfo = {
70 1.5 mycroft 4096, /* bsize */
71 1.5 mycroft 32, /* ffactor */
72 1.5 mycroft 256, /* nelem */
73 1.5 mycroft 2048 * 1024, /* cachesize */
74 1.5 mycroft NULL, /* hash() */
75 1.5 mycroft 0 /* lorder */
76 1.5 mycroft };
77 1.1 cgd
78 1.1 cgd static enum state { FILE_INSECURE, FILE_SECURE, FILE_ORIG } clean;
79 1.1 cgd static struct passwd pwd; /* password structure */
80 1.1 cgd static char *pname; /* password file name */
81 1.8 lukem static char prefix[MAXPATHLEN];
82 1.11 fair static char oldpwdfile[MAX(MAXPATHLEN, LINE_MAX * 2)];
83 1.11 fair static char pwd_db_tmp[MAX(MAXPATHLEN, LINE_MAX * 2)];
84 1.11 fair static char pwd_Sdb_tmp[MAX(MAXPATHLEN, LINE_MAX * 2)];
85 1.1 cgd
86 1.5 mycroft void cleanup __P((void));
87 1.5 mycroft void error __P((char *));
88 1.11 fair void wr_error __P((char *));
89 1.10 lukem int main __P((int, char **));
90 1.5 mycroft void mv __P((char *, char *));
91 1.11 fair void rm __P((char *));
92 1.17 mycroft int scan __P((FILE *, struct passwd *, u_int32_t *));
93 1.5 mycroft void usage __P((void));
94 1.5 mycroft
95 1.5 mycroft int
96 1.1 cgd main(argc, argv)
97 1.1 cgd int argc;
98 1.5 mycroft char *argv[];
99 1.1 cgd {
100 1.5 mycroft DB *dp, *edp;
101 1.5 mycroft DBT data, key;
102 1.1 cgd FILE *fp, *oldfp;
103 1.1 cgd sigset_t set;
104 1.17 mycroft int ch, len, makeold, tfd;
105 1.17 mycroft u_int32_t x, cnt, flags;
106 1.16 mycroft char *p;
107 1.16 mycroft const char *t;
108 1.11 fair char buf[MAX(MAXPATHLEN, LINE_MAX * 2)], tbuf[1024];
109 1.6 phil int hasyp = 0;
110 1.6 phil DBT ypdata, ypkey;
111 1.17 mycroft int lorder = BYTE_ORDER;
112 1.1 cgd
113 1.10 lukem oldfp = NULL;
114 1.8 lukem strcpy(prefix, "/");
115 1.1 cgd makeold = 0;
116 1.17 mycroft while ((ch = getopt(argc, argv, "d:pvBL")) != -1)
117 1.1 cgd switch(ch) {
118 1.8 lukem case 'd':
119 1.8 lukem strncpy(prefix, optarg, sizeof(prefix));
120 1.8 lukem prefix[sizeof(prefix)-1] = '\0';
121 1.8 lukem break;
122 1.1 cgd case 'p': /* create V7 "file.orig" */
123 1.1 cgd makeold = 1;
124 1.1 cgd break;
125 1.1 cgd case 'v': /* backward compatible */
126 1.1 cgd break;
127 1.17 mycroft case 'B':
128 1.17 mycroft lorder = BIG_ENDIAN;
129 1.17 mycroft break;
130 1.17 mycroft case 'L':
131 1.17 mycroft lorder = LITTLE_ENDIAN;
132 1.17 mycroft break;
133 1.1 cgd case '?':
134 1.1 cgd default:
135 1.1 cgd usage();
136 1.1 cgd }
137 1.1 cgd argc -= optind;
138 1.1 cgd argv += optind;
139 1.1 cgd
140 1.1 cgd if (argc != 1)
141 1.1 cgd usage();
142 1.4 cgd
143 1.1 cgd /*
144 1.5 mycroft * This could be changed to allow the user to interrupt.
145 1.5 mycroft * Probably not worth the effort.
146 1.1 cgd */
147 1.1 cgd sigemptyset(&set);
148 1.1 cgd sigaddset(&set, SIGTSTP);
149 1.1 cgd sigaddset(&set, SIGHUP);
150 1.1 cgd sigaddset(&set, SIGINT);
151 1.1 cgd sigaddset(&set, SIGQUIT);
152 1.1 cgd sigaddset(&set, SIGTERM);
153 1.1 cgd (void)sigprocmask(SIG_BLOCK, &set, (sigset_t *)NULL);
154 1.1 cgd
155 1.5 mycroft /* We don't care what the user wants. */
156 1.5 mycroft (void)umask(0);
157 1.5 mycroft
158 1.1 cgd pname = *argv;
159 1.1 cgd /* Open the original password file */
160 1.1 cgd if (!(fp = fopen(pname, "r")))
161 1.1 cgd error(pname);
162 1.1 cgd
163 1.17 mycroft openinfo.lorder = lorder;
164 1.17 mycroft
165 1.1 cgd /* Open the temporary insecure password database. */
166 1.11 fair (void)snprintf(pwd_db_tmp, sizeof(pwd_db_tmp), "%s%s.tmp", prefix,
167 1.11 fair _PATH_MP_DB);
168 1.11 fair dp = dbopen(pwd_db_tmp,
169 1.5 mycroft O_RDWR|O_CREAT|O_EXCL, PERM_INSECURE, DB_HASH, &openinfo);
170 1.5 mycroft if (dp == NULL)
171 1.11 fair error(pwd_db_tmp);
172 1.1 cgd clean = FILE_INSECURE;
173 1.1 cgd
174 1.1 cgd /*
175 1.1 cgd * Open file for old password file. Minor trickiness -- don't want to
176 1.1 cgd * chance the file already existing, since someone (stupidly) might
177 1.1 cgd * still be using this for permission checking. So, open it first and
178 1.5 mycroft * fdopen the resulting fd. The resulting file should be readable by
179 1.5 mycroft * everyone.
180 1.1 cgd */
181 1.1 cgd if (makeold) {
182 1.11 fair (void)snprintf(oldpwdfile, sizeof(oldpwdfile), "%s.orig",
183 1.11 fair pname);
184 1.11 fair if ((tfd = open(oldpwdfile,
185 1.1 cgd O_WRONLY|O_CREAT|O_EXCL, PERM_INSECURE)) < 0)
186 1.11 fair error(oldpwdfile);
187 1.5 mycroft if ((oldfp = fdopen(tfd, "w")) == NULL)
188 1.11 fair error(oldpwdfile);
189 1.1 cgd clean = FILE_ORIG;
190 1.1 cgd }
191 1.1 cgd
192 1.1 cgd /*
193 1.1 cgd * The databases actually contain three copies of the original data.
194 1.1 cgd * Each password file entry is converted into a rough approximation
195 1.1 cgd * of a ``struct passwd'', with the strings placed inline. This
196 1.1 cgd * object is then stored as the data for three separate keys. The
197 1.1 cgd * first key * is the pw_name field prepended by the _PW_KEYBYNAME
198 1.1 cgd * character. The second key is the pw_uid field prepended by the
199 1.1 cgd * _PW_KEYBYUID character. The third key is the line number in the
200 1.1 cgd * original file prepended by the _PW_KEYBYNUM character. (The special
201 1.1 cgd * characters are prepended to ensure that the keys do not collide.)
202 1.6 phil *
203 1.6 phil * If we see something go by that looks like YP, we save a special
204 1.6 phil * pointer record, which if YP is enabled in the C lib, will speed
205 1.6 phil * things up.
206 1.1 cgd */
207 1.1 cgd data.data = (u_char *)buf;
208 1.1 cgd key.data = (u_char *)tbuf;
209 1.6 phil for (cnt = 1; scan(fp, &pwd, &flags); ++cnt) {
210 1.8 lukem #define COMPACT(e) t = e; while ((*p++ = *t++));
211 1.6 phil
212 1.6 phil /* look like YP? */
213 1.6 phil if((pwd.pw_name[0] == '+') || (pwd.pw_name[0] == '-'))
214 1.6 phil hasyp++;
215 1.9 thorpej
216 1.9 thorpej /*
217 1.9 thorpej * Warn about potentially unsafe uid/gid overrides.
218 1.9 thorpej */
219 1.9 thorpej if (pwd.pw_name[0] == '+') {
220 1.9 thorpej if ((flags & _PASSWORD_NOUID) == 0 && pwd.pw_uid == 0)
221 1.15 lukem warnx(
222 1.15 lukem "line %d: superuser override in YP inclusion",
223 1.15 lukem cnt);
224 1.9 thorpej if ((flags & _PASSWORD_NOGID) == 0 && pwd.pw_gid == 0)
225 1.15 lukem warnx("line %d: wheel override in YP inclusion",
226 1.15 lukem cnt);
227 1.9 thorpej }
228 1.6 phil
229 1.17 mycroft if (lorder != BYTE_ORDER) {
230 1.17 mycroft M_32_SWAP(pwd.pw_uid);
231 1.17 mycroft M_32_SWAP(pwd.pw_gid);
232 1.17 mycroft M_32_SWAP(pwd.pw_change);
233 1.17 mycroft M_32_SWAP(pwd.pw_expire);
234 1.17 mycroft M_32_SWAP(flags);
235 1.17 mycroft }
236 1.17 mycroft
237 1.1 cgd /* Create insecure data. */
238 1.1 cgd p = buf;
239 1.1 cgd COMPACT(pwd.pw_name);
240 1.1 cgd COMPACT("*");
241 1.17 mycroft memmove(p, &pwd.pw_uid, sizeof(pwd.pw_uid));
242 1.17 mycroft p += sizeof(pwd.pw_uid);
243 1.17 mycroft memmove(p, &pwd.pw_gid, sizeof(pwd.pw_gid));
244 1.17 mycroft p += sizeof(pwd.pw_gid);
245 1.17 mycroft memmove(p, &pwd.pw_change, sizeof(pwd.pw_change));
246 1.17 mycroft p += sizeof(pwd.pw_change);
247 1.1 cgd COMPACT(pwd.pw_class);
248 1.1 cgd COMPACT(pwd.pw_gecos);
249 1.1 cgd COMPACT(pwd.pw_dir);
250 1.1 cgd COMPACT(pwd.pw_shell);
251 1.17 mycroft memmove(p, &pwd.pw_expire, sizeof(pwd.pw_expire));
252 1.17 mycroft p += sizeof(pwd.pw_expire);
253 1.17 mycroft memmove(p, &flags, sizeof(flags));
254 1.17 mycroft p += sizeof(flags);
255 1.1 cgd data.size = p - buf;
256 1.1 cgd
257 1.1 cgd /* Store insecure by name. */
258 1.1 cgd tbuf[0] = _PW_KEYBYNAME;
259 1.1 cgd len = strlen(pwd.pw_name);
260 1.5 mycroft memmove(tbuf + 1, pwd.pw_name, len);
261 1.1 cgd key.size = len + 1;
262 1.1 cgd if ((dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1)
263 1.11 fair wr_error(pwd_db_tmp);
264 1.1 cgd
265 1.1 cgd /* Store insecure by number. */
266 1.1 cgd tbuf[0] = _PW_KEYBYNUM;
267 1.17 mycroft x = cnt;
268 1.17 mycroft if (lorder != BYTE_ORDER)
269 1.17 mycroft M_32_SWAP(x);
270 1.17 mycroft memmove(tbuf + 1, &x, sizeof(x));
271 1.17 mycroft key.size = sizeof(x) + 1;
272 1.1 cgd if ((dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1)
273 1.11 fair wr_error(pwd_db_tmp);
274 1.1 cgd
275 1.1 cgd /* Store insecure by uid. */
276 1.1 cgd tbuf[0] = _PW_KEYBYUID;
277 1.5 mycroft memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid));
278 1.1 cgd key.size = sizeof(pwd.pw_uid) + 1;
279 1.1 cgd if ((dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1)
280 1.11 fair wr_error(pwd_db_tmp);
281 1.1 cgd
282 1.5 mycroft /* Create original format password file entry */
283 1.11 fair if (makeold) {
284 1.5 mycroft (void)fprintf(oldfp, "%s:*:%d:%d:%s:%s:%s\n",
285 1.5 mycroft pwd.pw_name, pwd.pw_uid, pwd.pw_gid, pwd.pw_gecos,
286 1.5 mycroft pwd.pw_dir, pwd.pw_shell);
287 1.11 fair if (ferror(oldfp)) {
288 1.11 fair wr_error(oldpwdfile);
289 1.11 fair }
290 1.11 fair }
291 1.5 mycroft }
292 1.6 phil
293 1.6 phil /* Store YP token, if needed. */
294 1.6 phil if(hasyp) {
295 1.6 phil ypkey.data = (u_char *)__yp_token;
296 1.6 phil ypkey.size = strlen(__yp_token);
297 1.6 phil ypdata.data = (u_char *)NULL;
298 1.6 phil ypdata.size = 0;
299 1.6 phil
300 1.6 phil if ((dp->put)(dp, &ypkey, &ypdata, R_NOOVERWRITE) == -1)
301 1.11 fair wr_error(pwd_db_tmp);
302 1.6 phil }
303 1.6 phil
304 1.11 fair if ((dp->close)(dp) < 0) {
305 1.11 fair wr_error(pwd_db_tmp);
306 1.11 fair }
307 1.5 mycroft if (makeold) {
308 1.11 fair if (fflush(oldfp) == EOF) {
309 1.11 fair wr_error(oldpwdfile);
310 1.11 fair }
311 1.11 fair if (fclose(oldfp) == EOF) {
312 1.11 fair wr_error(oldpwdfile);
313 1.11 fair }
314 1.5 mycroft }
315 1.5 mycroft
316 1.5 mycroft /* Open the temporary encrypted password database. */
317 1.11 fair (void)snprintf(pwd_Sdb_tmp, sizeof(pwd_Sdb_tmp), "%s%s.tmp", prefix,
318 1.11 fair _PATH_SMP_DB);
319 1.11 fair edp = dbopen(pwd_Sdb_tmp,
320 1.5 mycroft O_RDWR|O_CREAT|O_EXCL, PERM_SECURE, DB_HASH, &openinfo);
321 1.5 mycroft if (!edp)
322 1.11 fair error(pwd_Sdb_tmp);
323 1.5 mycroft clean = FILE_SECURE;
324 1.5 mycroft
325 1.5 mycroft rewind(fp);
326 1.6 phil for (cnt = 1; scan(fp, &pwd, &flags); ++cnt) {
327 1.5 mycroft
328 1.17 mycroft if (lorder != BYTE_ORDER) {
329 1.17 mycroft M_32_SWAP(pwd.pw_uid);
330 1.17 mycroft M_32_SWAP(pwd.pw_gid);
331 1.17 mycroft M_32_SWAP(pwd.pw_change);
332 1.17 mycroft M_32_SWAP(pwd.pw_expire);
333 1.17 mycroft M_32_SWAP(flags);
334 1.17 mycroft }
335 1.17 mycroft
336 1.1 cgd /* Create secure data. */
337 1.1 cgd p = buf;
338 1.1 cgd COMPACT(pwd.pw_name);
339 1.1 cgd COMPACT(pwd.pw_passwd);
340 1.17 mycroft memmove(p, &pwd.pw_uid, sizeof(pwd.pw_uid));
341 1.17 mycroft p += sizeof(pwd.pw_uid);
342 1.17 mycroft memmove(p, &pwd.pw_gid, sizeof(pwd.pw_gid));
343 1.17 mycroft p += sizeof(pwd.pw_gid);
344 1.17 mycroft memmove(p, &pwd.pw_change, sizeof(pwd.pw_change));
345 1.17 mycroft p += sizeof(pwd.pw_change);
346 1.1 cgd COMPACT(pwd.pw_class);
347 1.1 cgd COMPACT(pwd.pw_gecos);
348 1.1 cgd COMPACT(pwd.pw_dir);
349 1.1 cgd COMPACT(pwd.pw_shell);
350 1.17 mycroft memmove(p, &pwd.pw_expire, sizeof(pwd.pw_expire));
351 1.17 mycroft p += sizeof(pwd.pw_expire);
352 1.17 mycroft memmove(p, &flags, sizeof(flags));
353 1.17 mycroft p += sizeof(flags);
354 1.1 cgd data.size = p - buf;
355 1.1 cgd
356 1.1 cgd /* Store secure by name. */
357 1.1 cgd tbuf[0] = _PW_KEYBYNAME;
358 1.1 cgd len = strlen(pwd.pw_name);
359 1.5 mycroft memmove(tbuf + 1, pwd.pw_name, len);
360 1.1 cgd key.size = len + 1;
361 1.11 fair if ((edp->put)(edp, &key, &data, R_NOOVERWRITE) == -1)
362 1.12 fair wr_error(pwd_Sdb_tmp);
363 1.1 cgd
364 1.1 cgd /* Store secure by number. */
365 1.1 cgd tbuf[0] = _PW_KEYBYNUM;
366 1.17 mycroft x = cnt;
367 1.17 mycroft if (lorder != BYTE_ORDER)
368 1.17 mycroft M_32_SWAP(x);
369 1.17 mycroft memmove(tbuf + 1, &x, sizeof(x));
370 1.17 mycroft key.size = sizeof(x) + 1;
371 1.11 fair if ((edp->put)(edp, &key, &data, R_NOOVERWRITE) == -1)
372 1.12 fair wr_error(pwd_Sdb_tmp);
373 1.1 cgd
374 1.1 cgd /* Store secure by uid. */
375 1.1 cgd tbuf[0] = _PW_KEYBYUID;
376 1.5 mycroft memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid));
377 1.1 cgd key.size = sizeof(pwd.pw_uid) + 1;
378 1.11 fair if ((edp->put)(edp, &key, &data, R_NOOVERWRITE) == -1)
379 1.12 fair wr_error(pwd_Sdb_tmp);
380 1.5 mycroft }
381 1.1 cgd
382 1.6 phil /* Store YP token, if needed. */
383 1.6 phil if(hasyp) {
384 1.6 phil ypkey.data = (u_char *)__yp_token;
385 1.6 phil ypkey.size = strlen(__yp_token);
386 1.6 phil ypdata.data = (u_char *)NULL;
387 1.6 phil ypdata.size = 0;
388 1.6 phil
389 1.11 fair if((edp->put)(edp, &ypkey, &ypdata, R_NOOVERWRITE) == -1)
390 1.12 fair wr_error(pwd_Sdb_tmp);
391 1.6 phil }
392 1.6 phil
393 1.11 fair if ((edp->close)(edp) < 0) {
394 1.11 fair wr_error(_PATH_SMP_DB);
395 1.11 fair }
396 1.1 cgd
397 1.1 cgd /* Set master.passwd permissions, in case caller forgot. */
398 1.1 cgd (void)fchmod(fileno(fp), S_IRUSR|S_IWUSR);
399 1.11 fair if (fclose(fp) == EOF) {
400 1.11 fair wr_error(pname);
401 1.11 fair }
402 1.1 cgd
403 1.1 cgd /* Install as the real password files. */
404 1.11 fair {
405 1.11 fair char destination[MAXPATHLEN];
406 1.11 fair
407 1.11 fair (void)snprintf(destination, sizeof(destination),
408 1.11 fair "%s%s", prefix, _PATH_MP_DB);
409 1.11 fair mv(pwd_db_tmp, destination);
410 1.11 fair
411 1.11 fair (void)snprintf(destination, sizeof(destination),
412 1.11 fair "%s%s", prefix, _PATH_SMP_DB);
413 1.11 fair mv(pwd_Sdb_tmp, destination);
414 1.11 fair
415 1.11 fair if (makeold) {
416 1.11 fair (void)snprintf(destination, sizeof(destination),
417 1.11 fair "%s%s", prefix, _PATH_PASSWD);
418 1.11 fair mv(oldpwdfile, destination);
419 1.11 fair }
420 1.11 fair
421 1.11 fair /*
422 1.11 fair * Move the master password LAST -- chpass(1),
423 1.11 fair * passwd(1) and vipw(8) all use flock(2) on it to
424 1.11 fair * block other incarnations of themselves. The rename
425 1.11 fair * means that everything is unlocked, as the original
426 1.11 fair * file can no longer be accessed.
427 1.11 fair */
428 1.11 fair (void)snprintf(destination, sizeof(destination),
429 1.11 fair "%s%s", prefix, _PATH_MASTERPASSWD);
430 1.11 fair mv(pname, destination);
431 1.1 cgd }
432 1.1 cgd exit(0);
433 1.1 cgd }
434 1.1 cgd
435 1.5 mycroft int
436 1.6 phil scan(fp, pw, flags)
437 1.1 cgd FILE *fp;
438 1.1 cgd struct passwd *pw;
439 1.17 mycroft u_int32_t *flags;
440 1.1 cgd {
441 1.1 cgd static int lcnt;
442 1.1 cgd static char line[LINE_MAX];
443 1.1 cgd char *p;
444 1.17 mycroft int oflags;
445 1.1 cgd
446 1.1 cgd if (!fgets(line, sizeof(line), fp))
447 1.5 mycroft return (0);
448 1.1 cgd ++lcnt;
449 1.1 cgd /*
450 1.1 cgd * ``... if I swallow anything evil, put your fingers down my
451 1.1 cgd * throat...''
452 1.1 cgd * -- The Who
453 1.1 cgd */
454 1.5 mycroft if (!(p = strchr(line, '\n'))) {
455 1.5 mycroft warnx("line too long");
456 1.1 cgd goto fmt;
457 1.1 cgd
458 1.1 cgd }
459 1.1 cgd *p = '\0';
460 1.15 lukem if (strcmp(line, "+") == 0)
461 1.15 lukem strcpy(line, "+:::::::::"); /* pw_scan() can't handle "+" */
462 1.17 mycroft oflags = 0;
463 1.17 mycroft if (!pw_scan(line, pw, &oflags)) {
464 1.5 mycroft warnx("at line #%d", lcnt);
465 1.5 mycroft fmt: errno = EFTYPE; /* XXX */
466 1.1 cgd error(pname);
467 1.1 cgd }
468 1.17 mycroft *flags = oflags;
469 1.5 mycroft
470 1.5 mycroft return (1);
471 1.1 cgd }
472 1.1 cgd
473 1.5 mycroft void
474 1.1 cgd mv(from, to)
475 1.1 cgd char *from, *to;
476 1.1 cgd {
477 1.1 cgd char buf[MAXPATHLEN];
478 1.1 cgd
479 1.1 cgd if (rename(from, to)) {
480 1.5 mycroft int sverrno = errno;
481 1.5 mycroft (void)snprintf(buf, sizeof(buf), "%s to %s", from, to);
482 1.1 cgd errno = sverrno;
483 1.1 cgd error(buf);
484 1.1 cgd }
485 1.1 cgd }
486 1.1 cgd
487 1.5 mycroft void
488 1.11 fair wr_error(name)
489 1.11 fair char *name;
490 1.11 fair {
491 1.11 fair char errbuf[BUFSIZ];
492 1.11 fair int sverrno = errno;
493 1.11 fair
494 1.11 fair (void)snprintf(errbuf, sizeof(errbuf),
495 1.11 fair "attempt to write %s failed", name);
496 1.11 fair
497 1.11 fair errno = sverrno;
498 1.11 fair error(errbuf);
499 1.11 fair }
500 1.11 fair
501 1.11 fair void
502 1.1 cgd error(name)
503 1.1 cgd char *name;
504 1.1 cgd {
505 1.5 mycroft
506 1.5 mycroft warn(name);
507 1.1 cgd cleanup();
508 1.11 fair #ifdef think_about_this_a_while_longer
509 1.11 fair fputs("NOTE: possible inconsistencies between text files and databases\n", stderr);
510 1.11 fair fputs("re-run pwd_mkdb when you have fixed the problem.\n", stderr);
511 1.11 fair #endif
512 1.1 cgd exit(1);
513 1.1 cgd }
514 1.1 cgd
515 1.5 mycroft void
516 1.11 fair rm(victim)
517 1.11 fair char *victim;
518 1.11 fair {
519 1.11 fair if (unlink(victim) < 0) {
520 1.11 fair warn("unlink(%s)", victim);
521 1.11 fair }
522 1.11 fair }
523 1.11 fair
524 1.11 fair void
525 1.1 cgd cleanup()
526 1.1 cgd {
527 1.1 cgd switch(clean) {
528 1.1 cgd case FILE_ORIG:
529 1.11 fair rm(oldpwdfile);
530 1.1 cgd /* FALLTHROUGH */
531 1.1 cgd case FILE_SECURE:
532 1.11 fair rm(pwd_Sdb_tmp);
533 1.1 cgd /* FALLTHROUGH */
534 1.1 cgd case FILE_INSECURE:
535 1.11 fair rm(pwd_db_tmp);
536 1.1 cgd }
537 1.1 cgd }
538 1.1 cgd
539 1.5 mycroft void
540 1.1 cgd usage()
541 1.1 cgd {
542 1.5 mycroft
543 1.17 mycroft (void)fprintf(stderr, "usage: pwd_mkdb [-pBL] [-d directory] file\n");
544 1.1 cgd exit(1);
545 1.1 cgd }
546