]>
git.saurik.com Git - apple/system_cmds.git/blob - pwd_mkdb.tproj/pwd_mkdb.c
5d3d10cf3b7918fc81d8152228277b8e020f1302
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (c) 1991, 1993, 1994
27 * The Regents of the University of California. All rights reserved.
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
37 * 3. All advertising materials mentioning features or use of this software
38 * must display the following acknowledgement:
39 * This product includes software developed by the University of
40 * California, Berkeley and its contributors.
41 * 4. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 static char copyright
[] =
60 "@(#) Copyright (c) 1991, 1993, 1994\n\
61 The Regents of the University of California. All rights reserved.\n";
65 static char sccsid
[] = "@(#)pwd_mkdb.c 8.5 (Berkeley) 4/20/94";
68 #include <sys/param.h>
87 #define PERM_INSECURE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
88 #define PERM_SECURE (S_IRUSR|S_IWUSR)
94 2048 * 1024, /* cachesize */
99 static enum state
{ FILE_INSECURE
, FILE_SECURE
, FILE_ORIG
} clean
;
100 static struct passwd pwd
; /* password structure */
101 static char *pname
; /* password file name */
103 void cleanup
__P((void));
104 void error
__P((char *));
105 void mv
__P((char *, char *));
106 int scan
__P((FILE *, struct passwd
*));
107 void usage
__P((void));
118 int ch
, cnt
, len
, makeold
, tfd
;
120 char buf
[MAX(MAXPATHLEN
, LINE_MAX
* 2)], tbuf
[1024];
123 while ((ch
= getopt(argc
, argv
, "pv")) != EOF
)
125 case 'p': /* create V7 "file.orig" */
128 case 'v': /* backward compatible */
141 * This could be changed to allow the user to interrupt.
142 * Probably not worth the effort.
145 sigaddset(&set
, SIGTSTP
);
146 sigaddset(&set
, SIGHUP
);
147 sigaddset(&set
, SIGINT
);
148 sigaddset(&set
, SIGQUIT
);
149 sigaddset(&set
, SIGTERM
);
150 (void)sigprocmask(SIG_BLOCK
, &set
, (sigset_t
*)NULL
);
152 /* We don't care what the user wants. */
156 /* Open the original password file */
157 if (!(fp
= fopen(pname
, "r")))
160 /* Open the temporary insecure password database. */
161 (void)snprintf(buf
, sizeof(buf
), "%s.tmp", _PATH_MP_DB
);
163 O_RDWR
|O_CREAT
|O_EXCL
, PERM_INSECURE
, DB_HASH
, &openinfo
);
166 clean
= FILE_INSECURE
;
169 * Open file for old password file. Minor trickiness -- don't want to
170 * chance the file already existing, since someone (stupidly) might
171 * still be using this for permission checking. So, open it first and
172 * fdopen the resulting fd. The resulting file should be readable by
176 (void)snprintf(buf
, sizeof(buf
), "%s.orig", pname
);
178 O_WRONLY
|O_CREAT
|O_EXCL
, PERM_INSECURE
)) < 0)
180 if ((oldfp
= fdopen(tfd
, "w")) == NULL
)
186 * The databases actually contain three copies of the original data.
187 * Each password file entry is converted into a rough approximation
188 * of a ``struct passwd'', with the strings placed inline. This
189 * object is then stored as the data for three separate keys. The
190 * first key * is the pw_name field prepended by the _PW_KEYBYNAME
191 * character. The second key is the pw_uid field prepended by the
192 * _PW_KEYBYUID character. The third key is the line number in the
193 * original file prepended by the _PW_KEYBYNUM character. (The special
194 * characters are prepended to ensure that the keys do not collide.)
196 data
.data
= (u_char
*)buf
;
197 key
.data
= (u_char
*)tbuf
;
198 for (cnt
= 1; scan(fp
, &pwd
); ++cnt
) {
199 #define COMPACT(e) t = e; while (*p++ = *t++);
200 /* Create insecure data. */
202 COMPACT(pwd
.pw_name
);
204 memmove(p
, &pwd
.pw_uid
, sizeof(int));
206 memmove(p
, &pwd
.pw_gid
, sizeof(int));
208 memmove(p
, &pwd
.pw_change
, sizeof(time_t));
210 COMPACT(pwd
.pw_class
);
211 COMPACT(pwd
.pw_gecos
);
213 COMPACT(pwd
.pw_shell
);
214 memmove(p
, &pwd
.pw_expire
, sizeof(time_t));
218 /* Store insecure by name. */
219 tbuf
[0] = _PW_KEYBYNAME
;
220 len
= strlen(pwd
.pw_name
);
221 memmove(tbuf
+ 1, pwd
.pw_name
, len
);
223 if ((dp
->put
)(dp
, &key
, &data
, R_NOOVERWRITE
) == -1)
226 /* Store insecure by number. */
227 tbuf
[0] = _PW_KEYBYNUM
;
228 memmove(tbuf
+ 1, &cnt
, sizeof(cnt
));
229 key
.size
= sizeof(cnt
) + 1;
230 if ((dp
->put
)(dp
, &key
, &data
, R_NOOVERWRITE
) == -1)
233 /* Store insecure by uid. */
234 tbuf
[0] = _PW_KEYBYUID
;
235 memmove(tbuf
+ 1, &pwd
.pw_uid
, sizeof(pwd
.pw_uid
));
236 key
.size
= sizeof(pwd
.pw_uid
) + 1;
237 if ((dp
->put
)(dp
, &key
, &data
, R_NOOVERWRITE
) == -1)
240 /* Create original format password file entry */
242 (void)fprintf(oldfp
, "%s:*:%d:%d:%s:%s:%s\n",
243 pwd
.pw_name
, pwd
.pw_uid
, pwd
.pw_gid
, pwd
.pw_gecos
,
244 pwd
.pw_dir
, pwd
.pw_shell
);
246 (void)(dp
->close
)(dp
);
252 /* Open the temporary encrypted password database. */
253 (void)snprintf(buf
, sizeof(buf
), "%s.tmp", _PATH_SMP_DB
);
255 O_RDWR
|O_CREAT
|O_EXCL
, PERM_SECURE
, DB_HASH
, &openinfo
);
261 for (cnt
= 1; scan(fp
, &pwd
); ++cnt
) {
263 /* Create secure data. */
265 COMPACT(pwd
.pw_name
);
266 COMPACT(pwd
.pw_passwd
);
267 memmove(p
, &pwd
.pw_uid
, sizeof(int));
269 memmove(p
, &pwd
.pw_gid
, sizeof(int));
271 memmove(p
, &pwd
.pw_change
, sizeof(time_t));
273 COMPACT(pwd
.pw_class
);
274 COMPACT(pwd
.pw_gecos
);
276 COMPACT(pwd
.pw_shell
);
277 memmove(p
, &pwd
.pw_expire
, sizeof(time_t));
281 /* Store secure by name. */
282 tbuf
[0] = _PW_KEYBYNAME
;
283 len
= strlen(pwd
.pw_name
);
284 memmove(tbuf
+ 1, pwd
.pw_name
, len
);
286 if ((edp
->put
)(edp
, &key
, &data
, R_NOOVERWRITE
) == -1)
289 /* Store secure by number. */
290 tbuf
[0] = _PW_KEYBYNUM
;
291 memmove(tbuf
+ 1, &cnt
, sizeof(cnt
));
292 key
.size
= sizeof(cnt
) + 1;
293 if ((edp
->put
)(edp
, &key
, &data
, R_NOOVERWRITE
) == -1)
296 /* Store secure by uid. */
297 tbuf
[0] = _PW_KEYBYUID
;
298 memmove(tbuf
+ 1, &pwd
.pw_uid
, sizeof(pwd
.pw_uid
));
299 key
.size
= sizeof(pwd
.pw_uid
) + 1;
300 if ((edp
->put
)(edp
, &key
, &data
, R_NOOVERWRITE
) == -1)
304 (void)(edp
->close
)(edp
);
306 /* Set master.passwd permissions, in case caller forgot. */
307 (void)fchmod(fileno(fp
), S_IRUSR
|S_IWUSR
);
310 /* Install as the real password files. */
311 (void)snprintf(buf
, sizeof(buf
), "%s.tmp", _PATH_MP_DB
);
312 mv(buf
, _PATH_MP_DB
);
313 (void)snprintf(buf
, sizeof(buf
), "%s.tmp", _PATH_SMP_DB
);
314 mv(buf
, _PATH_SMP_DB
);
316 (void)snprintf(buf
, sizeof(buf
), "%s.orig", pname
);
317 mv(buf
, _PATH_PASSWD
);
320 * Move the master password LAST -- chpass(1), passwd(1) and vipw(8)
321 * all use flock(2) on it to block other incarnations of themselves.
322 * The rename means that everything is unlocked, as the original file
323 * can no longer be accessed.
325 mv(pname
, _PATH_MASTERPASSWD
);
335 static char line
[LINE_MAX
];
338 #if defined(__APPLE__)
340 if (!fgets(line
, sizeof(line
), fp
))
342 } while (line
[0] == '#');
344 if (!fgets(line
, sizeof(line
), fp
))
349 * ``... if I swallow anything evil, put your fingers down my
353 if (!(p
= strchr(line
, '\n'))) {
354 warnx("line too long");
359 if (!pw_scan(line
, pw
)) {
360 warnx("at line #%d", lcnt
);
361 fmt
: errno
= EFTYPE
; /* XXX */
372 char buf
[MAXPATHLEN
];
374 if (rename(from
, to
)) {
376 (void)snprintf(buf
, sizeof(buf
), "%s to %s", from
, to
);
395 char buf
[MAXPATHLEN
];
399 (void)snprintf(buf
, sizeof(buf
), "%s.orig", pname
);
403 (void)snprintf(buf
, sizeof(buf
), "%s.tmp", _PATH_SMP_DB
);
407 (void)snprintf(buf
, sizeof(buf
), "%s.tmp", _PATH_MP_DB
);
416 (void)fprintf(stderr
, "usage: pwd_mkdb [-p] file\n");