xref: /titanic_53/usr/src/cmd/keyserv/chkey.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 2004 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 #include <assert.h>
43*7c478bd9Sstevel@tonic-gate #include <stdio.h>
44*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
45*7c478bd9Sstevel@tonic-gate #include <string.h>
46*7c478bd9Sstevel@tonic-gate #include <pwd.h>
47*7c478bd9Sstevel@tonic-gate #include <shadow.h>
48*7c478bd9Sstevel@tonic-gate #include <crypt.h>
49*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
50*7c478bd9Sstevel@tonic-gate #include <unistd.h>
51*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
52*7c478bd9Sstevel@tonic-gate #include <rpc/key_prot.h>
53*7c478bd9Sstevel@tonic-gate #include <rpcsvc/nis.h>
54*7c478bd9Sstevel@tonic-gate #include <rpcsvc/nis_dhext.h>
55*7c478bd9Sstevel@tonic-gate #include <rpcsvc/ypclnt.h>
56*7c478bd9Sstevel@tonic-gate #include <nsswitch.h>
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate #define	PK_FILES	1
59*7c478bd9Sstevel@tonic-gate #define	PK_YP		2
60*7c478bd9Sstevel@tonic-gate #define	PK_NISPLUS	3
61*7c478bd9Sstevel@tonic-gate #define	PK_LDAP		4
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate #define	CURMECH		mechs[mcount]
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate static char	CRED_TABLE[] = "cred.org_dir";
66*7c478bd9Sstevel@tonic-gate static char	PKMAP[] = "publickey.byname";
67*7c478bd9Sstevel@tonic-gate static char	PKFILE[] = "/etc/publickey";
68*7c478bd9Sstevel@tonic-gate #define	MAXHOSTNAMELEN	256
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate #define	ROOTKEY_FILE		"/etc/.rootkey"
71*7c478bd9Sstevel@tonic-gate #define	ROOTKEY_FILE_BACKUP	"/etc/.rootkey.bak"
72*7c478bd9Sstevel@tonic-gate #define	MAXROOTKEY_LINE_LEN	4224	/* Good upto 16384-bit keys */
73*7c478bd9Sstevel@tonic-gate #define	MAXROOTKEY_LEN		4096
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate /* Should last up to 16384-bit keys */
76*7c478bd9Sstevel@tonic-gate #define	MAXPKENTLEN	8500
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate bool_t		makenew = TRUE;   /* Make new keys or reencrypt existing */
79*7c478bd9Sstevel@tonic-gate bool_t		specmech = FALSE; /* Specific mechs requested */
80*7c478bd9Sstevel@tonic-gate bool_t		force = FALSE;
81*7c478bd9Sstevel@tonic-gate int		dest_service = 0; /* To which nameservice do we store key(s) */
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate char		*program_name;
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate mechanism_t	**mechs = NULL;   /* List of DH mechanisms */
86*7c478bd9Sstevel@tonic-gate char		**plist = NULL;	  /* List of public key(s) */
87*7c478bd9Sstevel@tonic-gate char		**slist = NULL;	  /* List of secret key(s) */
88*7c478bd9Sstevel@tonic-gate char		**clist = NULL;   /* List of encrypted secret key(s) */
89*7c478bd9Sstevel@tonic-gate int		numspecmech = 0;  /* Number of mechanisms specified */
90*7c478bd9Sstevel@tonic-gate 
91*7c478bd9Sstevel@tonic-gate struct passwd	*pw = NULL;	  /* passwd entry of user */
92*7c478bd9Sstevel@tonic-gate struct spwd	*spw = NULL;	  /* shadow entry of user */
93*7c478bd9Sstevel@tonic-gate 
94*7c478bd9Sstevel@tonic-gate char		*netname = NULL;  /* RPC netname of user */
95*7c478bd9Sstevel@tonic-gate char		local_domain[MAXNETNAMELEN + 1];
96*7c478bd9Sstevel@tonic-gate char		*sec_domain = NULL;
97*7c478bd9Sstevel@tonic-gate 
98*7c478bd9Sstevel@tonic-gate char		**rpc_pws = NULL; /* List of S-RPC passwords */
99*7c478bd9Sstevel@tonic-gate int		rpc_pw_count = 0; /* Number of passwords entered by user */
100*7c478bd9Sstevel@tonic-gate char		*login_pw = NULL; /* Unencrypted login password */
101*7c478bd9Sstevel@tonic-gate 
102*7c478bd9Sstevel@tonic-gate static int add_cred_obj(nis_object *, char *);
103*7c478bd9Sstevel@tonic-gate static nis_error auth_exists(char *, char *, char *, char *);
104*7c478bd9Sstevel@tonic-gate static void cmp_passwd();
105*7c478bd9Sstevel@tonic-gate static nis_error cred_exists(const char *, const char *, const char *);
106*7c478bd9Sstevel@tonic-gate static void encryptkeys();
107*7c478bd9Sstevel@tonic-gate static void error_msg();
108*7c478bd9Sstevel@tonic-gate static char *fgets_ignorenul();
109*7c478bd9Sstevel@tonic-gate static void getpublics();
110*7c478bd9Sstevel@tonic-gate static void getrpcpws();
111*7c478bd9Sstevel@tonic-gate static void getsecrets();
112*7c478bd9Sstevel@tonic-gate static void initkeylist(bool_t);
113*7c478bd9Sstevel@tonic-gate static void keylogin(keylen_t, algtype_t);
114*7c478bd9Sstevel@tonic-gate static void keylogin_des();
115*7c478bd9Sstevel@tonic-gate static void makenewkeys();
116*7c478bd9Sstevel@tonic-gate static int modify_cred_obj(nis_object *, char *);
117*7c478bd9Sstevel@tonic-gate static int nisplus_update(nis_name, char *, char *, char *);
118*7c478bd9Sstevel@tonic-gate static int sanity_checks(char *, char *, char *);
119*7c478bd9Sstevel@tonic-gate static void storekeys();
120*7c478bd9Sstevel@tonic-gate static void usage();
121*7c478bd9Sstevel@tonic-gate static void write_rootkey();
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate extern char *get_nisplus_principal(char *, uid_t);
124*7c478bd9Sstevel@tonic-gate extern nis_object *init_entry();
125*7c478bd9Sstevel@tonic-gate extern int get_pk_source(char *);
126*7c478bd9Sstevel@tonic-gate extern int localupdate(char *, char *, uint_t, char *);
127*7c478bd9Sstevel@tonic-gate extern int xencrypt();
128*7c478bd9Sstevel@tonic-gate extern int xencrypt_g();
129*7c478bd9Sstevel@tonic-gate extern int __gen_dhkeys();
130*7c478bd9Sstevel@tonic-gate extern int key_setnet();
131*7c478bd9Sstevel@tonic-gate extern int key_setnet_g();
132*7c478bd9Sstevel@tonic-gate extern int key_secretkey_is_set_g();
133*7c478bd9Sstevel@tonic-gate extern int __getnetnamebyuid();
134*7c478bd9Sstevel@tonic-gate extern int getdomainname();
135*7c478bd9Sstevel@tonic-gate extern int ldap_update(char *, char *, char *, char *, char *);
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate static void
139*7c478bd9Sstevel@tonic-gate error_msg()
140*7c478bd9Sstevel@tonic-gate {
141*7c478bd9Sstevel@tonic-gate 	if (sec_domain && *sec_domain &&
142*7c478bd9Sstevel@tonic-gate 	    strcasecmp(sec_domain, local_domain)) {
143*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
144*7c478bd9Sstevel@tonic-gate "The system default domain '%s' is different from the Secure RPC\n\
145*7c478bd9Sstevel@tonic-gate domain %s where the key is stored.  The Secure RPC domainname is\n\
146*7c478bd9Sstevel@tonic-gate defined by the directory object stored in the /var/nis/NIS_COLD_START file.\n\
147*7c478bd9Sstevel@tonic-gate If you need to change this Secure RPC domainname, please use the nisinit(1M)\n\
148*7c478bd9Sstevel@tonic-gate command with the `-k` option.\n", local_domain, sec_domain);
149*7c478bd9Sstevel@tonic-gate 		exit(1);
150*7c478bd9Sstevel@tonic-gate 	}
151*7c478bd9Sstevel@tonic-gate }
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate static void
155*7c478bd9Sstevel@tonic-gate usage()
156*7c478bd9Sstevel@tonic-gate {
157*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "usage: %s [-p] [-s ldap | nisplus | nis | files] \n",
158*7c478bd9Sstevel@tonic-gate 		program_name);
159*7c478bd9Sstevel@tonic-gate 	exit(1);
160*7c478bd9Sstevel@tonic-gate }
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate /* Encrypt secret key(s) with login_pw */
164*7c478bd9Sstevel@tonic-gate static void
165*7c478bd9Sstevel@tonic-gate encryptkeys()
166*7c478bd9Sstevel@tonic-gate {
167*7c478bd9Sstevel@tonic-gate 	int	mcount, ccount = 0;
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate 	if (mechs) {
170*7c478bd9Sstevel@tonic-gate 		for (mcount = 0; CURMECH; mcount++) {
171*7c478bd9Sstevel@tonic-gate 			char		*crypt = NULL;
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate 			if (!xencrypt_g(slist[mcount], CURMECH->keylen,
174*7c478bd9Sstevel@tonic-gate 					CURMECH->algtype, login_pw, netname,
175*7c478bd9Sstevel@tonic-gate 					&crypt, TRUE)) {
176*7c478bd9Sstevel@tonic-gate 				/* Could not crypt key */
177*7c478bd9Sstevel@tonic-gate 				crypt = NULL;
178*7c478bd9Sstevel@tonic-gate 			} else
179*7c478bd9Sstevel@tonic-gate 				ccount++;
180*7c478bd9Sstevel@tonic-gate 			clist[mcount] = crypt;
181*7c478bd9Sstevel@tonic-gate 		}
182*7c478bd9Sstevel@tonic-gate 	} else {
183*7c478bd9Sstevel@tonic-gate 		char		*crypt = NULL;
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate 		if (!(crypt =
186*7c478bd9Sstevel@tonic-gate 			(char *)malloc(HEXKEYBYTES + KEYCHECKSUMSIZE + 1))) {
187*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "%s: Malloc failure.\n", program_name);
188*7c478bd9Sstevel@tonic-gate 			exit(1);
189*7c478bd9Sstevel@tonic-gate 		}
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate 		memcpy(crypt, slist[0], HEXKEYBYTES);
192*7c478bd9Sstevel@tonic-gate 		memcpy(crypt + HEXKEYBYTES, slist[0], KEYCHECKSUMSIZE);
193*7c478bd9Sstevel@tonic-gate 		crypt[HEXKEYBYTES + KEYCHECKSUMSIZE] = 0;
194*7c478bd9Sstevel@tonic-gate 		xencrypt(crypt, login_pw);
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate 		clist[0] = crypt;
197*7c478bd9Sstevel@tonic-gate 		ccount++;
198*7c478bd9Sstevel@tonic-gate 	}
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate 	if (!ccount) {
201*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: Could not encrypt any secret keys.\n",
202*7c478bd9Sstevel@tonic-gate 			program_name);
203*7c478bd9Sstevel@tonic-gate 		exit(1);
204*7c478bd9Sstevel@tonic-gate 	}
205*7c478bd9Sstevel@tonic-gate }
206*7c478bd9Sstevel@tonic-gate 
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate /* Initialize the array of public, secret, and encrypted secret keys */
209*7c478bd9Sstevel@tonic-gate static void
210*7c478bd9Sstevel@tonic-gate initkeylist(bool_t nomech)
211*7c478bd9Sstevel@tonic-gate {
212*7c478bd9Sstevel@tonic-gate 	int		mcount;
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate 	if (!nomech) {
215*7c478bd9Sstevel@tonic-gate 		assert(mechs && mechs[0]);
216*7c478bd9Sstevel@tonic-gate 		for (mcount = 0; CURMECH; mcount++);
217*7c478bd9Sstevel@tonic-gate 	} else
218*7c478bd9Sstevel@tonic-gate 		mcount = 1;
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate 	if (!(plist = (char **)malloc(sizeof (char *) * mcount))) {
221*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: Malloc failure.\n", program_name);
222*7c478bd9Sstevel@tonic-gate 		exit(1);
223*7c478bd9Sstevel@tonic-gate 	}
224*7c478bd9Sstevel@tonic-gate 	if (!(slist = (char **)malloc(sizeof (char *) * mcount))) {
225*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: Malloc failure.\n", program_name);
226*7c478bd9Sstevel@tonic-gate 		exit(1);
227*7c478bd9Sstevel@tonic-gate 	}
228*7c478bd9Sstevel@tonic-gate 	if (!(clist = (char **)malloc(sizeof (char *) * mcount))) {
229*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: Malloc failure.\n", program_name);
230*7c478bd9Sstevel@tonic-gate 		exit(1);
231*7c478bd9Sstevel@tonic-gate 	}
232*7c478bd9Sstevel@tonic-gate }
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate /* Retrieve public key(s) */
236*7c478bd9Sstevel@tonic-gate static void
237*7c478bd9Sstevel@tonic-gate getpublics()
238*7c478bd9Sstevel@tonic-gate {
239*7c478bd9Sstevel@tonic-gate 	int		mcount;
240*7c478bd9Sstevel@tonic-gate 	int		pcount = 0;
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate 	if (mechs) {
243*7c478bd9Sstevel@tonic-gate 		for (mcount = 0; CURMECH; mcount++) {
244*7c478bd9Sstevel@tonic-gate 			char		*public;
245*7c478bd9Sstevel@tonic-gate 			size_t		hexkeylen;
246*7c478bd9Sstevel@tonic-gate 
247*7c478bd9Sstevel@tonic-gate 			hexkeylen = ((CURMECH->keylen / 8) * 2) + 1;
248*7c478bd9Sstevel@tonic-gate 			if (!(public = (char *)malloc(hexkeylen))) {
249*7c478bd9Sstevel@tonic-gate 				fprintf(stderr, "%s: Malloc failure.\n",
250*7c478bd9Sstevel@tonic-gate 					program_name);
251*7c478bd9Sstevel@tonic-gate 				exit(1);
252*7c478bd9Sstevel@tonic-gate 			}
253*7c478bd9Sstevel@tonic-gate 			if (!getpublickey_g(netname, CURMECH->keylen,
254*7c478bd9Sstevel@tonic-gate 					    CURMECH->algtype, public,
255*7c478bd9Sstevel@tonic-gate 					    hexkeylen)) {
256*7c478bd9Sstevel@tonic-gate 				/* Could not get public key */
257*7c478bd9Sstevel@tonic-gate 				fprintf(stderr,
258*7c478bd9Sstevel@tonic-gate 					"Could not get %s public key.\n",
259*7c478bd9Sstevel@tonic-gate 					VALID_ALIAS(CURMECH->alias) ?
260*7c478bd9Sstevel@tonic-gate 					CURMECH->alias : "");
261*7c478bd9Sstevel@tonic-gate 				free(public);
262*7c478bd9Sstevel@tonic-gate 				public = NULL;
263*7c478bd9Sstevel@tonic-gate 			} else
264*7c478bd9Sstevel@tonic-gate 				pcount++;
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate 			plist[mcount] = public;
267*7c478bd9Sstevel@tonic-gate 		}
268*7c478bd9Sstevel@tonic-gate 	} else {
269*7c478bd9Sstevel@tonic-gate 		char		*public;
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate 		if (!(public = (char *)malloc(HEXKEYBYTES + 1))) {
272*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "%s: Malloc failure.\n", program_name);
273*7c478bd9Sstevel@tonic-gate 			exit(1);
274*7c478bd9Sstevel@tonic-gate 		}
275*7c478bd9Sstevel@tonic-gate 		if (!getpublickey(netname, public)) {
276*7c478bd9Sstevel@tonic-gate 			free(public);
277*7c478bd9Sstevel@tonic-gate 			public = NULL;
278*7c478bd9Sstevel@tonic-gate 		} else
279*7c478bd9Sstevel@tonic-gate 			pcount++;
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate 		plist[0] = public;
282*7c478bd9Sstevel@tonic-gate 	}
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate 	if (!pcount) {
285*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: cannot get any public keys for %s.\n",
286*7c478bd9Sstevel@tonic-gate 			program_name, pw->pw_name);
287*7c478bd9Sstevel@tonic-gate 		error_msg();
288*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
289*7c478bd9Sstevel@tonic-gate 	"Make sure that the public keys are stored in the domain %s.\n",
290*7c478bd9Sstevel@tonic-gate 			local_domain);
291*7c478bd9Sstevel@tonic-gate 		exit(1);
292*7c478bd9Sstevel@tonic-gate 	}
293*7c478bd9Sstevel@tonic-gate }
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate 
296*7c478bd9Sstevel@tonic-gate /* Generate a new set of public/secret key pair(s) */
297*7c478bd9Sstevel@tonic-gate static void
298*7c478bd9Sstevel@tonic-gate makenewkeys()
299*7c478bd9Sstevel@tonic-gate {
300*7c478bd9Sstevel@tonic-gate 	int		mcount;
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate 	if (mechs) {
303*7c478bd9Sstevel@tonic-gate 		for (mcount = 0; CURMECH; mcount++) {
304*7c478bd9Sstevel@tonic-gate 			char		*public, *secret;
305*7c478bd9Sstevel@tonic-gate 			size_t		hexkeylen;
306*7c478bd9Sstevel@tonic-gate 
307*7c478bd9Sstevel@tonic-gate 			if (slist[mcount])
308*7c478bd9Sstevel@tonic-gate 				free(slist[mcount]);
309*7c478bd9Sstevel@tonic-gate 
310*7c478bd9Sstevel@tonic-gate 			hexkeylen = ((CURMECH->keylen / 8) * 2) + 1;
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate 			if (!(public = malloc(hexkeylen))) {
313*7c478bd9Sstevel@tonic-gate 				fprintf(stderr, "%s: Malloc failure.\n",
314*7c478bd9Sstevel@tonic-gate 					program_name);
315*7c478bd9Sstevel@tonic-gate 				exit(1);
316*7c478bd9Sstevel@tonic-gate 			}
317*7c478bd9Sstevel@tonic-gate 			if (!(secret = malloc(hexkeylen))) {
318*7c478bd9Sstevel@tonic-gate 				fprintf(stderr, "%s: Malloc failure.\n",
319*7c478bd9Sstevel@tonic-gate 					program_name);
320*7c478bd9Sstevel@tonic-gate 				exit(1);
321*7c478bd9Sstevel@tonic-gate 			}
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate 			if (!(__gen_dhkeys_g(public, secret, CURMECH->keylen,
324*7c478bd9Sstevel@tonic-gate 					CURMECH->algtype, login_pw))) {
325*7c478bd9Sstevel@tonic-gate 				/* Could not generate key pair */
326*7c478bd9Sstevel@tonic-gate 				fprintf(stderr,
327*7c478bd9Sstevel@tonic-gate 				"WARNING  Could not generate key pair %s\n",
328*7c478bd9Sstevel@tonic-gate 					VALID_ALIAS(CURMECH->alias) ?
329*7c478bd9Sstevel@tonic-gate 					CURMECH->alias : "");
330*7c478bd9Sstevel@tonic-gate 				free(public);
331*7c478bd9Sstevel@tonic-gate 				free(secret);
332*7c478bd9Sstevel@tonic-gate 				public = NULL;
333*7c478bd9Sstevel@tonic-gate 				secret = NULL;
334*7c478bd9Sstevel@tonic-gate 			}
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate 			plist[mcount] = public;
337*7c478bd9Sstevel@tonic-gate 			slist[mcount] = secret;
338*7c478bd9Sstevel@tonic-gate 		}
339*7c478bd9Sstevel@tonic-gate 	} else {
340*7c478bd9Sstevel@tonic-gate 		char		*public, *secret;
341*7c478bd9Sstevel@tonic-gate 		if (slist[0])
342*7c478bd9Sstevel@tonic-gate 			free(slist[0]);
343*7c478bd9Sstevel@tonic-gate 
344*7c478bd9Sstevel@tonic-gate 		if (!(public = malloc(HEXKEYBYTES + 1))) {
345*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "%s: Malloc failure.\n", program_name);
346*7c478bd9Sstevel@tonic-gate 			exit(1);
347*7c478bd9Sstevel@tonic-gate 		}
348*7c478bd9Sstevel@tonic-gate 		if (!(secret = malloc(HEXKEYBYTES + 1))) {
349*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "%s: Malloc failure.\n", program_name);
350*7c478bd9Sstevel@tonic-gate 			exit(1);
351*7c478bd9Sstevel@tonic-gate 		}
352*7c478bd9Sstevel@tonic-gate 
353*7c478bd9Sstevel@tonic-gate 		__gen_dhkeys(public, secret, login_pw);
354*7c478bd9Sstevel@tonic-gate 
355*7c478bd9Sstevel@tonic-gate 		plist[0] = public;
356*7c478bd9Sstevel@tonic-gate 		slist[0] = secret;
357*7c478bd9Sstevel@tonic-gate 	}
358*7c478bd9Sstevel@tonic-gate }
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate /*
362*7c478bd9Sstevel@tonic-gate  * Make sure that the entered Secure-RPC password(s) match the login
363*7c478bd9Sstevel@tonic-gate  * password
364*7c478bd9Sstevel@tonic-gate  */
365*7c478bd9Sstevel@tonic-gate static void
366*7c478bd9Sstevel@tonic-gate cmp_passwd()
367*7c478bd9Sstevel@tonic-gate {
368*7c478bd9Sstevel@tonic-gate 	char	baseprompt[] = "Please enter the login password for";
369*7c478bd9Sstevel@tonic-gate 	char	prompt[BUFSIZ];
370*7c478bd9Sstevel@tonic-gate 	char	*en_login_pw = spw->sp_pwdp;
371*7c478bd9Sstevel@tonic-gate 	char	*try_en_login_pw;
372*7c478bd9Sstevel@tonic-gate 	bool_t	pwmatch = FALSE;
373*7c478bd9Sstevel@tonic-gate 	int	done = 0, tries = 0, pcount;
374*7c478bd9Sstevel@tonic-gate 
375*7c478bd9Sstevel@tonic-gate 	snprintf(prompt, BUFSIZ, "%s %s:", baseprompt, pw->pw_name);
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate 	if (en_login_pw && (strlen(en_login_pw) != 0)) {
378*7c478bd9Sstevel@tonic-gate 		for (pcount = 0; pcount < rpc_pw_count; pcount++) {
379*7c478bd9Sstevel@tonic-gate 			char	*try_en_rpc_pw;
380*7c478bd9Sstevel@tonic-gate 
381*7c478bd9Sstevel@tonic-gate 			try_en_rpc_pw = crypt(rpc_pws[pcount], en_login_pw);
382*7c478bd9Sstevel@tonic-gate 			if (strcmp(try_en_rpc_pw, en_login_pw) == 0) {
383*7c478bd9Sstevel@tonic-gate 				login_pw = rpc_pws[pcount];
384*7c478bd9Sstevel@tonic-gate 				pwmatch = TRUE;
385*7c478bd9Sstevel@tonic-gate 				break;
386*7c478bd9Sstevel@tonic-gate 			}
387*7c478bd9Sstevel@tonic-gate 		}
388*7c478bd9Sstevel@tonic-gate 		if (!pwmatch) {
389*7c478bd9Sstevel@tonic-gate 			/* pw don't match */
390*7c478bd9Sstevel@tonic-gate 			while (!done) {
391*7c478bd9Sstevel@tonic-gate 				/* ask for the pw */
392*7c478bd9Sstevel@tonic-gate 				login_pw = getpass(prompt);
393*7c478bd9Sstevel@tonic-gate 				if (login_pw && strlen(login_pw)) {
394*7c478bd9Sstevel@tonic-gate 					/* pw was not empty */
395*7c478bd9Sstevel@tonic-gate 					try_en_login_pw = crypt(login_pw,
396*7c478bd9Sstevel@tonic-gate 								en_login_pw);
397*7c478bd9Sstevel@tonic-gate 					/* compare the pw's */
398*7c478bd9Sstevel@tonic-gate 					if (!(strcmp(try_en_login_pw,
399*7c478bd9Sstevel@tonic-gate 							en_login_pw))) {
400*7c478bd9Sstevel@tonic-gate 						/* pw was correct */
401*7c478bd9Sstevel@tonic-gate 						return;
402*7c478bd9Sstevel@tonic-gate 					} else {
403*7c478bd9Sstevel@tonic-gate 						/* pw was wrong */
404*7c478bd9Sstevel@tonic-gate 						if (tries++) {
405*7c478bd9Sstevel@tonic-gate 							/* Sorry */
406*7c478bd9Sstevel@tonic-gate 							fprintf(stderr,
407*7c478bd9Sstevel@tonic-gate 								"Sorry.\n");
408*7c478bd9Sstevel@tonic-gate 							exit(1);
409*7c478bd9Sstevel@tonic-gate 						} else {
410*7c478bd9Sstevel@tonic-gate 							/* Try again */
411*7c478bd9Sstevel@tonic-gate 							snprintf(prompt,
412*7c478bd9Sstevel@tonic-gate 									BUFSIZ,
413*7c478bd9Sstevel@tonic-gate 							"Try again. %s %s:",
414*7c478bd9Sstevel@tonic-gate 								baseprompt,
415*7c478bd9Sstevel@tonic-gate 								pw->pw_name);
416*7c478bd9Sstevel@tonic-gate 						}
417*7c478bd9Sstevel@tonic-gate 					}
418*7c478bd9Sstevel@tonic-gate 				} else {
419*7c478bd9Sstevel@tonic-gate 					/* pw was empty */
420*7c478bd9Sstevel@tonic-gate 					if (tries++) {
421*7c478bd9Sstevel@tonic-gate 						/* Unchanged */
422*7c478bd9Sstevel@tonic-gate 						fprintf(stderr,
423*7c478bd9Sstevel@tonic-gate 					"%s: key-pair(s) unchanged for %s.\n",
424*7c478bd9Sstevel@tonic-gate 							program_name,
425*7c478bd9Sstevel@tonic-gate 							pw->pw_name);
426*7c478bd9Sstevel@tonic-gate 						exit(1);
427*7c478bd9Sstevel@tonic-gate 					} else {
428*7c478bd9Sstevel@tonic-gate 						/* Need a password */
429*7c478bd9Sstevel@tonic-gate 						snprintf(prompt, BUFSIZ,
430*7c478bd9Sstevel@tonic-gate 						"Need a password. %s %s:",
431*7c478bd9Sstevel@tonic-gate 								baseprompt,
432*7c478bd9Sstevel@tonic-gate 								pw->pw_name);
433*7c478bd9Sstevel@tonic-gate 					}
434*7c478bd9Sstevel@tonic-gate 				}
435*7c478bd9Sstevel@tonic-gate 			}
436*7c478bd9Sstevel@tonic-gate 		}
437*7c478bd9Sstevel@tonic-gate 		/* pw match */
438*7c478bd9Sstevel@tonic-gate 		return;
439*7c478bd9Sstevel@tonic-gate 	} else {
440*7c478bd9Sstevel@tonic-gate 		/* no pw found */
441*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
442*7c478bd9Sstevel@tonic-gate 		"%s: no passwd found for %s in the shadow passwd entry.\n",
443*7c478bd9Sstevel@tonic-gate 			program_name, pw->pw_name);
444*7c478bd9Sstevel@tonic-gate 		exit(1);
445*7c478bd9Sstevel@tonic-gate 	}
446*7c478bd9Sstevel@tonic-gate }
447*7c478bd9Sstevel@tonic-gate 
448*7c478bd9Sstevel@tonic-gate 
449*7c478bd9Sstevel@tonic-gate /* Prompt the user for a Secure-RPC password and store it in a cache. */
450*7c478bd9Sstevel@tonic-gate static void
451*7c478bd9Sstevel@tonic-gate getrpcpws(char *flavor)
452*7c478bd9Sstevel@tonic-gate {
453*7c478bd9Sstevel@tonic-gate 	char		*cur_pw = NULL;
454*7c478bd9Sstevel@tonic-gate 	char		prompt[BUFSIZ + 1];
455*7c478bd9Sstevel@tonic-gate 
456*7c478bd9Sstevel@tonic-gate 	if (flavor)
457*7c478bd9Sstevel@tonic-gate 		snprintf(prompt, BUFSIZ,
458*7c478bd9Sstevel@tonic-gate 			"Please enter the %s Secure-RPC password for %s:",
459*7c478bd9Sstevel@tonic-gate 			flavor, pw->pw_name);
460*7c478bd9Sstevel@tonic-gate 	else
461*7c478bd9Sstevel@tonic-gate 		snprintf(prompt, BUFSIZ,
462*7c478bd9Sstevel@tonic-gate 				"Please enter the Secure-RPC password for %s:",
463*7c478bd9Sstevel@tonic-gate 				pw->pw_name);
464*7c478bd9Sstevel@tonic-gate 
465*7c478bd9Sstevel@tonic-gate 	cur_pw = getpass(prompt);
466*7c478bd9Sstevel@tonic-gate 	if (!cur_pw) {
467*7c478bd9Sstevel@tonic-gate 		/* No changes */
468*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: key-pair(s) unchanged for %s.\n",
469*7c478bd9Sstevel@tonic-gate 			program_name, pw->pw_name);
470*7c478bd9Sstevel@tonic-gate 		exit(1);
471*7c478bd9Sstevel@tonic-gate 	}
472*7c478bd9Sstevel@tonic-gate 
473*7c478bd9Sstevel@tonic-gate 	rpc_pw_count++;
474*7c478bd9Sstevel@tonic-gate 	if (!(rpc_pws =
475*7c478bd9Sstevel@tonic-gate 		(char **)realloc(rpc_pws, sizeof (char *) * rpc_pw_count))) {
476*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: Realloc failure.\n", program_name);
477*7c478bd9Sstevel@tonic-gate 		exit(1);
478*7c478bd9Sstevel@tonic-gate 	}
479*7c478bd9Sstevel@tonic-gate rpc_pws[rpc_pw_count - 1] = cur_pw;
480*7c478bd9Sstevel@tonic-gate }
481*7c478bd9Sstevel@tonic-gate 
482*7c478bd9Sstevel@tonic-gate 
483*7c478bd9Sstevel@tonic-gate /* Retrieve the secret key(s) for the user and attempt to decrypt them */
484*7c478bd9Sstevel@tonic-gate static void
485*7c478bd9Sstevel@tonic-gate getsecrets()
486*7c478bd9Sstevel@tonic-gate {
487*7c478bd9Sstevel@tonic-gate 	int		mcount, scount = 0;
488*7c478bd9Sstevel@tonic-gate 	int		tries = 0;
489*7c478bd9Sstevel@tonic-gate 
490*7c478bd9Sstevel@tonic-gate 	getrpcpws(NULL);
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate 	if (mechs) {
493*7c478bd9Sstevel@tonic-gate 		for (mcount = 0; CURMECH; mcount++) {
494*7c478bd9Sstevel@tonic-gate 			char		*secret;
495*7c478bd9Sstevel@tonic-gate 			int		pcount;
496*7c478bd9Sstevel@tonic-gate 			size_t		hexkeylen;
497*7c478bd9Sstevel@tonic-gate 
498*7c478bd9Sstevel@tonic-gate 			hexkeylen = ((CURMECH->keylen / 8) * 2) + 1;
499*7c478bd9Sstevel@tonic-gate 			if (!(secret = (char *)calloc(hexkeylen,
500*7c478bd9Sstevel@tonic-gate 							sizeof (char)))) {
501*7c478bd9Sstevel@tonic-gate 				fprintf(stderr, "%s: Malloc failure.\n",
502*7c478bd9Sstevel@tonic-gate 					program_name);
503*7c478bd9Sstevel@tonic-gate 				exit(1);
504*7c478bd9Sstevel@tonic-gate 			}
505*7c478bd9Sstevel@tonic-gate 
506*7c478bd9Sstevel@tonic-gate 			for (pcount = 0; pcount < rpc_pw_count; pcount++) {
507*7c478bd9Sstevel@tonic-gate 				if (!getsecretkey_g(netname, CURMECH->keylen,
508*7c478bd9Sstevel@tonic-gate 						    CURMECH->algtype, secret,
509*7c478bd9Sstevel@tonic-gate 						    hexkeylen,
510*7c478bd9Sstevel@tonic-gate 						    rpc_pws[pcount]))
511*7c478bd9Sstevel@tonic-gate 					continue;
512*7c478bd9Sstevel@tonic-gate 
513*7c478bd9Sstevel@tonic-gate 				if (secret[0] == 0)
514*7c478bd9Sstevel@tonic-gate 					continue;
515*7c478bd9Sstevel@tonic-gate 				else
516*7c478bd9Sstevel@tonic-gate 					break;
517*7c478bd9Sstevel@tonic-gate 			}
518*7c478bd9Sstevel@tonic-gate 
519*7c478bd9Sstevel@tonic-gate 			tries = 0;
520*7c478bd9Sstevel@tonic-gate 		getsecrets_tryagain_g:
521*7c478bd9Sstevel@tonic-gate 			if (secret[0] == 0) {
522*7c478bd9Sstevel@tonic-gate 				if (!tries) {
523*7c478bd9Sstevel@tonic-gate 					/*
524*7c478bd9Sstevel@tonic-gate 					 * No existing pw can decrypt
525*7c478bd9Sstevel@tonic-gate 					 * secret key
526*7c478bd9Sstevel@tonic-gate 					 */
527*7c478bd9Sstevel@tonic-gate 					getrpcpws(CURMECH->alias);
528*7c478bd9Sstevel@tonic-gate 					if (!getsecretkey_g(netname,
529*7c478bd9Sstevel@tonic-gate 							    CURMECH->keylen,
530*7c478bd9Sstevel@tonic-gate 							    CURMECH->algtype,
531*7c478bd9Sstevel@tonic-gate 							    secret,
532*7c478bd9Sstevel@tonic-gate 							    hexkeylen,
533*7c478bd9Sstevel@tonic-gate 							    rpc_pws[pcount])) {
534*7c478bd9Sstevel@tonic-gate 						/*
535*7c478bd9Sstevel@tonic-gate 						 * Could not retreive
536*7c478bd9Sstevel@tonic-gate 						 * secret key, abort
537*7c478bd9Sstevel@tonic-gate 						 */
538*7c478bd9Sstevel@tonic-gate 						free(secret);
539*7c478bd9Sstevel@tonic-gate 						secret = NULL;
540*7c478bd9Sstevel@tonic-gate 						goto getsecrets_abort;
541*7c478bd9Sstevel@tonic-gate 					}
542*7c478bd9Sstevel@tonic-gate 
543*7c478bd9Sstevel@tonic-gate 					if (secret[0] == 0) {
544*7c478bd9Sstevel@tonic-gate 						/* Still no go, ask again */
545*7c478bd9Sstevel@tonic-gate 						free(rpc_pws[pcount]);
546*7c478bd9Sstevel@tonic-gate 						rpc_pw_count--;
547*7c478bd9Sstevel@tonic-gate 						tries++;
548*7c478bd9Sstevel@tonic-gate 						printf("Try again. ");
549*7c478bd9Sstevel@tonic-gate 						fflush(stdout);
550*7c478bd9Sstevel@tonic-gate 						goto getsecrets_tryagain_g;
551*7c478bd9Sstevel@tonic-gate 					} else
552*7c478bd9Sstevel@tonic-gate 						scount++;
553*7c478bd9Sstevel@tonic-gate 				} else {
554*7c478bd9Sstevel@tonic-gate 					fprintf(stderr,
555*7c478bd9Sstevel@tonic-gate 					"%s: key-pair unchanged for %s.\n",
556*7c478bd9Sstevel@tonic-gate 						program_name, pw->pw_name);
557*7c478bd9Sstevel@tonic-gate 					exit(1);
558*7c478bd9Sstevel@tonic-gate 				}
559*7c478bd9Sstevel@tonic-gate 			} else
560*7c478bd9Sstevel@tonic-gate 				scount++;
561*7c478bd9Sstevel@tonic-gate 
562*7c478bd9Sstevel@tonic-gate 		getsecrets_abort:
563*7c478bd9Sstevel@tonic-gate 			slist[mcount] = secret;
564*7c478bd9Sstevel@tonic-gate 		}
565*7c478bd9Sstevel@tonic-gate 	} else {
566*7c478bd9Sstevel@tonic-gate 		char		*secret = NULL;
567*7c478bd9Sstevel@tonic-gate 
568*7c478bd9Sstevel@tonic-gate 		if (!(secret = (char *)malloc(HEXKEYBYTES + 1))) {
569*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "%s: Malloc failure.\n", program_name);
570*7c478bd9Sstevel@tonic-gate 			exit(1);
571*7c478bd9Sstevel@tonic-gate 		}
572*7c478bd9Sstevel@tonic-gate 	getsecrets_tryagain:
573*7c478bd9Sstevel@tonic-gate 		if (!getsecretkey(netname, secret, rpc_pws[0])) {
574*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
575*7c478bd9Sstevel@tonic-gate 				"%s: could not get secret key for '%s'\n",
576*7c478bd9Sstevel@tonic-gate 				program_name, netname);
577*7c478bd9Sstevel@tonic-gate 			exit(1);
578*7c478bd9Sstevel@tonic-gate 		}
579*7c478bd9Sstevel@tonic-gate 
580*7c478bd9Sstevel@tonic-gate 		if (secret[0] == 0) {
581*7c478bd9Sstevel@tonic-gate 			if (!tries) {
582*7c478bd9Sstevel@tonic-gate 				free(rpc_pws[0]);
583*7c478bd9Sstevel@tonic-gate 				rpc_pw_count = 0;
584*7c478bd9Sstevel@tonic-gate 				tries++;
585*7c478bd9Sstevel@tonic-gate 				printf("Try again. ");
586*7c478bd9Sstevel@tonic-gate 				fflush(stdout);
587*7c478bd9Sstevel@tonic-gate 				getrpcpws(NULL);
588*7c478bd9Sstevel@tonic-gate 				goto getsecrets_tryagain;
589*7c478bd9Sstevel@tonic-gate 			} else {
590*7c478bd9Sstevel@tonic-gate 				fprintf(stderr,
591*7c478bd9Sstevel@tonic-gate 					"%s: key-pair unchanged for %s.\n",
592*7c478bd9Sstevel@tonic-gate 					program_name, pw->pw_name);
593*7c478bd9Sstevel@tonic-gate 				exit(1);
594*7c478bd9Sstevel@tonic-gate 			}
595*7c478bd9Sstevel@tonic-gate 		}
596*7c478bd9Sstevel@tonic-gate 
597*7c478bd9Sstevel@tonic-gate 		slist[0] = secret;
598*7c478bd9Sstevel@tonic-gate 		return;
599*7c478bd9Sstevel@tonic-gate 	}
600*7c478bd9Sstevel@tonic-gate 
601*7c478bd9Sstevel@tonic-gate 	if (!scount) {
602*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
603*7c478bd9Sstevel@tonic-gate 		"%s: could not get nor decrypt any secret keys for '%s'\n",
604*7c478bd9Sstevel@tonic-gate 					program_name, netname);
605*7c478bd9Sstevel@tonic-gate 		error_msg();
606*7c478bd9Sstevel@tonic-gate 		exit(1);
607*7c478bd9Sstevel@tonic-gate 	}
608*7c478bd9Sstevel@tonic-gate }
609*7c478bd9Sstevel@tonic-gate 
610*7c478bd9Sstevel@tonic-gate 
611*7c478bd9Sstevel@tonic-gate /* Register AUTH_DES secret key with keyserv */
612*7c478bd9Sstevel@tonic-gate static void
613*7c478bd9Sstevel@tonic-gate keylogin_des()
614*7c478bd9Sstevel@tonic-gate {
615*7c478bd9Sstevel@tonic-gate 	char			*secret = slist[0];
616*7c478bd9Sstevel@tonic-gate 	struct key_netstarg	netst;
617*7c478bd9Sstevel@tonic-gate 
618*7c478bd9Sstevel@tonic-gate 	/*
619*7c478bd9Sstevel@tonic-gate 	 * try to revoke the existing key/credentials, assuming
620*7c478bd9Sstevel@tonic-gate 	 * one exists.  this will effectively mark "stale" any
621*7c478bd9Sstevel@tonic-gate 	 * cached credientials...
622*7c478bd9Sstevel@tonic-gate 	 */
623*7c478bd9Sstevel@tonic-gate 	if (key_setsecret(secret) < 0) {
624*7c478bd9Sstevel@tonic-gate 		return;
625*7c478bd9Sstevel@tonic-gate 	}
626*7c478bd9Sstevel@tonic-gate 
627*7c478bd9Sstevel@tonic-gate #ifdef NFS_AUTH
628*7c478bd9Sstevel@tonic-gate 	/*
629*7c478bd9Sstevel@tonic-gate 	 * it looks like a credential already existed, so try and
630*7c478bd9Sstevel@tonic-gate 	 * revoke any lingering Secure-NFS privledges.
631*7c478bd9Sstevel@tonic-gate 	 */
632*7c478bd9Sstevel@tonic-gate 
633*7c478bd9Sstevel@tonic-gate 	nra.authtype = AUTH_DES;
634*7c478bd9Sstevel@tonic-gate 	nra.uid = getuid();
635*7c478bd9Sstevel@tonic-gate 
636*7c478bd9Sstevel@tonic-gate 	if (_nfssys(NFS_REVAUTH, &nra) < 0)
637*7c478bd9Sstevel@tonic-gate 		perror("Warning: NFS credentials not destroyed");
638*7c478bd9Sstevel@tonic-gate #endif /* NFS_AUTH */
639*7c478bd9Sstevel@tonic-gate 
640*7c478bd9Sstevel@tonic-gate 	memcpy(netst.st_priv_key, secret, HEXKEYBYTES);
641*7c478bd9Sstevel@tonic-gate 
642*7c478bd9Sstevel@tonic-gate 	netst.st_pub_key[0] = '\0';
643*7c478bd9Sstevel@tonic-gate 	netst.st_netname = strdup(netname);
644*7c478bd9Sstevel@tonic-gate 
645*7c478bd9Sstevel@tonic-gate 	/* do actual key login */
646*7c478bd9Sstevel@tonic-gate 	if (key_setnet(&netst) < 0) {
647*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Could not set %s's secret key\n", netname);
648*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "May be the keyserv is down?\n");
649*7c478bd9Sstevel@tonic-gate 	}
650*7c478bd9Sstevel@tonic-gate }
651*7c478bd9Sstevel@tonic-gate 
652*7c478bd9Sstevel@tonic-gate 
653*7c478bd9Sstevel@tonic-gate /* Register a secret key with the keyserv */
654*7c478bd9Sstevel@tonic-gate static void
655*7c478bd9Sstevel@tonic-gate keylogin(keylen_t keylen, algtype_t algtype)
656*7c478bd9Sstevel@tonic-gate {
657*7c478bd9Sstevel@tonic-gate 	int	mcount;
658*7c478bd9Sstevel@tonic-gate 
659*7c478bd9Sstevel@tonic-gate 	if (mechs) {
660*7c478bd9Sstevel@tonic-gate 		for (mcount = 0; CURMECH; mcount++) {
661*7c478bd9Sstevel@tonic-gate 			if (keylen == CURMECH->keylen &&
662*7c478bd9Sstevel@tonic-gate 			    algtype == CURMECH->algtype) {
663*7c478bd9Sstevel@tonic-gate 				if (key_setnet_g(netname, slist[mcount],
664*7c478bd9Sstevel@tonic-gate 							CURMECH->keylen,
665*7c478bd9Sstevel@tonic-gate 							NULL, 0,
666*7c478bd9Sstevel@tonic-gate 							CURMECH->algtype)
667*7c478bd9Sstevel@tonic-gate 				    < 0)
668*7c478bd9Sstevel@tonic-gate 					fprintf(stderr,
669*7c478bd9Sstevel@tonic-gate 					"Could not set %s's %s secret key\n",
670*7c478bd9Sstevel@tonic-gate 						netname,
671*7c478bd9Sstevel@tonic-gate 					VALID_ALIAS(CURMECH->alias) ?
672*7c478bd9Sstevel@tonic-gate 						CURMECH->alias : "");
673*7c478bd9Sstevel@tonic-gate 			}
674*7c478bd9Sstevel@tonic-gate 		}
675*7c478bd9Sstevel@tonic-gate 	} else {
676*7c478bd9Sstevel@tonic-gate 		if (keylen == 192 && algtype == 0)
677*7c478bd9Sstevel@tonic-gate 			keylogin_des();
678*7c478bd9Sstevel@tonic-gate 	}
679*7c478bd9Sstevel@tonic-gate }
680*7c478bd9Sstevel@tonic-gate 
681*7c478bd9Sstevel@tonic-gate 
682*7c478bd9Sstevel@tonic-gate /*
683*7c478bd9Sstevel@tonic-gate  * fgets is "broken" in that if it reads a NUL character it will
684*7c478bd9Sstevel@tonic-gate  * always return EOF for all reads, even when there is data left in
685*7c478bd9Sstevel@tonic-gate  * the file.  This replacement can deal with NUL's in a calm, rational
686*7c478bd9Sstevel@tonic-gate  * manner.
687*7c478bd9Sstevel@tonic-gate  */
688*7c478bd9Sstevel@tonic-gate static char *
689*7c478bd9Sstevel@tonic-gate fgets_ignorenul(char *s, int n, FILE *stream)
690*7c478bd9Sstevel@tonic-gate {
691*7c478bd9Sstevel@tonic-gate 	int fildes = fileno(stream);
692*7c478bd9Sstevel@tonic-gate 	int i = 0;
693*7c478bd9Sstevel@tonic-gate 	int rs = 0;
694*7c478bd9Sstevel@tonic-gate 	char c;
695*7c478bd9Sstevel@tonic-gate 
696*7c478bd9Sstevel@tonic-gate 	if (fildes < 0)
697*7c478bd9Sstevel@tonic-gate 		return (NULL);
698*7c478bd9Sstevel@tonic-gate 
699*7c478bd9Sstevel@tonic-gate 	while (i < n - 1) {
700*7c478bd9Sstevel@tonic-gate 		rs = read(fildes, &c, 1);
701*7c478bd9Sstevel@tonic-gate 		switch (rs) {
702*7c478bd9Sstevel@tonic-gate 		case 1:
703*7c478bd9Sstevel@tonic-gate 			break;
704*7c478bd9Sstevel@tonic-gate 		case 0:
705*7c478bd9Sstevel@tonic-gate 			/* EOF */
706*7c478bd9Sstevel@tonic-gate 			if (i > 0)
707*7c478bd9Sstevel@tonic-gate 				s[i] = '\0';
708*7c478bd9Sstevel@tonic-gate 			return (NULL);
709*7c478bd9Sstevel@tonic-gate 			break;
710*7c478bd9Sstevel@tonic-gate 		default:
711*7c478bd9Sstevel@tonic-gate 			return (NULL);
712*7c478bd9Sstevel@tonic-gate 		}
713*7c478bd9Sstevel@tonic-gate 		switch (c) {
714*7c478bd9Sstevel@tonic-gate 		case '\0':
715*7c478bd9Sstevel@tonic-gate 			break;
716*7c478bd9Sstevel@tonic-gate 		case '\n':
717*7c478bd9Sstevel@tonic-gate 			s[i] = c;
718*7c478bd9Sstevel@tonic-gate 			s[++i] = '\0';
719*7c478bd9Sstevel@tonic-gate 			return (s);
720*7c478bd9Sstevel@tonic-gate 		default:
721*7c478bd9Sstevel@tonic-gate 		if (c != '\0')
722*7c478bd9Sstevel@tonic-gate 			s[i++] = c;
723*7c478bd9Sstevel@tonic-gate 		}
724*7c478bd9Sstevel@tonic-gate 	}
725*7c478bd9Sstevel@tonic-gate 	s[i] = '\0';
726*7c478bd9Sstevel@tonic-gate 	return (s);
727*7c478bd9Sstevel@tonic-gate }
728*7c478bd9Sstevel@tonic-gate 
729*7c478bd9Sstevel@tonic-gate 
730*7c478bd9Sstevel@tonic-gate /* Write unencrypted secret key into root key file */
731*7c478bd9Sstevel@tonic-gate static void
732*7c478bd9Sstevel@tonic-gate write_rootkey(char *secret, char *flavor, keylen_t keylen, algtype_t algtype)
733*7c478bd9Sstevel@tonic-gate {
734*7c478bd9Sstevel@tonic-gate 	char		line[MAXROOTKEY_LINE_LEN];
735*7c478bd9Sstevel@tonic-gate 	char		keyent[MAXROOTKEY_LEN];
736*7c478bd9Sstevel@tonic-gate 	algtype_t	atent;
737*7c478bd9Sstevel@tonic-gate 	int		rootfd, bakfd, hexkeybytes;
738*7c478bd9Sstevel@tonic-gate 	bool_t		lineone = TRUE;
739*7c478bd9Sstevel@tonic-gate 	bool_t		gotit = FALSE;
740*7c478bd9Sstevel@tonic-gate 	FILE		*rootfile, *bakfile;
741*7c478bd9Sstevel@tonic-gate 
742*7c478bd9Sstevel@tonic-gate 	unlink(ROOTKEY_FILE_BACKUP);
743*7c478bd9Sstevel@tonic-gate 	if ((rename(ROOTKEY_FILE, ROOTKEY_FILE_BACKUP)) < 0) {
744*7c478bd9Sstevel@tonic-gate 		if ((bakfd = creat(ROOTKEY_FILE_BACKUP, 0600)) < 0) {
745*7c478bd9Sstevel@tonic-gate 			perror("Could not create /etc/.rootkey.bak");
746*7c478bd9Sstevel@tonic-gate 			goto rootkey_err;
747*7c478bd9Sstevel@tonic-gate 		}
748*7c478bd9Sstevel@tonic-gate 		close(bakfd);
749*7c478bd9Sstevel@tonic-gate 	}
750*7c478bd9Sstevel@tonic-gate 
751*7c478bd9Sstevel@tonic-gate 	if ((rootfd = open(ROOTKEY_FILE, O_WRONLY+O_CREAT, 0600)) < 0) {
752*7c478bd9Sstevel@tonic-gate 		perror("Could not open /etc/.rootkey for writing");
753*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
754*7c478bd9Sstevel@tonic-gate 			"Attempting to restore original /etc/.rootkey\n");
755*7c478bd9Sstevel@tonic-gate 		rename(ROOTKEY_FILE_BACKUP, ROOTKEY_FILE);
756*7c478bd9Sstevel@tonic-gate 		goto rootkey_err;
757*7c478bd9Sstevel@tonic-gate 	}
758*7c478bd9Sstevel@tonic-gate 	if (!(rootfile = fdopen(rootfd, "w"))) {
759*7c478bd9Sstevel@tonic-gate 		perror("Could not open /etc/.rootkey for writing");
760*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
761*7c478bd9Sstevel@tonic-gate 			"Attempting to restore original /etc/.rootkey\n");
762*7c478bd9Sstevel@tonic-gate 		close(rootfd);
763*7c478bd9Sstevel@tonic-gate 		unlink(ROOTKEY_FILE);
764*7c478bd9Sstevel@tonic-gate 		rename(ROOTKEY_FILE_BACKUP, ROOTKEY_FILE);
765*7c478bd9Sstevel@tonic-gate 		goto rootkey_err;
766*7c478bd9Sstevel@tonic-gate 	}
767*7c478bd9Sstevel@tonic-gate 	if (!(bakfile = fopen(ROOTKEY_FILE_BACKUP, "r"))) {
768*7c478bd9Sstevel@tonic-gate 		perror("Could not open /etc/.rootkey.bak for reading");
769*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
770*7c478bd9Sstevel@tonic-gate 			"Attempting to restore original /etc/.rootkey\n");
771*7c478bd9Sstevel@tonic-gate 		fclose(rootfile);
772*7c478bd9Sstevel@tonic-gate 		unlink(ROOTKEY_FILE);
773*7c478bd9Sstevel@tonic-gate 		rename(ROOTKEY_FILE_BACKUP, ROOTKEY_FILE);
774*7c478bd9Sstevel@tonic-gate 		goto rootkey_err;
775*7c478bd9Sstevel@tonic-gate 	}
776*7c478bd9Sstevel@tonic-gate 
777*7c478bd9Sstevel@tonic-gate 	hexkeybytes = ((keylen + 7) / 8) * 2;
778*7c478bd9Sstevel@tonic-gate 
779*7c478bd9Sstevel@tonic-gate 	while (fgets_ignorenul(line, MAXROOTKEY_LINE_LEN, bakfile)) {
780*7c478bd9Sstevel@tonic-gate 		sscanf(line, "%s %d", keyent, &atent);
781*7c478bd9Sstevel@tonic-gate 		/*
782*7c478bd9Sstevel@tonic-gate 		 * 192-bit keys always go on the first line
783*7c478bd9Sstevel@tonic-gate 		 */
784*7c478bd9Sstevel@tonic-gate 		if (lineone) {
785*7c478bd9Sstevel@tonic-gate 			lineone = FALSE;
786*7c478bd9Sstevel@tonic-gate 			if (keylen == 192) {
787*7c478bd9Sstevel@tonic-gate 				gotit = TRUE;
788*7c478bd9Sstevel@tonic-gate 				fprintf(rootfile, "%s\n", secret);
789*7c478bd9Sstevel@tonic-gate 			} else
790*7c478bd9Sstevel@tonic-gate 				fprintf(rootfile, "%s", line);
791*7c478bd9Sstevel@tonic-gate 			fflush(rootfile);
792*7c478bd9Sstevel@tonic-gate 		} else {
793*7c478bd9Sstevel@tonic-gate 			if ((strlen(keyent) == hexkeybytes) &&
794*7c478bd9Sstevel@tonic-gate 			    (atent == algtype)) {
795*7c478bd9Sstevel@tonic-gate 				/*
796*7c478bd9Sstevel@tonic-gate 				 * Silently remove lines with the same
797*7c478bd9Sstevel@tonic-gate 				 * keylen/algtype
798*7c478bd9Sstevel@tonic-gate 				 */
799*7c478bd9Sstevel@tonic-gate 				if (gotit)
800*7c478bd9Sstevel@tonic-gate 					continue;
801*7c478bd9Sstevel@tonic-gate 				else
802*7c478bd9Sstevel@tonic-gate 					gotit = TRUE;
803*7c478bd9Sstevel@tonic-gate 
804*7c478bd9Sstevel@tonic-gate 				fprintf(rootfile, "%s %d\n", secret, algtype);
805*7c478bd9Sstevel@tonic-gate 			} else
806*7c478bd9Sstevel@tonic-gate 				fprintf(rootfile, "%s", line);
807*7c478bd9Sstevel@tonic-gate 			fflush(rootfile);
808*7c478bd9Sstevel@tonic-gate 		}
809*7c478bd9Sstevel@tonic-gate 	}
810*7c478bd9Sstevel@tonic-gate 
811*7c478bd9Sstevel@tonic-gate 	/* Append key to rootkey file */
812*7c478bd9Sstevel@tonic-gate 	if (!gotit) {
813*7c478bd9Sstevel@tonic-gate 		if (keylen == 192)
814*7c478bd9Sstevel@tonic-gate 			fprintf(rootfile, "%s\n", secret);
815*7c478bd9Sstevel@tonic-gate 		else {
816*7c478bd9Sstevel@tonic-gate 			if (lineone)
817*7c478bd9Sstevel@tonic-gate 				fprintf(rootfile, "\n");
818*7c478bd9Sstevel@tonic-gate 			fprintf(rootfile, "%s %d\n", secret, algtype);
819*7c478bd9Sstevel@tonic-gate 		}
820*7c478bd9Sstevel@tonic-gate 	}
821*7c478bd9Sstevel@tonic-gate 	fflush(rootfile);
822*7c478bd9Sstevel@tonic-gate 	fclose(rootfile);
823*7c478bd9Sstevel@tonic-gate 	fclose(bakfile);
824*7c478bd9Sstevel@tonic-gate 	unlink(ROOTKEY_FILE_BACKUP);
825*7c478bd9Sstevel@tonic-gate 	return;
826*7c478bd9Sstevel@tonic-gate 
827*7c478bd9Sstevel@tonic-gate rootkey_err:
828*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "WARNING: Could not write %s key to /etc/.rootkey\n",
829*7c478bd9Sstevel@tonic-gate 		flavor);
830*7c478bd9Sstevel@tonic-gate }
831*7c478bd9Sstevel@tonic-gate 
832*7c478bd9Sstevel@tonic-gate 
833*7c478bd9Sstevel@tonic-gate /* Returns 0 if check fails; 1 if successful. */
834*7c478bd9Sstevel@tonic-gate static int
835*7c478bd9Sstevel@tonic-gate sanity_checks(char *nis_princ, char *domain, char *authtype)
836*7c478bd9Sstevel@tonic-gate {
837*7c478bd9Sstevel@tonic-gate 	char	netdomainaux[MAXHOSTNAMELEN+1];
838*7c478bd9Sstevel@tonic-gate 	char	*princdomain, *netdomain;
839*7c478bd9Sstevel@tonic-gate 	int	len;
840*7c478bd9Sstevel@tonic-gate 
841*7c478bd9Sstevel@tonic-gate 	/* Sanity check 0. Do we have a nis+ principal name to work with? */
842*7c478bd9Sstevel@tonic-gate 	if (nis_princ == NULL) {
843*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
844*7c478bd9Sstevel@tonic-gate 		"%s: you must create a \"LOCAL\" credential for '%s' first.\n",
845*7c478bd9Sstevel@tonic-gate 			program_name, netname);
846*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "\tSee nisaddcred(1).\n");
847*7c478bd9Sstevel@tonic-gate 		return (0);
848*7c478bd9Sstevel@tonic-gate 	}
849*7c478bd9Sstevel@tonic-gate 
850*7c478bd9Sstevel@tonic-gate 	/* Sanity check 0.5.  NIS+ principal names must be dotted. */
851*7c478bd9Sstevel@tonic-gate 	len = strlen(nis_princ);
852*7c478bd9Sstevel@tonic-gate 	if (nis_princ[len-1] != '.') {
853*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
854*7c478bd9Sstevel@tonic-gate 		"%s: invalid principal name: '%s' (forgot ending dot?).\n",
855*7c478bd9Sstevel@tonic-gate 			program_name, nis_princ);
856*7c478bd9Sstevel@tonic-gate 		return (0);
857*7c478bd9Sstevel@tonic-gate 	}
858*7c478bd9Sstevel@tonic-gate 
859*7c478bd9Sstevel@tonic-gate 	/* Sanity check 1.  We only deal with one type of netnames. */
860*7c478bd9Sstevel@tonic-gate 	if (strncmp(netname, "unix", 4) != 0) {
861*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
862*7c478bd9Sstevel@tonic-gate 			"%s: unrecognized netname type: '%s'.\n",
863*7c478bd9Sstevel@tonic-gate 			program_name, netname);
864*7c478bd9Sstevel@tonic-gate 		return (0);
865*7c478bd9Sstevel@tonic-gate 	}
866*7c478bd9Sstevel@tonic-gate 
867*7c478bd9Sstevel@tonic-gate 	/* Sanity check 2.  Should only add DES cred in home domain. */
868*7c478bd9Sstevel@tonic-gate 	princdomain = nis_domain_of(nis_princ);
869*7c478bd9Sstevel@tonic-gate 	if (strcasecmp(princdomain, domain) != 0) {
870*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
871*7c478bd9Sstevel@tonic-gate "%s: domain of principal '%s' does not match destination domain '%s'.\n",
872*7c478bd9Sstevel@tonic-gate 			program_name, nis_princ, domain);
873*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
874*7c478bd9Sstevel@tonic-gate 	"Should only add DES credential of principal in its home domain\n");
875*7c478bd9Sstevel@tonic-gate 		return (0);
876*7c478bd9Sstevel@tonic-gate 	}
877*7c478bd9Sstevel@tonic-gate 
878*7c478bd9Sstevel@tonic-gate 	/*
879*7c478bd9Sstevel@tonic-gate 	 * Sanity check 3:  Make sure netname's domain same as principal's
880*7c478bd9Sstevel@tonic-gate 	 * and don't have extraneous dot at the end.
881*7c478bd9Sstevel@tonic-gate 	 */
882*7c478bd9Sstevel@tonic-gate 	netdomain = (char *)strchr(netname, '@');
883*7c478bd9Sstevel@tonic-gate 	if (! netdomain || netname[strlen(netname)-1] == '.') {
884*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: invalid netname: '%s'. \n",
885*7c478bd9Sstevel@tonic-gate 			program_name, netname);
886*7c478bd9Sstevel@tonic-gate 		return (0);
887*7c478bd9Sstevel@tonic-gate 	}
888*7c478bd9Sstevel@tonic-gate 	netdomain++; /* skip '@' */
889*7c478bd9Sstevel@tonic-gate 
890*7c478bd9Sstevel@tonic-gate 	if (strlcpy(netdomainaux, netdomain, sizeof (netdomainaux)) >=
891*7c478bd9Sstevel@tonic-gate 	    sizeof (netdomainaux)) {
892*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: net domain name %s is too long\n",
893*7c478bd9Sstevel@tonic-gate 			    program_name, netdomain);
894*7c478bd9Sstevel@tonic-gate 		return (0);
895*7c478bd9Sstevel@tonic-gate 	}
896*7c478bd9Sstevel@tonic-gate 
897*7c478bd9Sstevel@tonic-gate 	if (netdomainaux[strlen(netdomainaux) - 1] != '.') {
898*7c478bd9Sstevel@tonic-gate 		if (strlcat(netdomainaux, ".", sizeof (netdomainaux)) >=
899*7c478bd9Sstevel@tonic-gate 		    sizeof (netdomainaux)) {
900*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
901*7c478bd9Sstevel@tonic-gate 				    "%s: net domain name %s is too long\n",
902*7c478bd9Sstevel@tonic-gate 				    program_name, netdomainaux);
903*7c478bd9Sstevel@tonic-gate 			return (0);
904*7c478bd9Sstevel@tonic-gate 		}
905*7c478bd9Sstevel@tonic-gate 	}
906*7c478bd9Sstevel@tonic-gate 
907*7c478bd9Sstevel@tonic-gate 	if (strcasecmp(princdomain, netdomainaux) != 0) {
908*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
909*7c478bd9Sstevel@tonic-gate 	"%s: domain of netname %s should be same as that of principal %s\n",
910*7c478bd9Sstevel@tonic-gate 			program_name, netname, nis_princ);
911*7c478bd9Sstevel@tonic-gate 		return (0);
912*7c478bd9Sstevel@tonic-gate 	}
913*7c478bd9Sstevel@tonic-gate 
914*7c478bd9Sstevel@tonic-gate 	/* Another principal owns same credentials? (exits if that happens) */
915*7c478bd9Sstevel@tonic-gate 	(void) auth_exists(nis_princ, netname, authtype, domain);
916*7c478bd9Sstevel@tonic-gate 
917*7c478bd9Sstevel@tonic-gate 	return (1); /* all passed */
918*7c478bd9Sstevel@tonic-gate }
919*7c478bd9Sstevel@tonic-gate 
920*7c478bd9Sstevel@tonic-gate 
921*7c478bd9Sstevel@tonic-gate /* Store new key information in the specified name service */
922*7c478bd9Sstevel@tonic-gate static void
923*7c478bd9Sstevel@tonic-gate storekeys()
924*7c478bd9Sstevel@tonic-gate {
925*7c478bd9Sstevel@tonic-gate 	int		mcount, ucount = 0;
926*7c478bd9Sstevel@tonic-gate 	char		*ypmaster, *ypdomain = NULL, pkent[MAXPKENTLEN];
927*7c478bd9Sstevel@tonic-gate 	nis_name	nis_princ;
928*7c478bd9Sstevel@tonic-gate 
929*7c478bd9Sstevel@tonic-gate 
930*7c478bd9Sstevel@tonic-gate 	/* Setup */
931*7c478bd9Sstevel@tonic-gate 	switch (dest_service) {
932*7c478bd9Sstevel@tonic-gate 	case PK_LDAP:
933*7c478bd9Sstevel@tonic-gate 		break;
934*7c478bd9Sstevel@tonic-gate 	case PK_NISPLUS:
935*7c478bd9Sstevel@tonic-gate 		nis_princ = get_nisplus_principal(nis_local_directory(),
936*7c478bd9Sstevel@tonic-gate 							geteuid());
937*7c478bd9Sstevel@tonic-gate 		break;
938*7c478bd9Sstevel@tonic-gate 	case PK_YP:
939*7c478bd9Sstevel@tonic-gate 		yp_get_default_domain(&ypdomain);
940*7c478bd9Sstevel@tonic-gate 		if (yp_master(ypdomain, PKMAP, &ypmaster) != 0) {
941*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
942*7c478bd9Sstevel@tonic-gate 			"%s: cannot find master of NIS publickey database\n",
943*7c478bd9Sstevel@tonic-gate 				program_name);
944*7c478bd9Sstevel@tonic-gate 			exit(1);
945*7c478bd9Sstevel@tonic-gate 		}
946*7c478bd9Sstevel@tonic-gate 		fprintf(stdout,
947*7c478bd9Sstevel@tonic-gate 			"Sending key change request to %s ...\n", ypmaster);
948*7c478bd9Sstevel@tonic-gate 		break;
949*7c478bd9Sstevel@tonic-gate 	case PK_FILES:
950*7c478bd9Sstevel@tonic-gate 		if (geteuid() != 0) {
951*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
952*7c478bd9Sstevel@tonic-gate 		"%s: non-root users cannot change their key-pair in %s\n",
953*7c478bd9Sstevel@tonic-gate 				program_name, PKFILE);
954*7c478bd9Sstevel@tonic-gate 			exit(1);
955*7c478bd9Sstevel@tonic-gate 		}
956*7c478bd9Sstevel@tonic-gate 		break;
957*7c478bd9Sstevel@tonic-gate 	default:
958*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
959*7c478bd9Sstevel@tonic-gate 			"could not update; database %d unknown\n",
960*7c478bd9Sstevel@tonic-gate 			dest_service);
961*7c478bd9Sstevel@tonic-gate 		exit(1);
962*7c478bd9Sstevel@tonic-gate 	}
963*7c478bd9Sstevel@tonic-gate 
964*7c478bd9Sstevel@tonic-gate 	if (mechs) {
965*7c478bd9Sstevel@tonic-gate 		for (mcount = 0; CURMECH; mcount++) {
966*7c478bd9Sstevel@tonic-gate 			char		authtype[MECH_MAXATNAME];
967*7c478bd9Sstevel@tonic-gate 
968*7c478bd9Sstevel@tonic-gate 			if (!plist[mcount] && !clist[mcount])
969*7c478bd9Sstevel@tonic-gate 				continue;
970*7c478bd9Sstevel@tonic-gate 
971*7c478bd9Sstevel@tonic-gate 			__nis_mechalias2authtype(CURMECH->alias, authtype,
972*7c478bd9Sstevel@tonic-gate 							MECH_MAXATNAME);
973*7c478bd9Sstevel@tonic-gate 			if (!authtype) {
974*7c478bd9Sstevel@tonic-gate 				fprintf(stderr,
975*7c478bd9Sstevel@tonic-gate 				"Could not generate auth_type for %s.\n",
976*7c478bd9Sstevel@tonic-gate 					CURMECH->alias);
977*7c478bd9Sstevel@tonic-gate 				continue;
978*7c478bd9Sstevel@tonic-gate 			}
979*7c478bd9Sstevel@tonic-gate 
980*7c478bd9Sstevel@tonic-gate 			snprintf(pkent, MAXPKENTLEN, "%s:%s:%d",
981*7c478bd9Sstevel@tonic-gate 					plist[mcount], clist[mcount],
982*7c478bd9Sstevel@tonic-gate 					CURMECH->algtype);
983*7c478bd9Sstevel@tonic-gate 
984*7c478bd9Sstevel@tonic-gate 			switch (dest_service) {
985*7c478bd9Sstevel@tonic-gate 			case PK_LDAP:
986*7c478bd9Sstevel@tonic-gate 				if (ldap_update(CURMECH->alias, netname,
987*7c478bd9Sstevel@tonic-gate 						plist[mcount], clist[mcount],
988*7c478bd9Sstevel@tonic-gate 						login_pw))
989*7c478bd9Sstevel@tonic-gate 					fprintf(stderr,
990*7c478bd9Sstevel@tonic-gate 			"%s: unable to update %s key in LDAP database\n",
991*7c478bd9Sstevel@tonic-gate 						program_name, authtype);
992*7c478bd9Sstevel@tonic-gate 				else
993*7c478bd9Sstevel@tonic-gate 					ucount++;
994*7c478bd9Sstevel@tonic-gate 				break;
995*7c478bd9Sstevel@tonic-gate 
996*7c478bd9Sstevel@tonic-gate 			case PK_NISPLUS:
997*7c478bd9Sstevel@tonic-gate 				if (nisplus_update(nis_princ,
998*7c478bd9Sstevel@tonic-gate 							authtype,
999*7c478bd9Sstevel@tonic-gate 							plist[mcount],
1000*7c478bd9Sstevel@tonic-gate 							clist[mcount]))
1001*7c478bd9Sstevel@tonic-gate 					fprintf(stderr,
1002*7c478bd9Sstevel@tonic-gate 			"%s: unable to update %s key in nisplus database\n",
1003*7c478bd9Sstevel@tonic-gate 						program_name, authtype);
1004*7c478bd9Sstevel@tonic-gate 				else
1005*7c478bd9Sstevel@tonic-gate 					ucount++;
1006*7c478bd9Sstevel@tonic-gate 				break;
1007*7c478bd9Sstevel@tonic-gate 
1008*7c478bd9Sstevel@tonic-gate 			case PK_YP:
1009*7c478bd9Sstevel@tonic-gate 				/* Should never get here. */
1010*7c478bd9Sstevel@tonic-gate 				break;
1011*7c478bd9Sstevel@tonic-gate 
1012*7c478bd9Sstevel@tonic-gate 			case PK_FILES:
1013*7c478bd9Sstevel@tonic-gate 				/* Should never get here. */
1014*7c478bd9Sstevel@tonic-gate 				break;
1015*7c478bd9Sstevel@tonic-gate 			}
1016*7c478bd9Sstevel@tonic-gate 		}
1017*7c478bd9Sstevel@tonic-gate 	} else {
1018*7c478bd9Sstevel@tonic-gate 		int	status = 0;
1019*7c478bd9Sstevel@tonic-gate 
1020*7c478bd9Sstevel@tonic-gate 		assert(plist[0] && clist[0]);
1021*7c478bd9Sstevel@tonic-gate 		snprintf(pkent, MAXPKENTLEN, "%s:%s", plist[0], clist[0]);
1022*7c478bd9Sstevel@tonic-gate 
1023*7c478bd9Sstevel@tonic-gate 		switch (dest_service) {
1024*7c478bd9Sstevel@tonic-gate 		case PK_LDAP:
1025*7c478bd9Sstevel@tonic-gate 			if (ldap_update("dh192-0", netname,
1026*7c478bd9Sstevel@tonic-gate 					plist[0], clist[0],
1027*7c478bd9Sstevel@tonic-gate 					login_pw)) {
1028*7c478bd9Sstevel@tonic-gate 				fprintf(stderr,
1029*7c478bd9Sstevel@tonic-gate 			"%s: unable to update %s key in LDAP database\n",
1030*7c478bd9Sstevel@tonic-gate 					program_name);
1031*7c478bd9Sstevel@tonic-gate 				exit(1);
1032*7c478bd9Sstevel@tonic-gate 			}
1033*7c478bd9Sstevel@tonic-gate 			break;
1034*7c478bd9Sstevel@tonic-gate 
1035*7c478bd9Sstevel@tonic-gate 		case PK_NISPLUS:
1036*7c478bd9Sstevel@tonic-gate 			assert(plist[0] && clist[0]);
1037*7c478bd9Sstevel@tonic-gate 			if (nisplus_update(nis_princ,
1038*7c478bd9Sstevel@tonic-gate 						AUTH_DES_AUTH_TYPE,
1039*7c478bd9Sstevel@tonic-gate 						plist[0],
1040*7c478bd9Sstevel@tonic-gate 						clist[0])) {
1041*7c478bd9Sstevel@tonic-gate 					fprintf(stderr,
1042*7c478bd9Sstevel@tonic-gate 			"%s: unable to update nisplus database\n",
1043*7c478bd9Sstevel@tonic-gate 						program_name);
1044*7c478bd9Sstevel@tonic-gate 					exit(1);
1045*7c478bd9Sstevel@tonic-gate 			}
1046*7c478bd9Sstevel@tonic-gate 			break;
1047*7c478bd9Sstevel@tonic-gate 
1048*7c478bd9Sstevel@tonic-gate 		case PK_YP:
1049*7c478bd9Sstevel@tonic-gate 			if (status = yp_update(ypdomain, PKMAP,
1050*7c478bd9Sstevel@tonic-gate 						YPOP_STORE, netname,
1051*7c478bd9Sstevel@tonic-gate 						strlen(netname), pkent,
1052*7c478bd9Sstevel@tonic-gate 						strlen(pkent))) {
1053*7c478bd9Sstevel@tonic-gate 				fprintf(stderr,
1054*7c478bd9Sstevel@tonic-gate 				"%s: unable to update NIS database (%u): %s\n",
1055*7c478bd9Sstevel@tonic-gate 					program_name, status,
1056*7c478bd9Sstevel@tonic-gate 					yperr_string(status));
1057*7c478bd9Sstevel@tonic-gate 				exit(1);
1058*7c478bd9Sstevel@tonic-gate 			}
1059*7c478bd9Sstevel@tonic-gate 			break;
1060*7c478bd9Sstevel@tonic-gate 
1061*7c478bd9Sstevel@tonic-gate 		case PK_FILES:
1062*7c478bd9Sstevel@tonic-gate 			if (localupdate(netname, PKFILE, YPOP_STORE, pkent)) {
1063*7c478bd9Sstevel@tonic-gate 				fprintf(stderr,
1064*7c478bd9Sstevel@tonic-gate 			"%s: hence, unable to update publickey database\n",
1065*7c478bd9Sstevel@tonic-gate 					program_name);
1066*7c478bd9Sstevel@tonic-gate 				exit(1);
1067*7c478bd9Sstevel@tonic-gate 			}
1068*7c478bd9Sstevel@tonic-gate 			break;
1069*7c478bd9Sstevel@tonic-gate 
1070*7c478bd9Sstevel@tonic-gate 		default:
1071*7c478bd9Sstevel@tonic-gate 			/* Should never get here */
1072*7c478bd9Sstevel@tonic-gate 			assert(0);
1073*7c478bd9Sstevel@tonic-gate 		}
1074*7c478bd9Sstevel@tonic-gate 		return;
1075*7c478bd9Sstevel@tonic-gate 	}
1076*7c478bd9Sstevel@tonic-gate 	if (!ucount) {
1077*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: unable to update any key-pairs for %s.\n",
1078*7c478bd9Sstevel@tonic-gate 			program_name, pw->pw_name);
1079*7c478bd9Sstevel@tonic-gate 		exit(1);
1080*7c478bd9Sstevel@tonic-gate 	}
1081*7c478bd9Sstevel@tonic-gate }
1082*7c478bd9Sstevel@tonic-gate 
1083*7c478bd9Sstevel@tonic-gate /* Check that someone else don't have the same auth information already */
1084*7c478bd9Sstevel@tonic-gate static
1085*7c478bd9Sstevel@tonic-gate nis_error
1086*7c478bd9Sstevel@tonic-gate auth_exists(char *princname, char *auth_name, char *auth_type, char *domain)
1087*7c478bd9Sstevel@tonic-gate {
1088*7c478bd9Sstevel@tonic-gate 	char sname[NIS_MAXNAMELEN+1];
1089*7c478bd9Sstevel@tonic-gate 	nis_result	*res;
1090*7c478bd9Sstevel@tonic-gate 	nis_error status;
1091*7c478bd9Sstevel@tonic-gate 	char *foundprinc;
1092*7c478bd9Sstevel@tonic-gate 
1093*7c478bd9Sstevel@tonic-gate 	(void) sprintf(sname, "[auth_name=%s,auth_type=%s],%s.%s",
1094*7c478bd9Sstevel@tonic-gate 		auth_name, auth_type, CRED_TABLE, domain);
1095*7c478bd9Sstevel@tonic-gate 	if (sname[strlen(sname)-1] != '.')
1096*7c478bd9Sstevel@tonic-gate 		strcat(sname, ".");
1097*7c478bd9Sstevel@tonic-gate 	/* Don't want FOLLOW_PATH here */
1098*7c478bd9Sstevel@tonic-gate 	res = nis_list(sname,
1099*7c478bd9Sstevel@tonic-gate 		MASTER_ONLY+USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS,
1100*7c478bd9Sstevel@tonic-gate 		NULL, NULL);
1101*7c478bd9Sstevel@tonic-gate 
1102*7c478bd9Sstevel@tonic-gate 	status = res->status;
1103*7c478bd9Sstevel@tonic-gate 	switch (res->status) {
1104*7c478bd9Sstevel@tonic-gate 	case NIS_NOTFOUND:
1105*7c478bd9Sstevel@tonic-gate 		break;
1106*7c478bd9Sstevel@tonic-gate 	case NIS_TRYAGAIN:
1107*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1108*7c478bd9Sstevel@tonic-gate 			"%s: NIS+ server busy, try again later.\n",
1109*7c478bd9Sstevel@tonic-gate 			program_name);
1110*7c478bd9Sstevel@tonic-gate 		exit(1);
1111*7c478bd9Sstevel@tonic-gate 		break;
1112*7c478bd9Sstevel@tonic-gate 	case NIS_PERMISSION:
1113*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1114*7c478bd9Sstevel@tonic-gate 		"%s: insufficient permission to look up old credentials.\n",
1115*7c478bd9Sstevel@tonic-gate 			program_name);
1116*7c478bd9Sstevel@tonic-gate 		exit(1);
1117*7c478bd9Sstevel@tonic-gate 		break;
1118*7c478bd9Sstevel@tonic-gate 	case NIS_SUCCESS:
1119*7c478bd9Sstevel@tonic-gate 		foundprinc = ENTRY_VAL(res->objects.objects_val, 0);
1120*7c478bd9Sstevel@tonic-gate 		if (nis_dir_cmp(foundprinc, princname) != SAME_NAME) {
1121*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
1122*7c478bd9Sstevel@tonic-gate 	"%s: %s credentials with auth_name '%s' already belong to '%s'.\n",
1123*7c478bd9Sstevel@tonic-gate 			program_name, auth_type, auth_name, foundprinc);
1124*7c478bd9Sstevel@tonic-gate 			exit(1);
1125*7c478bd9Sstevel@tonic-gate 		}
1126*7c478bd9Sstevel@tonic-gate 		break;
1127*7c478bd9Sstevel@tonic-gate 	default:
1128*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1129*7c478bd9Sstevel@tonic-gate 			"%s: error looking at cred table, NIS+ error: %s\n",
1130*7c478bd9Sstevel@tonic-gate 			program_name, nis_sperrno(res->status));
1131*7c478bd9Sstevel@tonic-gate 		exit(1);
1132*7c478bd9Sstevel@tonic-gate 	}
1133*7c478bd9Sstevel@tonic-gate 	nis_freeresult(res);
1134*7c478bd9Sstevel@tonic-gate 	return (status);
1135*7c478bd9Sstevel@tonic-gate }
1136*7c478bd9Sstevel@tonic-gate 
1137*7c478bd9Sstevel@tonic-gate 
1138*7c478bd9Sstevel@tonic-gate /* Check whether this principal already has this type of credentials */
1139*7c478bd9Sstevel@tonic-gate static nis_error
1140*7c478bd9Sstevel@tonic-gate cred_exists(const char *nisprinc, const char *flavor, const char *domain)
1141*7c478bd9Sstevel@tonic-gate {
1142*7c478bd9Sstevel@tonic-gate 	char sname[NIS_MAXNAMELEN+1];
1143*7c478bd9Sstevel@tonic-gate 	nis_result	*res;
1144*7c478bd9Sstevel@tonic-gate 	nis_error status;
1145*7c478bd9Sstevel@tonic-gate 
1146*7c478bd9Sstevel@tonic-gate 	snprintf(sname, NIS_MAXNAMELEN,
1147*7c478bd9Sstevel@tonic-gate 			"[cname=\"%s\",auth_type=%s],%s.%s",
1148*7c478bd9Sstevel@tonic-gate 			nisprinc, flavor, CRED_TABLE, domain);
1149*7c478bd9Sstevel@tonic-gate 	if (sname[strlen(sname)-1] != '.')
1150*7c478bd9Sstevel@tonic-gate 		strcat(sname, ".");
1151*7c478bd9Sstevel@tonic-gate 
1152*7c478bd9Sstevel@tonic-gate 	/* Don't want FOLLOW_PATH here */
1153*7c478bd9Sstevel@tonic-gate 	res = nis_list(sname,
1154*7c478bd9Sstevel@tonic-gate 				MASTER_ONLY+USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS,
1155*7c478bd9Sstevel@tonic-gate 				NULL, NULL);
1156*7c478bd9Sstevel@tonic-gate 
1157*7c478bd9Sstevel@tonic-gate 	status = res->status;
1158*7c478bd9Sstevel@tonic-gate 	switch (status) {
1159*7c478bd9Sstevel@tonic-gate 	case NIS_NOTFOUND:
1160*7c478bd9Sstevel@tonic-gate 		break;
1161*7c478bd9Sstevel@tonic-gate 	case NIS_TRYAGAIN:
1162*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
1163*7c478bd9Sstevel@tonic-gate 			"%s: NIS+ server busy, try again later.\n",
1164*7c478bd9Sstevel@tonic-gate 			program_name);
1165*7c478bd9Sstevel@tonic-gate 		exit(1);
1166*7c478bd9Sstevel@tonic-gate 		break;
1167*7c478bd9Sstevel@tonic-gate 	case NIS_PERMISSION:
1168*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1169*7c478bd9Sstevel@tonic-gate 		"%s: insufficient permission to look at credentials table\n",
1170*7c478bd9Sstevel@tonic-gate 			program_name);
1171*7c478bd9Sstevel@tonic-gate 		exit(1);
1172*7c478bd9Sstevel@tonic-gate 		break;
1173*7c478bd9Sstevel@tonic-gate 	case NIS_SUCCESS:
1174*7c478bd9Sstevel@tonic-gate 	case NIS_S_SUCCESS:
1175*7c478bd9Sstevel@tonic-gate 		break;
1176*7c478bd9Sstevel@tonic-gate 	default:
1177*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1178*7c478bd9Sstevel@tonic-gate 			"%s: error looking at cred table, NIS+ error: %s\n",
1179*7c478bd9Sstevel@tonic-gate 			program_name, nis_sperrno(res->status));
1180*7c478bd9Sstevel@tonic-gate 		exit(1);
1181*7c478bd9Sstevel@tonic-gate 	}
1182*7c478bd9Sstevel@tonic-gate 	nis_freeresult(res);
1183*7c478bd9Sstevel@tonic-gate 	return (status);
1184*7c478bd9Sstevel@tonic-gate }
1185*7c478bd9Sstevel@tonic-gate 
1186*7c478bd9Sstevel@tonic-gate 
1187*7c478bd9Sstevel@tonic-gate static int
1188*7c478bd9Sstevel@tonic-gate modify_cred_obj(nis_object *obj, char *domain)
1189*7c478bd9Sstevel@tonic-gate {
1190*7c478bd9Sstevel@tonic-gate 	int status = 0;
1191*7c478bd9Sstevel@tonic-gate 	char sname[NIS_MAXNAMELEN+1];
1192*7c478bd9Sstevel@tonic-gate 	nis_result	*res;
1193*7c478bd9Sstevel@tonic-gate 
1194*7c478bd9Sstevel@tonic-gate 	(void) sprintf(sname, "%s.%s", CRED_TABLE, domain);
1195*7c478bd9Sstevel@tonic-gate 	res = nis_modify_entry(sname, obj, 0);
1196*7c478bd9Sstevel@tonic-gate 	switch (res->status) {
1197*7c478bd9Sstevel@tonic-gate 	case NIS_TRYAGAIN:
1198*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1199*7c478bd9Sstevel@tonic-gate 			"%s: NIS+ server busy, try again later.\n",
1200*7c478bd9Sstevel@tonic-gate 			program_name);
1201*7c478bd9Sstevel@tonic-gate 		exit(1);
1202*7c478bd9Sstevel@tonic-gate 		break;
1203*7c478bd9Sstevel@tonic-gate 	case NIS_PERMISSION:
1204*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1205*7c478bd9Sstevel@tonic-gate 			"%s: insufficient permission to update credentials.\n",
1206*7c478bd9Sstevel@tonic-gate 			program_name);
1207*7c478bd9Sstevel@tonic-gate 		exit(1);
1208*7c478bd9Sstevel@tonic-gate 		break;
1209*7c478bd9Sstevel@tonic-gate 	case NIS_SUCCESS:
1210*7c478bd9Sstevel@tonic-gate 		status = 1;
1211*7c478bd9Sstevel@tonic-gate 		break;
1212*7c478bd9Sstevel@tonic-gate 	default:
1213*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1214*7c478bd9Sstevel@tonic-gate 			"%s: error modifying credential, NIS+ error: %s.\n",
1215*7c478bd9Sstevel@tonic-gate 			program_name, nis_sperrno(res->status));
1216*7c478bd9Sstevel@tonic-gate 		exit(1);
1217*7c478bd9Sstevel@tonic-gate 	}
1218*7c478bd9Sstevel@tonic-gate 	nis_freeresult(res);
1219*7c478bd9Sstevel@tonic-gate 	return (status);
1220*7c478bd9Sstevel@tonic-gate }
1221*7c478bd9Sstevel@tonic-gate 
1222*7c478bd9Sstevel@tonic-gate 
1223*7c478bd9Sstevel@tonic-gate static int
1224*7c478bd9Sstevel@tonic-gate add_cred_obj(nis_object *obj, char *domain)
1225*7c478bd9Sstevel@tonic-gate {
1226*7c478bd9Sstevel@tonic-gate 	int status = 0;
1227*7c478bd9Sstevel@tonic-gate 	char sname[NIS_MAXNAMELEN+1];
1228*7c478bd9Sstevel@tonic-gate 	nis_result	*res;
1229*7c478bd9Sstevel@tonic-gate 
1230*7c478bd9Sstevel@tonic-gate 	/* Assume check for cred_exists performed already */
1231*7c478bd9Sstevel@tonic-gate 
1232*7c478bd9Sstevel@tonic-gate 	(void) sprintf(sname, "%s.%s", CRED_TABLE, domain);
1233*7c478bd9Sstevel@tonic-gate 	res = nis_add_entry(sname, obj, 0);
1234*7c478bd9Sstevel@tonic-gate 	switch (res->status) {
1235*7c478bd9Sstevel@tonic-gate 	case NIS_TRYAGAIN:
1236*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1237*7c478bd9Sstevel@tonic-gate 			"%s: NIS+ server busy, try again later.\n",
1238*7c478bd9Sstevel@tonic-gate 			program_name);
1239*7c478bd9Sstevel@tonic-gate 		exit(1);
1240*7c478bd9Sstevel@tonic-gate 		break;
1241*7c478bd9Sstevel@tonic-gate 	case NIS_PERMISSION:
1242*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1243*7c478bd9Sstevel@tonic-gate 			"%s: insufficient permission to update credentials.\n",
1244*7c478bd9Sstevel@tonic-gate 			program_name);
1245*7c478bd9Sstevel@tonic-gate 		exit(1);
1246*7c478bd9Sstevel@tonic-gate 		break;
1247*7c478bd9Sstevel@tonic-gate 	case NIS_SUCCESS:
1248*7c478bd9Sstevel@tonic-gate 		status = 1;
1249*7c478bd9Sstevel@tonic-gate 		break;
1250*7c478bd9Sstevel@tonic-gate 	default:
1251*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1252*7c478bd9Sstevel@tonic-gate 			"%s: error creating credential, NIS+ error: %s.\n",
1253*7c478bd9Sstevel@tonic-gate 			program_name, nis_sperrno(res->status));
1254*7c478bd9Sstevel@tonic-gate 		exit(1);
1255*7c478bd9Sstevel@tonic-gate 	}
1256*7c478bd9Sstevel@tonic-gate 	nis_freeresult(res);
1257*7c478bd9Sstevel@tonic-gate 	return (status);
1258*7c478bd9Sstevel@tonic-gate }
1259*7c478bd9Sstevel@tonic-gate 
1260*7c478bd9Sstevel@tonic-gate 
1261*7c478bd9Sstevel@tonic-gate /* Update NIS+ table with new key information */
1262*7c478bd9Sstevel@tonic-gate static int
1263*7c478bd9Sstevel@tonic-gate nisplus_update(nis_name nis_princ, char *authtype, char *public, char *crypt)
1264*7c478bd9Sstevel@tonic-gate {
1265*7c478bd9Sstevel@tonic-gate 	nis_object	*obj = init_entry();
1266*7c478bd9Sstevel@tonic-gate 	int		status;
1267*7c478bd9Sstevel@tonic-gate 	bool_t		addition;
1268*7c478bd9Sstevel@tonic-gate 	char		*userdomain, *cmpdomain, *domain;
1269*7c478bd9Sstevel@tonic-gate 
1270*7c478bd9Sstevel@tonic-gate 	if (!(userdomain = strchr(netname, '@'))) {
1271*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: invalid netname: '%s'.\n",
1272*7c478bd9Sstevel@tonic-gate 			program_name, netname);
1273*7c478bd9Sstevel@tonic-gate 		exit(1);
1274*7c478bd9Sstevel@tonic-gate 	}
1275*7c478bd9Sstevel@tonic-gate 	userdomain++;
1276*7c478bd9Sstevel@tonic-gate 
1277*7c478bd9Sstevel@tonic-gate 	cmpdomain = strdup(userdomain);
1278*7c478bd9Sstevel@tonic-gate 	if (cmpdomain[strlen(cmpdomain) - 1] != '.')
1279*7c478bd9Sstevel@tonic-gate 		strcat(cmpdomain, ".");
1280*7c478bd9Sstevel@tonic-gate 
1281*7c478bd9Sstevel@tonic-gate 	domain = nis_domain_of(nis_princ);
1282*7c478bd9Sstevel@tonic-gate 	if (strcasecmp(domain, cmpdomain) != 0)
1283*7c478bd9Sstevel@tonic-gate 		domain = nis_local_directory();
1284*7c478bd9Sstevel@tonic-gate 
1285*7c478bd9Sstevel@tonic-gate 	if (!sanity_checks(nis_princ, domain, authtype))
1286*7c478bd9Sstevel@tonic-gate 		exit(1);
1287*7c478bd9Sstevel@tonic-gate 
1288*7c478bd9Sstevel@tonic-gate 	addition = (cred_exists(nis_princ, authtype, domain) == NIS_NOTFOUND);
1289*7c478bd9Sstevel@tonic-gate 
1290*7c478bd9Sstevel@tonic-gate 	ENTRY_VAL(obj, 0) = nis_princ;
1291*7c478bd9Sstevel@tonic-gate 	ENTRY_LEN(obj, 0) = strlen(nis_princ) + 1;
1292*7c478bd9Sstevel@tonic-gate 
1293*7c478bd9Sstevel@tonic-gate 	ENTRY_VAL(obj, 1) = authtype;
1294*7c478bd9Sstevel@tonic-gate 	ENTRY_LEN(obj, 1) = strlen(authtype) + 1;
1295*7c478bd9Sstevel@tonic-gate 
1296*7c478bd9Sstevel@tonic-gate 	ENTRY_VAL(obj, 2) = netname;
1297*7c478bd9Sstevel@tonic-gate 	ENTRY_LEN(obj, 2) = strlen(netname) + 1;
1298*7c478bd9Sstevel@tonic-gate 
1299*7c478bd9Sstevel@tonic-gate 	ENTRY_VAL(obj, 3) = public;
1300*7c478bd9Sstevel@tonic-gate 	ENTRY_LEN(obj, 3) = strlen(public) + 1;
1301*7c478bd9Sstevel@tonic-gate 
1302*7c478bd9Sstevel@tonic-gate 	ENTRY_VAL(obj, 4) = crypt;
1303*7c478bd9Sstevel@tonic-gate 	ENTRY_LEN(obj, 4) = strlen(crypt) + 1;
1304*7c478bd9Sstevel@tonic-gate 
1305*7c478bd9Sstevel@tonic-gate 	if (addition) {
1306*7c478bd9Sstevel@tonic-gate 		obj->zo_owner = nis_princ;
1307*7c478bd9Sstevel@tonic-gate 		obj->zo_group = nis_local_group();
1308*7c478bd9Sstevel@tonic-gate 		obj->zo_domain = domain;
1309*7c478bd9Sstevel@tonic-gate 		/* owner: r, group: rmcd */
1310*7c478bd9Sstevel@tonic-gate 		obj->zo_access = ((NIS_READ_ACC<<16)|
1311*7c478bd9Sstevel@tonic-gate 				(NIS_READ_ACC|NIS_MODIFY_ACC|NIS_CREATE_ACC|
1312*7c478bd9Sstevel@tonic-gate 				NIS_DESTROY_ACC)<<8);
1313*7c478bd9Sstevel@tonic-gate 		status = add_cred_obj(obj, domain);
1314*7c478bd9Sstevel@tonic-gate 	} else {
1315*7c478bd9Sstevel@tonic-gate 		obj->EN_data.en_cols.en_cols_val[3].ec_flags |= EN_MODIFIED;
1316*7c478bd9Sstevel@tonic-gate 		obj->EN_data.en_cols.en_cols_val[4].ec_flags |= EN_MODIFIED;
1317*7c478bd9Sstevel@tonic-gate 		status = modify_cred_obj(obj, domain);
1318*7c478bd9Sstevel@tonic-gate 	}
1319*7c478bd9Sstevel@tonic-gate 	return (status == 1 ? 0 : 1);
1320*7c478bd9Sstevel@tonic-gate }
1321*7c478bd9Sstevel@tonic-gate 
1322*7c478bd9Sstevel@tonic-gate 
1323*7c478bd9Sstevel@tonic-gate void
1324*7c478bd9Sstevel@tonic-gate addmechtolist(char *mechtype)
1325*7c478bd9Sstevel@tonic-gate {
1326*7c478bd9Sstevel@tonic-gate 	mechanism_t	**realmechlist;
1327*7c478bd9Sstevel@tonic-gate 	int		i;
1328*7c478bd9Sstevel@tonic-gate 
1329*7c478bd9Sstevel@tonic-gate 	if (realmechlist = __nis_get_mechanisms(FALSE)) {
1330*7c478bd9Sstevel@tonic-gate 		/* Match requested mech with list */
1331*7c478bd9Sstevel@tonic-gate 		for (i = 0; realmechlist[i]; i++) {
1332*7c478bd9Sstevel@tonic-gate 			if (realmechlist[i]->alias)
1333*7c478bd9Sstevel@tonic-gate 				if (strcmp(realmechlist[i]->alias, mechtype)
1334*7c478bd9Sstevel@tonic-gate 				    == 0) {
1335*7c478bd9Sstevel@tonic-gate 					/*
1336*7c478bd9Sstevel@tonic-gate 					 * Match, add it to the mechs.
1337*7c478bd9Sstevel@tonic-gate 					 * Don't worry about qop or
1338*7c478bd9Sstevel@tonic-gate 					 * secserv since they are not
1339*7c478bd9Sstevel@tonic-gate 					 * used by chkey.
1340*7c478bd9Sstevel@tonic-gate 					 */
1341*7c478bd9Sstevel@tonic-gate 					numspecmech++;
1342*7c478bd9Sstevel@tonic-gate 					if ((mechs =
1343*7c478bd9Sstevel@tonic-gate 						(mechanism_t **)realloc(mechs,
1344*7c478bd9Sstevel@tonic-gate 				sizeof (mechanism_t *) * (numspecmech + 1))) ==
1345*7c478bd9Sstevel@tonic-gate 					    NULL) {
1346*7c478bd9Sstevel@tonic-gate 						perror("Can not change keys");
1347*7c478bd9Sstevel@tonic-gate 						exit(1);
1348*7c478bd9Sstevel@tonic-gate 					}
1349*7c478bd9Sstevel@tonic-gate 
1350*7c478bd9Sstevel@tonic-gate 					if ((mechs[numspecmech - 1] =
1351*7c478bd9Sstevel@tonic-gate 		(mechanism_t *)malloc(sizeof (mechanism_t))) == NULL) {
1352*7c478bd9Sstevel@tonic-gate 						perror("Can not change keys");
1353*7c478bd9Sstevel@tonic-gate 						exit(1);
1354*7c478bd9Sstevel@tonic-gate 					}
1355*7c478bd9Sstevel@tonic-gate 					if (realmechlist[i]->mechname)
1356*7c478bd9Sstevel@tonic-gate 					mechs[numspecmech - 1]->mechname =
1357*7c478bd9Sstevel@tonic-gate 					strdup(realmechlist[i]->mechname);
1358*7c478bd9Sstevel@tonic-gate 					if (realmechlist[i]->alias)
1359*7c478bd9Sstevel@tonic-gate 					mechs[numspecmech - 1]->alias =
1360*7c478bd9Sstevel@tonic-gate 						strdup(realmechlist[i]->alias);
1361*7c478bd9Sstevel@tonic-gate 					mechs[numspecmech - 1]->keylen =
1362*7c478bd9Sstevel@tonic-gate 						realmechlist[i]->keylen;
1363*7c478bd9Sstevel@tonic-gate 					mechs[numspecmech - 1]->algtype =
1364*7c478bd9Sstevel@tonic-gate 						realmechlist[i]->algtype;
1365*7c478bd9Sstevel@tonic-gate 					mechs[numspecmech] = NULL;
1366*7c478bd9Sstevel@tonic-gate 					__nis_release_mechanisms(realmechlist);
1367*7c478bd9Sstevel@tonic-gate 					return;
1368*7c478bd9Sstevel@tonic-gate 				}
1369*7c478bd9Sstevel@tonic-gate 		}
1370*7c478bd9Sstevel@tonic-gate 
1371*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
1372*7c478bd9Sstevel@tonic-gate 		"WARNING: Mechanism '%s' not configured, skipping...\n",
1373*7c478bd9Sstevel@tonic-gate 			mechtype);
1374*7c478bd9Sstevel@tonic-gate 		__nis_release_mechanisms(realmechlist);
1375*7c478bd9Sstevel@tonic-gate 		return;
1376*7c478bd9Sstevel@tonic-gate 	}
1377*7c478bd9Sstevel@tonic-gate 	fprintf(stderr,
1378*7c478bd9Sstevel@tonic-gate 		"WARNING: Mechanism '%s' not configured, skipping...\n",
1379*7c478bd9Sstevel@tonic-gate 		mechtype);
1380*7c478bd9Sstevel@tonic-gate }
1381*7c478bd9Sstevel@tonic-gate 
1382*7c478bd9Sstevel@tonic-gate 
1383*7c478bd9Sstevel@tonic-gate void
1384*7c478bd9Sstevel@tonic-gate main(int argc, char **argv)
1385*7c478bd9Sstevel@tonic-gate {
1386*7c478bd9Sstevel@tonic-gate 	int		c, mcount;
1387*7c478bd9Sstevel@tonic-gate 	uid_t		uid;
1388*7c478bd9Sstevel@tonic-gate 	uid_t		orig_euid;
1389*7c478bd9Sstevel@tonic-gate 	char		*service = NULL;
1390*7c478bd9Sstevel@tonic-gate 	program_name = argv[0];
1391*7c478bd9Sstevel@tonic-gate 
1392*7c478bd9Sstevel@tonic-gate 	mechs = __nis_get_mechanisms(FALSE);
1393*7c478bd9Sstevel@tonic-gate 
1394*7c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "fps:m:")) != -1) {
1395*7c478bd9Sstevel@tonic-gate 		switch (c) {
1396*7c478bd9Sstevel@tonic-gate 		case 'f':
1397*7c478bd9Sstevel@tonic-gate 			/*
1398*7c478bd9Sstevel@tonic-gate 			 * Not documented as of on1093.
1399*7c478bd9Sstevel@tonic-gate 			 * Temporarily supported
1400*7c478bd9Sstevel@tonic-gate 			 */
1401*7c478bd9Sstevel@tonic-gate 			force++;
1402*7c478bd9Sstevel@tonic-gate 			break;
1403*7c478bd9Sstevel@tonic-gate 		case 'p':
1404*7c478bd9Sstevel@tonic-gate 			makenew = FALSE;
1405*7c478bd9Sstevel@tonic-gate 			break;
1406*7c478bd9Sstevel@tonic-gate 		case 's':
1407*7c478bd9Sstevel@tonic-gate 			if (!service)
1408*7c478bd9Sstevel@tonic-gate 				service = strdup(optarg);
1409*7c478bd9Sstevel@tonic-gate 			else
1410*7c478bd9Sstevel@tonic-gate 				usage();
1411*7c478bd9Sstevel@tonic-gate 			break;
1412*7c478bd9Sstevel@tonic-gate 		case 'm':
1413*7c478bd9Sstevel@tonic-gate 			if (mechs && specmech == FALSE) {
1414*7c478bd9Sstevel@tonic-gate 				__nis_release_mechanisms(mechs);
1415*7c478bd9Sstevel@tonic-gate 				mechs = NULL;
1416*7c478bd9Sstevel@tonic-gate 			}
1417*7c478bd9Sstevel@tonic-gate 			specmech = TRUE;
1418*7c478bd9Sstevel@tonic-gate 			addmechtolist(optarg);
1419*7c478bd9Sstevel@tonic-gate 			break;
1420*7c478bd9Sstevel@tonic-gate 		default:
1421*7c478bd9Sstevel@tonic-gate 			usage();
1422*7c478bd9Sstevel@tonic-gate 		}
1423*7c478bd9Sstevel@tonic-gate 	}
1424*7c478bd9Sstevel@tonic-gate 
1425*7c478bd9Sstevel@tonic-gate 	if (optind < argc)
1426*7c478bd9Sstevel@tonic-gate 		usage();
1427*7c478bd9Sstevel@tonic-gate 
1428*7c478bd9Sstevel@tonic-gate 	dest_service = get_pk_source(service);
1429*7c478bd9Sstevel@tonic-gate 
1430*7c478bd9Sstevel@tonic-gate 	if (!(netname = malloc(MAXNETNAMELEN + 1))) {
1431*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: Malloc failure.\n", program_name);
1432*7c478bd9Sstevel@tonic-gate 		exit(1);
1433*7c478bd9Sstevel@tonic-gate 	}
1434*7c478bd9Sstevel@tonic-gate 	if (!__getnetnamebyuid(netname, uid = getuid())) {
1435*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: cannot generate netname for uid %d\n",
1436*7c478bd9Sstevel@tonic-gate 			program_name, uid);
1437*7c478bd9Sstevel@tonic-gate 		exit(1);
1438*7c478bd9Sstevel@tonic-gate 	}
1439*7c478bd9Sstevel@tonic-gate 	sec_domain = strdup(strchr(netname, '@') + 1);
1440*7c478bd9Sstevel@tonic-gate 	getdomainname(local_domain, MAXNETNAMELEN);
1441*7c478bd9Sstevel@tonic-gate 
1442*7c478bd9Sstevel@tonic-gate 	if (makenew)
1443*7c478bd9Sstevel@tonic-gate 		fprintf(stdout, "Generating new key for '%s'.\n", netname);
1444*7c478bd9Sstevel@tonic-gate 	else
1445*7c478bd9Sstevel@tonic-gate 		fprintf(stdout, "Reencrypting key for '%s'.\n", netname);
1446*7c478bd9Sstevel@tonic-gate 
1447*7c478bd9Sstevel@tonic-gate 	if (mechs) {
1448*7c478bd9Sstevel@tonic-gate 		if (dest_service == PK_YP || dest_service == PK_FILES) {
1449*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
1450*7c478bd9Sstevel@tonic-gate 		"%s: can not add non-DES public keys to %s, skipping.\n",
1451*7c478bd9Sstevel@tonic-gate 				program_name, service);
1452*7c478bd9Sstevel@tonic-gate 			__nis_release_mechanisms(mechs);
1453*7c478bd9Sstevel@tonic-gate 			mechs = NULL;
1454*7c478bd9Sstevel@tonic-gate 			initkeylist(TRUE);
1455*7c478bd9Sstevel@tonic-gate 		} else
1456*7c478bd9Sstevel@tonic-gate 			initkeylist(FALSE);
1457*7c478bd9Sstevel@tonic-gate 	} else
1458*7c478bd9Sstevel@tonic-gate 		initkeylist(TRUE);
1459*7c478bd9Sstevel@tonic-gate 
1460*7c478bd9Sstevel@tonic-gate 	uid = getuid();
1461*7c478bd9Sstevel@tonic-gate 	orig_euid = geteuid();
1462*7c478bd9Sstevel@tonic-gate 
1463*7c478bd9Sstevel@tonic-gate 	/* Get password information */
1464*7c478bd9Sstevel@tonic-gate 	if ((pw = getpwuid(uid)) == NULL) {
1465*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
1466*7c478bd9Sstevel@tonic-gate 			"%s: Can not find passwd information for %d.\n",
1467*7c478bd9Sstevel@tonic-gate 			program_name, uid);
1468*7c478bd9Sstevel@tonic-gate 		exit(1);
1469*7c478bd9Sstevel@tonic-gate 	}
1470*7c478bd9Sstevel@tonic-gate 
1471*7c478bd9Sstevel@tonic-gate 	/* Set eUID to user */
1472*7c478bd9Sstevel@tonic-gate 	seteuid(uid);
1473*7c478bd9Sstevel@tonic-gate 
1474*7c478bd9Sstevel@tonic-gate 	/* Obtain a list of decrypted secret keys */
1475*7c478bd9Sstevel@tonic-gate 	getsecrets();
1476*7c478bd9Sstevel@tonic-gate 
1477*7c478bd9Sstevel@tonic-gate 	/* Keylogin user if not already done */
1478*7c478bd9Sstevel@tonic-gate 	if (mechs) {
1479*7c478bd9Sstevel@tonic-gate 		int mcount;
1480*7c478bd9Sstevel@tonic-gate 
1481*7c478bd9Sstevel@tonic-gate 		for (mcount = 0; CURMECH; mcount++) {
1482*7c478bd9Sstevel@tonic-gate 			keylen_t	keylen = CURMECH->keylen;
1483*7c478bd9Sstevel@tonic-gate 			algtype_t	algtype = CURMECH->algtype;
1484*7c478bd9Sstevel@tonic-gate 
1485*7c478bd9Sstevel@tonic-gate 			if (!key_secretkey_is_set_g(keylen, algtype) &&
1486*7c478bd9Sstevel@tonic-gate 			    slist[mcount]) {
1487*7c478bd9Sstevel@tonic-gate 				keylogin(CURMECH->keylen, CURMECH->algtype);
1488*7c478bd9Sstevel@tonic-gate 				if ((uid == 0) && (makenew == FALSE))
1489*7c478bd9Sstevel@tonic-gate 					write_rootkey(slist[mcount],
1490*7c478bd9Sstevel@tonic-gate 					VALID_ALIAS(CURMECH->alias) ?
1491*7c478bd9Sstevel@tonic-gate 							CURMECH->alias :
1492*7c478bd9Sstevel@tonic-gate 							"",
1493*7c478bd9Sstevel@tonic-gate 							keylen, algtype);
1494*7c478bd9Sstevel@tonic-gate 			}
1495*7c478bd9Sstevel@tonic-gate 		}
1496*7c478bd9Sstevel@tonic-gate 	} else {
1497*7c478bd9Sstevel@tonic-gate 		assert(slist[0]);
1498*7c478bd9Sstevel@tonic-gate 		if (!key_secretkey_is_set()) {
1499*7c478bd9Sstevel@tonic-gate 			keylogin_des();
1500*7c478bd9Sstevel@tonic-gate 			if ((uid == 0) && (makenew == FALSE))
1501*7c478bd9Sstevel@tonic-gate 				write_rootkey(slist[0], "des", 192, 0);
1502*7c478bd9Sstevel@tonic-gate 		}
1503*7c478bd9Sstevel@tonic-gate 	}
1504*7c478bd9Sstevel@tonic-gate 
1505*7c478bd9Sstevel@tonic-gate 	/* Set eUID back to root */
1506*7c478bd9Sstevel@tonic-gate 	(void) seteuid(orig_euid);
1507*7c478bd9Sstevel@tonic-gate 
1508*7c478bd9Sstevel@tonic-gate 	/*
1509*7c478bd9Sstevel@tonic-gate 	 * Call getspnam() after the keylogin has been done so we have
1510*7c478bd9Sstevel@tonic-gate 	 * the best chance of having read access to the encrypted pw.
1511*7c478bd9Sstevel@tonic-gate 	 *
1512*7c478bd9Sstevel@tonic-gate 	 * The eUID must be 0 for the getspnam() so the name service
1513*7c478bd9Sstevel@tonic-gate 	 * switch can handle the following eUID sensitive cases:
1514*7c478bd9Sstevel@tonic-gate 	 *
1515*7c478bd9Sstevel@tonic-gate 	 *	files/compat:	read /etc/shadow
1516*7c478bd9Sstevel@tonic-gate 	 *
1517*7c478bd9Sstevel@tonic-gate 	 *	nisplus:	try to read the encrypted pw as the root
1518*7c478bd9Sstevel@tonic-gate 	 *			principal and if that fails, and if the
1519*7c478bd9Sstevel@tonic-gate 	 *			user's secret key is set, seteuid(user)
1520*7c478bd9Sstevel@tonic-gate 	 *			and retry the read.
1521*7c478bd9Sstevel@tonic-gate 	 */
1522*7c478bd9Sstevel@tonic-gate 	if ((spw = getspnam(pw->pw_name)) == 0) {
1523*7c478bd9Sstevel@tonic-gate 
1524*7c478bd9Sstevel@tonic-gate 		/* Set eUID back to user */
1525*7c478bd9Sstevel@tonic-gate 		(void) seteuid(uid);
1526*7c478bd9Sstevel@tonic-gate 
1527*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1528*7c478bd9Sstevel@tonic-gate 			"%s: cannot find shadow entry for %s.\n",
1529*7c478bd9Sstevel@tonic-gate 			program_name, pw->pw_name);
1530*7c478bd9Sstevel@tonic-gate 		exit(1);
1531*7c478bd9Sstevel@tonic-gate 	}
1532*7c478bd9Sstevel@tonic-gate 
1533*7c478bd9Sstevel@tonic-gate 	/* Set eUID back to user */
1534*7c478bd9Sstevel@tonic-gate 	(void) seteuid(uid);
1535*7c478bd9Sstevel@tonic-gate 
1536*7c478bd9Sstevel@tonic-gate 	if (strcmp(spw->sp_pwdp, "*NP*") == 0) {
1537*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1538*7c478bd9Sstevel@tonic-gate 		"%s: do not have read access to the passwd field for %s\n",
1539*7c478bd9Sstevel@tonic-gate 				program_name, pw->pw_name);
1540*7c478bd9Sstevel@tonic-gate 		exit(1);
1541*7c478bd9Sstevel@tonic-gate 	}
1542*7c478bd9Sstevel@tonic-gate 
1543*7c478bd9Sstevel@tonic-gate 	/*
1544*7c478bd9Sstevel@tonic-gate 	 * force will be only supported for a while
1545*7c478bd9Sstevel@tonic-gate 	 * 	-- it is NOT documented as of s1093
1546*7c478bd9Sstevel@tonic-gate 	 */
1547*7c478bd9Sstevel@tonic-gate 	if (force) {
1548*7c478bd9Sstevel@tonic-gate 		char	*prompt = "Please enter New password:";
1549*7c478bd9Sstevel@tonic-gate 
1550*7c478bd9Sstevel@tonic-gate 		login_pw = getpass(prompt);
1551*7c478bd9Sstevel@tonic-gate 		if (!login_pw || !(strlen(login_pw))) {
1552*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "%s: key-pair(s) unchanged for %s.\n",
1553*7c478bd9Sstevel@tonic-gate 				program_name, pw->pw_name);
1554*7c478bd9Sstevel@tonic-gate 			exit(1);
1555*7c478bd9Sstevel@tonic-gate 		}
1556*7c478bd9Sstevel@tonic-gate 	} else {
1557*7c478bd9Sstevel@tonic-gate 		/*
1558*7c478bd9Sstevel@tonic-gate 		 * Reconsile rpc_pws and login_pw.
1559*7c478bd9Sstevel@tonic-gate 		 *
1560*7c478bd9Sstevel@tonic-gate 		 * This function will either return with login_pw == rpc_pw
1561*7c478bd9Sstevel@tonic-gate 		 * (and thus, the new pw to encrypt keys) or it will exit.
1562*7c478bd9Sstevel@tonic-gate 		 */
1563*7c478bd9Sstevel@tonic-gate 		cmp_passwd();
1564*7c478bd9Sstevel@tonic-gate 	}
1565*7c478bd9Sstevel@tonic-gate 
1566*7c478bd9Sstevel@tonic-gate 	if (makenew)
1567*7c478bd9Sstevel@tonic-gate 		makenewkeys();
1568*7c478bd9Sstevel@tonic-gate 	else
1569*7c478bd9Sstevel@tonic-gate 		getpublics();
1570*7c478bd9Sstevel@tonic-gate 
1571*7c478bd9Sstevel@tonic-gate 	encryptkeys();
1572*7c478bd9Sstevel@tonic-gate 
1573*7c478bd9Sstevel@tonic-gate 	storekeys();
1574*7c478bd9Sstevel@tonic-gate 
1575*7c478bd9Sstevel@tonic-gate 	if (makenew) {
1576*7c478bd9Sstevel@tonic-gate 		if (uid == 0) {
1577*7c478bd9Sstevel@tonic-gate 			if (mechs) {
1578*7c478bd9Sstevel@tonic-gate 				for (mcount = 0; CURMECH; mcount++) {
1579*7c478bd9Sstevel@tonic-gate 					if (!slist[mcount])
1580*7c478bd9Sstevel@tonic-gate 						continue;
1581*7c478bd9Sstevel@tonic-gate 					write_rootkey(slist[mcount],
1582*7c478bd9Sstevel@tonic-gate 							CURMECH->alias,
1583*7c478bd9Sstevel@tonic-gate 							CURMECH->keylen,
1584*7c478bd9Sstevel@tonic-gate 							CURMECH->algtype);
1585*7c478bd9Sstevel@tonic-gate 				}
1586*7c478bd9Sstevel@tonic-gate 			} else {
1587*7c478bd9Sstevel@tonic-gate 				assert(slist[0]);
1588*7c478bd9Sstevel@tonic-gate 				write_rootkey(slist[0], "des", 192, 0);
1589*7c478bd9Sstevel@tonic-gate 			}
1590*7c478bd9Sstevel@tonic-gate 		}
1591*7c478bd9Sstevel@tonic-gate 		if (mechs) {
1592*7c478bd9Sstevel@tonic-gate 			for (mcount = 0; CURMECH; mcount++)
1593*7c478bd9Sstevel@tonic-gate 				keylogin(CURMECH->keylen,
1594*7c478bd9Sstevel@tonic-gate 						CURMECH->algtype);
1595*7c478bd9Sstevel@tonic-gate 		} else
1596*7c478bd9Sstevel@tonic-gate 			keylogin_des();
1597*7c478bd9Sstevel@tonic-gate 	}
1598*7c478bd9Sstevel@tonic-gate 	exit(0);
1599*7c478bd9Sstevel@tonic-gate }
1600