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 <rpc/rpcent.h> 30*0Sstevel@tonic-gate #include "ns_internal.h" 31*0Sstevel@tonic-gate #include "ldap_common.h" 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate /* rpc attributes filters */ 34*0Sstevel@tonic-gate #define _R_NAME "cn" 35*0Sstevel@tonic-gate #define _R_NUMBER "oncrpcnumber" 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate 38*0Sstevel@tonic-gate #define _F_GETRPCBYNAME "(&(objectClass=oncRpc)(cn=%s))" 39*0Sstevel@tonic-gate #define _F_GETRPCBYNAME_SSD "(&(%%s)(cn=%s))" 40*0Sstevel@tonic-gate #define _F_GETRPCBYNUMBER "(&(objectClass=oncRpc)(oncRpcNumber=%d))" 41*0Sstevel@tonic-gate #define _F_GETRPCBYNUMBER_SSD "(&(%%s)(oncRpcNumber=%d))" 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate static const char *rpc_attrs[] = { 44*0Sstevel@tonic-gate _R_NAME, 45*0Sstevel@tonic-gate _R_NUMBER, 46*0Sstevel@tonic-gate (char *)NULL 47*0Sstevel@tonic-gate }; 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate /* 50*0Sstevel@tonic-gate * _nss_ldap_rpc2ent is the data marshaling method for the rpc getXbyY 51*0Sstevel@tonic-gate * (e.g., getbyname(), getbynumber(), getrpcent()) backend processes. 52*0Sstevel@tonic-gate * This method is called after a successful ldap search has been performed. 53*0Sstevel@tonic-gate * This method will parse the ldap search values into *rpc = (struct 54*0Sstevel@tonic-gate * rpcent *)argp->buf.result which the frontend process expects. Three 55*0Sstevel@tonic-gate * error conditions are expected and returned to nsswitch. 56*0Sstevel@tonic-gate */ 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate static int 59*0Sstevel@tonic-gate _nss_ldap_rpc2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp) 60*0Sstevel@tonic-gate { 61*0Sstevel@tonic-gate int i, j; 62*0Sstevel@tonic-gate int nss_result; 63*0Sstevel@tonic-gate int buflen = (int)0; 64*0Sstevel@tonic-gate int firstime = (int)1; 65*0Sstevel@tonic-gate unsigned long len = 0L; 66*0Sstevel@tonic-gate char **mp, *cname = NULL; 67*0Sstevel@tonic-gate char *buffer = (char *)NULL; 68*0Sstevel@tonic-gate char *ceiling = (char *)NULL; 69*0Sstevel@tonic-gate struct rpcent *rpc = (struct rpcent *)NULL; 70*0Sstevel@tonic-gate ns_ldap_result_t *result = be->result; 71*0Sstevel@tonic-gate ns_ldap_attr_t *attrptr; 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate buffer = (char *)argp->buf.buffer; 74*0Sstevel@tonic-gate buflen = (size_t)argp->buf.buflen; 75*0Sstevel@tonic-gate if (!argp->buf.result) { 76*0Sstevel@tonic-gate nss_result = (int)NSS_STR_PARSE_ERANGE; 77*0Sstevel@tonic-gate goto result_rpc2ent; 78*0Sstevel@tonic-gate } 79*0Sstevel@tonic-gate rpc = (struct rpcent *)argp->buf.result; 80*0Sstevel@tonic-gate ceiling = buffer + buflen; 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate nss_result = (int)NSS_STR_PARSE_SUCCESS; 83*0Sstevel@tonic-gate (void) memset(argp->buf.buffer, 0, buflen); 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate attrptr = getattr(result, 0); 86*0Sstevel@tonic-gate if (attrptr == NULL) { 87*0Sstevel@tonic-gate nss_result = (int)NSS_STR_PARSE_PARSE; 88*0Sstevel@tonic-gate goto result_rpc2ent; 89*0Sstevel@tonic-gate } 90*0Sstevel@tonic-gate for (i = 0; i < result->entry->attr_count; i++) { 91*0Sstevel@tonic-gate attrptr = getattr(result, i); 92*0Sstevel@tonic-gate if (attrptr == NULL) { 93*0Sstevel@tonic-gate nss_result = (int)NSS_STR_PARSE_PARSE; 94*0Sstevel@tonic-gate goto result_rpc2ent; 95*0Sstevel@tonic-gate } 96*0Sstevel@tonic-gate if (strcasecmp(attrptr->attrname, _R_NAME) == 0) { 97*0Sstevel@tonic-gate for (j = 0; j < attrptr->value_count; j++) { 98*0Sstevel@tonic-gate /* traverse for all multivalued values */ 99*0Sstevel@tonic-gate if (firstime) { 100*0Sstevel@tonic-gate /* rpc name */ 101*0Sstevel@tonic-gate cname = __s_api_get_canonical_name( 102*0Sstevel@tonic-gate result->entry, attrptr, 1); 103*0Sstevel@tonic-gate if (cname == NULL || 104*0Sstevel@tonic-gate (len = strlen(cname)) < 1) { 105*0Sstevel@tonic-gate nss_result = 106*0Sstevel@tonic-gate NSS_STR_PARSE_PARSE; 107*0Sstevel@tonic-gate goto result_rpc2ent; 108*0Sstevel@tonic-gate } 109*0Sstevel@tonic-gate rpc->r_name = buffer; 110*0Sstevel@tonic-gate buffer += len + 1; 111*0Sstevel@tonic-gate if (buffer >= ceiling) { 112*0Sstevel@tonic-gate nss_result = 113*0Sstevel@tonic-gate (int)NSS_STR_PARSE_ERANGE; 114*0Sstevel@tonic-gate goto result_rpc2ent; 115*0Sstevel@tonic-gate } 116*0Sstevel@tonic-gate (void) strcpy(rpc->r_name, cname); 117*0Sstevel@tonic-gate /* alias list */ 118*0Sstevel@tonic-gate mp = rpc->r_aliases = 119*0Sstevel@tonic-gate (char **)ROUND_UP(buffer, 120*0Sstevel@tonic-gate sizeof (char **)); 121*0Sstevel@tonic-gate buffer = (char *)rpc->r_aliases + 122*0Sstevel@tonic-gate sizeof (char *) * 123*0Sstevel@tonic-gate (attrptr->value_count + 1); 124*0Sstevel@tonic-gate buffer = (char *)ROUND_UP(buffer, 125*0Sstevel@tonic-gate sizeof (char **)); 126*0Sstevel@tonic-gate if (buffer >= ceiling) { 127*0Sstevel@tonic-gate nss_result = 128*0Sstevel@tonic-gate (int)NSS_STR_PARSE_ERANGE; 129*0Sstevel@tonic-gate goto result_rpc2ent; 130*0Sstevel@tonic-gate } 131*0Sstevel@tonic-gate firstime = (int)0; 132*0Sstevel@tonic-gate } 133*0Sstevel@tonic-gate /* alias list */ 134*0Sstevel@tonic-gate if ((attrptr->attrvalue[j] == NULL) || 135*0Sstevel@tonic-gate (len = strlen(attrptr->attrvalue[j])) < 1) { 136*0Sstevel@tonic-gate nss_result = (int)NSS_STR_PARSE_PARSE; 137*0Sstevel@tonic-gate goto result_rpc2ent; 138*0Sstevel@tonic-gate } 139*0Sstevel@tonic-gate /* skip canonical name */ 140*0Sstevel@tonic-gate if (strcmp(attrptr->attrvalue[j], cname) == 0) 141*0Sstevel@tonic-gate continue; 142*0Sstevel@tonic-gate *mp = buffer; 143*0Sstevel@tonic-gate buffer += len + 1; 144*0Sstevel@tonic-gate if (buffer >= ceiling) { 145*0Sstevel@tonic-gate nss_result = (int)NSS_STR_PARSE_ERANGE; 146*0Sstevel@tonic-gate goto result_rpc2ent; 147*0Sstevel@tonic-gate } 148*0Sstevel@tonic-gate (void) strcpy(*mp++, attrptr->attrvalue[j]); 149*0Sstevel@tonic-gate continue; 150*0Sstevel@tonic-gate } 151*0Sstevel@tonic-gate } 152*0Sstevel@tonic-gate if (strcasecmp(attrptr->attrname, _R_NUMBER) == 0) { 153*0Sstevel@tonic-gate if ((attrptr->attrvalue[0] == NULL) || 154*0Sstevel@tonic-gate (len = strlen(attrptr->attrvalue[0])) < 1) { 155*0Sstevel@tonic-gate nss_result = (int)NSS_STR_PARSE_PARSE; 156*0Sstevel@tonic-gate goto result_rpc2ent; 157*0Sstevel@tonic-gate } 158*0Sstevel@tonic-gate errno = 0; 159*0Sstevel@tonic-gate rpc->r_number = (int)strtol(attrptr->attrvalue[0], 160*0Sstevel@tonic-gate (char **)NULL, 10); 161*0Sstevel@tonic-gate if (errno != 0) { 162*0Sstevel@tonic-gate nss_result = (int)NSS_STR_PARSE_PARSE; 163*0Sstevel@tonic-gate goto result_rpc2ent; 164*0Sstevel@tonic-gate } 165*0Sstevel@tonic-gate continue; 166*0Sstevel@tonic-gate } 167*0Sstevel@tonic-gate } 168*0Sstevel@tonic-gate if (mp != NULL) 169*0Sstevel@tonic-gate *mp = NULL; 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate #ifdef DEBUG 172*0Sstevel@tonic-gate (void) fprintf(stdout, "\n[getrpcent.c: _nss_ldap_rpc2ent]\n"); 173*0Sstevel@tonic-gate (void) fprintf(stdout, " r_name: [%s]\n", rpc->r_name); 174*0Sstevel@tonic-gate if (mp != NULL) { 175*0Sstevel@tonic-gate for (mp = rpc->r_aliases; *mp != NULL; mp++) 176*0Sstevel@tonic-gate (void) fprintf(stdout, " r_aliases: [%s]\n", *mp); 177*0Sstevel@tonic-gate } 178*0Sstevel@tonic-gate (void) fprintf(stdout, " r_number: [%d]\n", rpc->r_number); 179*0Sstevel@tonic-gate #endif /* DEBUG */ 180*0Sstevel@tonic-gate 181*0Sstevel@tonic-gate result_rpc2ent: 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate (void) __ns_ldap_freeResult(&be->result); 184*0Sstevel@tonic-gate return ((int)nss_result); 185*0Sstevel@tonic-gate } 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate /* 189*0Sstevel@tonic-gate * getbyname gets struct rpcent values by rpc name. This function 190*0Sstevel@tonic-gate * constructs an ldap search filter using the rpc name invocation 191*0Sstevel@tonic-gate * parameter and the getrpcbyname search filter defined. Once the 192*0Sstevel@tonic-gate * filter is constructed, we search for a matching entry and marshal 193*0Sstevel@tonic-gate * the data results into *rpc = (struct rpcent *)argp->buf.result. 194*0Sstevel@tonic-gate * The function _nss_ldap_rpc2ent performs the data marshaling. 195*0Sstevel@tonic-gate */ 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate static nss_status_t 198*0Sstevel@tonic-gate getbyname(ldap_backend_ptr be, void *a) 199*0Sstevel@tonic-gate { 200*0Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 201*0Sstevel@tonic-gate char searchfilter[SEARCHFILTERLEN]; 202*0Sstevel@tonic-gate char userdata[SEARCHFILTERLEN]; 203*0Sstevel@tonic-gate char name[SEARCHFILTERLEN]; 204*0Sstevel@tonic-gate int ret; 205*0Sstevel@tonic-gate 206*0Sstevel@tonic-gate if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0) 207*0Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND); 208*0Sstevel@tonic-gate 209*0Sstevel@tonic-gate ret = snprintf(searchfilter, sizeof (searchfilter), _F_GETRPCBYNAME, 210*0Sstevel@tonic-gate name); 211*0Sstevel@tonic-gate if (ret >= sizeof (searchfilter) || ret < 0) 212*0Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND); 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate ret = snprintf(userdata, sizeof (userdata), _F_GETRPCBYNAME_SSD, name); 215*0Sstevel@tonic-gate if (ret >= sizeof (userdata) || ret < 0) 216*0Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND); 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate return ((nss_status_t)_nss_ldap_lookup(be, argp, _RPC, searchfilter, 219*0Sstevel@tonic-gate NULL, _merge_SSD_filter, userdata)); 220*0Sstevel@tonic-gate } 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gate 223*0Sstevel@tonic-gate /* 224*0Sstevel@tonic-gate * getbynumber gets struct rpcent values by rpc number. This function 225*0Sstevel@tonic-gate * constructs an ldap search filter using the rpc number invocation 226*0Sstevel@tonic-gate * parameter and the getrpcbynumber search filter defined. Once the 227*0Sstevel@tonic-gate * filter is constructed, we search for a matching entry and marshal 228*0Sstevel@tonic-gate * the data results into *rpc = (struct rpcent *)argp->buf.result. 229*0Sstevel@tonic-gate * The function _nss_ldap_rpc2ent performs the data marshaling. 230*0Sstevel@tonic-gate */ 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gate static nss_status_t 233*0Sstevel@tonic-gate getbynumber(ldap_backend_ptr be, void *a) 234*0Sstevel@tonic-gate { 235*0Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 236*0Sstevel@tonic-gate char searchfilter[SEARCHFILTERLEN]; 237*0Sstevel@tonic-gate char userdata[SEARCHFILTERLEN]; 238*0Sstevel@tonic-gate int ret; 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate ret = snprintf(searchfilter, sizeof (searchfilter), 241*0Sstevel@tonic-gate _F_GETRPCBYNUMBER, argp->key.number); 242*0Sstevel@tonic-gate if (ret >= sizeof (searchfilter) || ret < 0) 243*0Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND); 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate ret = snprintf(userdata, sizeof (userdata), 246*0Sstevel@tonic-gate _F_GETRPCBYNUMBER_SSD, argp->key.number); 247*0Sstevel@tonic-gate if (ret >= sizeof (userdata) || ret < 0) 248*0Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND); 249*0Sstevel@tonic-gate 250*0Sstevel@tonic-gate return ((nss_status_t)_nss_ldap_lookup(be, argp, _RPC, searchfilter, 251*0Sstevel@tonic-gate NULL, _merge_SSD_filter, userdata)); 252*0Sstevel@tonic-gate } 253*0Sstevel@tonic-gate 254*0Sstevel@tonic-gate 255*0Sstevel@tonic-gate static ldap_backend_op_t rpc_ops[] = { 256*0Sstevel@tonic-gate _nss_ldap_destr, 257*0Sstevel@tonic-gate _nss_ldap_endent, 258*0Sstevel@tonic-gate _nss_ldap_setent, 259*0Sstevel@tonic-gate _nss_ldap_getent, 260*0Sstevel@tonic-gate getbyname, 261*0Sstevel@tonic-gate getbynumber 262*0Sstevel@tonic-gate }; 263*0Sstevel@tonic-gate 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gate /* 266*0Sstevel@tonic-gate * _nss_ldap_rpc_constr is where life begins. This function calls the generic 267*0Sstevel@tonic-gate * ldap constructor function to define and build the abstract data types 268*0Sstevel@tonic-gate * required to support ldap operations. 269*0Sstevel@tonic-gate */ 270*0Sstevel@tonic-gate 271*0Sstevel@tonic-gate /*ARGSUSED0*/ 272*0Sstevel@tonic-gate nss_backend_t * 273*0Sstevel@tonic-gate _nss_ldap_rpc_constr(const char *dummy1, const char *dummy2, 274*0Sstevel@tonic-gate const char *dummy3) 275*0Sstevel@tonic-gate { 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gate return ((nss_backend_t *)_nss_ldap_constr(rpc_ops, 278*0Sstevel@tonic-gate sizeof (rpc_ops)/sizeof (rpc_ops[0]), 279*0Sstevel@tonic-gate _RPC, rpc_attrs, _nss_ldap_rpc2ent)); 280*0Sstevel@tonic-gate } 281