xref: /onnv-gate/usr/src/lib/nsswitch/ldap/common/getkeyent.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <pwd.h>
30*0Sstevel@tonic-gate #include <ctype.h>
31*0Sstevel@tonic-gate #include "ldap_common.h"
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate /* publickey attributes filters */
34*0Sstevel@tonic-gate #define	_KEY_CN			"cn"
35*0Sstevel@tonic-gate #define	_KEY_NISPUBLICKEY	"nisPublickey"
36*0Sstevel@tonic-gate #define	_KEY_NISSECRETKEY	"nisSecretkey"
37*0Sstevel@tonic-gate #define	_KEY_UIDNUMBER		"uidnumber"
38*0Sstevel@tonic-gate 
39*0Sstevel@tonic-gate #define	_F_GETKEY_USER		"(&(objectClass=nisKeyObject)(uidNumber=%s))"
40*0Sstevel@tonic-gate #define	_F_GETKEY_USER_SSD	"(&(%%s)(uidNumber=%s))"
41*0Sstevel@tonic-gate #define	_F_GETKEY_HOST		"(&(objectClass=nisKeyObject)(cn=%s))"
42*0Sstevel@tonic-gate #define	_F_GETKEY_HOST_SSD	"(&(%%s)(cn=%s))"
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate static const char *keys_attrs[] = {
45*0Sstevel@tonic-gate 	_KEY_NISPUBLICKEY,
46*0Sstevel@tonic-gate 	_KEY_NISSECRETKEY,
47*0Sstevel@tonic-gate 	(char *)NULL
48*0Sstevel@tonic-gate };
49*0Sstevel@tonic-gate 
50*0Sstevel@tonic-gate 
51*0Sstevel@tonic-gate /*
52*0Sstevel@tonic-gate  * _nss_ldap_key2ent is the data marshaling method for the publickey getXbyY
53*0Sstevel@tonic-gate  * (e.g., getpublickey() and getsecretkey()) backend processes. This method
54*0Sstevel@tonic-gate  * is called after a successful ldap search has been performed. This method
55*0Sstevel@tonic-gate  * will parse the ldap search values into "public:secret" key string =
56*0Sstevel@tonic-gate  * argp->buf.buffer which the frontend process expects. Three error
57*0Sstevel@tonic-gate  * conditions are expected and returned to nsswitch.
58*0Sstevel@tonic-gate  */
59*0Sstevel@tonic-gate 
60*0Sstevel@tonic-gate static int
61*0Sstevel@tonic-gate _nss_ldap_key2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
62*0Sstevel@tonic-gate {
63*0Sstevel@tonic-gate 	int		nss_result;
64*0Sstevel@tonic-gate 	char		*keytype = (char *)argp->key.pkey.keytype;
65*0Sstevel@tonic-gate 	int		keytypelen = strlen(keytype);
66*0Sstevel@tonic-gate 	char		*key_start = NULL;
67*0Sstevel@tonic-gate 	int		key_len;
68*0Sstevel@tonic-gate 	int		buflen = (size_t)argp->buf.buflen;
69*0Sstevel@tonic-gate 	char		*buffer = (char *)argp->buf.buffer;
70*0Sstevel@tonic-gate 	char		*ceiling = (char *)NULL;
71*0Sstevel@tonic-gate 	ns_ldap_result_t	*result = be->result;
72*0Sstevel@tonic-gate 	char		**key_array;
73*0Sstevel@tonic-gate 
74*0Sstevel@tonic-gate #ifdef DEBUG
75*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getpublikey.c: _nss_ldap_passwd2ent]\n");
76*0Sstevel@tonic-gate #endif /* DEBUG */
77*0Sstevel@tonic-gate 
78*0Sstevel@tonic-gate 	if (!argp->buf.result) {
79*0Sstevel@tonic-gate 		nss_result = (int)NSS_STR_PARSE_ERANGE;
80*0Sstevel@tonic-gate 		goto result_key2ent;
81*0Sstevel@tonic-gate 	}
82*0Sstevel@tonic-gate 	ceiling = buffer + buflen;
83*0Sstevel@tonic-gate 	nss_result = (int)NSS_STR_PARSE_SUCCESS;
84*0Sstevel@tonic-gate 	(void) memset(buffer, 0, buflen);
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate 	/* get the publickey */
87*0Sstevel@tonic-gate 	key_array = __ns_ldap_getAttr(result->entry, _KEY_NISPUBLICKEY);
88*0Sstevel@tonic-gate 	if (key_array == NULL) {
89*0Sstevel@tonic-gate 		nss_result = (int)NSS_STR_PARSE_PARSE;
90*0Sstevel@tonic-gate 		goto result_key2ent;
91*0Sstevel@tonic-gate 	}
92*0Sstevel@tonic-gate 	while (*key_array) {
93*0Sstevel@tonic-gate 		if (strncasecmp(*key_array, keytype, keytypelen) == NULL)
94*0Sstevel@tonic-gate 			break;
95*0Sstevel@tonic-gate 		key_array++;
96*0Sstevel@tonic-gate 	}
97*0Sstevel@tonic-gate 	if (*key_array == NULL) {
98*0Sstevel@tonic-gate 		nss_result = (int)NSS_STR_PARSE_PARSE;
99*0Sstevel@tonic-gate 		goto result_key2ent;
100*0Sstevel@tonic-gate 	}
101*0Sstevel@tonic-gate 
102*0Sstevel@tonic-gate 	key_start = *(key_array) + keytypelen;
103*0Sstevel@tonic-gate 	key_len = strlen(key_start) + 1;
104*0Sstevel@tonic-gate 	if (buffer + key_len + 2 > ceiling) {
105*0Sstevel@tonic-gate 		nss_result = (int)NSS_STR_PARSE_ERANGE;
106*0Sstevel@tonic-gate 		goto result_key2ent;
107*0Sstevel@tonic-gate 	}
108*0Sstevel@tonic-gate 	(void) strncpy(buffer, key_start, key_len);
109*0Sstevel@tonic-gate 	(void) strcat(buffer, ":");
110*0Sstevel@tonic-gate 	buffer += strlen(buffer);
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate 	/* get the secretkey */
113*0Sstevel@tonic-gate 	key_array = __ns_ldap_getAttr(result->entry, _KEY_NISSECRETKEY);
114*0Sstevel@tonic-gate 	if (key_array == NULL) {
115*0Sstevel@tonic-gate 		/*
116*0Sstevel@tonic-gate 		 * if we got this far, it's possible that the secret
117*0Sstevel@tonic-gate 		 * key is actually missing or no permission to read it.
118*0Sstevel@tonic-gate 		 * For the current implementation, we assume that the
119*0Sstevel@tonic-gate 		 * clients have read permission to the secret key.  So,
120*0Sstevel@tonic-gate 		 * the only possibility of reaching this here is due to
121*0Sstevel@tonic-gate 		 * missing secret key.
122*0Sstevel@tonic-gate 		 */
123*0Sstevel@tonic-gate 		nss_result = (int)NSS_STR_PARSE_PARSE;
124*0Sstevel@tonic-gate 		goto result_key2ent;
125*0Sstevel@tonic-gate 	}
126*0Sstevel@tonic-gate 	while (*key_array) {
127*0Sstevel@tonic-gate 		if (strncasecmp(*key_array, keytype, keytypelen) == NULL)
128*0Sstevel@tonic-gate 			break;
129*0Sstevel@tonic-gate 		key_array++;
130*0Sstevel@tonic-gate 	}
131*0Sstevel@tonic-gate 	if (*key_array == NULL) {
132*0Sstevel@tonic-gate 		nss_result = (int)NSS_STR_PARSE_PARSE;
133*0Sstevel@tonic-gate 		goto result_key2ent;
134*0Sstevel@tonic-gate 	}
135*0Sstevel@tonic-gate 
136*0Sstevel@tonic-gate 	key_start = *(key_array) + keytypelen;
137*0Sstevel@tonic-gate 	key_len = strlen(key_start);
138*0Sstevel@tonic-gate 	if (buffer + key_len + 1 > ceiling) {
139*0Sstevel@tonic-gate 		nss_result = (int)NSS_STR_PARSE_ERANGE;
140*0Sstevel@tonic-gate 		goto result_key2ent;
141*0Sstevel@tonic-gate 	}
142*0Sstevel@tonic-gate 	(void) strcat(buffer, key_start);
143*0Sstevel@tonic-gate 
144*0Sstevel@tonic-gate #ifdef DEBUG
145*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getkeys.c: _nss_ldap_key2ent]\n");
146*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\treturn: %s\n", buffer);
147*0Sstevel@tonic-gate #endif /* DEBUG */
148*0Sstevel@tonic-gate 
149*0Sstevel@tonic-gate result_key2ent:
150*0Sstevel@tonic-gate 
151*0Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&be->result);
152*0Sstevel@tonic-gate 	return ((int)nss_result);
153*0Sstevel@tonic-gate }
154*0Sstevel@tonic-gate 
155*0Sstevel@tonic-gate 
156*0Sstevel@tonic-gate /*
157*0Sstevel@tonic-gate  * getkeys gets both the public and secret keys from publickey entry by either
158*0Sstevel@tonic-gate  * uid name or host name. This function constructs an ldap search filter using
159*0Sstevel@tonic-gate  * the name invocation parameter and the getpwnam search filter defined. Once
160*0Sstevel@tonic-gate  * the filter is constructed, we search for a matching entry and marshal the
161*0Sstevel@tonic-gate  * data results into struct passwd for the frontend process. The function
162*0Sstevel@tonic-gate  * _nss_ldap_key2ent performs the data marshaling.
163*0Sstevel@tonic-gate  * The lookups will be done using the proxy credential.  We don't want to use
164*0Sstevel@tonic-gate  * the user's credential for lookup at this point because we don't have any
165*0Sstevel@tonic-gate  * secure transport.
166*0Sstevel@tonic-gate  */
167*0Sstevel@tonic-gate 
168*0Sstevel@tonic-gate static nss_status_t
169*0Sstevel@tonic-gate getkeys(ldap_backend_ptr be, void *a)
170*0Sstevel@tonic-gate {
171*0Sstevel@tonic-gate 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
172*0Sstevel@tonic-gate 	char	searchfilter[SEARCHFILTERLEN];
173*0Sstevel@tonic-gate 	char	userdata[SEARCHFILTERLEN];
174*0Sstevel@tonic-gate 	char	netname[SEARCHFILTERLEN];
175*0Sstevel@tonic-gate 	char	*name, *domain, *p;
176*0Sstevel@tonic-gate 	nss_status_t	rc;
177*0Sstevel@tonic-gate 	int	ret;
178*0Sstevel@tonic-gate 
179*0Sstevel@tonic-gate #ifdef DEBUG
180*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getpwnam.c: getbyname]\n");
181*0Sstevel@tonic-gate #endif /* DEBUG */
182*0Sstevel@tonic-gate 
183*0Sstevel@tonic-gate 	/*
184*0Sstevel@tonic-gate 	 * We need to break it down to find if this is a netname for host
185*0Sstevel@tonic-gate 	 * or user.  We'll pass the domain as is to the LDAP call.
186*0Sstevel@tonic-gate 	 */
187*0Sstevel@tonic-gate 	if (_ldap_filter_name(netname, argp->key.pkey.name, sizeof (netname))
188*0Sstevel@tonic-gate 			!= 0)
189*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
190*0Sstevel@tonic-gate 	domain = strchr(netname, '@');
191*0Sstevel@tonic-gate 	if (!domain)
192*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
193*0Sstevel@tonic-gate 
194*0Sstevel@tonic-gate 	*domain++ = '\0';
195*0Sstevel@tonic-gate 	if ((p = strchr(netname, '.')) == NULL)
196*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
197*0Sstevel@tonic-gate 
198*0Sstevel@tonic-gate 	name = ++p;
199*0Sstevel@tonic-gate 	if (isdigit(*name)) {
200*0Sstevel@tonic-gate 		/* user keys lookup */
201*0Sstevel@tonic-gate 		ret = snprintf(searchfilter, sizeof (searchfilter),
202*0Sstevel@tonic-gate 		    _F_GETKEY_USER, name);
203*0Sstevel@tonic-gate 		if (ret >= sizeof (searchfilter) || ret < 0)
204*0Sstevel@tonic-gate 			return ((nss_status_t)NSS_NOTFOUND);
205*0Sstevel@tonic-gate 
206*0Sstevel@tonic-gate 		ret = snprintf(userdata, sizeof (userdata),
207*0Sstevel@tonic-gate 		    _F_GETKEY_USER_SSD, name);
208*0Sstevel@tonic-gate 		if (ret >= sizeof (userdata) || ret < 0)
209*0Sstevel@tonic-gate 			return ((nss_status_t)NSS_NOTFOUND);
210*0Sstevel@tonic-gate 
211*0Sstevel@tonic-gate 		rc = (nss_status_t)_nss_ldap_lookup(be, argp,
212*0Sstevel@tonic-gate 				_PASSWD, searchfilter, domain,
213*0Sstevel@tonic-gate 				_merge_SSD_filter, userdata);
214*0Sstevel@tonic-gate 	} else {
215*0Sstevel@tonic-gate 		/* host keys lookup */
216*0Sstevel@tonic-gate 		ret = snprintf(searchfilter, sizeof (searchfilter),
217*0Sstevel@tonic-gate 		    _F_GETKEY_HOST, name);
218*0Sstevel@tonic-gate 		if (ret >= sizeof (searchfilter) || ret < 0)
219*0Sstevel@tonic-gate 			return ((nss_status_t)NSS_NOTFOUND);
220*0Sstevel@tonic-gate 
221*0Sstevel@tonic-gate 		ret = snprintf(userdata, sizeof (userdata),
222*0Sstevel@tonic-gate 		    _F_GETKEY_HOST_SSD, name);
223*0Sstevel@tonic-gate 		if (ret >= sizeof (userdata) || ret < 0)
224*0Sstevel@tonic-gate 			return ((nss_status_t)NSS_NOTFOUND);
225*0Sstevel@tonic-gate 
226*0Sstevel@tonic-gate 		rc = (nss_status_t)_nss_ldap_lookup(be, argp,
227*0Sstevel@tonic-gate 				_HOSTS, searchfilter, domain,
228*0Sstevel@tonic-gate 				_merge_SSD_filter, userdata);
229*0Sstevel@tonic-gate 	}
230*0Sstevel@tonic-gate 	return (rc);
231*0Sstevel@tonic-gate }
232*0Sstevel@tonic-gate 
233*0Sstevel@tonic-gate 
234*0Sstevel@tonic-gate static ldap_backend_op_t keys_ops[] = {
235*0Sstevel@tonic-gate 	_nss_ldap_destr,
236*0Sstevel@tonic-gate 	0,
237*0Sstevel@tonic-gate 	0,
238*0Sstevel@tonic-gate 	0,
239*0Sstevel@tonic-gate 	getkeys
240*0Sstevel@tonic-gate };
241*0Sstevel@tonic-gate 
242*0Sstevel@tonic-gate 
243*0Sstevel@tonic-gate /*
244*0Sstevel@tonic-gate  * _nss_ldap_publickey_constr is where life begins. This function calls the
245*0Sstevel@tonic-gate  * generic ldap constructor function to define and build the abstract
246*0Sstevel@tonic-gate  * data types required to support ldap operations.
247*0Sstevel@tonic-gate  */
248*0Sstevel@tonic-gate 
249*0Sstevel@tonic-gate /*ARGSUSED0*/
250*0Sstevel@tonic-gate nss_backend_t *
251*0Sstevel@tonic-gate _nss_ldap_publickey_constr(const char *dummy1, const char *dummy2,
252*0Sstevel@tonic-gate 			const char *dummy3)
253*0Sstevel@tonic-gate {
254*0Sstevel@tonic-gate 
255*0Sstevel@tonic-gate #ifdef DEBUG
256*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getkeys.c: _nss_ldap_keys_constr]\n");
257*0Sstevel@tonic-gate #endif /* DEBUG */
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate 	return ((nss_backend_t *)_nss_ldap_constr(keys_ops,
260*0Sstevel@tonic-gate 		    sizeof (keys_ops)/sizeof (keys_ops[0]),
261*0Sstevel@tonic-gate 		    _PUBLICKEY, keys_attrs, _nss_ldap_key2ent));
262*0Sstevel@tonic-gate }
263