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