xref: /openbsd-src/libexec/login_lchpass/login_lchpass.c (revision f414793931f0f39a413874f9e342e33d9fd35eac)
1 /*	$OpenBSD: login_lchpass.c,v 1.21 2018/04/26 12:42:51 guenther Exp $	*/
2 
3 /*-
4  * Copyright (c) 1995,1996 Berkeley Software Design, Inc. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *      This product includes software developed by Berkeley Software Design,
17  *      Inc.
18  * 4. The name of Berkeley Software Design, Inc.  may not be used to endorse
19  *    or promote products derived from this software without specific prior
20  *    written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN, INC. BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  *	BSDI $From: login_lchpass.c,v 1.4 1997/08/08 18:58:23 prb Exp $
35  */
36 
37 #include <sys/resource.h>
38 #include <sys/uio.h>
39 
40 #include <pwd.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <syslog.h>
45 #include <unistd.h>
46 #include <login_cap.h>
47 #include <readpassphrase.h>
48 
49 #define BACK_CHANNEL	3
50 
51 int local_passwd(char *, int);
52 
53 int
main(int argc,char * argv[])54 main(int argc, char *argv[])
55 {
56 	struct iovec iov[2];
57 	struct passwd *pwd;
58 	char *username = NULL, *hash = NULL;
59 	char oldpass[1024];
60 	struct rlimit rl;
61 	int c;
62 
63 	iov[0].iov_base = BI_SILENT;
64 	iov[0].iov_len = sizeof(BI_SILENT) - 1;
65 	iov[1].iov_base = "\n";
66 	iov[1].iov_len = 1;
67 
68 	rl.rlim_cur = 0;
69 	rl.rlim_max = 0;
70 	(void)setrlimit(RLIMIT_CORE, &rl);
71 
72 	(void)setpriority(PRIO_PROCESS, 0, 0);
73 
74 	openlog("login", LOG_ODELAY, LOG_AUTH);
75 
76 	while ((c = getopt(argc, argv, "v:s:")) != -1)
77 		switch (c) {
78 		case 'v':
79 			break;
80 		case 's':	/* service */
81 			if (strcmp(optarg, "login") != 0) {
82 				syslog(LOG_ERR, "%s: invalid service", optarg);
83 				exit(1);
84 			}
85 			break;
86 		default:
87 			syslog(LOG_ERR, "usage error");
88 			exit(1);
89 		}
90 
91 	switch (argc - optind) {
92 	case 2:
93 		/* class is not used */
94 	case 1:
95 		username = argv[optind];
96 		break;
97 	default:
98 		syslog(LOG_ERR, "usage error");
99 		exit(1);
100 	}
101 
102 	pwd = getpwnam_shadow(username);
103 	if (pwd) {
104 		if (pwd->pw_uid == 0) {
105 			syslog(LOG_ERR, "attempted root password change");
106 			pwd = NULL;
107 		} else if (*pwd->pw_passwd == '\0') {
108 			syslog(LOG_ERR, "%s attempting to add password",
109 			    username);
110 			pwd = NULL;
111 		}
112 	}
113 
114 	if (pwd)
115 		hash = pwd->pw_passwd;
116 
117 	(void)setpriority(PRIO_PROCESS, 0, -4);
118 
119 	(void)printf("Changing local password for %s.\n", username);
120 	if ((readpassphrase("Old Password:", oldpass, sizeof(oldpass),
121 		    RPP_ECHO_OFF)) == NULL)
122 		exit(1);
123 
124 	if (crypt_checkpass(oldpass, hash) != 0) {
125 		explicit_bzero(oldpass, strlen(oldpass));
126 		exit(1);
127 	}
128 	explicit_bzero(oldpass, strlen(oldpass));
129 
130 	/*
131 	 * We rely on local_passwd() to block signals during the
132 	 * critical section.
133 	 */
134 	local_passwd(pwd->pw_name, 1);
135 	(void)writev(BACK_CHANNEL, iov, 2);
136 	exit(0);
137 }
138