]>
git.saurik.com Git - apple/system_cmds.git/blob - pwd_mkdb.tproj/pwd_mkdb.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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
22 * @APPLE_LICENSE_HEADER_END@
25 * Copyright (c) 1991, 1993, 1994
26 * The Regents of the University of California. All rights reserved.
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by the University of
39 * California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 static char copyright
[] =
59 "@(#) Copyright (c) 1991, 1993, 1994\n\
60 The Regents of the University of California. All rights reserved.\n";
64 static char sccsid
[] = "@(#)pwd_mkdb.c 8.5 (Berkeley) 4/20/94";
67 #include <sys/param.h>
86 #define PERM_INSECURE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
87 #define PERM_SECURE (S_IRUSR|S_IWUSR)
93 2048 * 1024, /* cachesize */
98 static enum state
{ FILE_INSECURE
, FILE_SECURE
, FILE_ORIG
} clean
;
99 static struct passwd pwd
; /* password structure */
100 static char *pname
; /* password file name */
102 void cleanup
__P((void));
103 void error
__P((char *));
104 void mv
__P((char *, char *));
105 int scan
__P((FILE *, struct passwd
*));
106 void usage
__P((void));
117 int ch
, cnt
, len
, makeold
, tfd
;
119 char buf
[MAX(MAXPATHLEN
, LINE_MAX
* 2)], tbuf
[1024];
122 while ((ch
= getopt(argc
, argv
, "pv")) != EOF
)
124 case 'p': /* create V7 "file.orig" */
127 case 'v': /* backward compatible */
140 * This could be changed to allow the user to interrupt.
141 * Probably not worth the effort.
144 sigaddset(&set
, SIGTSTP
);
145 sigaddset(&set
, SIGHUP
);
146 sigaddset(&set
, SIGINT
);
147 sigaddset(&set
, SIGQUIT
);
148 sigaddset(&set
, SIGTERM
);
149 (void)sigprocmask(SIG_BLOCK
, &set
, (sigset_t
*)NULL
);
151 /* We don't care what the user wants. */
155 /* Open the original password file */
156 if (!(fp
= fopen(pname
, "r")))
159 /* Open the temporary insecure password database. */
160 (void)snprintf(buf
, sizeof(buf
), "%s.tmp", _PATH_MP_DB
);
162 O_RDWR
|O_CREAT
|O_EXCL
, PERM_INSECURE
, DB_HASH
, &openinfo
);
165 clean
= FILE_INSECURE
;
168 * Open file for old password file. Minor trickiness -- don't want to
169 * chance the file already existing, since someone (stupidly) might
170 * still be using this for permission checking. So, open it first and
171 * fdopen the resulting fd. The resulting file should be readable by
175 (void)snprintf(buf
, sizeof(buf
), "%s.orig", pname
);
177 O_WRONLY
|O_CREAT
|O_EXCL
, PERM_INSECURE
)) < 0)
179 if ((oldfp
= fdopen(tfd
, "w")) == NULL
)
185 * The databases actually contain three copies of the original data.
186 * Each password file entry is converted into a rough approximation
187 * of a ``struct passwd'', with the strings placed inline. This
188 * object is then stored as the data for three separate keys. The
189 * first key * is the pw_name field prepended by the _PW_KEYBYNAME
190 * character. The second key is the pw_uid field prepended by the
191 * _PW_KEYBYUID character. The third key is the line number in the
192 * original file prepended by the _PW_KEYBYNUM character. (The special
193 * characters are prepended to ensure that the keys do not collide.)
195 data
.data
= (u_char
*)buf
;
196 key
.data
= (u_char
*)tbuf
;
197 for (cnt
= 1; scan(fp
, &pwd
); ++cnt
) {
198 #define COMPACT(e) t = e; while (*p++ = *t++);
199 /* Create insecure data. */
201 COMPACT(pwd
.pw_name
);
203 memmove(p
, &pwd
.pw_uid
, sizeof(int));
205 memmove(p
, &pwd
.pw_gid
, sizeof(int));
207 memmove(p
, &pwd
.pw_change
, sizeof(time_t));
209 COMPACT(pwd
.pw_class
);
210 COMPACT(pwd
.pw_gecos
);
212 COMPACT(pwd
.pw_shell
);
213 memmove(p
, &pwd
.pw_expire
, sizeof(time_t));
217 /* Store insecure by name. */
218 tbuf
[0] = _PW_KEYBYNAME
;
219 len
= strlen(pwd
.pw_name
);
220 memmove(tbuf
+ 1, pwd
.pw_name
, len
);
222 if ((dp
->put
)(dp
, &key
, &data
, R_NOOVERWRITE
) == -1)
225 /* Store insecure by number. */
226 tbuf
[0] = _PW_KEYBYNUM
;
227 memmove(tbuf
+ 1, &cnt
, sizeof(cnt
));
228 key
.size
= sizeof(cnt
) + 1;
229 if ((dp
->put
)(dp
, &key
, &data
, R_NOOVERWRITE
) == -1)
232 /* Store insecure by uid. */
233 tbuf
[0] = _PW_KEYBYUID
;
234 memmove(tbuf
+ 1, &pwd
.pw_uid
, sizeof(pwd
.pw_uid
));
235 key
.size
= sizeof(pwd
.pw_uid
) + 1;
236 if ((dp
->put
)(dp
, &key
, &data
, R_NOOVERWRITE
) == -1)
239 /* Create original format password file entry */
241 (void)fprintf(oldfp
, "%s:*:%d:%d:%s:%s:%s\n",
242 pwd
.pw_name
, pwd
.pw_uid
, pwd
.pw_gid
, pwd
.pw_gecos
,
243 pwd
.pw_dir
, pwd
.pw_shell
);
245 (void)(dp
->close
)(dp
);
251 /* Open the temporary encrypted password database. */
252 (void)snprintf(buf
, sizeof(buf
), "%s.tmp", _PATH_SMP_DB
);
254 O_RDWR
|O_CREAT
|O_EXCL
, PERM_SECURE
, DB_HASH
, &openinfo
);
260 for (cnt
= 1; scan(fp
, &pwd
); ++cnt
) {
262 /* Create secure data. */
264 COMPACT(pwd
.pw_name
);
265 COMPACT(pwd
.pw_passwd
);
266 memmove(p
, &pwd
.pw_uid
, sizeof(int));
268 memmove(p
, &pwd
.pw_gid
, sizeof(int));
270 memmove(p
, &pwd
.pw_change
, sizeof(time_t));
272 COMPACT(pwd
.pw_class
);
273 COMPACT(pwd
.pw_gecos
);
275 COMPACT(pwd
.pw_shell
);
276 memmove(p
, &pwd
.pw_expire
, sizeof(time_t));
280 /* Store secure by name. */
281 tbuf
[0] = _PW_KEYBYNAME
;
282 len
= strlen(pwd
.pw_name
);
283 memmove(tbuf
+ 1, pwd
.pw_name
, len
);
285 if ((edp
->put
)(edp
, &key
, &data
, R_NOOVERWRITE
) == -1)
288 /* Store secure by number. */
289 tbuf
[0] = _PW_KEYBYNUM
;
290 memmove(tbuf
+ 1, &cnt
, sizeof(cnt
));
291 key
.size
= sizeof(cnt
) + 1;
292 if ((edp
->put
)(edp
, &key
, &data
, R_NOOVERWRITE
) == -1)
295 /* Store secure by uid. */
296 tbuf
[0] = _PW_KEYBYUID
;
297 memmove(tbuf
+ 1, &pwd
.pw_uid
, sizeof(pwd
.pw_uid
));
298 key
.size
= sizeof(pwd
.pw_uid
) + 1;
299 if ((edp
->put
)(edp
, &key
, &data
, R_NOOVERWRITE
) == -1)
303 (void)(edp
->close
)(edp
);
305 /* Set master.passwd permissions, in case caller forgot. */
306 (void)fchmod(fileno(fp
), S_IRUSR
|S_IWUSR
);
309 /* Install as the real password files. */
310 (void)snprintf(buf
, sizeof(buf
), "%s.tmp", _PATH_MP_DB
);
311 mv(buf
, _PATH_MP_DB
);
312 (void)snprintf(buf
, sizeof(buf
), "%s.tmp", _PATH_SMP_DB
);
313 mv(buf
, _PATH_SMP_DB
);
315 (void)snprintf(buf
, sizeof(buf
), "%s.orig", pname
);
316 mv(buf
, _PATH_PASSWD
);
319 * Move the master password LAST -- chpass(1), passwd(1) and vipw(8)
320 * all use flock(2) on it to block other incarnations of themselves.
321 * The rename means that everything is unlocked, as the original file
322 * can no longer be accessed.
324 mv(pname
, _PATH_MASTERPASSWD
);
334 static char line
[LINE_MAX
];
337 #if defined(__APPLE__)
339 if (!fgets(line
, sizeof(line
), fp
))
341 } while (line
[0] == '#');
343 if (!fgets(line
, sizeof(line
), fp
))
348 * ``... if I swallow anything evil, put your fingers down my
352 if (!(p
= strchr(line
, '\n'))) {
353 warnx("line too long");
358 if (!pw_scan(line
, pw
)) {
359 warnx("at line #%d", lcnt
);
360 fmt
: errno
= EFTYPE
; /* XXX */
371 char buf
[MAXPATHLEN
];
373 if (rename(from
, to
)) {
375 (void)snprintf(buf
, sizeof(buf
), "%s to %s", from
, to
);
394 char buf
[MAXPATHLEN
];
398 (void)snprintf(buf
, sizeof(buf
), "%s.orig", pname
);
402 (void)snprintf(buf
, sizeof(buf
), "%s.tmp", _PATH_SMP_DB
);
406 (void)snprintf(buf
, sizeof(buf
), "%s.tmp", _PATH_MP_DB
);
415 (void)fprintf(stderr
, "usage: pwd_mkdb [-p] file\n");