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