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