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 2004 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 <project.h> 30 #include "ldap_common.h" 31 32 /* Project attributes filters */ 33 #define _PROJ_NAME "SolarisProjectName" 34 #define _PROJ_PROJID "SolarisProjectID" 35 #define _PROJ_DESCR "description" 36 #define _PROJ_USERS "memberUid" 37 #define _PROJ_GROUPS "memberGid" 38 #define _PROJ_ATTR "SolarisProjectAttr" 39 40 #define _F_GETPROJNAME "(&(objectClass=SolarisProject)(SolarisProjectName=%s))" 41 #define _F_GETPROJID "(&(objectClass=SolarisProject)(SolarisProjectID=%ld))" 42 43 static const char *project_attrs[] = { 44 _PROJ_NAME, 45 _PROJ_PROJID, 46 _PROJ_DESCR, 47 _PROJ_USERS, 48 _PROJ_GROUPS, 49 _PROJ_ATTR, 50 (char *)NULL 51 }; 52 53 static char * 54 gettok(char **nextpp, char sep) 55 { 56 char *p = *nextpp; 57 char *q = p; 58 char c; 59 60 if (p == NULL) 61 return (NULL); 62 while ((c = *q) != '\0' && c != sep) 63 q++; 64 if (c == '\0') 65 *nextpp = 0; 66 else { 67 *q++ = '\0'; 68 *nextpp = q; 69 } 70 return (p); 71 } 72 73 /* 74 * _nss_ldap_proj2ent is the data marshalling method for the project getXbyY 75 * (getprojbyname, getprojbyid, getprojent) backend processes. This method 76 * is called after a successful ldap search has been performed. This method 77 * will parse the ldap search values into struct project = argp->buf.buffer 78 * which the frontend routine expects. Three error conditions are expected 79 * and returned to nsswitch. 80 */ 81 static int 82 _nss_ldap_proj2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp) 83 { 84 int i, nss_result; 85 unsigned long len = 0; 86 char **uglist; 87 char *buffer, *ceiling; 88 char *users, *groups, *p; 89 struct project *proj; 90 ns_ldap_result_t *result = be->result; 91 ns_ldap_attr_t *attrptr; 92 93 buffer = argp->buf.buffer; 94 if (!argp->buf.result) { 95 nss_result = NSS_STR_PARSE_ERANGE; 96 goto result_proj2ent; 97 } 98 attrptr = getattr(result, 0); 99 if (attrptr == NULL) { 100 nss_result = NSS_STR_PARSE_PARSE; 101 goto result_proj2ent; 102 } 103 nss_result = NSS_STR_PARSE_SUCCESS; 104 proj = argp->buf.result; 105 proj->pj_users = proj->pj_groups = NULL; 106 proj->pj_attr = proj->pj_comment = NULL; 107 ceiling = (char *)ROUND_DOWN(buffer + argp->buf.buflen, 108 sizeof (char *)); 109 (void) memset(argp->buf.buffer, 0, argp->buf.buflen); 110 for (i = 0; i < result->entry->attr_count; i++) { 111 attrptr = getattr(result, i); 112 if (attrptr == NULL) { 113 nss_result = NSS_STR_PARSE_PARSE; 114 goto result_proj2ent; 115 } 116 len = strlen(attrptr->attrvalue[0]); 117 if (strcasecmp(attrptr->attrname, _PROJ_NAME) == 0) { 118 if (len == 0) { 119 nss_result = NSS_STR_PARSE_PARSE; 120 goto result_proj2ent; 121 } 122 proj->pj_name = buffer; 123 buffer += len + 1; 124 if (buffer >= ceiling) { 125 nss_result = NSS_STR_PARSE_ERANGE; 126 goto result_proj2ent; 127 } 128 (void) strcpy(proj->pj_name, attrptr->attrvalue[0]); 129 continue; 130 } 131 if (strcasecmp(attrptr->attrname, _PROJ_PROJID) == 0) { 132 if (len == 0) { 133 nss_result = NSS_STR_PARSE_PARSE; 134 goto result_proj2ent; 135 } 136 errno = 0; 137 proj->pj_projid = 138 (projid_t)strtol(attrptr->attrvalue[0], 139 NULL, 10); 140 if (errno != 0) { 141 nss_result = NSS_STR_PARSE_PARSE; 142 goto result_proj2ent; 143 } 144 continue; 145 } 146 if (strcasecmp(attrptr->attrname, _PROJ_DESCR) == 0) { 147 proj->pj_comment = buffer; 148 buffer += len + 1; 149 if (buffer >= ceiling) { 150 nss_result = NSS_STR_PARSE_ERANGE; 151 goto result_proj2ent; 152 } 153 (void) strcpy(proj->pj_comment, attrptr->attrvalue[0]); 154 continue; 155 } 156 if (strcasecmp(attrptr->attrname, _PROJ_ATTR) == 0) { 157 proj->pj_attr = buffer; 158 buffer += len + 1; 159 if (buffer >= ceiling) { 160 nss_result = NSS_STR_PARSE_ERANGE; 161 goto result_proj2ent; 162 } 163 (void) strcpy(proj->pj_attr, attrptr->attrvalue[0]); 164 continue; 165 } 166 if (strcasecmp(attrptr->attrname, _PROJ_USERS) == 0) { 167 buffer = (char *)ROUND_UP(buffer, sizeof (char *)); 168 users = buffer; 169 buffer += len + 1; 170 if (buffer >= ceiling) { 171 nss_result = NSS_STR_PARSE_ERANGE; 172 goto result_proj2ent; 173 } 174 (void) strcpy(users, attrptr->attrvalue[0]); 175 buffer = (char *)ROUND_UP(buffer, sizeof (char *)); 176 if (buffer >= ceiling) { 177 nss_result = NSS_STR_PARSE_ERANGE; 178 goto result_proj2ent; 179 } 180 proj->pj_users = uglist = (char **)buffer; 181 *uglist = NULL; 182 while (uglist < (char **)ceiling) { 183 p = gettok(&users, ','); 184 if (p == NULL || *p == '\0') { 185 *uglist++ = 0; 186 break; 187 } 188 *uglist++ = p; 189 } 190 buffer = (char *)uglist; 191 if (buffer >= ceiling) 192 return (NSS_STR_PARSE_ERANGE); 193 continue; 194 } 195 if (strcasecmp(attrptr->attrname, _PROJ_GROUPS) == 0) { 196 buffer = (char *)ROUND_UP(buffer, sizeof (char *)); 197 groups = buffer; 198 buffer += len + 1; 199 if (buffer >= ceiling) { 200 nss_result = NSS_STR_PARSE_ERANGE; 201 goto result_proj2ent; 202 } 203 (void) strcpy(groups, attrptr->attrvalue[0]); 204 buffer = (char *)ROUND_UP(buffer, sizeof (char *)); 205 if (buffer >= ceiling) { 206 nss_result = NSS_STR_PARSE_ERANGE; 207 goto result_proj2ent; 208 } 209 proj->pj_groups = uglist = (char **)buffer; 210 *uglist = NULL; 211 while (uglist < (char **)ceiling) { 212 p = gettok(&groups, ','); 213 if (p == NULL || *p == '\0') { 214 *uglist++ = 0; 215 break; 216 } 217 *uglist++ = p; 218 } 219 buffer = (char *)uglist; 220 if (buffer >= ceiling) 221 return (NSS_STR_PARSE_ERANGE); 222 continue; 223 } 224 } 225 if (proj->pj_comment == NULL) { 226 buffer = (char *)ROUND_UP(buffer, sizeof (char *)); 227 if (buffer >= ceiling) { 228 nss_result = NSS_STR_PARSE_ERANGE; 229 goto result_proj2ent; 230 } 231 proj->pj_comment = buffer; 232 *buffer = '\0'; 233 buffer++; 234 } 235 if (proj->pj_users == NULL) { 236 buffer = (char *)ROUND_UP(buffer, sizeof (char *)); 237 if (buffer >= ceiling) { 238 nss_result = NSS_STR_PARSE_ERANGE; 239 goto result_proj2ent; 240 } 241 proj->pj_users = (char **)buffer; 242 *buffer = '\0'; 243 buffer++; 244 } 245 if (proj->pj_groups == NULL) { 246 buffer = (char *)ROUND_UP(buffer, sizeof (char *)); 247 if (buffer >= ceiling) { 248 nss_result = NSS_STR_PARSE_ERANGE; 249 goto result_proj2ent; 250 } 251 proj->pj_groups = (char **)buffer; 252 *buffer = '\0'; 253 buffer++; 254 } 255 if (proj->pj_attr == NULL) { 256 buffer = (char *)ROUND_UP(buffer, sizeof (char *)); 257 if (buffer >= ceiling) { 258 nss_result = NSS_STR_PARSE_ERANGE; 259 goto result_proj2ent; 260 } 261 proj->pj_attr = buffer; 262 *buffer = '\0'; 263 buffer++; 264 } 265 266 result_proj2ent: 267 (void) __ns_ldap_freeResult(&be->result); 268 return ((int)nss_result); 269 } 270 271 272 /* 273 * getbyname gets a project entry by name. This function constructs an ldap 274 * search filter using the name invocation parameter and the getprojname search 275 * filter defined. Once the filter is constructed, we search for a matching 276 * entry and marshal the data results into struct project for the frontend 277 * process. The function _nss_ldap_proj2ent performs the data marshaling. 278 */ 279 static nss_status_t 280 getbyname(ldap_backend_ptr be, void *a) 281 { 282 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 283 char searchfilter[SEARCHFILTERLEN]; 284 285 if (snprintf(searchfilter, SEARCHFILTERLEN, 286 _F_GETPROJNAME, argp->key.name) < 0) 287 return (NSS_NOTFOUND); 288 return (_nss_ldap_lookup(be, argp, _PROJECT, searchfilter, NULL, 289 NULL, NULL)); 290 } 291 292 293 /* 294 * getbyprojid gets a project entry by number. This function constructs an ldap 295 * search filter using the name invocation parameter and the getprojid search 296 * filter defined. Once the filter is constructed, we search for a matching 297 * entry and marshal the data results into struct project for the frontend 298 * process. The function _nss_ldap_proj2ent performs the data marshaling. 299 */ 300 static nss_status_t 301 getbyprojid(ldap_backend_ptr be, void *a) 302 { 303 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 304 char searchfilter[SEARCHFILTERLEN]; 305 306 if (snprintf(searchfilter, SEARCHFILTERLEN, 307 _F_GETPROJID, (long)argp->key.projid) < 0) 308 return (NSS_NOTFOUND); 309 return (_nss_ldap_lookup(be, argp, _PROJECT, searchfilter, NULL, 310 NULL, NULL)); 311 } 312 313 static ldap_backend_op_t project_ops[] = { 314 _nss_ldap_destr, 315 _nss_ldap_endent, 316 _nss_ldap_setent, 317 _nss_ldap_getent, 318 getbyname, 319 getbyprojid 320 }; 321 322 323 /*ARGSUSED0*/ 324 nss_backend_t * 325 _nss_ldap_project_constr(const char *dummy1, const char *dummy2, 326 const char *dummy3) 327 { 328 return (_nss_ldap_constr(project_ops, 329 sizeof (project_ops) / sizeof (project_ops[0]), 330 _PROJECT, project_attrs, _nss_ldap_proj2ent)); 331 } 332