xref: /titanic_52/usr/src/cmd/keyserv/chkey_common.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 2005 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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <stdio.h>
30*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
31*7c478bd9Sstevel@tonic-gate #include <ctype.h>
32*7c478bd9Sstevel@tonic-gate #include <strings.h>
33*7c478bd9Sstevel@tonic-gate #include <pwd.h>
34*7c478bd9Sstevel@tonic-gate #include <shadow.h>
35*7c478bd9Sstevel@tonic-gate #include <netdb.h>
36*7c478bd9Sstevel@tonic-gate #include <mp.h>
37*7c478bd9Sstevel@tonic-gate #include <rpcsvc/nis.h>
38*7c478bd9Sstevel@tonic-gate #include <rpc/key_prot.h>
39*7c478bd9Sstevel@tonic-gate #include <nsswitch.h>
40*7c478bd9Sstevel@tonic-gate #include <ns_sldap.h>
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate extern char *crypt();
43*7c478bd9Sstevel@tonic-gate extern long random();
44*7c478bd9Sstevel@tonic-gate extern char *getpassphrase();
45*7c478bd9Sstevel@tonic-gate extern char *program_name;
46*7c478bd9Sstevel@tonic-gate static const char *CRED_TABLE = "cred.org_dir";
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate #define	ROOTKEY_FILE	"/etc/.rootkey"
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate #ifndef MAXHOSTNAMELEN
51*7c478bd9Sstevel@tonic-gate #define	MAXHOSTNAMELEN 256
52*7c478bd9Sstevel@tonic-gate #endif
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate #define	PK_FILES	1
55*7c478bd9Sstevel@tonic-gate #define	PK_YP		2
56*7c478bd9Sstevel@tonic-gate #define	PK_NISPLUS	3
57*7c478bd9Sstevel@tonic-gate #define	PK_LDAP		4
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate #define	LDAP_BINDDN_DEFAULT	"cn=Directory Manager"
60*7c478bd9Sstevel@tonic-gate #define	PROMPTGET_SUCCESS	1
61*7c478bd9Sstevel@tonic-gate #define	PROMPTGET_FAIL		-1
62*7c478bd9Sstevel@tonic-gate #define	PROMPTGET_MEMORY_FAIL	-2
63*7c478bd9Sstevel@tonic-gate #define	PASSWD_UNMATCHED	-3
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate #define	FREE_CREDINFO(s) \
66*7c478bd9Sstevel@tonic-gate 	if ((s)) { (void) memset((s), 0, strlen((s))); }
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate /* ************************ switch functions *************************** */
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate /*	NSW_NOTSUCCESS  NSW_NOTFOUND   NSW_UNAVAIL    NSW_TRYAGAIN */
72*7c478bd9Sstevel@tonic-gate #define	DEF_ACTION {__NSW_RETURN, __NSW_RETURN, __NSW_CONTINUE, __NSW_CONTINUE}
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate static struct __nsw_lookup lookup_files = {"files", DEF_ACTION, NULL, NULL},
75*7c478bd9Sstevel@tonic-gate 		lookup_nis = {"nis", DEF_ACTION, NULL, &lookup_files};
76*7c478bd9Sstevel@tonic-gate static struct __nsw_switchconfig publickey_default =
77*7c478bd9Sstevel@tonic-gate 			{0, "publickey", 2, &lookup_nis};
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate static int get_ldap_bindDN(char **);
80*7c478bd9Sstevel@tonic-gate static int get_ldap_bindPassword(char **);
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate /*
83*7c478bd9Sstevel@tonic-gate  * Prompt the users for a ldap bind DN. If users do not enter a value but just
84*7c478bd9Sstevel@tonic-gate  * simply hit the return key, the default bindDN "cn=Directory Manager"
85*7c478bd9Sstevel@tonic-gate  * will be used.
86*7c478bd9Sstevel@tonic-gate  */
87*7c478bd9Sstevel@tonic-gate static int
88*7c478bd9Sstevel@tonic-gate get_ldap_bindDN(char **ret_bindDN) {
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate 	char	bindDN[BUFSIZ];
91*7c478bd9Sstevel@tonic-gate 	char	prompt[BUFSIZ];
92*7c478bd9Sstevel@tonic-gate 	int	blen, pos;
93*7c478bd9Sstevel@tonic-gate 
94*7c478bd9Sstevel@tonic-gate 	/* set the initial value for bindDN buffer */
95*7c478bd9Sstevel@tonic-gate 	(void) memset(bindDN, 0, BUFSIZ);
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate 	(void) snprintf(prompt, BUFSIZ,
98*7c478bd9Sstevel@tonic-gate 	"\nThe LDAP bind DN and password are required for this update.\n"
99*7c478bd9Sstevel@tonic-gate 	"If you are not sure what values to enter, please contact your\n"
100*7c478bd9Sstevel@tonic-gate 	"LDAP administrator.\n\nPlease enter LDAP bind DN [%s]: ",
101*7c478bd9Sstevel@tonic-gate 	LDAP_BINDDN_DEFAULT);
102*7c478bd9Sstevel@tonic-gate 
103*7c478bd9Sstevel@tonic-gate 	printf(prompt);
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate 	if (fgets(bindDN, sizeof (bindDN), stdin) == NULL) {
106*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(bindDN, LDAP_BINDDN_DEFAULT, BUFSIZ);
107*7c478bd9Sstevel@tonic-gate 	}
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate 	blen = strlen(bindDN);
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate 	/* Check if the buffer ends with a newline */
112*7c478bd9Sstevel@tonic-gate 	if ((blen > 0) && (bindDN[blen - 1] == '\n')) {
113*7c478bd9Sstevel@tonic-gate 		bindDN[blen - 1] = '\0';
114*7c478bd9Sstevel@tonic-gate 		blen -= 1;
115*7c478bd9Sstevel@tonic-gate 	}
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate 	/* Remove the white spaces */
118*7c478bd9Sstevel@tonic-gate 	if (blen > 0) {
119*7c478bd9Sstevel@tonic-gate 		for (pos = blen - 1; pos >= 0; pos--) {
120*7c478bd9Sstevel@tonic-gate 			if (isspace(bindDN[pos]))
121*7c478bd9Sstevel@tonic-gate 				bindDN[pos] = '\0';
122*7c478bd9Sstevel@tonic-gate 			else
123*7c478bd9Sstevel@tonic-gate 				break;
124*7c478bd9Sstevel@tonic-gate 		}
125*7c478bd9Sstevel@tonic-gate 	}
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate 	/* Use the default bindDN, if the buffer contains no characters */
128*7c478bd9Sstevel@tonic-gate 	if (strlen(bindDN) == 0)
129*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(bindDN, LDAP_BINDDN_DEFAULT, BUFSIZ);
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate 	if ((*ret_bindDN = (char *)malloc(strlen(bindDN)+1)) == NULL) {
132*7c478bd9Sstevel@tonic-gate 		(void) memset(bindDN, 0, BUFSIZ);
133*7c478bd9Sstevel@tonic-gate 		return (PROMPTGET_MEMORY_FAIL);
134*7c478bd9Sstevel@tonic-gate 	}
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(*ret_bindDN, bindDN, strlen(bindDN)+1);
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate 	/* Clean up and erase the credential info */
139*7c478bd9Sstevel@tonic-gate 	(void) memset(bindDN, 0, BUFSIZ);
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate 	return (PROMPTGET_SUCCESS);
142*7c478bd9Sstevel@tonic-gate }
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate /*
146*7c478bd9Sstevel@tonic-gate  * Prompt the user for a ldap bind password.
147*7c478bd9Sstevel@tonic-gate  */
148*7c478bd9Sstevel@tonic-gate static int
149*7c478bd9Sstevel@tonic-gate get_ldap_bindPassword(char **ret_bindPass) {
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate 	char 	bindPassword[BUFSIZ];
152*7c478bd9Sstevel@tonic-gate 	char	prompt[BUFSIZ];
153*7c478bd9Sstevel@tonic-gate 	char	*bindPass = NULL;
154*7c478bd9Sstevel@tonic-gate 
155*7c478bd9Sstevel@tonic-gate 	/* set the initial value for bindPassword buffer */
156*7c478bd9Sstevel@tonic-gate 	(void) memset(bindPassword, 0, BUFSIZ);
157*7c478bd9Sstevel@tonic-gate 	*ret_bindPass = NULL;
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate 	(void) snprintf(prompt, BUFSIZ,
160*7c478bd9Sstevel@tonic-gate 		"Please enter LDAP bind password: ");
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate 	bindPass = getpassphrase(prompt);
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate 	if (bindPass == NULL)
165*7c478bd9Sstevel@tonic-gate 		return (PROMPTGET_FAIL);
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(bindPassword, bindPass, BUFSIZ);
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate 	/* clean the static buffer returned from getpassphrase call */
170*7c478bd9Sstevel@tonic-gate 	(void) memset(bindPass, 0, strlen(bindPass));
171*7c478bd9Sstevel@tonic-gate 	bindPass = NULL;
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate 	/*
174*7c478bd9Sstevel@tonic-gate 	 * Re-enter the bind passowrd and compare it with the one
175*7c478bd9Sstevel@tonic-gate 	 * from previous entered.
176*7c478bd9Sstevel@tonic-gate 	 */
177*7c478bd9Sstevel@tonic-gate 	(void) snprintf(prompt, BUFSIZ,
178*7c478bd9Sstevel@tonic-gate 		"Re-enter LDAP bind password to confirm: ");
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate 	bindPass = getpassphrase(prompt);
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate 	if (bindPass == NULL) {
183*7c478bd9Sstevel@tonic-gate 		(void) memset(bindPassword, 0, BUFSIZ);
184*7c478bd9Sstevel@tonic-gate 		return (PASSWD_UNMATCHED);
185*7c478bd9Sstevel@tonic-gate 	}
186*7c478bd9Sstevel@tonic-gate 
187*7c478bd9Sstevel@tonic-gate 	if (strcmp(bindPass, bindPassword) != 0) {
188*7c478bd9Sstevel@tonic-gate 		(void) memset(bindPassword, 0, BUFSIZ);
189*7c478bd9Sstevel@tonic-gate 		(void) memset(bindPass, 0, strlen(bindPass));
190*7c478bd9Sstevel@tonic-gate 		return (PASSWD_UNMATCHED);
191*7c478bd9Sstevel@tonic-gate 	} else {
192*7c478bd9Sstevel@tonic-gate 		(void) memset(bindPass, 0, strlen(bindPass));
193*7c478bd9Sstevel@tonic-gate 		if ((*ret_bindPass = (char *)malloc(strlen(bindPassword)+1))
194*7c478bd9Sstevel@tonic-gate 			== NULL) {
195*7c478bd9Sstevel@tonic-gate 			(void) memset(bindPassword, 0, BUFSIZ);
196*7c478bd9Sstevel@tonic-gate 			return (PROMPTGET_MEMORY_FAIL);
197*7c478bd9Sstevel@tonic-gate 		}
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(*ret_bindPass, bindPassword,
200*7c478bd9Sstevel@tonic-gate 			strlen(bindPassword)+1);
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 		/* Clean up and erase the credential info */
203*7c478bd9Sstevel@tonic-gate 		(void) memset(bindPassword, 0, BUFSIZ);
204*7c478bd9Sstevel@tonic-gate 
205*7c478bd9Sstevel@tonic-gate 		return (PROMPTGET_SUCCESS);
206*7c478bd9Sstevel@tonic-gate 	}
207*7c478bd9Sstevel@tonic-gate }
208*7c478bd9Sstevel@tonic-gate 
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate 
211*7c478bd9Sstevel@tonic-gate char *
212*7c478bd9Sstevel@tonic-gate switch_policy_str(struct __nsw_switchconfig *conf)
213*7c478bd9Sstevel@tonic-gate {
214*7c478bd9Sstevel@tonic-gate 	struct __nsw_lookup *look;
215*7c478bd9Sstevel@tonic-gate 	static char policy[256];  /* 256 is enough for (nis, files...etc) */
216*7c478bd9Sstevel@tonic-gate 	int previous = 0;
217*7c478bd9Sstevel@tonic-gate 
218*7c478bd9Sstevel@tonic-gate 	memset((char *)policy, 0, 256);
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate 	for (look = conf->lookups; look; look = look->next) {
221*7c478bd9Sstevel@tonic-gate 		if (previous)
222*7c478bd9Sstevel@tonic-gate 			strcat(policy, " ");
223*7c478bd9Sstevel@tonic-gate 		strcat(policy, look->service_name);
224*7c478bd9Sstevel@tonic-gate 		previous = 1;
225*7c478bd9Sstevel@tonic-gate 	}
226*7c478bd9Sstevel@tonic-gate 	return (policy);
227*7c478bd9Sstevel@tonic-gate }
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate int
230*7c478bd9Sstevel@tonic-gate no_switch_policy(struct __nsw_switchconfig *conf)
231*7c478bd9Sstevel@tonic-gate {
232*7c478bd9Sstevel@tonic-gate 	return (conf == NULL || conf->lookups == NULL);
233*7c478bd9Sstevel@tonic-gate }
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate is_switch_policy(struct __nsw_switchconfig *conf, char *target)
236*7c478bd9Sstevel@tonic-gate {
237*7c478bd9Sstevel@tonic-gate 	return (conf &&
238*7c478bd9Sstevel@tonic-gate 		conf->lookups &&
239*7c478bd9Sstevel@tonic-gate 		strcmp(conf->lookups->service_name, target) == 0 &&
240*7c478bd9Sstevel@tonic-gate 		conf->lookups->next == NULL);
241*7c478bd9Sstevel@tonic-gate }
242*7c478bd9Sstevel@tonic-gate 
243*7c478bd9Sstevel@tonic-gate char *
244*7c478bd9Sstevel@tonic-gate first_and_only_switch_policy(char *policy,
245*7c478bd9Sstevel@tonic-gate 		    struct __nsw_switchconfig *default_conf,
246*7c478bd9Sstevel@tonic-gate 		    char *head_msg)
247*7c478bd9Sstevel@tonic-gate {
248*7c478bd9Sstevel@tonic-gate 	struct __nsw_switchconfig *conf;
249*7c478bd9Sstevel@tonic-gate 	enum __nsw_parse_err perr;
250*7c478bd9Sstevel@tonic-gate 	int policy_correct = 1;
251*7c478bd9Sstevel@tonic-gate 	char *target_service = 0;
252*7c478bd9Sstevel@tonic-gate 	int use_default = 0;
253*7c478bd9Sstevel@tonic-gate 
254*7c478bd9Sstevel@tonic-gate 	if (default_conf == 0)
255*7c478bd9Sstevel@tonic-gate 		default_conf = &publickey_default;
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate 	conf = __nsw_getconfig(policy, &perr);
258*7c478bd9Sstevel@tonic-gate 	if (no_switch_policy(conf)) {
259*7c478bd9Sstevel@tonic-gate 		use_default = 1;
260*7c478bd9Sstevel@tonic-gate 		conf = default_conf;
261*7c478bd9Sstevel@tonic-gate 	}
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate 	target_service = conf->lookups->service_name;
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate 	if (conf->lookups->next != NULL) {
266*7c478bd9Sstevel@tonic-gate 		policy_correct = 0;
267*7c478bd9Sstevel@tonic-gate 		if (use_default) {
268*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
269*7c478bd9Sstevel@tonic-gate 			"\n%s\n There is no publickey entry in %s.\n",
270*7c478bd9Sstevel@tonic-gate 				head_msg, __NSW_CONFIG_FILE);
271*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
272*7c478bd9Sstevel@tonic-gate 			"The default publickey policy is \"publickey: %s\".\n",
273*7c478bd9Sstevel@tonic-gate 			switch_policy_str(default_conf));
274*7c478bd9Sstevel@tonic-gate 		} else
275*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
276*7c478bd9Sstevel@tonic-gate 		"\n%s\nThe publickey entry in %s is \"publickey: %s\".\n",
277*7c478bd9Sstevel@tonic-gate 			head_msg, __NSW_CONFIG_FILE,
278*7c478bd9Sstevel@tonic-gate 			switch_policy_str(conf));
279*7c478bd9Sstevel@tonic-gate 	}
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate 	if (policy_correct == 0)
282*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
283*7c478bd9Sstevel@tonic-gate 	"I cannot figure out which publickey database you want to update.\n");
284*7c478bd9Sstevel@tonic-gate 	if (!use_default && conf)
285*7c478bd9Sstevel@tonic-gate 		__nsw_freeconfig(conf);
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate 	if (policy_correct)
288*7c478bd9Sstevel@tonic-gate 		return (target_service);
289*7c478bd9Sstevel@tonic-gate 	else
290*7c478bd9Sstevel@tonic-gate 		return (0);
291*7c478bd9Sstevel@tonic-gate }
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate int
296*7c478bd9Sstevel@tonic-gate check_switch_policy(char *policy, char *target_service,
297*7c478bd9Sstevel@tonic-gate 		    struct __nsw_switchconfig *default_conf,
298*7c478bd9Sstevel@tonic-gate 		    char *head_msg, char *tail_msg)
299*7c478bd9Sstevel@tonic-gate {
300*7c478bd9Sstevel@tonic-gate 	struct __nsw_switchconfig *conf;
301*7c478bd9Sstevel@tonic-gate 	enum __nsw_parse_err perr;
302*7c478bd9Sstevel@tonic-gate 	int policy_correct = 1;
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate 	if (default_conf == 0)
305*7c478bd9Sstevel@tonic-gate 		default_conf = &publickey_default;
306*7c478bd9Sstevel@tonic-gate 
307*7c478bd9Sstevel@tonic-gate 	conf = __nsw_getconfig(policy, &perr);
308*7c478bd9Sstevel@tonic-gate 	if (no_switch_policy(conf)) {
309*7c478bd9Sstevel@tonic-gate 		if (!is_switch_policy(default_conf, target_service)) {
310*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
311*7c478bd9Sstevel@tonic-gate 				"\n%s\nThere is no publickey entry in %s.\n",
312*7c478bd9Sstevel@tonic-gate 				head_msg, __NSW_CONFIG_FILE);
313*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
314*7c478bd9Sstevel@tonic-gate 			"The default publickey policy is \"publickey: %s\".\n",
315*7c478bd9Sstevel@tonic-gate 			switch_policy_str(default_conf));
316*7c478bd9Sstevel@tonic-gate 			policy_correct = 0;
317*7c478bd9Sstevel@tonic-gate 		}
318*7c478bd9Sstevel@tonic-gate 	} else if (!is_switch_policy(conf, target_service)) {
319*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
320*7c478bd9Sstevel@tonic-gate 		"\n%s\nThe publickey entry in %s is \"publickey: %s\".\n",
321*7c478bd9Sstevel@tonic-gate 			head_msg, __NSW_CONFIG_FILE,
322*7c478bd9Sstevel@tonic-gate 			switch_policy_str(conf));
323*7c478bd9Sstevel@tonic-gate 		policy_correct = 0;
324*7c478bd9Sstevel@tonic-gate 	}
325*7c478bd9Sstevel@tonic-gate 	/* should we exit ? */
326*7c478bd9Sstevel@tonic-gate 	if (policy_correct == 0)
327*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
328*7c478bd9Sstevel@tonic-gate 		"It should be \"publickey: %s\"%s\n\n",
329*7c478bd9Sstevel@tonic-gate 			target_service, tail_msg);
330*7c478bd9Sstevel@tonic-gate 	if (conf)
331*7c478bd9Sstevel@tonic-gate 		__nsw_freeconfig(conf);
332*7c478bd9Sstevel@tonic-gate 
333*7c478bd9Sstevel@tonic-gate 	return (policy_correct);
334*7c478bd9Sstevel@tonic-gate }
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate int
337*7c478bd9Sstevel@tonic-gate get_pk_source(char *pk_service)
338*7c478bd9Sstevel@tonic-gate {
339*7c478bd9Sstevel@tonic-gate 	int db = 0, got_from_switch = 0;
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate 	/* No service specified, try to figure out from switch */
342*7c478bd9Sstevel@tonic-gate 	if (pk_service == 0) {
343*7c478bd9Sstevel@tonic-gate 		pk_service = first_and_only_switch_policy("publickey", 0,
344*7c478bd9Sstevel@tonic-gate 				"ERROR:");
345*7c478bd9Sstevel@tonic-gate 		if (pk_service == 0)
346*7c478bd9Sstevel@tonic-gate 			return (0);
347*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout,
348*7c478bd9Sstevel@tonic-gate 			"Updating %s publickey database.\n",
349*7c478bd9Sstevel@tonic-gate 			pk_service);
350*7c478bd9Sstevel@tonic-gate 		got_from_switch = 1;
351*7c478bd9Sstevel@tonic-gate 	}
352*7c478bd9Sstevel@tonic-gate 
353*7c478bd9Sstevel@tonic-gate 	if (strcmp(pk_service, "ldap") == 0)
354*7c478bd9Sstevel@tonic-gate 		db = PK_LDAP;
355*7c478bd9Sstevel@tonic-gate 	else if (strcmp(pk_service, "nisplus") == 0)
356*7c478bd9Sstevel@tonic-gate 		db = PK_NISPLUS;
357*7c478bd9Sstevel@tonic-gate 	else if (strcmp(pk_service, "nis") == 0)
358*7c478bd9Sstevel@tonic-gate 		db = PK_YP;
359*7c478bd9Sstevel@tonic-gate 	else if (strcmp(pk_service, "files") == 0)
360*7c478bd9Sstevel@tonic-gate 		db = PK_FILES;
361*7c478bd9Sstevel@tonic-gate 	else return (0);
362*7c478bd9Sstevel@tonic-gate 
363*7c478bd9Sstevel@tonic-gate 	/*
364*7c478bd9Sstevel@tonic-gate 	 * If we didn't get service name from switch, check switch
365*7c478bd9Sstevel@tonic-gate 	 * and print warning about it source of publickeys if not unique
366*7c478bd9Sstevel@tonic-gate 	 */
367*7c478bd9Sstevel@tonic-gate 	if (got_from_switch == 0)
368*7c478bd9Sstevel@tonic-gate 		check_switch_policy("publickey", pk_service, 0, "WARNING:",
369*7c478bd9Sstevel@tonic-gate 				    db == PK_FILES ? "" :
370*7c478bd9Sstevel@tonic-gate 			    "; add 'files' if you want the 'nobody' key.");
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate 
373*7c478bd9Sstevel@tonic-gate 	return (db); /* all passed */
374*7c478bd9Sstevel@tonic-gate }
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate /* ***************************** keylogin stuff *************************** */
378*7c478bd9Sstevel@tonic-gate int
379*7c478bd9Sstevel@tonic-gate keylogin(char *netname, char *secret)
380*7c478bd9Sstevel@tonic-gate {
381*7c478bd9Sstevel@tonic-gate 	struct key_netstarg netst;
382*7c478bd9Sstevel@tonic-gate 
383*7c478bd9Sstevel@tonic-gate 	netst.st_pub_key[0] = 0;
384*7c478bd9Sstevel@tonic-gate 	memcpy(netst.st_priv_key, secret, HEXKEYBYTES);
385*7c478bd9Sstevel@tonic-gate 	netst.st_netname = netname;
386*7c478bd9Sstevel@tonic-gate 
387*7c478bd9Sstevel@tonic-gate #ifdef NFS_AUTH
388*7c478bd9Sstevel@tonic-gate 	nra.authtype = AUTH_DES;	/* only revoke DES creds */
389*7c478bd9Sstevel@tonic-gate 	nra.uid = getuid();		/* use the real uid */
390*7c478bd9Sstevel@tonic-gate 	if (_nfssys(NFS_REVAUTH, &nra) < 0) {
391*7c478bd9Sstevel@tonic-gate 		perror("Warning: NFS credentials not destroyed");
392*7c478bd9Sstevel@tonic-gate 		err = 1;
393*7c478bd9Sstevel@tonic-gate 	}
394*7c478bd9Sstevel@tonic-gate #endif
395*7c478bd9Sstevel@tonic-gate 
396*7c478bd9Sstevel@tonic-gate 
397*7c478bd9Sstevel@tonic-gate 	/* do actual key login */
398*7c478bd9Sstevel@tonic-gate 	if (key_setnet(&netst) < 0) {
399*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
400*7c478bd9Sstevel@tonic-gate 			"Could not set %s's secret key\n", netname);
401*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "May be the keyserv is down?\n");
402*7c478bd9Sstevel@tonic-gate 		return (0);
403*7c478bd9Sstevel@tonic-gate 	}
404*7c478bd9Sstevel@tonic-gate 
405*7c478bd9Sstevel@tonic-gate 	return (1);
406*7c478bd9Sstevel@tonic-gate }
407*7c478bd9Sstevel@tonic-gate 
408*7c478bd9Sstevel@tonic-gate /*
409*7c478bd9Sstevel@tonic-gate  * XXX unused routine.
410*7c478bd9Sstevel@tonic-gate  * Can not locate any routine that is using this write_rootkey()
411*7c478bd9Sstevel@tonic-gate  * function. There are 2 other write_rootkey() routines defined in chkey.c
412*7c478bd9Sstevel@tonic-gate  * and in cmd/rpcsvc/nis/utils/nisaddcred/makedhextcred.c.
413*7c478bd9Sstevel@tonic-gate  *
414*7c478bd9Sstevel@tonic-gate  * write unencrypted secret key into root key file
415*7c478bd9Sstevel@tonic-gate  */
416*7c478bd9Sstevel@tonic-gate write_rootkey(char *secret)
417*7c478bd9Sstevel@tonic-gate {
418*7c478bd9Sstevel@tonic-gate 	char sbuf[HEXKEYBYTES+2];
419*7c478bd9Sstevel@tonic-gate 	int fd, len;
420*7c478bd9Sstevel@tonic-gate 
421*7c478bd9Sstevel@tonic-gate 	strcpy(sbuf, secret);
422*7c478bd9Sstevel@tonic-gate 	strcat(sbuf, "\n");
423*7c478bd9Sstevel@tonic-gate 	len = strlen(sbuf);
424*7c478bd9Sstevel@tonic-gate 	sbuf[len] = '\0';
425*7c478bd9Sstevel@tonic-gate 	unlink(ROOTKEY_FILE);
426*7c478bd9Sstevel@tonic-gate 	if ((fd = open(ROOTKEY_FILE, O_WRONLY+O_CREAT, 0600)) != -1) {
427*7c478bd9Sstevel@tonic-gate 		write(fd, sbuf, len+1);
428*7c478bd9Sstevel@tonic-gate 		close(fd);
429*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, "Wrote secret key into %s\n",
430*7c478bd9Sstevel@tonic-gate 			ROOTKEY_FILE);
431*7c478bd9Sstevel@tonic-gate 	} else {
432*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Could not open %s for update\n",
433*7c478bd9Sstevel@tonic-gate 			ROOTKEY_FILE);
434*7c478bd9Sstevel@tonic-gate 		perror(ROOTKEY_FILE);
435*7c478bd9Sstevel@tonic-gate 	}
436*7c478bd9Sstevel@tonic-gate }
437*7c478bd9Sstevel@tonic-gate 
438*7c478bd9Sstevel@tonic-gate /* ****************************** nisplus stuff ************************* */
439*7c478bd9Sstevel@tonic-gate /* most of it gotten from nisaddcred */
440*7c478bd9Sstevel@tonic-gate 
441*7c478bd9Sstevel@tonic-gate 
442*7c478bd9Sstevel@tonic-gate /* Check that someone else don't have the same auth information already */
443*7c478bd9Sstevel@tonic-gate static
444*7c478bd9Sstevel@tonic-gate nis_error
445*7c478bd9Sstevel@tonic-gate auth_exists(char *princname, char *auth_name, char *auth_type, char *domain)
446*7c478bd9Sstevel@tonic-gate {
447*7c478bd9Sstevel@tonic-gate 	char sname[NIS_MAXNAMELEN+MAXHOSTNAMELEN+64];
448*7c478bd9Sstevel@tonic-gate 	nis_result	*res;
449*7c478bd9Sstevel@tonic-gate 	nis_error status;
450*7c478bd9Sstevel@tonic-gate 	char *foundprinc;
451*7c478bd9Sstevel@tonic-gate 
452*7c478bd9Sstevel@tonic-gate 	(void) sprintf(sname, "[auth_name=%s,auth_type=%s],%s.%s",
453*7c478bd9Sstevel@tonic-gate 		auth_name, auth_type, CRED_TABLE, domain);
454*7c478bd9Sstevel@tonic-gate 	if (sname[strlen(sname)-1] != '.')
455*7c478bd9Sstevel@tonic-gate 		strcat(sname, ".");
456*7c478bd9Sstevel@tonic-gate 	/* Don't want FOLLOW_PATH here */
457*7c478bd9Sstevel@tonic-gate 	res = nis_list(sname,
458*7c478bd9Sstevel@tonic-gate 		MASTER_ONLY+USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS,
459*7c478bd9Sstevel@tonic-gate 		NULL, NULL);
460*7c478bd9Sstevel@tonic-gate 
461*7c478bd9Sstevel@tonic-gate 	status = res->status;
462*7c478bd9Sstevel@tonic-gate 	switch (res->status) {
463*7c478bd9Sstevel@tonic-gate 	case NIS_NOTFOUND:
464*7c478bd9Sstevel@tonic-gate 		break;
465*7c478bd9Sstevel@tonic-gate 	case NIS_TRYAGAIN :
466*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
467*7c478bd9Sstevel@tonic-gate 			"%s: NIS+ server busy, try again later.\n",
468*7c478bd9Sstevel@tonic-gate 			program_name);
469*7c478bd9Sstevel@tonic-gate 		exit(1);
470*7c478bd9Sstevel@tonic-gate 	case NIS_PERMISSION :
471*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
472*7c478bd9Sstevel@tonic-gate 		"%s: insufficient permission to look up old credentials.\n",
473*7c478bd9Sstevel@tonic-gate 			program_name);
474*7c478bd9Sstevel@tonic-gate 		exit(1);
475*7c478bd9Sstevel@tonic-gate 	case NIS_SUCCESS:
476*7c478bd9Sstevel@tonic-gate 		foundprinc = ENTRY_VAL(res->objects.objects_val, 0);
477*7c478bd9Sstevel@tonic-gate 		if (nis_dir_cmp(foundprinc, princname) != SAME_NAME) {
478*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
479*7c478bd9Sstevel@tonic-gate 	"%s: %s credentials with auth_name '%s' already belong to '%s'.\n",
480*7c478bd9Sstevel@tonic-gate 			program_name, auth_type, auth_name, foundprinc);
481*7c478bd9Sstevel@tonic-gate 			exit(1);
482*7c478bd9Sstevel@tonic-gate 		}
483*7c478bd9Sstevel@tonic-gate 		break;
484*7c478bd9Sstevel@tonic-gate 	default:
485*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
486*7c478bd9Sstevel@tonic-gate 			"%s: error looking at cred table, NIS+ error: %s\n",
487*7c478bd9Sstevel@tonic-gate 			program_name, nis_sperrno(res->status));
488*7c478bd9Sstevel@tonic-gate 		exit(1);
489*7c478bd9Sstevel@tonic-gate 	}
490*7c478bd9Sstevel@tonic-gate 	nis_freeresult(res);
491*7c478bd9Sstevel@tonic-gate 	return (status);
492*7c478bd9Sstevel@tonic-gate }
493*7c478bd9Sstevel@tonic-gate 
494*7c478bd9Sstevel@tonic-gate /* Returns 0 if check fails; 1 if successful. */
495*7c478bd9Sstevel@tonic-gate static int
496*7c478bd9Sstevel@tonic-gate sanity_checks(nis_princ, netname, domain)
497*7c478bd9Sstevel@tonic-gate char	*nis_princ,
498*7c478bd9Sstevel@tonic-gate 	*netname,
499*7c478bd9Sstevel@tonic-gate 	*domain;
500*7c478bd9Sstevel@tonic-gate {
501*7c478bd9Sstevel@tonic-gate 	char	netdomainaux[MAXHOSTNAMELEN+1];
502*7c478bd9Sstevel@tonic-gate 	char	*princdomain, *netdomain;
503*7c478bd9Sstevel@tonic-gate 	int	len;
504*7c478bd9Sstevel@tonic-gate 
505*7c478bd9Sstevel@tonic-gate 	/* Sanity check 0. Do we have a nis+ principal name to work with? */
506*7c478bd9Sstevel@tonic-gate 	if (nis_princ == NULL) {
507*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
508*7c478bd9Sstevel@tonic-gate 		"%s: you must create a \"LOCAL\" credential for '%s' first.\n",
509*7c478bd9Sstevel@tonic-gate 			program_name, netname);
510*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "\tSee nisaddcred(1).\n");
511*7c478bd9Sstevel@tonic-gate 		return (0);
512*7c478bd9Sstevel@tonic-gate 	}
513*7c478bd9Sstevel@tonic-gate 
514*7c478bd9Sstevel@tonic-gate 	/* Sanity check 0.5.  NIS+ principal names must be dotted. */
515*7c478bd9Sstevel@tonic-gate 	len = strlen(nis_princ);
516*7c478bd9Sstevel@tonic-gate 	if (nis_princ[len-1] != '.') {
517*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
518*7c478bd9Sstevel@tonic-gate 		"%s: invalid principal name: '%s' (forgot ending dot?).\n",
519*7c478bd9Sstevel@tonic-gate 			program_name, nis_princ);
520*7c478bd9Sstevel@tonic-gate 		return (0);
521*7c478bd9Sstevel@tonic-gate 	}
522*7c478bd9Sstevel@tonic-gate 
523*7c478bd9Sstevel@tonic-gate 	/* Sanity check 1.  We only deal with one type of netnames. */
524*7c478bd9Sstevel@tonic-gate 	if (strncmp(netname, "unix", 4) != 0) {
525*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
526*7c478bd9Sstevel@tonic-gate 			"%s: unrecognized netname type: '%s'.\n",
527*7c478bd9Sstevel@tonic-gate 			program_name, netname);
528*7c478bd9Sstevel@tonic-gate 		return (0);
529*7c478bd9Sstevel@tonic-gate 	}
530*7c478bd9Sstevel@tonic-gate 
531*7c478bd9Sstevel@tonic-gate 	/* Sanity check 2.  Should only add DES cred in home domain. */
532*7c478bd9Sstevel@tonic-gate 	princdomain = nis_domain_of(nis_princ);
533*7c478bd9Sstevel@tonic-gate 	if (strcasecmp(princdomain, domain) != 0) {
534*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
535*7c478bd9Sstevel@tonic-gate "%s: domain of principal '%s' does not match destination domain '%s'.\n",
536*7c478bd9Sstevel@tonic-gate 			program_name, nis_princ, domain);
537*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
538*7c478bd9Sstevel@tonic-gate 	"Should only add DES credential of principal in its home domain\n");
539*7c478bd9Sstevel@tonic-gate 		return (0);
540*7c478bd9Sstevel@tonic-gate 	}
541*7c478bd9Sstevel@tonic-gate 
542*7c478bd9Sstevel@tonic-gate 	/*
543*7c478bd9Sstevel@tonic-gate 	 * Sanity check 3:  Make sure netname's domain same as principal's
544*7c478bd9Sstevel@tonic-gate 	 * and don't have extraneous dot at the end.
545*7c478bd9Sstevel@tonic-gate 	 */
546*7c478bd9Sstevel@tonic-gate 	netdomain = (char *)strchr(netname, '@');
547*7c478bd9Sstevel@tonic-gate 	if (! netdomain || netname[strlen(netname)-1] == '.') {
548*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: invalid netname: '%s'. \n",
549*7c478bd9Sstevel@tonic-gate 			program_name, netname);
550*7c478bd9Sstevel@tonic-gate 		return (0);
551*7c478bd9Sstevel@tonic-gate 	}
552*7c478bd9Sstevel@tonic-gate 	netdomain++; /* skip '@' */
553*7c478bd9Sstevel@tonic-gate 	/* make sure we don't run into buffer overflow */
554*7c478bd9Sstevel@tonic-gate 	if (strlen(netdomain) > sizeof (netdomainaux))
555*7c478bd9Sstevel@tonic-gate 		return (0);
556*7c478bd9Sstevel@tonic-gate 	strcpy(netdomainaux, netdomain);
557*7c478bd9Sstevel@tonic-gate 	if (netdomainaux[strlen(netdomainaux)-1] != '.')
558*7c478bd9Sstevel@tonic-gate 		strcat(netdomainaux, ".");
559*7c478bd9Sstevel@tonic-gate 
560*7c478bd9Sstevel@tonic-gate 	if (strcasecmp(princdomain, netdomainaux) != 0) {
561*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
562*7c478bd9Sstevel@tonic-gate 	"%s: domain of netname %s should be same as that of principal %s\n",
563*7c478bd9Sstevel@tonic-gate 			program_name, netname, nis_princ);
564*7c478bd9Sstevel@tonic-gate 		return (0);
565*7c478bd9Sstevel@tonic-gate 	}
566*7c478bd9Sstevel@tonic-gate 
567*7c478bd9Sstevel@tonic-gate 	/* Another principal owns same credentials? (exits if that happens) */
568*7c478bd9Sstevel@tonic-gate 	(void) auth_exists(nis_princ, netname, "DES", domain);
569*7c478bd9Sstevel@tonic-gate 
570*7c478bd9Sstevel@tonic-gate 	return (1); /* all passed */
571*7c478bd9Sstevel@tonic-gate }
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate 
574*7c478bd9Sstevel@tonic-gate /*
575*7c478bd9Sstevel@tonic-gate  * Similar to nis_local_principal in "nis_subr.c" except
576*7c478bd9Sstevel@tonic-gate  * this gets the results from the MASTER_ONLY and no FOLLOW_PATH.
577*7c478bd9Sstevel@tonic-gate  * We only want the master because we'll be making updates there,
578*7c478bd9Sstevel@tonic-gate  * and also the replicas may not have seen the 'nisaddacred local'
579*7c478bd9Sstevel@tonic-gate  * that may have just occurred.
580*7c478bd9Sstevel@tonic-gate  * Returns NULL if not found.
581*7c478bd9Sstevel@tonic-gate  */
582*7c478bd9Sstevel@tonic-gate char *
583*7c478bd9Sstevel@tonic-gate get_nisplus_principal(directory, uid)
584*7c478bd9Sstevel@tonic-gate char	*directory;
585*7c478bd9Sstevel@tonic-gate uid_t	uid;
586*7c478bd9Sstevel@tonic-gate {
587*7c478bd9Sstevel@tonic-gate 	nis_result	*res;
588*7c478bd9Sstevel@tonic-gate 	char		buf[NIS_MAXNAMELEN + 1];
589*7c478bd9Sstevel@tonic-gate 	int		status;
590*7c478bd9Sstevel@tonic-gate 	static	char	principal_name[NIS_MAXNAMELEN + 1];
591*7c478bd9Sstevel@tonic-gate 
592*7c478bd9Sstevel@tonic-gate 	if (uid == 0)
593*7c478bd9Sstevel@tonic-gate 		return (nis_local_host());
594*7c478bd9Sstevel@tonic-gate 
595*7c478bd9Sstevel@tonic-gate 	/* buf is enough to hold the string, no buffer overflow */
596*7c478bd9Sstevel@tonic-gate 	(void) sprintf(buf, "[auth_name=%d,auth_type=LOCAL],%s.%s",
597*7c478bd9Sstevel@tonic-gate 		uid, CRED_TABLE, directory);
598*7c478bd9Sstevel@tonic-gate 
599*7c478bd9Sstevel@tonic-gate 	if (buf[strlen(buf)-1] != '.')
600*7c478bd9Sstevel@tonic-gate 		strcat(buf, ".");
601*7c478bd9Sstevel@tonic-gate 
602*7c478bd9Sstevel@tonic-gate 	res = nis_list(buf,
603*7c478bd9Sstevel@tonic-gate 		MASTER_ONLY+USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS,
604*7c478bd9Sstevel@tonic-gate 		NULL, NULL);
605*7c478bd9Sstevel@tonic-gate 
606*7c478bd9Sstevel@tonic-gate 	if (res == NULL) {
607*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
608*7c478bd9Sstevel@tonic-gate 			"%s: unable to get result from NIS+ server.",
609*7c478bd9Sstevel@tonic-gate 			program_name);
610*7c478bd9Sstevel@tonic-gate 		exit(1);
611*7c478bd9Sstevel@tonic-gate 	}
612*7c478bd9Sstevel@tonic-gate 	switch (res->status) {
613*7c478bd9Sstevel@tonic-gate 	case NIS_SUCCESS:
614*7c478bd9Sstevel@tonic-gate 		if (res->objects.objects_len > 1) {
615*7c478bd9Sstevel@tonic-gate 			/*
616*7c478bd9Sstevel@tonic-gate 			 * More than one principal with same uid?
617*7c478bd9Sstevel@tonic-gate 			 * something wrong with cred table. Should be unique
618*7c478bd9Sstevel@tonic-gate 			 * Warn user and continue.
619*7c478bd9Sstevel@tonic-gate 			 */
620*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
621*7c478bd9Sstevel@tonic-gate 			"%s: LOCAL entry for %d in directory %s not unique",
622*7c478bd9Sstevel@tonic-gate 				program_name, uid, directory);
623*7c478bd9Sstevel@tonic-gate 		}
624*7c478bd9Sstevel@tonic-gate 		/* make sure we don't run into buffer overflow */
625*7c478bd9Sstevel@tonic-gate 		if (strlen(ENTRY_VAL(res->objects.objects_val, 0)) >
626*7c478bd9Sstevel@tonic-gate 			sizeof (principal_name))
627*7c478bd9Sstevel@tonic-gate 			return (NULL);
628*7c478bd9Sstevel@tonic-gate 		strcpy(principal_name,
629*7c478bd9Sstevel@tonic-gate 			ENTRY_VAL(res->objects.objects_val, 0));
630*7c478bd9Sstevel@tonic-gate 		nis_freeresult(res);
631*7c478bd9Sstevel@tonic-gate 		return (principal_name);
632*7c478bd9Sstevel@tonic-gate 
633*7c478bd9Sstevel@tonic-gate 	case NIS_NOTFOUND:
634*7c478bd9Sstevel@tonic-gate 		nis_freeresult(res);
635*7c478bd9Sstevel@tonic-gate 		return (NULL);
636*7c478bd9Sstevel@tonic-gate 
637*7c478bd9Sstevel@tonic-gate 	case NIS_TRYAGAIN :
638*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
639*7c478bd9Sstevel@tonic-gate 			"%s: NIS+ server busy, try again later.\n",
640*7c478bd9Sstevel@tonic-gate 			program_name);
641*7c478bd9Sstevel@tonic-gate 		exit(1);
642*7c478bd9Sstevel@tonic-gate 
643*7c478bd9Sstevel@tonic-gate 	case NIS_PERMISSION :
644*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
645*7c478bd9Sstevel@tonic-gate 			"%s: insufficient permission to update credentials.\n",
646*7c478bd9Sstevel@tonic-gate 			program_name);
647*7c478bd9Sstevel@tonic-gate 		exit(1);
648*7c478bd9Sstevel@tonic-gate 
649*7c478bd9Sstevel@tonic-gate 	default:
650*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
651*7c478bd9Sstevel@tonic-gate 			"%s: error talking to server, NIS+ error: %s.\n",
652*7c478bd9Sstevel@tonic-gate 			program_name, nis_sperrno(res->status));
653*7c478bd9Sstevel@tonic-gate 		exit(1);
654*7c478bd9Sstevel@tonic-gate 	}
655*7c478bd9Sstevel@tonic-gate 	return (NULL);
656*7c478bd9Sstevel@tonic-gate }
657*7c478bd9Sstevel@tonic-gate 
658*7c478bd9Sstevel@tonic-gate 
659*7c478bd9Sstevel@tonic-gate 
660*7c478bd9Sstevel@tonic-gate /* Check whether this principal already has this type of credentials */
661*7c478bd9Sstevel@tonic-gate static nis_error
662*7c478bd9Sstevel@tonic-gate cred_exists(char *nisprinc, char *flavor, char *domain)
663*7c478bd9Sstevel@tonic-gate {
664*7c478bd9Sstevel@tonic-gate 	char sname[NIS_MAXNAMELEN+MAXHOSTNAMELEN+64];
665*7c478bd9Sstevel@tonic-gate 	nis_result	*res;
666*7c478bd9Sstevel@tonic-gate 	nis_error status;
667*7c478bd9Sstevel@tonic-gate 
668*7c478bd9Sstevel@tonic-gate 	(void) sprintf(sname, "[cname=\"%s\",auth_type=%s],%s.%s",
669*7c478bd9Sstevel@tonic-gate 		nisprinc, flavor, CRED_TABLE, domain);
670*7c478bd9Sstevel@tonic-gate 	if (sname[strlen(sname)-1] != '.')
671*7c478bd9Sstevel@tonic-gate 		strcat(sname, ".");
672*7c478bd9Sstevel@tonic-gate 
673*7c478bd9Sstevel@tonic-gate 	/* Don't want FOLLOW_PATH here */
674*7c478bd9Sstevel@tonic-gate 	res = nis_list(sname,
675*7c478bd9Sstevel@tonic-gate 		MASTER_ONLY+USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS,
676*7c478bd9Sstevel@tonic-gate 		NULL, NULL);
677*7c478bd9Sstevel@tonic-gate 
678*7c478bd9Sstevel@tonic-gate 	status = res->status;
679*7c478bd9Sstevel@tonic-gate 	switch (status) {
680*7c478bd9Sstevel@tonic-gate 	case NIS_NOTFOUND:
681*7c478bd9Sstevel@tonic-gate 		break;
682*7c478bd9Sstevel@tonic-gate 	case NIS_TRYAGAIN:
683*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
684*7c478bd9Sstevel@tonic-gate 			"%s: NIS+ server busy, try again later.\n",
685*7c478bd9Sstevel@tonic-gate 			program_name);
686*7c478bd9Sstevel@tonic-gate 		exit(1);
687*7c478bd9Sstevel@tonic-gate 	case NIS_PERMISSION:
688*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
689*7c478bd9Sstevel@tonic-gate 		"%s: insufficient permission to look at credentials table\n",
690*7c478bd9Sstevel@tonic-gate 			program_name);
691*7c478bd9Sstevel@tonic-gate 		exit(1);
692*7c478bd9Sstevel@tonic-gate 	case NIS_SUCCESS:
693*7c478bd9Sstevel@tonic-gate 	case NIS_S_SUCCESS:
694*7c478bd9Sstevel@tonic-gate 		break;
695*7c478bd9Sstevel@tonic-gate 	default:
696*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
697*7c478bd9Sstevel@tonic-gate 			"%s: error looking at cred table, NIS+ error: %s\n",
698*7c478bd9Sstevel@tonic-gate 			program_name, nis_sperrno(res->status));
699*7c478bd9Sstevel@tonic-gate 		exit(1);
700*7c478bd9Sstevel@tonic-gate 	}
701*7c478bd9Sstevel@tonic-gate 	nis_freeresult(res);
702*7c478bd9Sstevel@tonic-gate 	return (status);
703*7c478bd9Sstevel@tonic-gate }
704*7c478bd9Sstevel@tonic-gate 
705*7c478bd9Sstevel@tonic-gate 
706*7c478bd9Sstevel@tonic-gate /* Returns 0 if operation fails; 1 if successful. */
707*7c478bd9Sstevel@tonic-gate static
708*7c478bd9Sstevel@tonic-gate int
709*7c478bd9Sstevel@tonic-gate modify_cred_obj(obj, domain)
710*7c478bd9Sstevel@tonic-gate 	char *domain;
711*7c478bd9Sstevel@tonic-gate 	nis_object *obj;
712*7c478bd9Sstevel@tonic-gate {
713*7c478bd9Sstevel@tonic-gate 	int status = 0;
714*7c478bd9Sstevel@tonic-gate 	char sname[NIS_MAXNAMELEN+1];
715*7c478bd9Sstevel@tonic-gate 	nis_result	*res;
716*7c478bd9Sstevel@tonic-gate 
717*7c478bd9Sstevel@tonic-gate 	(void) sprintf(sname, "%s.%s", CRED_TABLE, domain);
718*7c478bd9Sstevel@tonic-gate 	res = nis_modify_entry(sname, obj, 0);
719*7c478bd9Sstevel@tonic-gate 	switch (res->status) {
720*7c478bd9Sstevel@tonic-gate 	case NIS_TRYAGAIN :
721*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
722*7c478bd9Sstevel@tonic-gate 			"%s: NIS+ server busy, try again later.\n",
723*7c478bd9Sstevel@tonic-gate 			program_name);
724*7c478bd9Sstevel@tonic-gate 		exit(1);
725*7c478bd9Sstevel@tonic-gate 	case NIS_PERMISSION :
726*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
727*7c478bd9Sstevel@tonic-gate 			"%s: insufficient permission to update credentials.\n",
728*7c478bd9Sstevel@tonic-gate 			program_name);
729*7c478bd9Sstevel@tonic-gate 		exit(1);
730*7c478bd9Sstevel@tonic-gate 	case NIS_SUCCESS :
731*7c478bd9Sstevel@tonic-gate 		status = 1;
732*7c478bd9Sstevel@tonic-gate 		break;
733*7c478bd9Sstevel@tonic-gate 	default:
734*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
735*7c478bd9Sstevel@tonic-gate 			"%s: error modifying credential, NIS+ error: %s.\n",
736*7c478bd9Sstevel@tonic-gate 			program_name, nis_sperrno(res->status));
737*7c478bd9Sstevel@tonic-gate 		exit(1);
738*7c478bd9Sstevel@tonic-gate 	}
739*7c478bd9Sstevel@tonic-gate 	nis_freeresult(res);
740*7c478bd9Sstevel@tonic-gate 	return (status);
741*7c478bd9Sstevel@tonic-gate }
742*7c478bd9Sstevel@tonic-gate 
743*7c478bd9Sstevel@tonic-gate 
744*7c478bd9Sstevel@tonic-gate static
745*7c478bd9Sstevel@tonic-gate int
746*7c478bd9Sstevel@tonic-gate add_cred_obj(obj, domain)
747*7c478bd9Sstevel@tonic-gate 	char *domain;
748*7c478bd9Sstevel@tonic-gate 	nis_object *obj;
749*7c478bd9Sstevel@tonic-gate {
750*7c478bd9Sstevel@tonic-gate 	int status = 0;
751*7c478bd9Sstevel@tonic-gate 	char sname[NIS_MAXNAMELEN+1];
752*7c478bd9Sstevel@tonic-gate 	nis_result	*res;
753*7c478bd9Sstevel@tonic-gate 
754*7c478bd9Sstevel@tonic-gate 	/* Assume check for cred_exists performed already */
755*7c478bd9Sstevel@tonic-gate 
756*7c478bd9Sstevel@tonic-gate 	(void) sprintf(sname, "%s.%s", CRED_TABLE, domain);
757*7c478bd9Sstevel@tonic-gate 	res = nis_add_entry(sname, obj, 0);
758*7c478bd9Sstevel@tonic-gate 	switch (res->status) {
759*7c478bd9Sstevel@tonic-gate 	case NIS_TRYAGAIN :
760*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
761*7c478bd9Sstevel@tonic-gate 			"%s: NIS+ server busy, try again later.\n",
762*7c478bd9Sstevel@tonic-gate 			program_name);
763*7c478bd9Sstevel@tonic-gate 		exit(1);
764*7c478bd9Sstevel@tonic-gate 	case NIS_PERMISSION :
765*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
766*7c478bd9Sstevel@tonic-gate 			"%s: insufficient permission to update credentials.\n",
767*7c478bd9Sstevel@tonic-gate 			program_name);
768*7c478bd9Sstevel@tonic-gate 		exit(1);
769*7c478bd9Sstevel@tonic-gate 	case NIS_SUCCESS :
770*7c478bd9Sstevel@tonic-gate 		status = 1;
771*7c478bd9Sstevel@tonic-gate 		break;
772*7c478bd9Sstevel@tonic-gate 	default:
773*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
774*7c478bd9Sstevel@tonic-gate 			"%s: error creating credential, NIS+ error: %s.\n",
775*7c478bd9Sstevel@tonic-gate 			program_name, nis_sperrno(res->status));
776*7c478bd9Sstevel@tonic-gate 		exit(1);
777*7c478bd9Sstevel@tonic-gate 	}
778*7c478bd9Sstevel@tonic-gate 	nis_freeresult(res);
779*7c478bd9Sstevel@tonic-gate 	return (status);
780*7c478bd9Sstevel@tonic-gate }
781*7c478bd9Sstevel@tonic-gate 
782*7c478bd9Sstevel@tonic-gate nis_object *
783*7c478bd9Sstevel@tonic-gate init_entry()
784*7c478bd9Sstevel@tonic-gate {
785*7c478bd9Sstevel@tonic-gate 	static nis_object	obj;
786*7c478bd9Sstevel@tonic-gate 	static entry_col	cred_data[10];
787*7c478bd9Sstevel@tonic-gate 	entry_obj		*eo;
788*7c478bd9Sstevel@tonic-gate 
789*7c478bd9Sstevel@tonic-gate 	memset((char *)(&obj), 0, sizeof (obj));
790*7c478bd9Sstevel@tonic-gate 	memset((char *)(cred_data), 0, sizeof (entry_col) * 10);
791*7c478bd9Sstevel@tonic-gate 
792*7c478bd9Sstevel@tonic-gate 	obj.zo_name = "cred";
793*7c478bd9Sstevel@tonic-gate 	obj.zo_group = "";
794*7c478bd9Sstevel@tonic-gate 	obj.zo_ttl = 43200;
795*7c478bd9Sstevel@tonic-gate 	obj.zo_data.zo_type = NIS_ENTRY_OBJ;
796*7c478bd9Sstevel@tonic-gate 	eo = &(obj.EN_data);
797*7c478bd9Sstevel@tonic-gate 	eo->en_type = "cred_tbl";
798*7c478bd9Sstevel@tonic-gate 	eo->en_cols.en_cols_val = cred_data;
799*7c478bd9Sstevel@tonic-gate 	eo->en_cols.en_cols_len = 5;
800*7c478bd9Sstevel@tonic-gate 	cred_data[4].ec_flags |= EN_CRYPT;
801*7c478bd9Sstevel@tonic-gate 	return (&obj);
802*7c478bd9Sstevel@tonic-gate }
803*7c478bd9Sstevel@tonic-gate 
804*7c478bd9Sstevel@tonic-gate 
805*7c478bd9Sstevel@tonic-gate static char	*attrFilter[] = {
806*7c478bd9Sstevel@tonic-gate 	"objectclass",
807*7c478bd9Sstevel@tonic-gate 	"nispublickey",
808*7c478bd9Sstevel@tonic-gate 	"nissecretkey",
809*7c478bd9Sstevel@tonic-gate 	(char *)NULL
810*7c478bd9Sstevel@tonic-gate };
811*7c478bd9Sstevel@tonic-gate 
812*7c478bd9Sstevel@tonic-gate 
813*7c478bd9Sstevel@tonic-gate /* Determines if there is a NisKeyObject objectclass in a given entry */
814*7c478bd9Sstevel@tonic-gate static int
815*7c478bd9Sstevel@tonic-gate ldap_keyobj_exist(ns_ldap_entry_t *entry)
816*7c478bd9Sstevel@tonic-gate {
817*7c478bd9Sstevel@tonic-gate 	char		**fattrs;
818*7c478bd9Sstevel@tonic-gate 
819*7c478bd9Sstevel@tonic-gate 	fattrs = __ns_ldap_getAttr(entry, "objectClass");
820*7c478bd9Sstevel@tonic-gate 
821*7c478bd9Sstevel@tonic-gate 	if (fattrs == NULL)
822*7c478bd9Sstevel@tonic-gate 		return (1);
823*7c478bd9Sstevel@tonic-gate 
824*7c478bd9Sstevel@tonic-gate 	while (*fattrs) {
825*7c478bd9Sstevel@tonic-gate 		if (strcasecmp("NisKeyObject", *fattrs) == 0)
826*7c478bd9Sstevel@tonic-gate 			return (1);
827*7c478bd9Sstevel@tonic-gate 		fattrs++;
828*7c478bd9Sstevel@tonic-gate 	}
829*7c478bd9Sstevel@tonic-gate 
830*7c478bd9Sstevel@tonic-gate 	return (0);
831*7c478bd9Sstevel@tonic-gate }
832*7c478bd9Sstevel@tonic-gate 
833*7c478bd9Sstevel@tonic-gate 
834*7c478bd9Sstevel@tonic-gate static char *keyAttrs[] = {
835*7c478bd9Sstevel@tonic-gate 	"nispublickey",
836*7c478bd9Sstevel@tonic-gate 	"nissecretkey",
837*7c478bd9Sstevel@tonic-gate 	NULL
838*7c478bd9Sstevel@tonic-gate };
839*7c478bd9Sstevel@tonic-gate 
840*7c478bd9Sstevel@tonic-gate /*
841*7c478bd9Sstevel@tonic-gate  * Replace or append new attribute value(s) to an attribute.
842*7c478bd9Sstevel@tonic-gate  * Don't care about memory leaks, because program is short running.
843*7c478bd9Sstevel@tonic-gate  */
844*7c478bd9Sstevel@tonic-gate 
845*7c478bd9Sstevel@tonic-gate static int
846*7c478bd9Sstevel@tonic-gate ldap_attr_mod(ns_ldap_entry_t *entry,
847*7c478bd9Sstevel@tonic-gate 	    char *mechname,
848*7c478bd9Sstevel@tonic-gate 	    char *public,
849*7c478bd9Sstevel@tonic-gate 	    ns_ldap_attr_t **pkeyattrs,
850*7c478bd9Sstevel@tonic-gate 	    char *crypt,
851*7c478bd9Sstevel@tonic-gate 	    ns_ldap_attr_t **ckeyattrs)
852*7c478bd9Sstevel@tonic-gate {
853*7c478bd9Sstevel@tonic-gate 	char		**alist[2];
854*7c478bd9Sstevel@tonic-gate 	char		*keys[2];
855*7c478bd9Sstevel@tonic-gate 
856*7c478bd9Sstevel@tonic-gate 	char		*mechfilter;
857*7c478bd9Sstevel@tonic-gate 	int		mechfilterlen;
858*7c478bd9Sstevel@tonic-gate 	int		q = 0;
859*7c478bd9Sstevel@tonic-gate 	int		i, j;
860*7c478bd9Sstevel@tonic-gate 	int		keycount[] = {0, 0};
861*7c478bd9Sstevel@tonic-gate 	ns_ldap_attr_t	*attrs;
862*7c478bd9Sstevel@tonic-gate 
863*7c478bd9Sstevel@tonic-gate 	keys[0] = public;
864*7c478bd9Sstevel@tonic-gate 	keys[1] = crypt;
865*7c478bd9Sstevel@tonic-gate 
866*7c478bd9Sstevel@tonic-gate 	mechfilter = (char *)malloc(strlen(mechname) + 3);
867*7c478bd9Sstevel@tonic-gate 	if (mechfilter == NULL)
868*7c478bd9Sstevel@tonic-gate 		return (0);
869*7c478bd9Sstevel@tonic-gate 	sprintf(mechfilter, "{%s}", mechname);
870*7c478bd9Sstevel@tonic-gate 	mechfilterlen = strlen(mechfilter);
871*7c478bd9Sstevel@tonic-gate 
872*7c478bd9Sstevel@tonic-gate 	for (q = 0; keyAttrs[q] != NULL; q++) {
873*7c478bd9Sstevel@tonic-gate 		int		found = 0;
874*7c478bd9Sstevel@tonic-gate 
875*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < entry->attr_count; i++) {
876*7c478bd9Sstevel@tonic-gate 			int		rep = 0;
877*7c478bd9Sstevel@tonic-gate 			ns_ldap_attr_t	*attr = entry->attr_pair[i];
878*7c478bd9Sstevel@tonic-gate 			char		*name = attr->attrname;
879*7c478bd9Sstevel@tonic-gate 			int		count = 0;
880*7c478bd9Sstevel@tonic-gate 
881*7c478bd9Sstevel@tonic-gate 			if (strcasecmp(keyAttrs[q], name) == 0) {
882*7c478bd9Sstevel@tonic-gate 				found++;
883*7c478bd9Sstevel@tonic-gate 				count = attr->value_count;
884*7c478bd9Sstevel@tonic-gate 		alist[q] = (char **)malloc(sizeof (char *) * (count + 1));
885*7c478bd9Sstevel@tonic-gate 				if (alist[q] == NULL)
886*7c478bd9Sstevel@tonic-gate 					return (0);
887*7c478bd9Sstevel@tonic-gate 				alist[q][attr->value_count] = NULL;
888*7c478bd9Sstevel@tonic-gate 				for (j = 0; j < attr->value_count; j++) {
889*7c478bd9Sstevel@tonic-gate 					char	*val = attr->attrvalue[j];
890*7c478bd9Sstevel@tonic-gate 					if (strncasecmp(val, mechfilter,
891*7c478bd9Sstevel@tonic-gate 							mechfilterlen) == 0) {
892*7c478bd9Sstevel@tonic-gate 						/* Replace entry */
893*7c478bd9Sstevel@tonic-gate 						rep++;
894*7c478bd9Sstevel@tonic-gate 						alist[q][j] = keys[q];
895*7c478bd9Sstevel@tonic-gate 					} else
896*7c478bd9Sstevel@tonic-gate 						alist[q][j] = val;
897*7c478bd9Sstevel@tonic-gate 					++keycount[q];
898*7c478bd9Sstevel@tonic-gate 				}
899*7c478bd9Sstevel@tonic-gate 				if (!rep) {
900*7c478bd9Sstevel@tonic-gate 					/* Add entry to list */
901*7c478bd9Sstevel@tonic-gate 					alist[q] = (char **)realloc(alist[q],
902*7c478bd9Sstevel@tonic-gate 					    sizeof (char *) * (count + 2));
903*7c478bd9Sstevel@tonic-gate 					if (alist[q] == NULL)
904*7c478bd9Sstevel@tonic-gate 						return (0);
905*7c478bd9Sstevel@tonic-gate 					alist[q][attr->value_count + 1] = NULL;
906*7c478bd9Sstevel@tonic-gate 					alist[q][attr->value_count] = keys[q];
907*7c478bd9Sstevel@tonic-gate 					++keycount[q];
908*7c478bd9Sstevel@tonic-gate 				}
909*7c478bd9Sstevel@tonic-gate 			}
910*7c478bd9Sstevel@tonic-gate 		}
911*7c478bd9Sstevel@tonic-gate 		if (!found) {
912*7c478bd9Sstevel@tonic-gate 			/* Attribute does not exist, add entry anyways */
913*7c478bd9Sstevel@tonic-gate 			alist[q] = (char **)malloc(sizeof (char *) * 2);
914*7c478bd9Sstevel@tonic-gate 			if (alist[q] == NULL)
915*7c478bd9Sstevel@tonic-gate 				return (0);
916*7c478bd9Sstevel@tonic-gate 			alist[q][0] = keys[q];
917*7c478bd9Sstevel@tonic-gate 			alist[q][1] = NULL;
918*7c478bd9Sstevel@tonic-gate 			++keycount[q];
919*7c478bd9Sstevel@tonic-gate 		}
920*7c478bd9Sstevel@tonic-gate 	}
921*7c478bd9Sstevel@tonic-gate 	if ((attrs = (ns_ldap_attr_t *)calloc(1,
922*7c478bd9Sstevel@tonic-gate 			sizeof (ns_ldap_attr_t))) == NULL)
923*7c478bd9Sstevel@tonic-gate 		return (0);
924*7c478bd9Sstevel@tonic-gate 	attrs->attrname = "nisPublicKey";
925*7c478bd9Sstevel@tonic-gate 	attrs->attrvalue = alist[0];
926*7c478bd9Sstevel@tonic-gate 	attrs->value_count = keycount[0];
927*7c478bd9Sstevel@tonic-gate 	*pkeyattrs = attrs;
928*7c478bd9Sstevel@tonic-gate 
929*7c478bd9Sstevel@tonic-gate 	if ((attrs = (ns_ldap_attr_t *)calloc(1,
930*7c478bd9Sstevel@tonic-gate 			sizeof (ns_ldap_attr_t))) == NULL)
931*7c478bd9Sstevel@tonic-gate 		return (0);
932*7c478bd9Sstevel@tonic-gate 	attrs->attrname = "nisSecretKey";
933*7c478bd9Sstevel@tonic-gate 	attrs->attrvalue = alist[1];
934*7c478bd9Sstevel@tonic-gate 	attrs->value_count = keycount[1];
935*7c478bd9Sstevel@tonic-gate 	*ckeyattrs = attrs;
936*7c478bd9Sstevel@tonic-gate 	return (1);
937*7c478bd9Sstevel@tonic-gate }
938*7c478bd9Sstevel@tonic-gate 
939*7c478bd9Sstevel@tonic-gate 
940*7c478bd9Sstevel@tonic-gate /*
941*7c478bd9Sstevel@tonic-gate  * Do the actual Add or update of attributes in attrs.
942*7c478bd9Sstevel@tonic-gate  * The parameter 'update4host' is a flag that tells the function which
943*7c478bd9Sstevel@tonic-gate  * DN and password should be used to bind to ldap. If it is an update
944*7c478bd9Sstevel@tonic-gate  * for a host (update4host > 0), the two parameters "bindDN" and
945*7c478bd9Sstevel@tonic-gate  * "bindPasswd" would be used to bind as the directory manager,
946*7c478bd9Sstevel@tonic-gate  * otherwise "dn" and "passwd" would be used to bind as an individual
947*7c478bd9Sstevel@tonic-gate  * user.
948*7c478bd9Sstevel@tonic-gate  */
949*7c478bd9Sstevel@tonic-gate static void
950*7c478bd9Sstevel@tonic-gate update_ldap_attr(const char *dn,
951*7c478bd9Sstevel@tonic-gate 		ns_ldap_attr_t **attrs,
952*7c478bd9Sstevel@tonic-gate 		const char *passwd,
953*7c478bd9Sstevel@tonic-gate 		int add,
954*7c478bd9Sstevel@tonic-gate 		int update4host,
955*7c478bd9Sstevel@tonic-gate 		const char *bindDN,
956*7c478bd9Sstevel@tonic-gate 		const char *bindPasswd)
957*7c478bd9Sstevel@tonic-gate {
958*7c478bd9Sstevel@tonic-gate 	int		ldaprc;
959*7c478bd9Sstevel@tonic-gate 	int		authstried = 0;
960*7c478bd9Sstevel@tonic-gate 	char		*msg;
961*7c478bd9Sstevel@tonic-gate 	char		*ldap_pw;
962*7c478bd9Sstevel@tonic-gate 	char		**certpath = NULL;
963*7c478bd9Sstevel@tonic-gate 	ns_auth_t	**app;
964*7c478bd9Sstevel@tonic-gate 	ns_auth_t	**authpp = NULL;
965*7c478bd9Sstevel@tonic-gate 	ns_auth_t	*authp = NULL;
966*7c478bd9Sstevel@tonic-gate 	ns_cred_t	*credp;
967*7c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*errorp = NULL;
968*7c478bd9Sstevel@tonic-gate 	int		status;
969*7c478bd9Sstevel@tonic-gate 
970*7c478bd9Sstevel@tonic-gate 	if ((credp = (ns_cred_t *)calloc(1, sizeof (ns_cred_t))) == NULL) {
971*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Can not allocate cred buffer.\n");
972*7c478bd9Sstevel@tonic-gate 		goto out;
973*7c478bd9Sstevel@tonic-gate 	}
974*7c478bd9Sstevel@tonic-gate 
975*7c478bd9Sstevel@tonic-gate 	/*
976*7c478bd9Sstevel@tonic-gate 	 * if this is an update for host, use the bindDN from the
977*7c478bd9Sstevel@tonic-gate 	 * command prompt, otherwise use user's DN directly.
978*7c478bd9Sstevel@tonic-gate 	 */
979*7c478bd9Sstevel@tonic-gate 	if (update4host)
980*7c478bd9Sstevel@tonic-gate 		credp->cred.unix_cred.userID = strdup(bindDN);
981*7c478bd9Sstevel@tonic-gate 	else
982*7c478bd9Sstevel@tonic-gate 		credp->cred.unix_cred.userID = strdup(dn);
983*7c478bd9Sstevel@tonic-gate 
984*7c478bd9Sstevel@tonic-gate 	if (credp->cred.unix_cred.userID == NULL) {
985*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Memory allocation failure (userID)\n");
986*7c478bd9Sstevel@tonic-gate 		goto out;
987*7c478bd9Sstevel@tonic-gate 	}
988*7c478bd9Sstevel@tonic-gate 
989*7c478bd9Sstevel@tonic-gate 	if (update4host) {
990*7c478bd9Sstevel@tonic-gate 		credp->cred.unix_cred.passwd = strdup(bindPasswd);
991*7c478bd9Sstevel@tonic-gate 	} else {
992*7c478bd9Sstevel@tonic-gate 		if (passwd)
993*7c478bd9Sstevel@tonic-gate 			credp->cred.unix_cred.passwd = strdup(passwd);
994*7c478bd9Sstevel@tonic-gate 		else {
995*7c478bd9Sstevel@tonic-gate 			/* Make sure a valid password is received. */
996*7c478bd9Sstevel@tonic-gate 			status = get_ldap_bindPassword(&ldap_pw);
997*7c478bd9Sstevel@tonic-gate 
998*7c478bd9Sstevel@tonic-gate 			if (status != PROMPTGET_SUCCESS) {
999*7c478bd9Sstevel@tonic-gate 				if (!ldap_pw)
1000*7c478bd9Sstevel@tonic-gate 					free(ldap_pw);
1001*7c478bd9Sstevel@tonic-gate 				goto out;
1002*7c478bd9Sstevel@tonic-gate 			}
1003*7c478bd9Sstevel@tonic-gate 			credp->cred.unix_cred.passwd = ldap_pw;
1004*7c478bd9Sstevel@tonic-gate 		}
1005*7c478bd9Sstevel@tonic-gate 	}
1006*7c478bd9Sstevel@tonic-gate 
1007*7c478bd9Sstevel@tonic-gate 	if (credp->cred.unix_cred.passwd == NULL) {
1008*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Memory allocation failure (passwd)\n");
1009*7c478bd9Sstevel@tonic-gate 		goto out;
1010*7c478bd9Sstevel@tonic-gate 	}
1011*7c478bd9Sstevel@tonic-gate 
1012*7c478bd9Sstevel@tonic-gate 	/* get host certificate path, if one is configured */
1013*7c478bd9Sstevel@tonic-gate 	if (__ns_ldap_getParam(NS_LDAP_HOST_CERTPATH_P,
1014*7c478bd9Sstevel@tonic-gate 		(void ***)&certpath, &errorp) != NS_LDAP_SUCCESS)
1015*7c478bd9Sstevel@tonic-gate 		goto out;
1016*7c478bd9Sstevel@tonic-gate 
1017*7c478bd9Sstevel@tonic-gate 	if (certpath && *certpath)
1018*7c478bd9Sstevel@tonic-gate 		credp->hostcertpath = *certpath;
1019*7c478bd9Sstevel@tonic-gate 
1020*7c478bd9Sstevel@tonic-gate 	/* Load the service specific authentication method */
1021*7c478bd9Sstevel@tonic-gate 	if (__ns_ldap_getServiceAuthMethods("keyserv", &authpp, &errorp) !=
1022*7c478bd9Sstevel@tonic-gate 		NS_LDAP_SUCCESS)
1023*7c478bd9Sstevel@tonic-gate 		goto out;
1024*7c478bd9Sstevel@tonic-gate 
1025*7c478bd9Sstevel@tonic-gate 	/*
1026*7c478bd9Sstevel@tonic-gate 	 * if authpp is null, there is no serviceAuthenticationMethod
1027*7c478bd9Sstevel@tonic-gate 	 * try default authenticationMethod
1028*7c478bd9Sstevel@tonic-gate 	 */
1029*7c478bd9Sstevel@tonic-gate 	if (authpp == NULL) {
1030*7c478bd9Sstevel@tonic-gate 		if (__ns_ldap_getParam(NS_LDAP_AUTH_P, (void ***)&authpp,
1031*7c478bd9Sstevel@tonic-gate 			&errorp) != NS_LDAP_SUCCESS)
1032*7c478bd9Sstevel@tonic-gate 			goto out;
1033*7c478bd9Sstevel@tonic-gate 	}
1034*7c478bd9Sstevel@tonic-gate 
1035*7c478bd9Sstevel@tonic-gate 	/*
1036*7c478bd9Sstevel@tonic-gate 	 * if authpp is still null, then can not authenticate, log
1037*7c478bd9Sstevel@tonic-gate 	 * error message and return error
1038*7c478bd9Sstevel@tonic-gate 	 */
1039*7c478bd9Sstevel@tonic-gate 	if (authpp == NULL) {
1040*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "No LDAP authentication method configured.\n"
1041*7c478bd9Sstevel@tonic-gate 			" configured.\n");
1042*7c478bd9Sstevel@tonic-gate 		goto out;
1043*7c478bd9Sstevel@tonic-gate 	}
1044*7c478bd9Sstevel@tonic-gate 
1045*7c478bd9Sstevel@tonic-gate 	/*
1046*7c478bd9Sstevel@tonic-gate 	 * Walk the array and try all authentication methods in order except
1047*7c478bd9Sstevel@tonic-gate 	 * for "none".
1048*7c478bd9Sstevel@tonic-gate 	 */
1049*7c478bd9Sstevel@tonic-gate 	for (app = authpp; *app; app++) {
1050*7c478bd9Sstevel@tonic-gate 		authp = *app;
1051*7c478bd9Sstevel@tonic-gate 		/* what about disabling other mechanisms? "tls:sasl/EXTERNAL" */
1052*7c478bd9Sstevel@tonic-gate 		if (authp->type == NS_LDAP_AUTH_NONE)
1053*7c478bd9Sstevel@tonic-gate 			continue;
1054*7c478bd9Sstevel@tonic-gate 		authstried++;
1055*7c478bd9Sstevel@tonic-gate 		credp->auth.type = authp->type;
1056*7c478bd9Sstevel@tonic-gate 		credp->auth.tlstype = authp->tlstype;
1057*7c478bd9Sstevel@tonic-gate 		credp->auth.saslmech = authp->saslmech;
1058*7c478bd9Sstevel@tonic-gate 		credp->auth.saslopt = authp->saslopt;
1059*7c478bd9Sstevel@tonic-gate 
1060*7c478bd9Sstevel@tonic-gate 		if (add == TRUE)
1061*7c478bd9Sstevel@tonic-gate 			ldaprc = __ns_ldap_addAttr("publickey", dn,
1062*7c478bd9Sstevel@tonic-gate 				(const ns_ldap_attr_t * const *)attrs,
1063*7c478bd9Sstevel@tonic-gate 				credp, NULL, &errorp);
1064*7c478bd9Sstevel@tonic-gate 		else
1065*7c478bd9Sstevel@tonic-gate 			ldaprc = __ns_ldap_repAttr("publickey", dn,
1066*7c478bd9Sstevel@tonic-gate 				(const ns_ldap_attr_t * const *)attrs,
1067*7c478bd9Sstevel@tonic-gate 				credp, NULL, &errorp);
1068*7c478bd9Sstevel@tonic-gate 		if (ldaprc == NS_LDAP_SUCCESS) {
1069*7c478bd9Sstevel@tonic-gate 			/* clean up ns_cred_t structure in memory */
1070*7c478bd9Sstevel@tonic-gate 			if (credp != NULL)
1071*7c478bd9Sstevel@tonic-gate 				(void) __ns_ldap_freeCred(&credp);
1072*7c478bd9Sstevel@tonic-gate 			return;
1073*7c478bd9Sstevel@tonic-gate 		}
1074*7c478bd9Sstevel@tonic-gate 
1075*7c478bd9Sstevel@tonic-gate 		/* XXX add checking for cases of authentication errors */
1076*7c478bd9Sstevel@tonic-gate 		if ((ldaprc == NS_LDAP_INTERNAL) &&
1077*7c478bd9Sstevel@tonic-gate 			((errorp->status == LDAP_INAPPROPRIATE_AUTH) ||
1078*7c478bd9Sstevel@tonic-gate 			(errorp->status == LDAP_INVALID_CREDENTIALS))) {
1079*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "LDAP authentication failed.\n");
1080*7c478bd9Sstevel@tonic-gate 			goto out;
1081*7c478bd9Sstevel@tonic-gate 		}
1082*7c478bd9Sstevel@tonic-gate 	}
1083*7c478bd9Sstevel@tonic-gate 	if (authstried == 0)
1084*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "No legal authentication method configured.\n");
1085*7c478bd9Sstevel@tonic-gate 
1086*7c478bd9Sstevel@tonic-gate out:
1087*7c478bd9Sstevel@tonic-gate 	/* clean up ns_cred_t structure in memory */
1088*7c478bd9Sstevel@tonic-gate 	if (credp != NULL) {
1089*7c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeCred(&credp);
1090*7c478bd9Sstevel@tonic-gate 	}
1091*7c478bd9Sstevel@tonic-gate 
1092*7c478bd9Sstevel@tonic-gate 	if (errorp) {
1093*7c478bd9Sstevel@tonic-gate 		__ns_ldap_err2str(errorp->status, &msg);
1094*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "LDAP error: %s.\n", msg);
1095*7c478bd9Sstevel@tonic-gate 	}
1096*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name);
1097*7c478bd9Sstevel@tonic-gate 	exit(1);
1098*7c478bd9Sstevel@tonic-gate }
1099*7c478bd9Sstevel@tonic-gate 
1100*7c478bd9Sstevel@tonic-gate 
1101*7c478bd9Sstevel@tonic-gate /*
1102*7c478bd9Sstevel@tonic-gate  * Update LDAP nisplublickey entry with new key information via SLDAP.
1103*7c478bd9Sstevel@tonic-gate  * Free and clean up memory that stores credential data soon after
1104*7c478bd9Sstevel@tonic-gate  * they are not used or an error comes up.
1105*7c478bd9Sstevel@tonic-gate  */
1106*7c478bd9Sstevel@tonic-gate int
1107*7c478bd9Sstevel@tonic-gate ldap_update(char *mechname,
1108*7c478bd9Sstevel@tonic-gate 	    char *netname,
1109*7c478bd9Sstevel@tonic-gate 	    char *public,
1110*7c478bd9Sstevel@tonic-gate 	    char *crypt,
1111*7c478bd9Sstevel@tonic-gate 	    char *passwd)
1112*7c478bd9Sstevel@tonic-gate {
1113*7c478bd9Sstevel@tonic-gate 	char		*netnamecpy;
1114*7c478bd9Sstevel@tonic-gate 	char		*id;
1115*7c478bd9Sstevel@tonic-gate 	char		*domain;
1116*7c478bd9Sstevel@tonic-gate 	char		*dn;
1117*7c478bd9Sstevel@tonic-gate 	char		*db;
1118*7c478bd9Sstevel@tonic-gate 	char		*filter;
1119*7c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*errorp;
1120*7c478bd9Sstevel@tonic-gate 	char		*pkeyatval, *ckeyatval;
1121*7c478bd9Sstevel@tonic-gate 	ns_ldap_result_t	*res;
1122*7c478bd9Sstevel@tonic-gate 	ns_ldap_attr_t	*pattrs, *cattrs;
1123*7c478bd9Sstevel@tonic-gate 	int		update4host = FALSE;
1124*7c478bd9Sstevel@tonic-gate 	char		*bindDN = NULL;
1125*7c478bd9Sstevel@tonic-gate 	char		*bindPasswd = NULL;
1126*7c478bd9Sstevel@tonic-gate 	int		status;
1127*7c478bd9Sstevel@tonic-gate 
1128*7c478bd9Sstevel@tonic-gate 	/* Generate DN */
1129*7c478bd9Sstevel@tonic-gate 	if ((netnamecpy = strdup(netname)) == NULL)
1130*7c478bd9Sstevel@tonic-gate 		return (0);
1131*7c478bd9Sstevel@tonic-gate 	if (((id = strchr(netnamecpy, '.')) == NULL) ||
1132*7c478bd9Sstevel@tonic-gate 	    ((domain = strchr(netnamecpy, '@')) == NULL))
1133*7c478bd9Sstevel@tonic-gate 		return (0);
1134*7c478bd9Sstevel@tonic-gate 	else {
1135*7c478bd9Sstevel@tonic-gate 		*domain++ = '\0';
1136*7c478bd9Sstevel@tonic-gate 		*id++ = '\0';
1137*7c478bd9Sstevel@tonic-gate 
1138*7c478bd9Sstevel@tonic-gate 		id = strdup(id);
1139*7c478bd9Sstevel@tonic-gate 		if (id == NULL) {
1140*7c478bd9Sstevel@tonic-gate 			free(netnamecpy);
1141*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "LDAP memory error (id)\n");
1142*7c478bd9Sstevel@tonic-gate 			return (0);
1143*7c478bd9Sstevel@tonic-gate 		}
1144*7c478bd9Sstevel@tonic-gate 		domain = strdup(domain);
1145*7c478bd9Sstevel@tonic-gate 		if (domain == NULL) {
1146*7c478bd9Sstevel@tonic-gate 			free(netnamecpy);
1147*7c478bd9Sstevel@tonic-gate 			free(id);
1148*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "LDAP memory error (domain)\n");
1149*7c478bd9Sstevel@tonic-gate 			return (0);
1150*7c478bd9Sstevel@tonic-gate 		}
1151*7c478bd9Sstevel@tonic-gate 		free(netnamecpy);
1152*7c478bd9Sstevel@tonic-gate 	}
1153*7c478bd9Sstevel@tonic-gate 
1154*7c478bd9Sstevel@tonic-gate 	if (isdigit(*id)) {
1155*7c478bd9Sstevel@tonic-gate 		/* We be user. */
1156*7c478bd9Sstevel@tonic-gate 		__ns_ldap_uid2dn(id, &dn, NULL, &errorp);
1157*7c478bd9Sstevel@tonic-gate 		if (dn == NULL) {
1158*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Could not obtain LDAP dn\n");
1159*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "%s: key-pair(s) unchanged.\n",
1160*7c478bd9Sstevel@tonic-gate 				program_name);
1161*7c478bd9Sstevel@tonic-gate 			exit(1);
1162*7c478bd9Sstevel@tonic-gate 		}
1163*7c478bd9Sstevel@tonic-gate 		db = "passwd";
1164*7c478bd9Sstevel@tonic-gate 		filter = (char *)malloc(strlen(id) + 13);
1165*7c478bd9Sstevel@tonic-gate 		if (filter)
1166*7c478bd9Sstevel@tonic-gate 			sprintf(filter, "(uidnumber=%s)", id);
1167*7c478bd9Sstevel@tonic-gate 		else {
1168*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Can not allocate filter buffer.\n");
1169*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "%s: key-pair(s) unchanged.\n",
1170*7c478bd9Sstevel@tonic-gate 				program_name);
1171*7c478bd9Sstevel@tonic-gate 			exit(1);
1172*7c478bd9Sstevel@tonic-gate 		}
1173*7c478bd9Sstevel@tonic-gate 	} else {
1174*7c478bd9Sstevel@tonic-gate 		/* We be host. */
1175*7c478bd9Sstevel@tonic-gate 		update4host = TRUE;
1176*7c478bd9Sstevel@tonic-gate 
1177*7c478bd9Sstevel@tonic-gate 		__ns_ldap_host2dn(id, NULL, &dn, NULL, &errorp);
1178*7c478bd9Sstevel@tonic-gate 		if (dn == NULL) {
1179*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Could not obtain LDAP dn\n");
1180*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "%s: key-pair(s) unchanged.\n",
1181*7c478bd9Sstevel@tonic-gate 				program_name);
1182*7c478bd9Sstevel@tonic-gate 			exit(1);
1183*7c478bd9Sstevel@tonic-gate 		}
1184*7c478bd9Sstevel@tonic-gate 
1185*7c478bd9Sstevel@tonic-gate 		db = "hosts";
1186*7c478bd9Sstevel@tonic-gate 		filter = (char *)malloc(strlen(id) + 6);
1187*7c478bd9Sstevel@tonic-gate 		if (filter)
1188*7c478bd9Sstevel@tonic-gate 			sprintf(filter, "(cn=%s)", id);
1189*7c478bd9Sstevel@tonic-gate 		else {
1190*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Can not allocate filter buffer.\n");
1191*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "%s: key-pair(s) unchanged.\n",
1192*7c478bd9Sstevel@tonic-gate 				program_name);
1193*7c478bd9Sstevel@tonic-gate 			exit(1);
1194*7c478bd9Sstevel@tonic-gate 		}
1195*7c478bd9Sstevel@tonic-gate 
1196*7c478bd9Sstevel@tonic-gate 		/* Prompt for ldap bind DN for entry udpates */
1197*7c478bd9Sstevel@tonic-gate 		status = get_ldap_bindDN(&bindDN);
1198*7c478bd9Sstevel@tonic-gate 
1199*7c478bd9Sstevel@tonic-gate 		if (status != PROMPTGET_SUCCESS) {
1200*7c478bd9Sstevel@tonic-gate 			FREE_CREDINFO(bindDN);
1201*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
1202*7c478bd9Sstevel@tonic-gate 				"Failed to get a valid LDAP bind DN.\n"
1203*7c478bd9Sstevel@tonic-gate 				"%s: key-pair(s) unchanged.\n",
1204*7c478bd9Sstevel@tonic-gate 				program_name);
1205*7c478bd9Sstevel@tonic-gate 			exit(1);
1206*7c478bd9Sstevel@tonic-gate 		}
1207*7c478bd9Sstevel@tonic-gate 
1208*7c478bd9Sstevel@tonic-gate 		/* Prompt for ldap bind password */
1209*7c478bd9Sstevel@tonic-gate 		status = get_ldap_bindPassword(&bindPasswd);
1210*7c478bd9Sstevel@tonic-gate 
1211*7c478bd9Sstevel@tonic-gate 		if (status != PROMPTGET_SUCCESS) {
1212*7c478bd9Sstevel@tonic-gate 			FREE_CREDINFO(bindPasswd);
1213*7c478bd9Sstevel@tonic-gate 			FREE_CREDINFO(bindDN);
1214*7c478bd9Sstevel@tonic-gate 
1215*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
1216*7c478bd9Sstevel@tonic-gate 				"Failed to get a valid LDAP bind password."
1217*7c478bd9Sstevel@tonic-gate 				"\n%s: key-pair(s) unchanged.\n",
1218*7c478bd9Sstevel@tonic-gate 				program_name);
1219*7c478bd9Sstevel@tonic-gate 			exit(1);
1220*7c478bd9Sstevel@tonic-gate 		}
1221*7c478bd9Sstevel@tonic-gate 	}
1222*7c478bd9Sstevel@tonic-gate 
1223*7c478bd9Sstevel@tonic-gate 	/* Construct attribute values */
1224*7c478bd9Sstevel@tonic-gate 	pkeyatval = (char *)malloc(strlen(mechname) + strlen(public) + 3);
1225*7c478bd9Sstevel@tonic-gate 	if (pkeyatval == NULL) {
1226*7c478bd9Sstevel@tonic-gate 		FREE_CREDINFO(bindPasswd);
1227*7c478bd9Sstevel@tonic-gate 		FREE_CREDINFO(bindDN);
1228*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "LDAP memory error (pkeyatval)\n");
1229*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name);
1230*7c478bd9Sstevel@tonic-gate 		exit(1);
1231*7c478bd9Sstevel@tonic-gate 	}
1232*7c478bd9Sstevel@tonic-gate 	sprintf(pkeyatval, "{%s}%s", mechname, public);
1233*7c478bd9Sstevel@tonic-gate 	ckeyatval = (char *)malloc(strlen(mechname) + strlen(crypt) + 3);
1234*7c478bd9Sstevel@tonic-gate 	if (ckeyatval == NULL) {
1235*7c478bd9Sstevel@tonic-gate 		FREE_CREDINFO(pkeyatval);
1236*7c478bd9Sstevel@tonic-gate 		FREE_CREDINFO(bindPasswd);
1237*7c478bd9Sstevel@tonic-gate 		FREE_CREDINFO(bindDN);
1238*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "LDAP memory error (pkeyatval)\n");
1239*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name);
1240*7c478bd9Sstevel@tonic-gate 		exit(1);
1241*7c478bd9Sstevel@tonic-gate 	}
1242*7c478bd9Sstevel@tonic-gate 	sprintf(ckeyatval, "{%s}%s", mechname, crypt);
1243*7c478bd9Sstevel@tonic-gate 
1244*7c478bd9Sstevel@tonic-gate 	/* Does entry exist? */
1245*7c478bd9Sstevel@tonic-gate 	if ((__ns_ldap_list(db, filter, NULL, (const char **)attrFilter,
1246*7c478bd9Sstevel@tonic-gate 			    NULL, 0, &res, &errorp,
1247*7c478bd9Sstevel@tonic-gate 			    NULL, NULL) == NS_LDAP_SUCCESS) && res == NULL) {
1248*7c478bd9Sstevel@tonic-gate 		FREE_CREDINFO(ckeyatval);
1249*7c478bd9Sstevel@tonic-gate 		FREE_CREDINFO(pkeyatval);
1250*7c478bd9Sstevel@tonic-gate 		FREE_CREDINFO(bindPasswd);
1251*7c478bd9Sstevel@tonic-gate 		FREE_CREDINFO(bindDN);
1252*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "LDAP entry does not exist.\n");
1253*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name);
1254*7c478bd9Sstevel@tonic-gate 		exit(1);
1255*7c478bd9Sstevel@tonic-gate 	}
1256*7c478bd9Sstevel@tonic-gate 
1257*7c478bd9Sstevel@tonic-gate 	/* Entry exists, modify attributes for public and secret keys */
1258*7c478bd9Sstevel@tonic-gate 
1259*7c478bd9Sstevel@tonic-gate 	/* Is there a NisKeyObject in entry? */
1260*7c478bd9Sstevel@tonic-gate 	if (!ldap_keyobj_exist(&res->entry[0])) {
1261*7c478bd9Sstevel@tonic-gate 		/* Add NisKeyObject objectclass and the keys */
1262*7c478bd9Sstevel@tonic-gate 		char	**newattr;
1263*7c478bd9Sstevel@tonic-gate 		ns_ldap_attr_t	*attrs[4]; /* objectclass, pk, sk, NULL */
1264*7c478bd9Sstevel@tonic-gate 
1265*7c478bd9Sstevel@tonic-gate 		/* set objectclass */
1266*7c478bd9Sstevel@tonic-gate 		newattr = (char **)calloc(2, sizeof (char *));
1267*7c478bd9Sstevel@tonic-gate 		newattr[0] = "NisKeyObject";
1268*7c478bd9Sstevel@tonic-gate 		newattr[1] = NULL;
1269*7c478bd9Sstevel@tonic-gate 		if ((attrs[0] = (ns_ldap_attr_t *)calloc(1,
1270*7c478bd9Sstevel@tonic-gate 				sizeof (ns_ldap_attr_t))) == NULL) {
1271*7c478bd9Sstevel@tonic-gate 			FREE_CREDINFO(ckeyatval);
1272*7c478bd9Sstevel@tonic-gate 			FREE_CREDINFO(pkeyatval);
1273*7c478bd9Sstevel@tonic-gate 			FREE_CREDINFO(bindPasswd);
1274*7c478bd9Sstevel@tonic-gate 			FREE_CREDINFO(bindDN);
1275*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Memory allocation failed\n");
1276*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "%s: key-pair(s) unchanged.\n",
1277*7c478bd9Sstevel@tonic-gate 				program_name);
1278*7c478bd9Sstevel@tonic-gate 			exit(1);
1279*7c478bd9Sstevel@tonic-gate 		}
1280*7c478bd9Sstevel@tonic-gate 		attrs[0]->attrname = "objectClass";
1281*7c478bd9Sstevel@tonic-gate 		attrs[0]->attrvalue = newattr;
1282*7c478bd9Sstevel@tonic-gate 		attrs[0]->value_count = 1;
1283*7c478bd9Sstevel@tonic-gate 
1284*7c478bd9Sstevel@tonic-gate 		/* set publickey */
1285*7c478bd9Sstevel@tonic-gate 		newattr = (char **)calloc(2, sizeof (char *));
1286*7c478bd9Sstevel@tonic-gate 		newattr[0] = pkeyatval;
1287*7c478bd9Sstevel@tonic-gate 		newattr[1] = NULL;
1288*7c478bd9Sstevel@tonic-gate 		if ((attrs[1] = (ns_ldap_attr_t *)calloc(1,
1289*7c478bd9Sstevel@tonic-gate 				sizeof (ns_ldap_attr_t))) == NULL) {
1290*7c478bd9Sstevel@tonic-gate 			FREE_CREDINFO(ckeyatval);
1291*7c478bd9Sstevel@tonic-gate 			FREE_CREDINFO(pkeyatval);
1292*7c478bd9Sstevel@tonic-gate 			FREE_CREDINFO(bindPasswd);
1293*7c478bd9Sstevel@tonic-gate 			FREE_CREDINFO(bindDN);
1294*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Memory allocation failed\n");
1295*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "%s: key-pair(s) unchanged.\n",
1296*7c478bd9Sstevel@tonic-gate 				program_name);
1297*7c478bd9Sstevel@tonic-gate 			exit(1);
1298*7c478bd9Sstevel@tonic-gate 		}
1299*7c478bd9Sstevel@tonic-gate 		attrs[1]->attrname = "nisPublicKey";
1300*7c478bd9Sstevel@tonic-gate 		attrs[1]->attrvalue = newattr;
1301*7c478bd9Sstevel@tonic-gate 		attrs[1]->value_count = 1;
1302*7c478bd9Sstevel@tonic-gate 
1303*7c478bd9Sstevel@tonic-gate 		/* set privatekey */
1304*7c478bd9Sstevel@tonic-gate 		newattr = (char **)calloc(2, sizeof (char *));
1305*7c478bd9Sstevel@tonic-gate 		newattr[0] = ckeyatval;
1306*7c478bd9Sstevel@tonic-gate 		newattr[1] = NULL;
1307*7c478bd9Sstevel@tonic-gate 		if ((attrs[2] = (ns_ldap_attr_t *)calloc(1,
1308*7c478bd9Sstevel@tonic-gate 				sizeof (ns_ldap_attr_t))) == NULL) {
1309*7c478bd9Sstevel@tonic-gate 			FREE_CREDINFO(ckeyatval);
1310*7c478bd9Sstevel@tonic-gate 			FREE_CREDINFO(pkeyatval);
1311*7c478bd9Sstevel@tonic-gate 			FREE_CREDINFO(bindPasswd);
1312*7c478bd9Sstevel@tonic-gate 			FREE_CREDINFO(bindDN);
1313*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Memory allocation failed\n");
1314*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "%s: key-pair(s) unchanged.\n",
1315*7c478bd9Sstevel@tonic-gate 				program_name);
1316*7c478bd9Sstevel@tonic-gate 			exit(1);
1317*7c478bd9Sstevel@tonic-gate 		}
1318*7c478bd9Sstevel@tonic-gate 		attrs[2]->attrname = "nisSecretKey";
1319*7c478bd9Sstevel@tonic-gate 		attrs[2]->attrvalue = newattr;
1320*7c478bd9Sstevel@tonic-gate 		attrs[2]->value_count = 1;
1321*7c478bd9Sstevel@tonic-gate 
1322*7c478bd9Sstevel@tonic-gate 		/* terminator */
1323*7c478bd9Sstevel@tonic-gate 		attrs[3] = NULL;
1324*7c478bd9Sstevel@tonic-gate 
1325*7c478bd9Sstevel@tonic-gate 		update_ldap_attr(dn, attrs, passwd, TRUE, update4host,
1326*7c478bd9Sstevel@tonic-gate 				bindDN, bindPasswd);
1327*7c478bd9Sstevel@tonic-gate 	} else {
1328*7c478bd9Sstevel@tonic-gate 		/* object class already exists, replace keys */
1329*7c478bd9Sstevel@tonic-gate 		ns_ldap_attr_t	*attrs[4]; /* objectclass, pk, sk, NULL */
1330*7c478bd9Sstevel@tonic-gate 
1331*7c478bd9Sstevel@tonic-gate 		if (!ldap_attr_mod(&res->entry[0], mechname,
1332*7c478bd9Sstevel@tonic-gate 				pkeyatval, &pattrs,
1333*7c478bd9Sstevel@tonic-gate 				ckeyatval, &cattrs)) {
1334*7c478bd9Sstevel@tonic-gate 			FREE_CREDINFO(ckeyatval);
1335*7c478bd9Sstevel@tonic-gate 			FREE_CREDINFO(pkeyatval);
1336*7c478bd9Sstevel@tonic-gate 			FREE_CREDINFO(bindPasswd);
1337*7c478bd9Sstevel@tonic-gate 			FREE_CREDINFO(bindDN);
1338*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
1339*7c478bd9Sstevel@tonic-gate 				"Could not generate LDAP attribute list.\n");
1340*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
1341*7c478bd9Sstevel@tonic-gate 				"%s: key-pair(s) unchanged.\n", program_name);
1342*7c478bd9Sstevel@tonic-gate 			exit(1);
1343*7c478bd9Sstevel@tonic-gate 		}
1344*7c478bd9Sstevel@tonic-gate 
1345*7c478bd9Sstevel@tonic-gate 		attrs[0] = pattrs;
1346*7c478bd9Sstevel@tonic-gate 		attrs[1] = cattrs;
1347*7c478bd9Sstevel@tonic-gate 		attrs[2] = NULL;
1348*7c478bd9Sstevel@tonic-gate 
1349*7c478bd9Sstevel@tonic-gate 		update_ldap_attr(dn, attrs, passwd, FALSE, update4host,
1350*7c478bd9Sstevel@tonic-gate 				bindDN, bindPasswd);
1351*7c478bd9Sstevel@tonic-gate 	}
1352*7c478bd9Sstevel@tonic-gate 
1353*7c478bd9Sstevel@tonic-gate 	FREE_CREDINFO(ckeyatval);
1354*7c478bd9Sstevel@tonic-gate 	FREE_CREDINFO(pkeyatval);
1355*7c478bd9Sstevel@tonic-gate 	FREE_CREDINFO(bindPasswd);
1356*7c478bd9Sstevel@tonic-gate 	FREE_CREDINFO(bindDN);
1357*7c478bd9Sstevel@tonic-gate 
1358*7c478bd9Sstevel@tonic-gate 	return (0);
1359*7c478bd9Sstevel@tonic-gate }
1360*7c478bd9Sstevel@tonic-gate 
1361*7c478bd9Sstevel@tonic-gate 
1362*7c478bd9Sstevel@tonic-gate /* Returns 0 if successful; -1 if failure. (expected by setpublicmap). */
1363*7c478bd9Sstevel@tonic-gate 
1364*7c478bd9Sstevel@tonic-gate int
1365*7c478bd9Sstevel@tonic-gate nisplus_update(char *netname, char *public, char *secret, nis_name nis_princ)
1366*7c478bd9Sstevel@tonic-gate {
1367*7c478bd9Sstevel@tonic-gate 	nis_object	*obj = init_entry();
1368*7c478bd9Sstevel@tonic-gate 	char	*domain, *netdomain;
1369*7c478bd9Sstevel@tonic-gate 	char	netdomainaux[MAXHOSTNAMELEN + 1];
1370*7c478bd9Sstevel@tonic-gate 	int status, addition;
1371*7c478bd9Sstevel@tonic-gate 
1372*7c478bd9Sstevel@tonic-gate 	/*
1373*7c478bd9Sstevel@tonic-gate 	 * we take the domain given in the netname & the principal
1374*7c478bd9Sstevel@tonic-gate 	 * name if they match otherwise the local domain.
1375*7c478bd9Sstevel@tonic-gate 	 */
1376*7c478bd9Sstevel@tonic-gate 
1377*7c478bd9Sstevel@tonic-gate 	netdomain = (char *)strchr(netname, '@');
1378*7c478bd9Sstevel@tonic-gate 	if (! netdomain) {
1379*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: invalid netname: '%s'. \n",
1380*7c478bd9Sstevel@tonic-gate 			program_name, netname);
1381*7c478bd9Sstevel@tonic-gate 		return (0);
1382*7c478bd9Sstevel@tonic-gate 	}
1383*7c478bd9Sstevel@tonic-gate 	netdomain++; /* skip '@' */
1384*7c478bd9Sstevel@tonic-gate 	/* make sure we don't run into buffer overflow */
1385*7c478bd9Sstevel@tonic-gate 	if (strlen(netdomain) > sizeof (netdomainaux))
1386*7c478bd9Sstevel@tonic-gate 		return (0);
1387*7c478bd9Sstevel@tonic-gate 	strcpy(netdomainaux, netdomain);
1388*7c478bd9Sstevel@tonic-gate 	if (netdomainaux[strlen(netdomainaux) - 1] != '.')
1389*7c478bd9Sstevel@tonic-gate 		strcat(netdomainaux, ".");
1390*7c478bd9Sstevel@tonic-gate 
1391*7c478bd9Sstevel@tonic-gate 	domain = nis_domain_of(nis_princ);
1392*7c478bd9Sstevel@tonic-gate 	if (strcasecmp(domain, netdomainaux) != 0)
1393*7c478bd9Sstevel@tonic-gate 		domain = nis_local_directory();
1394*7c478bd9Sstevel@tonic-gate 
1395*7c478bd9Sstevel@tonic-gate 	if (sanity_checks(nis_princ, netname, domain) == 0)
1396*7c478bd9Sstevel@tonic-gate 		return (-1);
1397*7c478bd9Sstevel@tonic-gate 
1398*7c478bd9Sstevel@tonic-gate 	addition = (cred_exists(nis_princ, "DES", domain) == NIS_NOTFOUND);
1399*7c478bd9Sstevel@tonic-gate 
1400*7c478bd9Sstevel@tonic-gate 	/* Now we have a key pair, build up the cred entry */
1401*7c478bd9Sstevel@tonic-gate 	ENTRY_VAL(obj, 0) = nis_princ;
1402*7c478bd9Sstevel@tonic-gate 	ENTRY_LEN(obj, 0) = strlen(nis_princ) + 1;
1403*7c478bd9Sstevel@tonic-gate 
1404*7c478bd9Sstevel@tonic-gate 	ENTRY_VAL(obj, 1) = "DES";
1405*7c478bd9Sstevel@tonic-gate 	ENTRY_LEN(obj, 1) = 4;
1406*7c478bd9Sstevel@tonic-gate 
1407*7c478bd9Sstevel@tonic-gate 	ENTRY_VAL(obj, 2) = netname;
1408*7c478bd9Sstevel@tonic-gate 	ENTRY_LEN(obj, 2) = strlen(netname) + 1;
1409*7c478bd9Sstevel@tonic-gate 
1410*7c478bd9Sstevel@tonic-gate 	ENTRY_VAL(obj, 3) = public;
1411*7c478bd9Sstevel@tonic-gate 	ENTRY_LEN(obj, 3) = strlen(public) + 1;
1412*7c478bd9Sstevel@tonic-gate 
1413*7c478bd9Sstevel@tonic-gate 	ENTRY_VAL(obj, 4) = secret;
1414*7c478bd9Sstevel@tonic-gate 	ENTRY_LEN(obj, 4) = strlen(secret) + 1;
1415*7c478bd9Sstevel@tonic-gate 
1416*7c478bd9Sstevel@tonic-gate 	if (addition) {
1417*7c478bd9Sstevel@tonic-gate 		obj->zo_owner = nis_princ;
1418*7c478bd9Sstevel@tonic-gate 		obj->zo_group = nis_local_group();
1419*7c478bd9Sstevel@tonic-gate 		obj->zo_domain = domain;
1420*7c478bd9Sstevel@tonic-gate 		/* owner: r, group: rmcd */
1421*7c478bd9Sstevel@tonic-gate 		obj->zo_access = ((NIS_READ_ACC<<16)|
1422*7c478bd9Sstevel@tonic-gate 				(NIS_READ_ACC|NIS_MODIFY_ACC|NIS_CREATE_ACC|
1423*7c478bd9Sstevel@tonic-gate 					NIS_DESTROY_ACC)<<8);
1424*7c478bd9Sstevel@tonic-gate 		status = add_cred_obj(obj, domain);
1425*7c478bd9Sstevel@tonic-gate 	} else {
1426*7c478bd9Sstevel@tonic-gate 		obj->EN_data.en_cols.en_cols_val[3].ec_flags |= EN_MODIFIED;
1427*7c478bd9Sstevel@tonic-gate 		obj->EN_data.en_cols.en_cols_val[4].ec_flags |= EN_MODIFIED;
1428*7c478bd9Sstevel@tonic-gate 		status = modify_cred_obj(obj, domain);
1429*7c478bd9Sstevel@tonic-gate 	}
1430*7c478bd9Sstevel@tonic-gate 
1431*7c478bd9Sstevel@tonic-gate 	return (status == 1 ? 0 : -1);
1432*7c478bd9Sstevel@tonic-gate }
1433