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