xref: /titanic_53/usr/src/cmd/keyserv/newkey.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate /*
31*7c478bd9Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
32*7c478bd9Sstevel@tonic-gate  * The Regents of the University of California
33*7c478bd9Sstevel@tonic-gate  * All Rights Reserved
34*7c478bd9Sstevel@tonic-gate  *
35*7c478bd9Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
36*7c478bd9Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
37*7c478bd9Sstevel@tonic-gate  * contributors.
38*7c478bd9Sstevel@tonic-gate  */
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate /*
43*7c478bd9Sstevel@tonic-gate  * Administrative tool to add a new user to the publickey database
44*7c478bd9Sstevel@tonic-gate  */
45*7c478bd9Sstevel@tonic-gate #include <stdio.h>
46*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
47*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
48*7c478bd9Sstevel@tonic-gate #include <rpc/key_prot.h>
49*7c478bd9Sstevel@tonic-gate #include <rpcsvc/ypclnt.h>
50*7c478bd9Sstevel@tonic-gate #include <sys/wait.h>
51*7c478bd9Sstevel@tonic-gate #include <netdb.h>
52*7c478bd9Sstevel@tonic-gate #include <pwd.h>
53*7c478bd9Sstevel@tonic-gate #include <shadow.h>
54*7c478bd9Sstevel@tonic-gate #include <crypt.h>
55*7c478bd9Sstevel@tonic-gate #include <string.h>
56*7c478bd9Sstevel@tonic-gate #include <sys/resource.h>
57*7c478bd9Sstevel@tonic-gate #include <netdir.h>
58*7c478bd9Sstevel@tonic-gate #include <rpcsvc/nis.h>
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate #define	MAXMAPNAMELEN	256
61*7c478bd9Sstevel@tonic-gate #define	MAXPASSWD	256	/* max significant characters in password */
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate #define	PK_FILES	1
64*7c478bd9Sstevel@tonic-gate #define	PK_YP		2
65*7c478bd9Sstevel@tonic-gate #define	PK_NISPLUS	3
66*7c478bd9Sstevel@tonic-gate #define	PK_LDAP		4
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate extern	int optind;
69*7c478bd9Sstevel@tonic-gate extern	char *optarg;
70*7c478bd9Sstevel@tonic-gate extern	char *get_nisplus_principal();
71*7c478bd9Sstevel@tonic-gate extern	int __getnetnamebyuid();
72*7c478bd9Sstevel@tonic-gate extern  int self_check(char *name);
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate #define	local_host(host_name)	self_check(host_name)
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate char	*program_name;
77*7c478bd9Sstevel@tonic-gate int		pk_database;
78*7c478bd9Sstevel@tonic-gate static	char	*get_password();
79*7c478bd9Sstevel@tonic-gate static	char *basename();
80*7c478bd9Sstevel@tonic-gate static	char SHELL[] = "/bin/sh";
81*7c478bd9Sstevel@tonic-gate static	char YPDBPATH[] = "/var/yp";
82*7c478bd9Sstevel@tonic-gate static	char PKMAP[] = "publickey.byname";
83*7c478bd9Sstevel@tonic-gate static	char UPDATEFILE[] = "updaters";
84*7c478bd9Sstevel@tonic-gate static	char PKFILE[] = "/etc/publickey";
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate main(argc, argv)
87*7c478bd9Sstevel@tonic-gate 	int argc;
88*7c478bd9Sstevel@tonic-gate 	char *argv[];
89*7c478bd9Sstevel@tonic-gate {
90*7c478bd9Sstevel@tonic-gate 	char	name[MAXNETNAMELEN + 1];
91*7c478bd9Sstevel@tonic-gate 	char	public[HEXKEYBYTES + 1];
92*7c478bd9Sstevel@tonic-gate 	char	secret[HEXKEYBYTES + 1];
93*7c478bd9Sstevel@tonic-gate 	char	crypt1[HEXKEYBYTES + KEYCHECKSUMSIZE + 1];
94*7c478bd9Sstevel@tonic-gate 	int	status;
95*7c478bd9Sstevel@tonic-gate 	char	*pass, *target_host = NULL,
96*7c478bd9Sstevel@tonic-gate 		*username = NULL, *pk_service = NULL;
97*7c478bd9Sstevel@tonic-gate 	struct passwd	*pw;
98*7c478bd9Sstevel@tonic-gate 	NCONF_HANDLE	*nc_handle;
99*7c478bd9Sstevel@tonic-gate 	struct	netconfig *nconf;
100*7c478bd9Sstevel@tonic-gate 	struct	nd_hostserv service;
101*7c478bd9Sstevel@tonic-gate 	struct	nd_addrlist *addrs;
102*7c478bd9Sstevel@tonic-gate 	bool_t	validhost;
103*7c478bd9Sstevel@tonic-gate 	uid_t	uid;
104*7c478bd9Sstevel@tonic-gate 	int	c;
105*7c478bd9Sstevel@tonic-gate 	char	*nprinc = NULL;  /* nisplus principal name */
106*7c478bd9Sstevel@tonic-gate 	char	host_pname[NIS_MAXNAMELEN];
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate 	program_name = argv[0];
109*7c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "s:u:h:")) != -1) {
110*7c478bd9Sstevel@tonic-gate 		switch (c) {
111*7c478bd9Sstevel@tonic-gate 		case 's':
112*7c478bd9Sstevel@tonic-gate 			if (pk_service == NULL)
113*7c478bd9Sstevel@tonic-gate 				pk_service = optarg;
114*7c478bd9Sstevel@tonic-gate 			else
115*7c478bd9Sstevel@tonic-gate 				usage();
116*7c478bd9Sstevel@tonic-gate 			break;
117*7c478bd9Sstevel@tonic-gate 		case 'u':
118*7c478bd9Sstevel@tonic-gate 			if (username || target_host)
119*7c478bd9Sstevel@tonic-gate 				usage();
120*7c478bd9Sstevel@tonic-gate 			username = optarg;
121*7c478bd9Sstevel@tonic-gate 			break;
122*7c478bd9Sstevel@tonic-gate 		case 'h':
123*7c478bd9Sstevel@tonic-gate 			if (username || target_host)
124*7c478bd9Sstevel@tonic-gate 				usage();
125*7c478bd9Sstevel@tonic-gate 			target_host = optarg;
126*7c478bd9Sstevel@tonic-gate 			break;
127*7c478bd9Sstevel@tonic-gate 		default:
128*7c478bd9Sstevel@tonic-gate 			usage();
129*7c478bd9Sstevel@tonic-gate 		}
130*7c478bd9Sstevel@tonic-gate 	}
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate 	if (optind < argc || (username == 0 && target_host == 0)) {
133*7c478bd9Sstevel@tonic-gate 		usage();
134*7c478bd9Sstevel@tonic-gate 	}
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate 	if ((pk_database = get_pk_source(pk_service)) == 0)
137*7c478bd9Sstevel@tonic-gate 		usage();
138*7c478bd9Sstevel@tonic-gate 
139*7c478bd9Sstevel@tonic-gate 	if (geteuid() != 0) {
140*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Must be superuser to run %s\n",
141*7c478bd9Sstevel@tonic-gate 		    program_name);
142*7c478bd9Sstevel@tonic-gate 		exit(1);
143*7c478bd9Sstevel@tonic-gate 	}
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate 	if (username) {
146*7c478bd9Sstevel@tonic-gate 		pw = getpwnam(username);
147*7c478bd9Sstevel@tonic-gate 		if (pw == NULL) {
148*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: unknown user: '%s'\n",
149*7c478bd9Sstevel@tonic-gate 				program_name, username);
150*7c478bd9Sstevel@tonic-gate 			exit(1);
151*7c478bd9Sstevel@tonic-gate 		}
152*7c478bd9Sstevel@tonic-gate 		uid = pw->pw_uid;
153*7c478bd9Sstevel@tonic-gate 		if (uid == 0) {
154*7c478bd9Sstevel@tonic-gate 			if (! getnetname(name)) {
155*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
156*7c478bd9Sstevel@tonic-gate 			"%s: could not get the equivalent netname for %s\n",
157*7c478bd9Sstevel@tonic-gate 				program_name, username);
158*7c478bd9Sstevel@tonic-gate 				usage();
159*7c478bd9Sstevel@tonic-gate 			}
160*7c478bd9Sstevel@tonic-gate 			if (pk_database == PK_NISPLUS)
161*7c478bd9Sstevel@tonic-gate 				target_host = nis_local_host();
162*7c478bd9Sstevel@tonic-gate 			else {
163*7c478bd9Sstevel@tonic-gate 				if (gethostname(host_pname, NIS_MAXNAMELEN)
164*7c478bd9Sstevel@tonic-gate 					< 0) {
165*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
166*7c478bd9Sstevel@tonic-gate 				"%s: could not get the hostname for %s\n",
167*7c478bd9Sstevel@tonic-gate 					program_name, username);
168*7c478bd9Sstevel@tonic-gate 					usage();
169*7c478bd9Sstevel@tonic-gate 				}
170*7c478bd9Sstevel@tonic-gate 				target_host = host_pname;
171*7c478bd9Sstevel@tonic-gate 			}
172*7c478bd9Sstevel@tonic-gate 		}
173*7c478bd9Sstevel@tonic-gate 		if (__getnetnamebyuid(name, uid) == 0) {
174*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
175*7c478bd9Sstevel@tonic-gate 			"%s: could not get the equivalent netname for %s\n",
176*7c478bd9Sstevel@tonic-gate 				program_name, username);
177*7c478bd9Sstevel@tonic-gate 			usage();
178*7c478bd9Sstevel@tonic-gate 		}
179*7c478bd9Sstevel@tonic-gate 		if (pk_database == PK_NISPLUS)
180*7c478bd9Sstevel@tonic-gate 			nprinc = get_nisplus_principal(nis_local_directory(),
181*7c478bd9Sstevel@tonic-gate 					uid);
182*7c478bd9Sstevel@tonic-gate 	} else {
183*7c478bd9Sstevel@tonic-gate 		/* -h hostname option */
184*7c478bd9Sstevel@tonic-gate 		service.h_host = target_host;
185*7c478bd9Sstevel@tonic-gate 		service.h_serv = NULL;
186*7c478bd9Sstevel@tonic-gate 		validhost = FALSE;
187*7c478bd9Sstevel@tonic-gate 		/* verify if this is a valid hostname */
188*7c478bd9Sstevel@tonic-gate 		nc_handle = setnetconfig();
189*7c478bd9Sstevel@tonic-gate 		if (nc_handle == NULL) {
190*7c478bd9Sstevel@tonic-gate 			/* fails to open netconfig file */
191*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
192*7c478bd9Sstevel@tonic-gate 				"%s: failed in routine setnetconfig()\n",
193*7c478bd9Sstevel@tonic-gate 				program_name);
194*7c478bd9Sstevel@tonic-gate 			exit(2);
195*7c478bd9Sstevel@tonic-gate 		}
196*7c478bd9Sstevel@tonic-gate 		while (nconf = getnetconfig(nc_handle)) {
197*7c478bd9Sstevel@tonic-gate 			/* check to see if hostname exists for this transport */
198*7c478bd9Sstevel@tonic-gate 			if ((netdir_getbyname(nconf, &service, &addrs) == 0) &&
199*7c478bd9Sstevel@tonic-gate 			    (addrs->n_cnt != 0)) {
200*7c478bd9Sstevel@tonic-gate 				/* at least one valid address */
201*7c478bd9Sstevel@tonic-gate 				validhost = TRUE;
202*7c478bd9Sstevel@tonic-gate 				break;
203*7c478bd9Sstevel@tonic-gate 			}
204*7c478bd9Sstevel@tonic-gate 		}
205*7c478bd9Sstevel@tonic-gate 		endnetconfig(nc_handle);
206*7c478bd9Sstevel@tonic-gate 		if (!validhost) {
207*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: unknown host: %s\n",
208*7c478bd9Sstevel@tonic-gate 				program_name, target_host);
209*7c478bd9Sstevel@tonic-gate 			exit(1);
210*7c478bd9Sstevel@tonic-gate 		}
211*7c478bd9Sstevel@tonic-gate 		(void) host2netname(name, target_host, (char *)NULL);
212*7c478bd9Sstevel@tonic-gate 		if (pk_database == PK_NISPLUS) {
213*7c478bd9Sstevel@tonic-gate 			if (target_host[strlen(target_host) - 1] != '.') {
214*7c478bd9Sstevel@tonic-gate 				sprintf(host_pname, "%s.%s",
215*7c478bd9Sstevel@tonic-gate 					target_host, nis_local_directory());
216*7c478bd9Sstevel@tonic-gate 				nprinc = host_pname;
217*7c478bd9Sstevel@tonic-gate 			} else
218*7c478bd9Sstevel@tonic-gate 				nprinc = target_host;
219*7c478bd9Sstevel@tonic-gate 		}
220*7c478bd9Sstevel@tonic-gate 		uid = 0;
221*7c478bd9Sstevel@tonic-gate 	}
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "Adding new key for %s.\n", name);
224*7c478bd9Sstevel@tonic-gate 	pass = get_password(uid, target_host, username);
225*7c478bd9Sstevel@tonic-gate 
226*7c478bd9Sstevel@tonic-gate 	if (pass == NULL)
227*7c478bd9Sstevel@tonic-gate 		exit(1);
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate 	(void) __gen_dhkeys(public, secret, pass);
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate 	memcpy(crypt1, secret, HEXKEYBYTES);
232*7c478bd9Sstevel@tonic-gate 	memcpy(crypt1 + HEXKEYBYTES, secret, KEYCHECKSUMSIZE);
233*7c478bd9Sstevel@tonic-gate 	crypt1[HEXKEYBYTES + KEYCHECKSUMSIZE] = 0;
234*7c478bd9Sstevel@tonic-gate 	xencrypt(crypt1, pass);
235*7c478bd9Sstevel@tonic-gate 
236*7c478bd9Sstevel@tonic-gate 	if (status = setpublicmap(name, public, crypt1, pk_database,
237*7c478bd9Sstevel@tonic-gate 				nprinc, pass)) {
238*7c478bd9Sstevel@tonic-gate 		switch (pk_database) {
239*7c478bd9Sstevel@tonic-gate 		case PK_YP:
240*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
241*7c478bd9Sstevel@tonic-gate 				"%s: unable to update NIS database (%u): %s\n",
242*7c478bd9Sstevel@tonic-gate 				program_name, status,
243*7c478bd9Sstevel@tonic-gate 				yperr_string(status));
244*7c478bd9Sstevel@tonic-gate 			break;
245*7c478bd9Sstevel@tonic-gate 		case PK_FILES:
246*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
247*7c478bd9Sstevel@tonic-gate 			"%s: hence, unable to update publickey database\n",
248*7c478bd9Sstevel@tonic-gate 				program_name);
249*7c478bd9Sstevel@tonic-gate 			break;
250*7c478bd9Sstevel@tonic-gate 		case PK_NISPLUS:
251*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
252*7c478bd9Sstevel@tonic-gate 				"%s: unable to update nisplus database\n",
253*7c478bd9Sstevel@tonic-gate 				program_name);
254*7c478bd9Sstevel@tonic-gate 			break;
255*7c478bd9Sstevel@tonic-gate 		default:
256*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
257*7c478bd9Sstevel@tonic-gate 				"%s: could not update unknown database: %d\n",
258*7c478bd9Sstevel@tonic-gate 				program_name, pk_database);
259*7c478bd9Sstevel@tonic-gate 		}
260*7c478bd9Sstevel@tonic-gate 		exit(1);
261*7c478bd9Sstevel@tonic-gate 	}
262*7c478bd9Sstevel@tonic-gate 	exit(0);
263*7c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
264*7c478bd9Sstevel@tonic-gate }
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate /*
267*7c478bd9Sstevel@tonic-gate  * Set the entry in the public key file
268*7c478bd9Sstevel@tonic-gate  */
269*7c478bd9Sstevel@tonic-gate setpublicmap(name, public, secret, database, nis_princ, pw)
270*7c478bd9Sstevel@tonic-gate 	int database;
271*7c478bd9Sstevel@tonic-gate 	char *name;
272*7c478bd9Sstevel@tonic-gate 	char *public;
273*7c478bd9Sstevel@tonic-gate 	char *secret;
274*7c478bd9Sstevel@tonic-gate 	nis_name nis_princ;
275*7c478bd9Sstevel@tonic-gate 	char *pw;
276*7c478bd9Sstevel@tonic-gate {
277*7c478bd9Sstevel@tonic-gate 	char pkent[HEXKEYBYTES + HEXKEYBYTES + KEYCHECKSUMSIZE + 2];
278*7c478bd9Sstevel@tonic-gate 	char *domain = NULL;
279*7c478bd9Sstevel@tonic-gate 	char *master = NULL;
280*7c478bd9Sstevel@tonic-gate 	char hostname[MAXHOSTNAMELEN+1];
281*7c478bd9Sstevel@tonic-gate 
282*7c478bd9Sstevel@tonic-gate 	(void) sprintf(pkent, "%s:%s", public, secret);
283*7c478bd9Sstevel@tonic-gate 	switch (database) {
284*7c478bd9Sstevel@tonic-gate 	case PK_YP:
285*7c478bd9Sstevel@tonic-gate 		/* check that we're on the master server */
286*7c478bd9Sstevel@tonic-gate 		(void) yp_get_default_domain(&domain);
287*7c478bd9Sstevel@tonic-gate 		if (yp_master(domain, PKMAP, &master) != 0) {
288*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
289*7c478bd9Sstevel@tonic-gate 			"%s: cannot find master of NIS publickey database\n",
290*7c478bd9Sstevel@tonic-gate 				program_name);
291*7c478bd9Sstevel@tonic-gate 			exit(1);
292*7c478bd9Sstevel@tonic-gate 		}
293*7c478bd9Sstevel@tonic-gate 		if (gethostname(hostname, MAXHOSTNAMELEN) < 0) {
294*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
295*7c478bd9Sstevel@tonic-gate 				"%s: cannot find my own host name\n",
296*7c478bd9Sstevel@tonic-gate 				program_name);
297*7c478bd9Sstevel@tonic-gate 			exit(1);
298*7c478bd9Sstevel@tonic-gate 		}
299*7c478bd9Sstevel@tonic-gate 		if (strcmp(master, hostname) != 0) {
300*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
301*7c478bd9Sstevel@tonic-gate 			"%s: can only be used on NIS master machine '%s'\n",
302*7c478bd9Sstevel@tonic-gate 				program_name, master);
303*7c478bd9Sstevel@tonic-gate 			exit(1);
304*7c478bd9Sstevel@tonic-gate 		}
305*7c478bd9Sstevel@tonic-gate 
306*7c478bd9Sstevel@tonic-gate 		if (chdir(YPDBPATH) < 0) {
307*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: cannot chdir to %s",
308*7c478bd9Sstevel@tonic-gate 			program_name, YPDBPATH);
309*7c478bd9Sstevel@tonic-gate 		}
310*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout,
311*7c478bd9Sstevel@tonic-gate 			"Please wait for the database to get updated ...\n");
312*7c478bd9Sstevel@tonic-gate 		return (mapupdate(name, PKMAP, YPOP_STORE, pkent));
313*7c478bd9Sstevel@tonic-gate 	case PK_FILES:
314*7c478bd9Sstevel@tonic-gate 		return (localupdate(name, PKFILE, YPOP_STORE, pkent));
315*7c478bd9Sstevel@tonic-gate 	case PK_NISPLUS:
316*7c478bd9Sstevel@tonic-gate 		return (nisplus_update(name, public, secret, nis_princ));
317*7c478bd9Sstevel@tonic-gate 	case PK_LDAP:
318*7c478bd9Sstevel@tonic-gate 		return (ldap_update("dh192-0", name, public, secret, pw));
319*7c478bd9Sstevel@tonic-gate 	default:
320*7c478bd9Sstevel@tonic-gate 		break;
321*7c478bd9Sstevel@tonic-gate 	}
322*7c478bd9Sstevel@tonic-gate 	return (1);
323*7c478bd9Sstevel@tonic-gate }
324*7c478bd9Sstevel@tonic-gate 
325*7c478bd9Sstevel@tonic-gate usage()
326*7c478bd9Sstevel@tonic-gate {
327*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
328*7c478bd9Sstevel@tonic-gate 		"usage:\t%s -u username [-s ldap | nisplus | nis | files]\n",
329*7c478bd9Sstevel@tonic-gate 		program_name);
330*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
331*7c478bd9Sstevel@tonic-gate 		"\t%s -h hostname [-s ldap | nisplus | nis | files]\n",
332*7c478bd9Sstevel@tonic-gate 		program_name);
333*7c478bd9Sstevel@tonic-gate 	exit(1);
334*7c478bd9Sstevel@tonic-gate }
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate /*
337*7c478bd9Sstevel@tonic-gate  * The parameters passed into the routine get_password and the
338*7c478bd9Sstevel@tonic-gate  * return values are as follows:
339*7c478bd9Sstevel@tonic-gate  * If the -h flag was specified on the command line:
340*7c478bd9Sstevel@tonic-gate  * (a) username is null
341*7c478bd9Sstevel@tonic-gate  * (b) target_host is non-null
342*7c478bd9Sstevel@tonic-gate  * (c) uid is 0
343*7c478bd9Sstevel@tonic-gate  * (d) the login password of root on target_host is returned
344*7c478bd9Sstevel@tonic-gate  *
345*7c478bd9Sstevel@tonic-gate  * If the -u flag was specified on the command line:
346*7c478bd9Sstevel@tonic-gate  * (a) username is non-null
347*7c478bd9Sstevel@tonic-gate  * (b) target_host is null in all cases except when username is root;
348*7c478bd9Sstevel@tonic-gate  *	in that case target_host is set to the local host
349*7c478bd9Sstevel@tonic-gate  * (c) uid is set to the username's uid
350*7c478bd9Sstevel@tonic-gate  * (d) the login password of the user <username> is returned
351*7c478bd9Sstevel@tonic-gate  */
352*7c478bd9Sstevel@tonic-gate static char *
353*7c478bd9Sstevel@tonic-gate get_password(uid, target_host, username)
354*7c478bd9Sstevel@tonic-gate uid_t	uid;
355*7c478bd9Sstevel@tonic-gate char	*target_host;
356*7c478bd9Sstevel@tonic-gate char	*username;
357*7c478bd9Sstevel@tonic-gate {
358*7c478bd9Sstevel@tonic-gate 	static	char	password[MAXPASSWD+1];
359*7c478bd9Sstevel@tonic-gate 	char		prompt[MAXPASSWD+MAXHOSTNAMELEN+64];
360*7c478bd9Sstevel@tonic-gate 	char		*encrypted_password,
361*7c478bd9Sstevel@tonic-gate 			*login_password = NULL,
362*7c478bd9Sstevel@tonic-gate 			*pass = NULL;
363*7c478bd9Sstevel@tonic-gate 	struct	passwd	*pw;
364*7c478bd9Sstevel@tonic-gate 	struct	spwd	*spw;
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate 	if ((username != 0) ||
367*7c478bd9Sstevel@tonic-gate 	    (target_host != 0) && (local_host(target_host))) {
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate 	/*
370*7c478bd9Sstevel@tonic-gate 	 * "-u username" or "-h localhost" was specified on the
371*7c478bd9Sstevel@tonic-gate 	 * command line
372*7c478bd9Sstevel@tonic-gate 	 */
373*7c478bd9Sstevel@tonic-gate 
374*7c478bd9Sstevel@tonic-gate 	pw = getpwuid(uid);
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate 	if (! pw) {
377*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
378*7c478bd9Sstevel@tonic-gate 			"%s: unable to locate password record for uid %d\n",
379*7c478bd9Sstevel@tonic-gate 			program_name, uid);
380*7c478bd9Sstevel@tonic-gate 		return (0);
381*7c478bd9Sstevel@tonic-gate 	}
382*7c478bd9Sstevel@tonic-gate 	spw = getspnam(pw->pw_name);
383*7c478bd9Sstevel@tonic-gate 	if (spw)
384*7c478bd9Sstevel@tonic-gate 		login_password = spw->sp_pwdp;
385*7c478bd9Sstevel@tonic-gate 
386*7c478bd9Sstevel@tonic-gate 	if (! login_password || (strlen(login_password) == 0)) {
387*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
388*7c478bd9Sstevel@tonic-gate 			"%s: unable to locate shadow password record for %s\n",
389*7c478bd9Sstevel@tonic-gate 			program_name, pw->pw_name);
390*7c478bd9Sstevel@tonic-gate 		return (0);
391*7c478bd9Sstevel@tonic-gate 	}
392*7c478bd9Sstevel@tonic-gate 
393*7c478bd9Sstevel@tonic-gate 	if (uid == 0) {
394*7c478bd9Sstevel@tonic-gate 		(void) sprintf(prompt, "Enter local root login password:");
395*7c478bd9Sstevel@tonic-gate 	} else
396*7c478bd9Sstevel@tonic-gate 	    (void) sprintf(prompt, "Enter %s's login password:",
397*7c478bd9Sstevel@tonic-gate 		pw->pw_name);
398*7c478bd9Sstevel@tonic-gate 
399*7c478bd9Sstevel@tonic-gate 	pass = getpass(prompt);
400*7c478bd9Sstevel@tonic-gate 	if (pass && strlen(pass) == 0) {
401*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: Invalid password.\n",
402*7c478bd9Sstevel@tonic-gate 			program_name);
403*7c478bd9Sstevel@tonic-gate 		return (0);
404*7c478bd9Sstevel@tonic-gate 	}
405*7c478bd9Sstevel@tonic-gate 	strcpy(password, pass);
406*7c478bd9Sstevel@tonic-gate 	encrypted_password = crypt(password, login_password);
407*7c478bd9Sstevel@tonic-gate 
408*7c478bd9Sstevel@tonic-gate 	/* Verify that password supplied matches login password */
409*7c478bd9Sstevel@tonic-gate 	if (strcmp(encrypted_password, login_password) != 0) {
410*7c478bd9Sstevel@tonic-gate 		/*
411*7c478bd9Sstevel@tonic-gate 		 * Give another chance for typo
412*7c478bd9Sstevel@tonic-gate 		 */
413*7c478bd9Sstevel@tonic-gate 		pass = getpass("Please retype password:");
414*7c478bd9Sstevel@tonic-gate 	    if (pass && strlen(pass) == 0) {
415*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: Invalid password.\n",
416*7c478bd9Sstevel@tonic-gate 			program_name);
417*7c478bd9Sstevel@tonic-gate 		return (0);
418*7c478bd9Sstevel@tonic-gate 	    }
419*7c478bd9Sstevel@tonic-gate 	    strcpy(password, pass);
420*7c478bd9Sstevel@tonic-gate 	    encrypted_password = crypt(password, login_password);
421*7c478bd9Sstevel@tonic-gate 	    if (strcmp(encrypted_password, login_password) != 0) {
422*7c478bd9Sstevel@tonic-gate 		    (void) fprintf(stderr,
423*7c478bd9Sstevel@tonic-gate 			"%s: ERROR, invalid password.\n",
424*7c478bd9Sstevel@tonic-gate 			program_name);
425*7c478bd9Sstevel@tonic-gate 		    return (0);
426*7c478bd9Sstevel@tonic-gate 	    }
427*7c478bd9Sstevel@tonic-gate 	}
428*7c478bd9Sstevel@tonic-gate 	} else {
429*7c478bd9Sstevel@tonic-gate 		/*
430*7c478bd9Sstevel@tonic-gate 		 * "-h remotehost" was specified on the command line
431*7c478bd9Sstevel@tonic-gate 		 *
432*7c478bd9Sstevel@tonic-gate 		 * Since we cannot verify the root password of the remote
433*7c478bd9Sstevel@tonic-gate 		 * host we have to trust what the user inputs. We can,
434*7c478bd9Sstevel@tonic-gate 		 * however, reduce the possibility of an  error by prompting
435*7c478bd9Sstevel@tonic-gate 		 * the user to enter the target host's password twice and
436*7c478bd9Sstevel@tonic-gate 		 * comparing those two. We can also authenticate the
437*7c478bd9Sstevel@tonic-gate 		 * user to be root by checking the real uid.
438*7c478bd9Sstevel@tonic-gate 		 */
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate 		if (getuid() != 0) {
441*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "Must be superuser to run %s\n",
442*7c478bd9Sstevel@tonic-gate 			    program_name);
443*7c478bd9Sstevel@tonic-gate 			return (0);
444*7c478bd9Sstevel@tonic-gate 		}
445*7c478bd9Sstevel@tonic-gate 
446*7c478bd9Sstevel@tonic-gate 		(void) sprintf(prompt,
447*7c478bd9Sstevel@tonic-gate 		    "Enter %s's root login password:",
448*7c478bd9Sstevel@tonic-gate 		    target_host);
449*7c478bd9Sstevel@tonic-gate 		pass = getpass(prompt);
450*7c478bd9Sstevel@tonic-gate 		if (!pass) {
451*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
452*7c478bd9Sstevel@tonic-gate 			    "%s: getpass failed.\n",
453*7c478bd9Sstevel@tonic-gate 			    program_name);
454*7c478bd9Sstevel@tonic-gate 			return (0);
455*7c478bd9Sstevel@tonic-gate 		}
456*7c478bd9Sstevel@tonic-gate 		if (!*pass) {
457*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
458*7c478bd9Sstevel@tonic-gate 			    "%s: Invalid root password.\n",
459*7c478bd9Sstevel@tonic-gate 			    program_name);
460*7c478bd9Sstevel@tonic-gate 			return (0);
461*7c478bd9Sstevel@tonic-gate 		}
462*7c478bd9Sstevel@tonic-gate 		strcpy(password, pass);
463*7c478bd9Sstevel@tonic-gate 
464*7c478bd9Sstevel@tonic-gate 		/*
465*7c478bd9Sstevel@tonic-gate 		 * Now re-enter the password and compare it to the
466*7c478bd9Sstevel@tonic-gate 		 * one just read.
467*7c478bd9Sstevel@tonic-gate 		 */
468*7c478bd9Sstevel@tonic-gate 		(void) sprintf(prompt,
469*7c478bd9Sstevel@tonic-gate 		    "Please confirm %s's root login password:",
470*7c478bd9Sstevel@tonic-gate 		    target_host);
471*7c478bd9Sstevel@tonic-gate 		pass = getpass(prompt);
472*7c478bd9Sstevel@tonic-gate 		if (!pass) {
473*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
474*7c478bd9Sstevel@tonic-gate 			    "%s: getpass failed.\n",
475*7c478bd9Sstevel@tonic-gate 			    program_name);
476*7c478bd9Sstevel@tonic-gate 			return (0);
477*7c478bd9Sstevel@tonic-gate 		}
478*7c478bd9Sstevel@tonic-gate 		if (!*pass) {
479*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
480*7c478bd9Sstevel@tonic-gate 			    "%s: Invalid root password.\n",
481*7c478bd9Sstevel@tonic-gate 			    program_name);
482*7c478bd9Sstevel@tonic-gate 			return (0);
483*7c478bd9Sstevel@tonic-gate 		}
484*7c478bd9Sstevel@tonic-gate 		if (strcmp(pass, password) != 0) {
485*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
486*7c478bd9Sstevel@tonic-gate 			    "%s: Password Incorrect.\n",
487*7c478bd9Sstevel@tonic-gate 			    program_name);
488*7c478bd9Sstevel@tonic-gate 			return (0);
489*7c478bd9Sstevel@tonic-gate 		}
490*7c478bd9Sstevel@tonic-gate 	}
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate 	return (password);
493*7c478bd9Sstevel@tonic-gate }
494