Annotation of src/usr.bin/chpass/chpass.c, Revision 1.1
1.1 ! deraadt 1: /* $NetBSD: chpass.c,v 1.7 1995/07/28 07:01:32 phil Exp $ */
! 2:
! 3: /*-
! 4: * Copyright (c) 1988, 1993, 1994
! 5: * The Regents of the University of California. All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgement:
! 17: * This product includes software developed by the University of
! 18: * California, Berkeley and its contributors.
! 19: * 4. Neither the name of the University nor the names of its contributors
! 20: * may be used to endorse or promote products derived from this software
! 21: * without specific prior written permission.
! 22: *
! 23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 33: * SUCH DAMAGE.
! 34: */
! 35:
! 36: #ifndef lint
! 37: static char copyright[] =
! 38: "@(#) Copyright (c) 1988, 1993, 1994\n\
! 39: The Regents of the University of California. All rights reserved.\n";
! 40: #endif /* not lint */
! 41:
! 42: #ifndef lint
! 43: #if 0
! 44: static char sccsid[] = "@(#)chpass.c 8.4 (Berkeley) 4/2/94";
! 45: #else
! 46: static char rcsid[] = "$NetBSD: chpass.c,v 1.7 1995/07/28 07:01:32 phil Exp $";
! 47: #endif
! 48: #endif /* not lint */
! 49:
! 50: #include <sys/param.h>
! 51: #include <sys/stat.h>
! 52: #include <sys/time.h>
! 53: #include <sys/resource.h>
! 54:
! 55: #include <ctype.h>
! 56: #include <err.h>
! 57: #include <errno.h>
! 58: #include <fcntl.h>
! 59: #include <pwd.h>
! 60: #include <stdio.h>
! 61: #include <stdlib.h>
! 62: #include <string.h>
! 63: #include <unistd.h>
! 64:
! 65: #include <pw_scan.h>
! 66: #include <pw_util.h>
! 67: #include "pw_copy.h"
! 68:
! 69: #include "chpass.h"
! 70: #include "pathnames.h"
! 71:
! 72: char *progname = "chpass";
! 73: char *tempname;
! 74: uid_t uid;
! 75:
! 76: #ifdef YP
! 77: int use_yp;
! 78: int force_yp = 0;
! 79: extern struct passwd *ypgetpwnam(), *ypgetpwuid();
! 80: #endif
! 81:
! 82: void baduser __P((void));
! 83: void usage __P((void));
! 84:
! 85: int
! 86: main(argc, argv)
! 87: int argc;
! 88: char **argv;
! 89: {
! 90: enum { NEWSH, LOADENTRY, EDITENTRY } op;
! 91: struct passwd *pw, lpw;
! 92: int ch, pfd, tfd;
! 93: char *arg;
! 94:
! 95: #ifdef YP
! 96: use_yp = _yp_check(NULL);
! 97: #endif
! 98:
! 99: op = EDITENTRY;
! 100: while ((ch = getopt(argc, argv, "a:s:ly")) != EOF)
! 101: switch(ch) {
! 102: case 'a':
! 103: op = LOADENTRY;
! 104: arg = optarg;
! 105: break;
! 106: case 's':
! 107: op = NEWSH;
! 108: arg = optarg;
! 109: break;
! 110: #ifdef YP
! 111: case 'l':
! 112: use_yp = 0;
! 113: break;
! 114: case 'y':
! 115: if (!use_yp) {
! 116: warnx("YP not in use.");
! 117: usage();
! 118: }
! 119: force_yp = 1;
! 120: break;
! 121: #endif
! 122: case '?':
! 123: default:
! 124: usage();
! 125: }
! 126: argc -= optind;
! 127: argv += optind;
! 128:
! 129: #ifdef YP
! 130: if (op == LOADENTRY && use_yp)
! 131: errx(1, "cannot load entry using NIS.\n\tUse the -l flag to load local.");
! 132: #endif
! 133: uid = getuid();
! 134:
! 135: if (op == EDITENTRY || op == NEWSH)
! 136: switch(argc) {
! 137: case 0:
! 138: pw = getpwuid(uid);
! 139: #ifdef YP
! 140: if (pw && !force_yp)
! 141: use_yp = 0;
! 142: else if (use_yp)
! 143: pw = ypgetpwuid(uid);
! 144: #endif /* YP */
! 145: if (!pw)
! 146: errx(1, "unknown user: uid %u\n", uid);
! 147: break;
! 148: case 1:
! 149: pw = getpwnam(*argv);
! 150: #ifdef YP
! 151: if (pw && !force_yp)
! 152: use_yp = 0;
! 153: else if (use_yp)
! 154: pw = ypgetpwnam(*argv);
! 155: #endif /* YP */
! 156: if (!pw)
! 157: errx(1, "unknown user: %s", *argv);
! 158: if (uid && uid != pw->pw_uid)
! 159: baduser();
! 160: break;
! 161: default:
! 162: usage();
! 163: }
! 164:
! 165: if (op == NEWSH) {
! 166: /* protect p_shell -- it thinks NULL is /bin/sh */
! 167: if (!arg[0])
! 168: usage();
! 169: if (p_shell(arg, pw, (ENTRY *)NULL))
! 170: pw_error((char *)NULL, 0, 1);
! 171: }
! 172:
! 173: if (op == LOADENTRY) {
! 174: if (uid)
! 175: baduser();
! 176: pw = &lpw;
! 177: if (!pw_scan(arg, pw, (int *)NULL))
! 178: exit(1);
! 179: }
! 180:
! 181: /*
! 182: * The temporary file/file descriptor usage is a little tricky here.
! 183: * 1: We start off with two fd's, one for the master password
! 184: * file (used to lock everything), and one for a temporary file.
! 185: * 2: Display() gets an fp for the temporary file, and copies the
! 186: * user's information into it. It then gives the temporary file
! 187: * to the user and closes the fp, closing the underlying fd.
! 188: * 3: The user edits the temporary file some number of times.
! 189: * 4: Verify() gets an fp for the temporary file, and verifies the
! 190: * contents. It can't use an fp derived from the step #2 fd,
! 191: * because the user's editor may have created a new instance of
! 192: * the file. Once the file is verified, its contents are stored
! 193: * in a password structure. The verify routine closes the fp,
! 194: * closing the underlying fd.
! 195: * 5: Delete the temporary file.
! 196: * 6: Get a new temporary file/fd. Pw_copy() gets an fp for it
! 197: * file and copies the master password file into it, replacing
! 198: * the user record with a new one. We can't use the first
! 199: * temporary file for this because it was owned by the user.
! 200: * Pw_copy() closes its fp, flushing the data and closing the
! 201: * underlying file descriptor. We can't close the master
! 202: * password fp, or we'd lose the lock.
! 203: * 7: Call pw_mkdb() (which renames the temporary file) and exit.
! 204: * The exit closes the master passwd fp/fd.
! 205: */
! 206: pw_init();
! 207: pfd = pw_lock();
! 208: tfd = pw_tmp();
! 209:
! 210: if (op == EDITENTRY) {
! 211: display(tfd, pw);
! 212: edit(pw);
! 213: (void)unlink(tempname);
! 214: tfd = pw_tmp();
! 215: }
! 216:
! 217: #ifdef YP
! 218: if (use_yp) {
! 219: (void)unlink(tempname);
! 220: if (pw_yp(pw, uid))
! 221: pw_error((char *)NULL, 0, 1);
! 222: else
! 223: exit(0);
! 224: }
! 225: else
! 226: #endif /* YP */
! 227: pw_copy(pfd, tfd, pw);
! 228:
! 229: if (!pw_mkdb())
! 230: pw_error((char *)NULL, 0, 1);
! 231:
! 232: exit(0);
! 233: }
! 234:
! 235: void
! 236: baduser()
! 237: {
! 238:
! 239: errx(1, "%s", strerror(EACCES));
! 240: }
! 241:
! 242: void
! 243: usage()
! 244: {
! 245:
! 246: #ifdef YP
! 247: (void)fprintf(stderr, "usage: chpass [-a list] [-s shell] [-l]%s [user]\n", use_yp?" [-y]":"");
! 248: #else
! 249: (void)fprintf(stderr, "usage: chpass [-a list] [-s shell] [user]\n");
! 250: #endif
! 251: exit(1);
! 252: }