Print this page
12236 getmembers_DN doesn't properly handle errors from __ns_ldap_dn2uid
12240 nss_ldap does not properly look up group members by distinguished name
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libsldap/common/ns_reads.c
+++ new/usr/src/lib/libsldap/common/ns_reads.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
24 + * Copyright 2020 Joyent, Inc.
24 25 */
25 26
26 27 #include <stdio.h>
27 28 #include <sys/types.h>
28 29 #include <stdlib.h>
29 30 #include <libintl.h>
30 31 #include <ctype.h>
31 32 #include <syslog.h>
32 33 #include <sys/stat.h>
33 34 #include <fcntl.h>
34 35 #include <unistd.h>
35 36 #include <string.h>
36 37 #include <strings.h>
37 38 #include <priv.h>
38 39
39 40 #include "ns_sldap.h"
40 41 #include "ns_internal.h"
41 42 #include "ns_cache_door.h"
42 43 #include "ns_connmgmt.h"
43 44
44 45 #define _NIS_FILTER "nisdomain=*"
45 46 #define _NIS_DOMAIN "nisdomain"
46 47 static const char *nis_domain_attrs[] = {
47 48 _NIS_DOMAIN,
48 49 (char *)NULL
49 50 };
50 51
51 52 static int validate_filter(ns_ldap_cookie_t *cookie);
52 53
53 54 void
54 55 __ns_ldap_freeEntry(ns_ldap_entry_t *ep)
55 56 {
56 57 int j, k = 0;
57 58
58 59 if (ep == NULL)
59 60 return;
60 61
61 62 if (ep->attr_pair == NULL) {
62 63 free(ep);
63 64 return;
64 65 }
65 66 for (j = 0; j < ep->attr_count; j++) {
66 67 if (ep->attr_pair[j] == NULL)
67 68 continue;
68 69 if (ep->attr_pair[j]->attrname)
69 70 free(ep->attr_pair[j]->attrname);
70 71 if (ep->attr_pair[j]->attrvalue) {
71 72 for (k = 0; (k < ep->attr_pair[j]->value_count) &&
72 73 (ep->attr_pair[j]->attrvalue[k]); k++) {
73 74 free(ep->attr_pair[j]->attrvalue[k]);
74 75 }
75 76 free(ep->attr_pair[j]->attrvalue);
76 77 }
77 78 free(ep->attr_pair[j]);
78 79 }
79 80 free(ep->attr_pair);
80 81 free(ep);
81 82 }
82 83
83 84 static void
84 85 _freeControlList(LDAPControl ***ctrls)
85 86 {
86 87 LDAPControl **ctrl;
87 88
88 89 if (ctrls == NULL || *ctrls == NULL)
89 90 return;
90 91
91 92 for (ctrl = *ctrls; *ctrl != NULL; ctrl++)
92 93 ldap_control_free(*ctrl);
93 94 free(*ctrls);
94 95 *ctrls = NULL;
95 96 }
96 97 /*
97 98 * Convert attribute type in a RDN that has an attribute mapping to the
98 99 * original mappped type.
99 100 * e.g.
100 101 * cn<->cn-st and iphostnumber<->iphostnumber-st
101 102 * cn-st=aaa+iphostnumber-st=10.10.01.01
102 103 * is mapped to
103 104 * cn=aaa+iphostnumber=10.10.01.01
104 105 *
105 106 * Input - service: e.g. hosts, passwd etc.
106 107 * rdn: RDN
107 108 * Return: NULL - No attribute mapping in the RDN
108 109 * Non-NULL - The attribute type(s) in the RDN are mapped and
109 110 * the memory is allocated for the new rdn.
110 111 *
111 112 */
112 113 static char *
113 114 _cvtRDN(const char *service, const char *rdn)
114 115 {
115 116 char **attrs, **mapped_attrs, **mapp, *type, *value, *attr;
116 117 char *new_rdn = NULL;
117 118 int nAttr = 0, i, attr_mapped, len = 0;
118 119
119 120 /* Break down "type=value\0" pairs. Assume RDN is normalized */
120 121 if ((attrs = ldap_explode_rdn(rdn, 0)) == NULL)
121 122 return (NULL);
122 123
123 124 for (nAttr = 0; attrs[nAttr] != NULL; nAttr++)
124 125 ;
125 126
126 127 if ((mapped_attrs = (char **)calloc(nAttr, sizeof (char *))) == NULL) {
127 128 ldap_value_free(attrs);
128 129 return (NULL);
129 130 }
130 131
131 132 attr_mapped = 0;
132 133 for (i = 0; i < nAttr; i++) {
133 134 /* Parse type=value pair */
134 135 if ((type = strtok_r(attrs[i], "=", &value)) == NULL ||
135 136 value == NULL)
136 137 goto cleanup;
137 138 /* Reverse map: e.g. cn-sm -> cn */
138 139 mapp = __ns_ldap_getOrigAttribute(service, type);
139 140 if (mapp != NULL && mapp[0] != NULL) {
140 141 /* The attribute mapping is found */
141 142 type = mapp[0];
142 143 attr_mapped = 1;
143 144
144 145 /* "type=value\0" */
145 146 len = strlen(type) + strlen(value) + 2;
146 147
147 148 /* Reconstruct type=value pair. A string is allocated */
148 149 if ((attr = (char *)calloc(1, len)) == NULL) {
149 150 __s_api_free2dArray(mapp);
150 151 goto cleanup;
151 152 }
152 153 (void) snprintf(attr, len, "%s=%s", type, value);
153 154 mapped_attrs[i] = attr;
154 155 } else {
155 156 /*
156 157 * No attribute mapping. attrs[i] is going to be copied
157 158 * later. Restore "type\0value\0" back to
158 159 * "type=value\0".
159 160 */
160 161 type[strlen(type)] = '=';
161 162 }
162 163 __s_api_free2dArray(mapp);
163 164 }
164 165 if (attr_mapped == 0)
165 166 /* No attribute mapping. Don't bother to reconstruct RDN */
166 167 goto cleanup;
167 168
168 169 len = 0;
169 170 /* Reconstruct RDN from type=value pairs */
170 171 for (i = 0; i < nAttr; i++) {
171 172 if (mapped_attrs[i])
172 173 len += strlen(mapped_attrs[i]);
173 174 else
174 175 len += strlen(attrs[i]);
175 176 /* Add 1 for "+" */
176 177 len++;
177 178 }
178 179 if ((new_rdn = (char *)calloc(1, ++len)) == NULL)
179 180 goto cleanup;
180 181 for (i = 0; i < nAttr; i++) {
181 182 if (i > 0)
182 183 /* Add seperator */
183 184 (void) strlcat(new_rdn, "+", len);
184 185
185 186 if (mapped_attrs[i])
186 187 (void) strlcat(new_rdn, mapped_attrs[i], len);
187 188 else
188 189 (void) strlcat(new_rdn, attrs[i], len);
189 190
190 191 }
191 192 cleanup:
192 193 ldap_value_free(attrs);
193 194 if (mapped_attrs) {
194 195 if (attr_mapped) {
195 196 for (i = 0; i < nAttr; i++) {
196 197 if (mapped_attrs[i])
197 198 free(mapped_attrs[i]);
198 199 }
199 200 }
200 201 free(mapped_attrs);
201 202 }
202 203
203 204 return (new_rdn);
204 205 }
205 206 /*
206 207 * Convert attribute type in a DN that has an attribute mapping to the
207 208 * original mappped type.
208 209 * e.g
209 210 * The mappings are cn<->cn-sm, iphostnumber<->iphostnumber-sm
210 211 *
211 212 * dn: cn-sm=aaa+iphostnumber-sm=9.9.9.9,dc=central,dc=sun,dc=com
212 213 * is converted to
213 214 * dn: cn=aaa+iphostnumber=9.9.9.9,dc=central,dc=sun,dc=com
214 215 *
215 216 * Input - service: e.g. hosts, passwd etc.
216 217 * dn: the value of a distinguished name
217 218 * Return - NULL: error
218 219 * non-NULL: A converted DN and the memory is allocated
219 220 */
220 221 static char *
221 222 _cvtDN(const char *service, const char *dn)
222 223 {
223 224 char **mapped_rdns;
224 225 char **rdns, *new_rdn, *new_dn = NULL;
225 226 int nRdn = 0, i, len = 0, rdn_mapped;
226 227
227 228 if (service == NULL || dn == NULL)
228 229 return (NULL);
229 230
230 231 if ((rdns = ldap_explode_dn(dn, 0)) == NULL)
231 232 return (NULL);
232 233
233 234 for (nRdn = 0; rdns[nRdn] != NULL; nRdn++)
234 235 ;
235 236
236 237 if ((mapped_rdns = (char **)calloc(nRdn, sizeof (char *))) == NULL) {
237 238 ldap_value_free(rdns);
238 239 return (NULL);
239 240 }
240 241
241 242 rdn_mapped = 0;
242 243 /* Break down RDNs in a DN */
243 244 for (i = 0; i < nRdn; i++) {
244 245 if ((new_rdn = _cvtRDN(service, rdns[i])) != NULL) {
245 246 mapped_rdns[i] = new_rdn;
246 247 rdn_mapped = 1;
247 248 }
248 249 }
249 250 if (rdn_mapped == 0) {
250 251 /*
251 252 * No RDN contains any attribute mapping.
252 253 * Don't bother to reconstruct DN from RDN. Copy DN directly.
253 254 */
254 255 new_dn = strdup(dn);
255 256 goto cleanup;
256 257 }
257 258 /*
258 259 * Reconstruct dn from RDNs.
259 260 * Calculate the length first.
260 261 */
261 262 for (i = 0; i < nRdn; i++) {
262 263 if (mapped_rdns[i])
263 264 len += strlen(mapped_rdns[i]);
264 265 else
265 266 len += strlen(rdns[i]);
266 267
267 268 /* add 1 for ',' */
268 269 len ++;
269 270 }
270 271 if ((new_dn = (char *)calloc(1, ++len)) == NULL)
271 272 goto cleanup;
272 273 for (i = 0; i < nRdn; i++) {
273 274 if (i > 0)
274 275 /* Add seperator */
275 276 (void) strlcat(new_dn, ",", len);
276 277
277 278 if (mapped_rdns[i])
278 279 (void) strlcat(new_dn, mapped_rdns[i], len);
279 280 else
280 281 (void) strlcat(new_dn, rdns[i], len);
281 282
282 283 }
283 284
284 285 cleanup:
285 286 ldap_value_free(rdns);
286 287 if (mapped_rdns) {
287 288 if (rdn_mapped) {
288 289 for (i = 0; i < nRdn; i++) {
289 290 if (mapped_rdns[i])
290 291 free(mapped_rdns[i]);
291 292 }
292 293 }
293 294 free(mapped_rdns);
294 295 }
295 296
296 297 return (new_dn);
297 298 }
298 299 /*
299 300 * Convert a single ldap entry from a LDAPMessage
300 301 * into an ns_ldap_entry structure.
301 302 * Schema map the entry if specified in flags
302 303 */
303 304
304 305 static int
305 306 __s_api_cvtEntry(LDAP *ld, const char *service, LDAPMessage *e, int flags,
306 307 ns_ldap_entry_t **ret, ns_ldap_error_t **error)
307 308 {
308 309
309 310 ns_ldap_entry_t *ep = NULL;
310 311 ns_ldap_attr_t **ap = NULL;
311 312 BerElement *ber;
312 313 char *attr = NULL;
313 314 char **vals = NULL;
314 315 char **mapping;
315 316 char *dn;
316 317 int nAttrs = 0;
317 318 int i, j, k = 0;
318 319 char **gecos_mapping = NULL;
319 320 int gecos_val_index[3] = { -1, -1, -1};
320 321 char errstr[MAXERROR];
321 322 int schema_mapping_existed = FALSE;
322 323 int gecos_mapping_existed = FALSE;
323 324 int gecos_attr_matched;
324 325 int auto_service = FALSE;
325 326 int rc = NS_LDAP_SUCCESS;
326 327
327 328 if (e == NULL || ret == NULL || error == NULL)
328 329 return (NS_LDAP_INVALID_PARAM);
329 330
330 331 *error = NULL;
331 332
332 333 ep = (ns_ldap_entry_t *)calloc(1, sizeof (ns_ldap_entry_t));
333 334 if (ep == NULL)
334 335 return (NS_LDAP_MEMORY);
335 336
336 337 if (service != NULL &&
337 338 (strncasecmp(service, "auto_", 5) == 0 ||
338 339 strcasecmp(service, "automount") == 0))
339 340 auto_service = TRUE;
340 341 /*
341 342 * see if schema mapping existed for the given service
342 343 */
343 344 mapping = __ns_ldap_getOrigAttribute(service,
344 345 NS_HASH_SCHEMA_MAPPING_EXISTED);
345 346 if (mapping) {
346 347 schema_mapping_existed = TRUE;
347 348 __s_api_free2dArray(mapping);
348 349 mapping = NULL;
349 350 } else if (auto_service) {
350 351 /*
351 352 * If service == auto_* and no
352 353 * schema mapping found
353 354 * then try automount
354 355 * There is certain case that schema mapping exist
355 356 * but __ns_ldap_getOrigAttribute(service,
356 357 * NS_HASH_SCHEMA_MAPPING_EXISTED);
357 358 * returns NULL.
358 359 * e.g.
359 360 * NS_LDAP_ATTRIBUTEMAP = automount:automountMapName=AAA
360 361 * NS_LDAP_OBJECTCLASSMAP = automount:automountMap=MynisMap
361 362 * NS_LDAP_OBJECTCLASSMAP = automount:automount=MynisObject
362 363 *
363 364 * Make a check for schema_mapping_existed here
364 365 * so later on __s_api_convert_automountmapname won't be called
365 366 * unnecessarily. It is also used for attribute mapping
366 367 * and objectclass mapping.
367 368 */
368 369 mapping = __ns_ldap_getOrigAttribute("automount",
369 370 NS_HASH_SCHEMA_MAPPING_EXISTED);
370 371 if (mapping) {
371 372 schema_mapping_existed = TRUE;
372 373 __s_api_free2dArray(mapping);
373 374 mapping = NULL;
374 375 }
375 376 }
376 377
377 378 nAttrs = 1; /* start with 1 for the DN attr */
378 379 for (attr = ldap_first_attribute(ld, e, &ber); attr != NULL;
379 380 attr = ldap_next_attribute(ld, e, ber)) {
380 381 nAttrs++;
381 382 ldap_memfree(attr);
382 383 attr = NULL;
383 384 }
384 385 ber_free(ber, 0);
385 386 ber = NULL;
386 387
387 388 ep->attr_count = nAttrs;
388 389
389 390 /*
390 391 * add 1 for "gecos" 1 to N attribute mapping,
391 392 * just in case it is needed.
392 393 * ep->attr_count will be updated later if that is true.
393 394 */
394 395 ap = (ns_ldap_attr_t **)calloc(ep->attr_count + 1,
395 396 sizeof (ns_ldap_attr_t *));
396 397 if (ap == NULL) {
397 398 __ns_ldap_freeEntry(ep);
398 399 ep = NULL;
399 400 return (NS_LDAP_MEMORY);
400 401 }
401 402 ep->attr_pair = ap;
402 403
403 404 /* DN attribute */
404 405 dn = ldap_get_dn(ld, e);
405 406 ap[0] = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t));
406 407 if (ap[0] == NULL) {
407 408 ldap_memfree(dn);
408 409 dn = NULL;
409 410 __ns_ldap_freeEntry(ep);
410 411 ep = NULL;
411 412 return (NS_LDAP_MEMORY);
412 413 }
413 414
414 415 if ((ap[0]->attrname = strdup("dn")) == NULL) {
415 416 ldap_memfree(dn);
416 417 dn = NULL;
417 418 __ns_ldap_freeEntry(ep);
418 419 ep = NULL;
419 420 return (NS_LDAP_INVALID_PARAM);
420 421 }
421 422 ap[0]->value_count = 1;
422 423 if ((ap[0]->attrvalue = (char **)
423 424 calloc(2, sizeof (char *))) == NULL) {
424 425 ldap_memfree(dn);
425 426 dn = NULL;
426 427 __ns_ldap_freeEntry(ep);
427 428 ep = NULL;
428 429 return (NS_LDAP_MEMORY);
429 430 }
430 431
431 432 if (schema_mapping_existed && ((flags & NS_LDAP_NOT_CVT_DN) == 0))
432 433 ap[0]->attrvalue[0] = _cvtDN(service, dn);
433 434 else
434 435 ap[0]->attrvalue[0] = strdup(dn);
435 436
436 437 if (ap[0]->attrvalue[0] == NULL) {
437 438 ldap_memfree(dn);
438 439 dn = NULL;
439 440 __ns_ldap_freeEntry(ep);
440 441 ep = NULL;
441 442 return (NS_LDAP_MEMORY);
442 443 }
443 444 ldap_memfree(dn);
444 445 dn = NULL;
445 446
446 447 if ((flags & NS_LDAP_NOMAP) == 0 && auto_service &&
447 448 schema_mapping_existed) {
448 449 rc = __s_api_convert_automountmapname(service,
449 450 &ap[0]->attrvalue[0],
450 451 error);
451 452 if (rc != NS_LDAP_SUCCESS) {
452 453 __ns_ldap_freeEntry(ep);
453 454 ep = NULL;
454 455 return (rc);
455 456 }
456 457 }
457 458
458 459 /* other attributes */
459 460 for (attr = ldap_first_attribute(ld, e, &ber), j = 1;
460 461 attr != NULL && j != nAttrs;
461 462 attr = ldap_next_attribute(ld, e, ber), j++) {
462 463 /* allocate new attr name */
463 464
464 465 if ((ap[j] = (ns_ldap_attr_t *)
465 466 calloc(1, sizeof (ns_ldap_attr_t))) == NULL) {
466 467 ber_free(ber, 0);
467 468 ber = NULL;
468 469 __ns_ldap_freeEntry(ep);
469 470 ep = NULL;
470 471 if (gecos_mapping)
471 472 __s_api_free2dArray(gecos_mapping);
472 473 gecos_mapping = NULL;
473 474 return (NS_LDAP_MEMORY);
474 475 }
475 476
476 477 if ((flags & NS_LDAP_NOMAP) || schema_mapping_existed == FALSE)
477 478 mapping = NULL;
478 479 else
479 480 mapping = __ns_ldap_getOrigAttribute(service, attr);
480 481
481 482 if (mapping == NULL && auto_service &&
482 483 schema_mapping_existed && (flags & NS_LDAP_NOMAP) == 0)
483 484 /*
484 485 * if service == auto_* and no schema mapping found
485 486 * and schema_mapping_existed is TRUE and NS_LDAP_NOMAP
486 487 * is not set then try automount e.g.
487 488 * NS_LDAP_ATTRIBUTEMAP = automount:automountMapName=AAA
488 489 */
489 490 mapping = __ns_ldap_getOrigAttribute("automount",
490 491 attr);
491 492
492 493 if (mapping == NULL) {
493 494 if ((ap[j]->attrname = strdup(attr)) == NULL) {
494 495 ber_free(ber, 0);
495 496 ber = NULL;
496 497 __ns_ldap_freeEntry(ep);
497 498 ep = NULL;
498 499 if (gecos_mapping)
499 500 __s_api_free2dArray(gecos_mapping);
500 501 gecos_mapping = NULL;
501 502 return (NS_LDAP_MEMORY);
502 503 }
503 504 } else {
504 505 /*
505 506 * for "gecos" 1 to N mapping,
506 507 * do not remove the mapped attribute,
507 508 * just create a new gecos attribute
508 509 * and append it to the end of the attribute list
509 510 */
510 511 if (strcasecmp(mapping[0], "gecos") == 0) {
511 512 ap[j]->attrname = strdup(attr);
512 513 gecos_mapping_existed = TRUE;
513 514 } else {
514 515 ap[j]->attrname = strdup(mapping[0]);
515 516 }
516 517
517 518 if (ap[j]->attrname == NULL) {
518 519 ber_free(ber, 0);
519 520 ber = NULL;
520 521 __ns_ldap_freeEntry(ep);
521 522 ep = NULL;
522 523 if (gecos_mapping)
523 524 __s_api_free2dArray(gecos_mapping);
524 525 gecos_mapping = NULL;
525 526 return (NS_LDAP_MEMORY);
526 527 }
527 528 /*
528 529 * 1 to N attribute mapping processing
529 530 * is only done for "gecos"
530 531 */
531 532
532 533 if (strcasecmp(mapping[0], "gecos") == 0) {
533 534 /*
534 535 * get attribute mapping for "gecos",
535 536 * need to know the number and order of the
536 537 * mapped attributes
537 538 */
538 539 if (gecos_mapping == NULL) {
539 540 gecos_mapping =
540 541 __ns_ldap_getMappedAttributes(
541 542 service, mapping[0]);
542 543 if (gecos_mapping == NULL ||
543 544 gecos_mapping[0] == NULL) {
544 545 /*
545 546 * this should never happens,
546 547 * syslog the error
547 548 */
548 549 (void) sprintf(errstr,
549 550 gettext(
550 551 "Attribute mapping "
551 552 "inconsistency "
552 553 "found for attributes "
553 554 "'%s' and '%s'."),
554 555 mapping[0], attr);
555 556 syslog(LOG_ERR, "libsldap: %s",
556 557 errstr);
557 558
558 559 ber_free(ber, 0);
559 560 ber = NULL;
560 561 __ns_ldap_freeEntry(ep);
561 562 ep = NULL;
562 563 __s_api_free2dArray(mapping);
563 564 mapping = NULL;
564 565 if (gecos_mapping)
565 566 __s_api_free2dArray(
566 567 gecos_mapping);
567 568 gecos_mapping = NULL;
568 569 return (NS_LDAP_INTERNAL);
569 570 }
570 571 }
571 572
572 573 /*
573 574 * is this attribute the 1st, 2nd, or
574 575 * 3rd attr in the mapping list?
575 576 */
576 577 gecos_attr_matched = FALSE;
577 578 for (i = 0; i < 3 && gecos_mapping[i]; i++) {
578 579 if (gecos_mapping[i] &&
579 580 strcasecmp(gecos_mapping[i],
580 581 attr) == 0) {
581 582 gecos_val_index[i] = j;
582 583 gecos_attr_matched = TRUE;
583 584 break;
584 585 }
585 586 }
586 587 if (gecos_attr_matched == FALSE) {
587 588 /*
588 589 * Not match found.
589 590 * This should never happens,
590 591 * syslog the error
591 592 */
592 593 (void) sprintf(errstr,
593 594 gettext(
594 595 "Attribute mapping "
595 596 "inconsistency "
596 597 "found for attributes "
597 598 "'%s' and '%s'."),
598 599 mapping[0], attr);
599 600 syslog(LOG_ERR, "libsldap: %s", errstr);
600 601
601 602 ber_free(ber, 0);
602 603 ber = NULL;
603 604 __ns_ldap_freeEntry(ep);
604 605 ep = NULL;
605 606 __s_api_free2dArray(mapping);
606 607 mapping = NULL;
607 608 __s_api_free2dArray(gecos_mapping);
608 609 gecos_mapping = NULL;
609 610 return (NS_LDAP_INTERNAL);
610 611 }
611 612 }
612 613 __s_api_free2dArray(mapping);
613 614 mapping = NULL;
614 615 }
615 616
616 617 if ((vals = ldap_get_values(ld, e, attr)) != NULL) {
617 618
618 619 if ((ap[j]->value_count =
619 620 ldap_count_values(vals)) == 0) {
620 621 ldap_value_free(vals);
621 622 vals = NULL;
622 623 continue;
623 624 } else {
624 625 ap[j]->attrvalue = (char **)
625 626 calloc(ap[j]->value_count+1,
626 627 sizeof (char *));
627 628 if (ap[j]->attrvalue == NULL) {
628 629 ber_free(ber, 0);
629 630 ber = NULL;
630 631 __ns_ldap_freeEntry(ep);
631 632 ep = NULL;
632 633 if (gecos_mapping)
633 634 __s_api_free2dArray(
634 635 gecos_mapping);
635 636 gecos_mapping = NULL;
636 637 return (NS_LDAP_MEMORY);
637 638 }
638 639 }
639 640
640 641 /* map object classes if necessary */
641 642 if ((flags & NS_LDAP_NOMAP) == 0 &&
642 643 schema_mapping_existed && ap[j]->attrname &&
643 644 strcasecmp(ap[j]->attrname, "objectclass") == 0) {
644 645 for (k = 0; k < ap[j]->value_count; k++) {
645 646 mapping =
646 647 __ns_ldap_getOrigObjectClass(
647 648 service, vals[k]);
648 649
649 650 if (mapping == NULL && auto_service)
650 651 /*
651 652 * if service == auto_* and no
652 653 * schema mapping found
653 654 * then try automount
654 655 */
655 656 mapping =
656 657 __ns_ldap_getOrigObjectClass(
657 658 "automount", vals[k]);
658 659
659 660 if (mapping == NULL) {
660 661 ap[j]->attrvalue[k] =
661 662 strdup(vals[k]);
662 663 } else {
663 664 ap[j]->attrvalue[k] =
664 665 strdup(mapping[0]);
665 666 __s_api_free2dArray(mapping);
666 667 mapping = NULL;
667 668 }
668 669 if (ap[j]->attrvalue[k] == NULL) {
669 670 ber_free(ber, 0);
670 671 ber = NULL;
671 672 __ns_ldap_freeEntry(ep);
672 673 ep = NULL;
673 674 if (gecos_mapping)
674 675 __s_api_free2dArray(
675 676 gecos_mapping);
676 677 gecos_mapping = NULL;
677 678 return (NS_LDAP_MEMORY);
678 679 }
679 680 }
680 681 } else {
681 682 for (k = 0; k < ap[j]->value_count; k++) {
682 683 if ((ap[j]->attrvalue[k] =
683 684 strdup(vals[k])) == NULL) {
684 685 ber_free(ber, 0);
685 686 ber = NULL;
686 687 __ns_ldap_freeEntry(ep);
687 688 ep = NULL;
688 689 if (gecos_mapping)
689 690 __s_api_free2dArray(
690 691 gecos_mapping);
691 692 gecos_mapping = NULL;
692 693 return (NS_LDAP_MEMORY);
693 694 }
694 695 }
695 696 }
696 697
697 698 ap[j]->attrvalue[k] = NULL;
698 699 ldap_value_free(vals);
699 700 vals = NULL;
700 701 }
701 702
702 703 ldap_memfree(attr);
703 704 attr = NULL;
704 705 }
705 706
706 707 ber_free(ber, 0);
707 708 ber = NULL;
708 709
709 710 if (gecos_mapping) {
710 711 __s_api_free2dArray(gecos_mapping);
711 712 gecos_mapping = NULL;
712 713 }
713 714
714 715 /* special processing for gecos 1 to up to 3 attribute mapping */
715 716 if (schema_mapping_existed && gecos_mapping_existed) {
716 717
717 718 int f = -1;
718 719
719 720 for (i = 0; i < 3; i++) {
720 721 k = gecos_val_index[i];
721 722
722 723 /*
723 724 * f is the index of the first returned
724 725 * attribute which "gecos" attribute mapped to
725 726 */
726 727 if (k != -1 && f == -1)
727 728 f = k;
728 729
729 730 if (k != -1 && ap[k]->value_count > 0 &&
730 731 ap[k]->attrvalue[0] &&
731 732 strlen(ap[k]->attrvalue[0]) > 0) {
732 733
733 734 if (k == f) {
734 735 /*
735 736 * Create and fill in the last reserved
736 737 * ap with the data from the "gecos"
737 738 * mapping attributes
738 739 */
739 740 ap[nAttrs] = (ns_ldap_attr_t *)
740 741 calloc(1,
741 742 sizeof (ns_ldap_attr_t));
742 743 if (ap[nAttrs] == NULL) {
743 744 __ns_ldap_freeEntry(ep);
744 745 ep = NULL;
745 746 return (NS_LDAP_MEMORY);
746 747 }
747 748 ap[nAttrs]->attrvalue = (char **)calloc(
748 749 2, sizeof (char *));
749 750 if (ap[nAttrs]->attrvalue == NULL) {
750 751 __ns_ldap_freeEntry(ep);
751 752 ep = NULL;
752 753 return (NS_LDAP_MEMORY);
753 754 }
754 755 /* add 1 more for a possible "," */
755 756 ap[nAttrs]->attrvalue[0] =
756 757 (char *)calloc(
757 758 strlen(ap[f]->attrvalue[0]) +
758 759 2, 1);
759 760 if (ap[nAttrs]->attrvalue[0] == NULL) {
760 761 __ns_ldap_freeEntry(ep);
761 762 ep = NULL;
762 763 return (NS_LDAP_MEMORY);
763 764 }
764 765 (void) strcpy(ap[nAttrs]->attrvalue[0],
765 766 ap[f]->attrvalue[0]);
766 767
767 768 ap[nAttrs]->attrname = strdup("gecos");
768 769 if (ap[nAttrs]->attrname == NULL) {
769 770 __ns_ldap_freeEntry(ep);
770 771 ep = NULL;
771 772 return (NS_LDAP_MEMORY);
772 773 }
773 774
774 775 ap[nAttrs]->value_count = 1;
775 776 ep->attr_count = nAttrs + 1;
776 777
777 778 } else {
778 779 char *tmp = NULL;
779 780
780 781 /*
781 782 * realloc to add "," and
782 783 * ap[k]->attrvalue[0]
783 784 */
784 785 tmp = (char *)realloc(
785 786 ap[nAttrs]->attrvalue[0],
786 787 strlen(ap[nAttrs]->
787 788 attrvalue[0]) +
788 789 strlen(ap[k]->
789 790 attrvalue[0]) + 2);
790 791 if (tmp == NULL) {
791 792 __ns_ldap_freeEntry(ep);
792 793 ep = NULL;
793 794 return (NS_LDAP_MEMORY);
794 795 }
795 796 ap[nAttrs]->attrvalue[0] = tmp;
796 797 (void) strcat(ap[nAttrs]->attrvalue[0],
797 798 ",");
798 799 (void) strcat(ap[nAttrs]->attrvalue[0],
799 800 ap[k]->attrvalue[0]);
800 801 }
801 802 }
802 803 }
803 804 }
804 805
805 806 *ret = ep;
806 807 return (NS_LDAP_SUCCESS);
807 808 }
808 809
809 810 static int
810 811 __s_api_getEntry(ns_ldap_cookie_t *cookie)
811 812 {
812 813 ns_ldap_entry_t *curEntry = NULL;
813 814 int ret;
814 815
815 816 #ifdef DEBUG
816 817 (void) fprintf(stderr, "__s_api_getEntry START\n");
817 818 #endif
818 819
819 820 if (cookie->resultMsg == NULL) {
820 821 return (NS_LDAP_INVALID_PARAM);
821 822 }
822 823 ret = __s_api_cvtEntry(cookie->conn->ld, cookie->service,
823 824 cookie->resultMsg, cookie->i_flags,
824 825 &curEntry, &cookie->errorp);
825 826 if (ret != NS_LDAP_SUCCESS) {
826 827 return (ret);
827 828 }
828 829
829 830 if (cookie->result == NULL) {
830 831 cookie->result = (ns_ldap_result_t *)
831 832 calloc(1, sizeof (ns_ldap_result_t));
832 833 if (cookie->result == NULL) {
833 834 __ns_ldap_freeEntry(curEntry);
834 835 curEntry = NULL;
835 836 return (NS_LDAP_MEMORY);
836 837 }
837 838 cookie->result->entry = curEntry;
838 839 cookie->nextEntry = curEntry;
839 840 } else {
840 841 cookie->nextEntry->next = curEntry;
841 842 cookie->nextEntry = curEntry;
842 843 }
843 844 cookie->result->entries_count++;
844 845
845 846 return (NS_LDAP_SUCCESS);
846 847 }
847 848
848 849 static int
849 850 __s_api_get_cachemgr_data(const char *type, const char *from, char **to)
850 851 {
851 852 union {
852 853 ldap_data_t s_d;
853 854 char s_b[DOORBUFFERSIZE];
854 855 } space;
855 856 ldap_data_t *sptr;
856 857 int ndata;
857 858 int adata;
858 859 int rc;
859 860
860 861 #ifdef DEBUG
861 862 (void) fprintf(stderr, "__s_api_get_cachemgr_data START\n");
862 863 #endif
863 864 /*
864 865 * We are not going to perform DN to domain mapping
865 866 * in the Standalone mode
866 867 */
867 868 if (__s_api_isStandalone()) {
868 869 return (-1);
869 870 }
870 871
871 872 if (from == NULL || from[0] == '\0' || to == NULL)
872 873 return (-1);
873 874
874 875 *to = NULL;
875 876 (void) memset(space.s_b, 0, DOORBUFFERSIZE);
876 877
877 878 space.s_d.ldap_call.ldap_callnumber = GETCACHE;
878 879 (void) snprintf(space.s_d.ldap_call.ldap_u.domainname,
879 880 DOORBUFFERSIZE - sizeof (space.s_d.ldap_call.ldap_callnumber),
880 881 "%s%s%s",
881 882 type,
882 883 DOORLINESEP,
883 884 from);
884 885 ndata = sizeof (space);
885 886 adata = sizeof (ldap_call_t) +
886 887 strlen(space.s_d.ldap_call.ldap_u.domainname) + 1;
887 888 sptr = &space.s_d;
888 889
889 890 rc = __ns_ldap_trydoorcall(&sptr, &ndata, &adata);
890 891 if (rc != NS_CACHE_SUCCESS)
891 892 return (-1);
892 893 else
893 894 *to = strdup(sptr->ldap_ret.ldap_u.buff);
894 895 return (NS_LDAP_SUCCESS);
895 896 }
896 897
897 898 static int
898 899 __s_api_set_cachemgr_data(const char *type, const char *from, const char *to)
899 900 {
900 901 union {
901 902 ldap_data_t s_d;
902 903 char s_b[DOORBUFFERSIZE];
903 904 } space;
904 905 ldap_data_t *sptr;
905 906 int ndata;
906 907 int adata;
907 908 int rc;
908 909
909 910 #ifdef DEBUG
910 911 (void) fprintf(stderr, "__s_api_set_cachemgr_data START\n");
911 912 #endif
912 913 /*
913 914 * We are not going to perform DN to domain mapping
914 915 * in the Standalone mode
915 916 */
916 917 if (__s_api_isStandalone()) {
917 918 return (-1);
918 919 }
919 920
920 921 if ((from == NULL) || (from[0] == '\0') ||
921 922 (to == NULL) || (to[0] == '\0'))
922 923 return (-1);
923 924
924 925 (void) memset(space.s_b, 0, DOORBUFFERSIZE);
925 926
926 927 space.s_d.ldap_call.ldap_callnumber = SETCACHE;
927 928 (void) snprintf(space.s_d.ldap_call.ldap_u.domainname,
928 929 DOORBUFFERSIZE - sizeof (space.s_d.ldap_call.ldap_callnumber),
929 930 "%s%s%s%s%s",
930 931 type,
931 932 DOORLINESEP,
932 933 from,
933 934 DOORLINESEP,
934 935 to);
935 936
936 937 ndata = sizeof (space);
937 938 adata = sizeof (ldap_call_t) +
938 939 strlen(space.s_d.ldap_call.ldap_u.domainname) + 1;
939 940 sptr = &space.s_d;
940 941
941 942 rc = __ns_ldap_trydoorcall(&sptr, &ndata, &adata);
942 943 if (rc != NS_CACHE_SUCCESS)
943 944 return (-1);
944 945
945 946 return (NS_LDAP_SUCCESS);
946 947 }
947 948
948 949
949 950 static char *
950 951 __s_api_remove_rdn_space(char *rdn)
951 952 {
952 953 char *tf, *tl, *vf, *vl, *eqsign;
953 954
954 955 /* if no space(s) to remove, return */
955 956 if (strchr(rdn, SPACETOK) == NULL)
956 957 return (rdn);
957 958
958 959 /* if no '=' separator, return */
959 960 eqsign = strchr(rdn, '=');
960 961 if (eqsign == NULL)
961 962 return (rdn);
962 963
963 964 tf = rdn;
964 965 tl = eqsign - 1;
965 966 vf = eqsign + 1;
966 967 vl = rdn + strlen(rdn) - 1;
967 968
968 969 /* now two strings, type and value */
969 970 *eqsign = '\0';
970 971
971 972 /* remove type's leading spaces */
972 973 while (tf < tl && *tf == SPACETOK)
973 974 tf++;
974 975 /* remove type's trailing spaces */
975 976 while (tf < tl && *tl == SPACETOK)
976 977 tl--;
977 978 /* add '=' separator back */
978 979 *(++tl) = '=';
979 980 /* remove value's leading spaces */
980 981 while (vf < vl && *vf == SPACETOK)
981 982 vf++;
982 983 /* remove value's trailing spaces */
983 984 while (vf < vl && *vl == SPACETOK)
984 985 *vl-- = '\0';
985 986
986 987 /* move value up if necessary */
987 988 if (vf != tl + 1)
988 989 (void) strcpy(tl + 1, vf);
989 990
990 991 return (tf);
991 992 }
992 993
993 994 static
994 995 ns_ldap_cookie_t *
995 996 init_search_state_machine()
996 997 {
997 998 ns_ldap_cookie_t *cookie;
998 999 ns_config_t *cfg;
999 1000
1000 1001 cookie = (ns_ldap_cookie_t *)calloc(1, sizeof (ns_ldap_cookie_t));
1001 1002 if (cookie == NULL)
1002 1003 return (NULL);
1003 1004 cookie->state = INIT;
1004 1005 /* assign other state variables */
1005 1006 cfg = __s_api_loadrefresh_config();
1006 1007 cookie->connectionId = -1;
1007 1008 if (cfg == NULL ||
1008 1009 cfg->paramList[NS_LDAP_SEARCH_TIME_P].ns_ptype == NS_UNKNOWN) {
1009 1010 cookie->search_timeout.tv_sec = NS_DEFAULT_SEARCH_TIMEOUT;
1010 1011 } else {
1011 1012 cookie->search_timeout.tv_sec =
1012 1013 cfg->paramList[NS_LDAP_SEARCH_TIME_P].ns_i;
1013 1014 }
1014 1015 if (cfg != NULL)
1015 1016 __s_api_release_config(cfg);
1016 1017 cookie->search_timeout.tv_usec = 0;
1017 1018
1018 1019 return (cookie);
1019 1020 }
1020 1021
1021 1022 static void
1022 1023 delete_search_cookie(ns_ldap_cookie_t *cookie)
1023 1024 {
1024 1025 if (cookie == NULL)
1025 1026 return;
1026 1027 if (cookie->connectionId > -1)
1027 1028 DropConnection(cookie->connectionId, cookie->i_flags);
1028 1029 if (cookie->filter)
1029 1030 free(cookie->filter);
1030 1031 if (cookie->i_filter)
1031 1032 free(cookie->i_filter);
1032 1033 if (cookie->service)
1033 1034 free(cookie->service);
1034 1035 if (cookie->sdlist)
1035 1036 (void) __ns_ldap_freeSearchDescriptors(&(cookie->sdlist));
1036 1037 if (cookie->result)
1037 1038 (void) __ns_ldap_freeResult(&cookie->result);
1038 1039 if (cookie->attribute)
1039 1040 __s_api_free2dArray(cookie->attribute);
1040 1041 if (cookie->errorp)
1041 1042 (void) __ns_ldap_freeError(&cookie->errorp);
1042 1043 if (cookie->reflist)
1043 1044 __s_api_deleteRefInfo(cookie->reflist);
1044 1045 if (cookie->basedn)
1045 1046 free(cookie->basedn);
1046 1047 if (cookie->ctrlCookie)
1047 1048 ber_bvfree(cookie->ctrlCookie);
1048 1049 _freeControlList(&cookie->p_serverctrls);
1049 1050 if (cookie->resultctrl)
1050 1051 ldap_controls_free(cookie->resultctrl);
1051 1052 free(cookie);
1052 1053 }
1053 1054
1054 1055 static int
1055 1056 get_mapped_filter(ns_ldap_cookie_t *cookie, char **new_filter)
1056 1057 {
1057 1058
1058 1059 typedef struct filter_mapping_info {
1059 1060 char oc_or_attr;
1060 1061 char *name_start;
1061 1062 char *name_end;
1062 1063 char *veq_pos;
1063 1064 char *from_name;
1064 1065 char *to_name;
1065 1066 char **mapping;
1066 1067 } filter_mapping_info_t;
1067 1068
1068 1069 char *c, *last_copied;
1069 1070 char *filter_c, *filter_c_next;
1070 1071 char *key, *tail, *head;
1071 1072 char errstr[MAXERROR];
1072 1073 int num_eq = 0, num_veq = 0;
1073 1074 boolean_t in_quote = B_FALSE;
1074 1075 boolean_t is_value = B_FALSE;
1075 1076 int i, j, oc_len, len;
1076 1077 boolean_t at_least_one = B_FALSE;
1077 1078 filter_mapping_info_t **info, *info1;
1078 1079 char **mapping;
1079 1080 char *service, *filter, *err;
1080 1081 boolean_t auto_service = B_FALSE;
1081 1082
1082 1083 if (cookie == NULL || new_filter == NULL)
1083 1084 return (NS_LDAP_INVALID_PARAM);
1084 1085
1085 1086 *new_filter = NULL;
1086 1087 service = cookie->service;
1087 1088 filter = cookie->filter;
1088 1089
1089 1090 /*
1090 1091 * count the number of '=' char
1091 1092 */
1092 1093 for (c = filter; *c; c++) {
1093 1094 if (*c == TOKENSEPARATOR)
1094 1095 num_eq++;
1095 1096 }
1096 1097
1097 1098 if (service != NULL && strncasecmp(service, "auto_", 5) == 0)
1098 1099 auto_service = TRUE;
1099 1100
1100 1101 /*
1101 1102 * See if schema mapping existed for the given service.
1102 1103 * If not, just return success.
1103 1104 */
1104 1105 mapping = __ns_ldap_getOrigAttribute(service,
1105 1106 NS_HASH_SCHEMA_MAPPING_EXISTED);
1106 1107
1107 1108 if (mapping == NULL && auto_service)
1108 1109 /*
1109 1110 * if service == auto_* and no
1110 1111 * schema mapping found
1111 1112 * then try automount
1112 1113 */
1113 1114 mapping = __ns_ldap_getOrigAttribute(
1114 1115 "automount", NS_HASH_SCHEMA_MAPPING_EXISTED);
1115 1116
1116 1117 if (mapping)
1117 1118 __s_api_free2dArray(mapping);
1118 1119 else
1119 1120 return (NS_LDAP_SUCCESS);
1120 1121
1121 1122 /*
1122 1123 * no '=' sign, just say OK and return nothing
1123 1124 */
1124 1125 if (num_eq == 0)
1125 1126 return (NS_LDAP_SUCCESS);
1126 1127
1127 1128 /*
1128 1129 * Make a copy of the filter string
1129 1130 * for saving the name of the objectclasses or
1130 1131 * attributes that need to be passed to the
1131 1132 * objectclass or attribute mapping functions.
1132 1133 * pointer "info->from_name" points to the locations
1133 1134 * within this string.
1134 1135 *
1135 1136 * The input filter string, filter, will be used
1136 1137 * to indicate where these names start and end.
1137 1138 * pointers "info->name_start" and "info->name_end"
1138 1139 * point to locations within the input filter string,
1139 1140 * and are used at the end of this function to
1140 1141 * merge the original filter data with the
1141 1142 * mapped objectclass or attribute names.
1142 1143 */
1143 1144 filter_c = strdup(filter);
1144 1145 if (filter_c == NULL)
1145 1146 return (NS_LDAP_MEMORY);
1146 1147 filter_c_next = filter_c;
1147 1148
1148 1149 /*
1149 1150 * get memory for info arrays
1150 1151 */
1151 1152 info = (filter_mapping_info_t **)calloc(num_eq + 1,
1152 1153 sizeof (filter_mapping_info_t *));
1153 1154
1154 1155 if (info == NULL) {
1155 1156 free(filter_c);
1156 1157 return (NS_LDAP_MEMORY);
1157 1158 }
1158 1159
1159 1160 /*
1160 1161 * find valid '=' for further processing,
1161 1162 * ignore the "escaped =" (.i.e. "\="), or
1162 1163 * "=" in quoted string
1163 1164 */
1164 1165 for (c = filter_c; *c; c++) {
1165 1166
1166 1167 switch (*c) {
1167 1168 case TOKENSEPARATOR:
1168 1169 if (!in_quote && !is_value) {
1169 1170 info1 = (filter_mapping_info_t *)calloc(1,
1170 1171 sizeof (filter_mapping_info_t));
1171 1172 if (info1 == NULL) {
1172 1173 free(filter_c);
1173 1174 for (i = 0; i < num_veq; i++)
1174 1175 free(info[i]);
1175 1176 free(info);
1176 1177 return (NS_LDAP_MEMORY);
1177 1178 }
1178 1179 info[num_veq] = info1;
1179 1180
1180 1181 /*
1181 1182 * remember the location of this "="
1182 1183 */
1183 1184 info[num_veq++]->veq_pos = c;
1184 1185
1185 1186 /*
1186 1187 * skip until the end of the attribute value
1187 1188 */
1188 1189 is_value = B_TRUE;
1189 1190 }
1190 1191 break;
1191 1192 case CPARATOK:
1192 1193 /*
1193 1194 * mark the end of the attribute value
1194 1195 */
1195 1196 if (!in_quote)
1196 1197 is_value = B_FALSE;
1197 1198 break;
1198 1199 case QUOTETOK:
1199 1200 /*
1200 1201 * switch on/off the in_quote mode
1201 1202 */
1202 1203 in_quote = (in_quote == B_FALSE);
1203 1204 break;
1204 1205 case '\\':
1205 1206 /*
1206 1207 * ignore escape characters
1207 1208 * don't skip if next char is '\0'
1208 1209 */
1209 1210 if (!in_quote)
1210 1211 if (*(++c) == '\0')
1211 1212 c--;
1212 1213 break;
1213 1214 }
1214 1215
1215 1216 }
1216 1217
1217 1218 /*
1218 1219 * for each valid "=" found, get the name to
1219 1220 * be mapped
1220 1221 */
1221 1222 oc_len = strlen("objectclass");
1222 1223 for (i = 0; i < num_veq; i++) {
1223 1224
1224 1225 /*
1225 1226 * look at the left side of "=" to see
1226 1227 * if assertion is "objectclass=<ocname>"
1227 1228 * or "<attribute name>=<attribute value>"
1228 1229 *
1229 1230 * first skip spaces before "=".
1230 1231 * Note that filter_c_next may not point to the
1231 1232 * start of the filter string. For i > 0,
1232 1233 * it points to the end of the last name processed + 2
1233 1234 */
1234 1235 for (tail = info[i]->veq_pos; (tail > filter_c_next) &&
1235 1236 (*(tail - 1) == SPACETOK); tail--)
1236 1237 ;
1237 1238
1238 1239 /*
1239 1240 * mark the end of the left side string (the key)
1240 1241 */
1241 1242 *tail = '\0';
1242 1243 info[i]->name_end = tail - filter_c - 1 + filter;
1243 1244
1244 1245 /*
1245 1246 * find the start of the key
1246 1247 */
1247 1248 key = filter_c_next;
1248 1249 for (c = tail; filter_c_next <= c; c--) {
1249 1250 /* OPARATOK is '(' */
1250 1251 if (*c == OPARATOK ||
1251 1252 *c == SPACETOK) {
1252 1253 key = c + 1;
1253 1254 break;
1254 1255 }
1255 1256 }
1256 1257 info[i]->name_start = key - filter_c + filter;
1257 1258
1258 1259 if ((key + oc_len) <= tail) {
1259 1260 if (strncasecmp(key, "objectclass",
1260 1261 oc_len) == 0) {
1261 1262 /*
1262 1263 * assertion is "objectclass=ocname",
1263 1264 * ocname is the one needs to be mapped
1264 1265 *
1265 1266 * skip spaces after "=" to find start
1266 1267 * of the ocname
1267 1268 */
1268 1269 head = info[i]->veq_pos;
1269 1270 for (head = info[i]->veq_pos + 1;
1270 1271 *head && *head == SPACETOK; head++)
1271 1272 ;
1272 1273
1273 1274 /* ignore empty ocname */
1274 1275 if (!(*head))
1275 1276 continue;
1276 1277
1277 1278 info[i]->name_start = head - filter_c +
1278 1279 filter;
1279 1280
1280 1281 /*
1281 1282 * now find the end of the ocname
1282 1283 */
1283 1284 for (c = head; ; c++) {
1284 1285 /* CPARATOK is ')' */
1285 1286 if (*c == CPARATOK ||
1286 1287 *c == '\0' ||
1287 1288 *c == SPACETOK) {
1288 1289 *c = '\0';
1289 1290 info[i]->name_end =
1290 1291 c - filter_c - 1 +
1291 1292 filter;
1292 1293 filter_c_next = c + 1;
1293 1294 info[i]->oc_or_attr = 'o';
1294 1295 info[i]->from_name = head;
1295 1296 break;
1296 1297 }
1297 1298 }
1298 1299 }
1299 1300 }
1300 1301
1301 1302 /*
1302 1303 * assertion is not "objectclass=ocname",
1303 1304 * assume assertion is "<key> = <value>",
1304 1305 * <key> is the one needs to be mapped
1305 1306 */
1306 1307 if (info[i]->from_name == NULL && strlen(key) > 0) {
1307 1308 info[i]->oc_or_attr = 'a';
1308 1309 info[i]->from_name = key;
1309 1310 }
1310 1311 }
1311 1312
1312 1313 /* perform schema mapping */
1313 1314 for (i = 0; i < num_veq; i++) {
1314 1315 if (info[i]->from_name == NULL)
1315 1316 continue;
1316 1317
1317 1318 if (info[i]->oc_or_attr == 'a')
1318 1319 info[i]->mapping =
1319 1320 __ns_ldap_getMappedAttributes(service,
1320 1321 info[i]->from_name);
1321 1322 else
1322 1323 info[i]->mapping =
1323 1324 __ns_ldap_getMappedObjectClass(service,
1324 1325 info[i]->from_name);
1325 1326
1326 1327 if (info[i]->mapping == NULL && auto_service) {
1327 1328 /*
1328 1329 * If no mapped attribute/objectclass is found
1329 1330 * and service == auto*
1330 1331 * try to find automount's
1331 1332 * mapped attribute/objectclass
1332 1333 */
1333 1334 if (info[i]->oc_or_attr == 'a')
1334 1335 info[i]->mapping =
1335 1336 __ns_ldap_getMappedAttributes("automount",
1336 1337 info[i]->from_name);
1337 1338 else
1338 1339 info[i]->mapping =
1339 1340 __ns_ldap_getMappedObjectClass("automount",
1340 1341 info[i]->from_name);
1341 1342 }
1342 1343
1343 1344 if (info[i]->mapping == NULL ||
1344 1345 info[i]->mapping[0] == NULL) {
1345 1346 info[i]->to_name = NULL;
1346 1347 } else if (info[i]->mapping[1] == NULL) {
1347 1348 info[i]->to_name = info[i]->mapping[0];
1348 1349 at_least_one = TRUE;
1349 1350 } else {
1350 1351 __s_api_free2dArray(info[i]->mapping);
1351 1352 /*
1352 1353 * multiple mapping
1353 1354 * not allowed
1354 1355 */
1355 1356 (void) sprintf(errstr,
1356 1357 gettext(
1357 1358 "Multiple attribute or objectclass "
1358 1359 "mapping for '%s' in filter "
1359 1360 "'%s' not allowed."),
1360 1361 info[i]->from_name, filter);
1361 1362 err = strdup(errstr);
1362 1363 if (err) {
1363 1364 MKERROR(LOG_WARNING, cookie->errorp,
1364 1365 NS_CONFIG_SYNTAX,
1365 1366 err, NS_LDAP_MEMORY);
1366 1367 }
1367 1368
1368 1369 free(filter_c);
1369 1370 for (j = 0; j < num_veq; j++) {
1370 1371 if (info[j]->mapping)
1371 1372 __s_api_free2dArray(
1372 1373 info[j]->mapping);
1373 1374 free(info[j]);
1374 1375 }
1375 1376 free(info);
1376 1377 return (NS_LDAP_CONFIG);
1377 1378 }
1378 1379 }
1379 1380
1380 1381
1381 1382 if (at_least_one) {
1382 1383
1383 1384 len = strlen(filter);
1384 1385 last_copied = filter - 1;
1385 1386
1386 1387 for (i = 0; i < num_veq; i++) {
1387 1388 if (info[i]->to_name)
1388 1389 len += strlen(info[i]->to_name);
1389 1390 }
1390 1391
1391 1392 *new_filter = (char *)calloc(1, len);
1392 1393 if (*new_filter == NULL) {
1393 1394 free(filter_c);
1394 1395 for (j = 0; j < num_veq; j++) {
1395 1396 if (info[j]->mapping)
1396 1397 __s_api_free2dArray(
1397 1398 info[j]->mapping);
1398 1399 free(info[j]);
1399 1400 }
1400 1401 free(info);
1401 1402 return (NS_LDAP_MEMORY);
1402 1403 }
1403 1404
1404 1405 for (i = 0; i < num_veq; i++) {
1405 1406 if (info[i]->to_name != NULL &&
1406 1407 info[i]->to_name != NULL) {
1407 1408
1408 1409 /*
1409 1410 * copy the original filter data
1410 1411 * between the last name and current
1411 1412 * name
1412 1413 */
1413 1414 if ((last_copied + 1) != info[i]->name_start)
1414 1415 (void) strncat(*new_filter,
1415 1416 last_copied + 1,
1416 1417 info[i]->name_start -
1417 1418 last_copied - 1);
1418 1419
1419 1420 /* the data is copied */
1420 1421 last_copied = info[i]->name_end;
1421 1422
1422 1423 /*
1423 1424 * replace the name with
1424 1425 * the mapped name
1425 1426 */
1426 1427 (void) strcat(*new_filter, info[i]->to_name);
1427 1428 }
1428 1429
1429 1430 /* copy the filter data after the last name */
1430 1431 if (i == (num_veq -1) &&
1431 1432 info[i]->name_end <
1432 1433 (filter + strlen(filter)))
1433 1434 (void) strncat(*new_filter, last_copied + 1,
1434 1435 filter + strlen(filter) -
1435 1436 last_copied - 1);
1436 1437 }
1437 1438
1438 1439 }
1439 1440
1440 1441 /* free memory */
1441 1442 free(filter_c);
1442 1443 for (j = 0; j < num_veq; j++) {
1443 1444 if (info[j]->mapping)
1444 1445 __s_api_free2dArray(info[j]->mapping);
1445 1446 free(info[j]);
1446 1447 }
1447 1448 free(info);
1448 1449
1449 1450 return (NS_LDAP_SUCCESS);
1450 1451 }
1451 1452
1452 1453 static int
1453 1454 setup_next_search(ns_ldap_cookie_t *cookie)
1454 1455 {
1455 1456 ns_ldap_search_desc_t *dptr;
1456 1457 int scope;
1457 1458 char *filter, *str;
1458 1459 int baselen;
1459 1460 int rc;
1460 1461 void **param;
1461 1462
1462 1463 dptr = *cookie->sdpos;
1463 1464 scope = cookie->i_flags & (NS_LDAP_SCOPE_BASE |
1464 1465 NS_LDAP_SCOPE_ONELEVEL |
1465 1466 NS_LDAP_SCOPE_SUBTREE);
1466 1467 if (scope)
1467 1468 cookie->scope = scope;
1468 1469 else
1469 1470 cookie->scope = dptr->scope;
1470 1471 switch (cookie->scope) {
1471 1472 case NS_LDAP_SCOPE_BASE:
1472 1473 cookie->scope = LDAP_SCOPE_BASE;
1473 1474 break;
1474 1475 case NS_LDAP_SCOPE_ONELEVEL:
1475 1476 cookie->scope = LDAP_SCOPE_ONELEVEL;
1476 1477 break;
1477 1478 case NS_LDAP_SCOPE_SUBTREE:
1478 1479 cookie->scope = LDAP_SCOPE_SUBTREE;
1479 1480 break;
1480 1481 }
1481 1482
1482 1483 filter = NULL;
1483 1484 if (cookie->use_filtercb && cookie->init_filter_cb &&
1484 1485 dptr->filter && strlen(dptr->filter) > 0) {
1485 1486 (*cookie->init_filter_cb)(dptr, &filter,
1486 1487 cookie->userdata);
1487 1488 }
1488 1489 if (filter == NULL) {
1489 1490 if (cookie->i_filter == NULL) {
1490 1491 cookie->err_rc = NS_LDAP_INVALID_PARAM;
1491 1492 return (-1);
1492 1493 } else {
1493 1494 if (cookie->filter)
1494 1495 free(cookie->filter);
1495 1496 cookie->filter = strdup(cookie->i_filter);
1496 1497 if (cookie->filter == NULL) {
1497 1498 cookie->err_rc = NS_LDAP_MEMORY;
1498 1499 return (-1);
1499 1500 }
1500 1501 }
1501 1502 } else {
1502 1503 if (cookie->filter)
1503 1504 free(cookie->filter);
1504 1505 cookie->filter = strdup(filter);
1505 1506 free(filter);
1506 1507 if (cookie->filter == NULL) {
1507 1508 cookie->err_rc = NS_LDAP_MEMORY;
1508 1509 return (-1);
1509 1510 }
1510 1511 }
1511 1512
1512 1513 /*
1513 1514 * perform attribute/objectclass mapping on filter
1514 1515 */
1515 1516 filter = NULL;
1516 1517
1517 1518 if (cookie->service) {
1518 1519 rc = get_mapped_filter(cookie, &filter);
1519 1520 if (rc != NS_LDAP_SUCCESS) {
1520 1521 cookie->err_rc = rc;
1521 1522 return (-1);
1522 1523 } else {
1523 1524 /*
1524 1525 * get_mapped_filter returns
1525 1526 * NULL filter pointer, if
1526 1527 * no mapping was done
1527 1528 */
1528 1529 if (filter) {
1529 1530 free(cookie->filter);
1530 1531 cookie->filter = filter;
1531 1532 }
1532 1533 }
1533 1534 }
1534 1535
1535 1536 /*
1536 1537 * validate filter to make sure it's legal
1537 1538 * [remove redundant ()'s]
1538 1539 */
1539 1540 rc = validate_filter(cookie);
1540 1541 if (rc != NS_LDAP_SUCCESS) {
1541 1542 cookie->err_rc = rc;
1542 1543 return (-1);
1543 1544 }
1544 1545
1545 1546 baselen = strlen(dptr->basedn);
1546 1547 if (baselen > 0 && dptr->basedn[baselen-1] == COMMATOK) {
1547 1548 rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P,
1548 1549 (void ***)¶m, &cookie->errorp);
1549 1550 if (rc != NS_LDAP_SUCCESS) {
1550 1551 cookie->err_rc = rc;
1551 1552 return (-1);
1552 1553 }
1553 1554 str = ((char **)param)[0];
1554 1555 baselen += strlen(str)+1;
1555 1556 if (cookie->basedn)
1556 1557 free(cookie->basedn);
1557 1558 cookie->basedn = (char *)malloc(baselen);
1558 1559 if (cookie->basedn == NULL) {
1559 1560 cookie->err_rc = NS_LDAP_MEMORY;
1560 1561 return (-1);
1561 1562 }
1562 1563 (void) strcpy(cookie->basedn, dptr->basedn);
1563 1564 (void) strcat(cookie->basedn, str);
1564 1565 (void) __ns_ldap_freeParam(¶m);
1565 1566 } else {
1566 1567 if (cookie->basedn)
1567 1568 free(cookie->basedn);
1568 1569 cookie->basedn = strdup(dptr->basedn);
1569 1570 }
1570 1571 return (0);
1571 1572 }
1572 1573
1573 1574 static int
1574 1575 setup_referral_search(ns_ldap_cookie_t *cookie)
1575 1576 {
1576 1577 ns_referral_info_t *ref;
1577 1578
1578 1579 ref = cookie->refpos;
1579 1580 cookie->scope = ref->refScope;
1580 1581 if (cookie->filter) {
1581 1582 free(cookie->filter);
1582 1583 }
1583 1584 cookie->filter = strdup(ref->refFilter);
1584 1585 if (cookie->basedn) {
1585 1586 free(cookie->basedn);
1586 1587 }
1587 1588 cookie->basedn = strdup(ref->refDN);
1588 1589 if (cookie->filter == NULL || cookie->basedn == NULL) {
1589 1590 cookie->err_rc = NS_LDAP_MEMORY;
1590 1591 return (-1);
1591 1592 }
1592 1593 return (0);
1593 1594 }
1594 1595
1595 1596 static int
1596 1597 get_current_session(ns_ldap_cookie_t *cookie)
1597 1598 {
1598 1599 ConnectionID connectionId = -1;
1599 1600 Connection *conp = NULL;
1600 1601 int rc;
1601 1602 int fail_if_new_pwd_reqd = 1;
1602 1603
1603 1604 rc = __s_api_getConnection(NULL, cookie->i_flags,
1604 1605 cookie->i_auth, &connectionId, &conp,
1605 1606 &cookie->errorp, fail_if_new_pwd_reqd,
1606 1607 cookie->nopasswd_acct_mgmt, cookie->conn_user);
1607 1608
1608 1609 /*
1609 1610 * If password control attached in *cookie->errorp,
1610 1611 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
1611 1612 * free the error structure (we do not need
1612 1613 * the sec_to_expired info).
1613 1614 * Reset rc to NS_LDAP_SUCCESS.
1614 1615 */
1615 1616 if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
1616 1617 (void) __ns_ldap_freeError(
1617 1618 &cookie->errorp);
1618 1619 cookie->errorp = NULL;
1619 1620 rc = NS_LDAP_SUCCESS;
1620 1621 }
1621 1622
1622 1623 if (rc != NS_LDAP_SUCCESS) {
1623 1624 cookie->err_rc = rc;
1624 1625 return (-1);
1625 1626 }
1626 1627 cookie->conn = conp;
1627 1628 cookie->connectionId = connectionId;
1628 1629
1629 1630 return (0);
1630 1631 }
1631 1632
1632 1633 static int
1633 1634 get_next_session(ns_ldap_cookie_t *cookie)
1634 1635 {
1635 1636 ConnectionID connectionId = -1;
1636 1637 Connection *conp = NULL;
1637 1638 int rc;
1638 1639 int fail_if_new_pwd_reqd = 1;
1639 1640
1640 1641 if (cookie->connectionId > -1) {
1641 1642 DropConnection(cookie->connectionId, cookie->i_flags);
1642 1643 cookie->connectionId = -1;
1643 1644 }
1644 1645
1645 1646 /* If using a MT connection, return it. */
1646 1647 if (cookie->conn_user != NULL &&
1647 1648 cookie->conn_user->conn_mt != NULL)
1648 1649 __s_api_conn_mt_return(cookie->conn_user);
1649 1650
1650 1651 rc = __s_api_getConnection(NULL, cookie->i_flags,
1651 1652 cookie->i_auth, &connectionId, &conp,
1652 1653 &cookie->errorp, fail_if_new_pwd_reqd,
1653 1654 cookie->nopasswd_acct_mgmt, cookie->conn_user);
1654 1655
1655 1656 /*
1656 1657 * If password control attached in *cookie->errorp,
1657 1658 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
1658 1659 * free the error structure (we do not need
1659 1660 * the sec_to_expired info).
1660 1661 * Reset rc to NS_LDAP_SUCCESS.
1661 1662 */
1662 1663 if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
1663 1664 (void) __ns_ldap_freeError(
1664 1665 &cookie->errorp);
1665 1666 cookie->errorp = NULL;
1666 1667 rc = NS_LDAP_SUCCESS;
1667 1668 }
1668 1669
1669 1670 if (rc != NS_LDAP_SUCCESS) {
1670 1671 cookie->err_rc = rc;
1671 1672 return (-1);
1672 1673 }
1673 1674 cookie->conn = conp;
1674 1675 cookie->connectionId = connectionId;
1675 1676 return (0);
1676 1677 }
1677 1678
1678 1679 static int
1679 1680 get_referral_session(ns_ldap_cookie_t *cookie)
1680 1681 {
1681 1682 ConnectionID connectionId = -1;
1682 1683 Connection *conp = NULL;
1683 1684 int rc;
1684 1685 int fail_if_new_pwd_reqd = 1;
1685 1686
1686 1687 if (cookie->connectionId > -1) {
1687 1688 DropConnection(cookie->connectionId, cookie->i_flags);
1688 1689 cookie->connectionId = -1;
1689 1690 }
1690 1691
1691 1692 /* set it up to use a connection opened for referral */
1692 1693 if (cookie->conn_user != NULL) {
1693 1694 /* If using a MT connection, return it. */
1694 1695 if (cookie->conn_user->conn_mt != NULL)
1695 1696 __s_api_conn_mt_return(cookie->conn_user);
1696 1697 cookie->conn_user->referral = B_TRUE;
1697 1698 }
1698 1699
1699 1700 rc = __s_api_getConnection(cookie->refpos->refHost, 0,
1700 1701 cookie->i_auth, &connectionId, &conp,
1701 1702 &cookie->errorp, fail_if_new_pwd_reqd,
1702 1703 cookie->nopasswd_acct_mgmt, cookie->conn_user);
1703 1704
1704 1705 /*
1705 1706 * If password control attached in *cookie->errorp,
1706 1707 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
1707 1708 * free the error structure (we do not need
1708 1709 * the sec_to_expired info).
1709 1710 * Reset rc to NS_LDAP_SUCCESS.
1710 1711 */
1711 1712 if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
1712 1713 (void) __ns_ldap_freeError(
1713 1714 &cookie->errorp);
1714 1715 cookie->errorp = NULL;
1715 1716 rc = NS_LDAP_SUCCESS;
1716 1717 }
1717 1718
1718 1719 if (rc != NS_LDAP_SUCCESS) {
1719 1720 cookie->err_rc = rc;
1720 1721 return (-1);
1721 1722 }
1722 1723 cookie->conn = conp;
1723 1724 cookie->connectionId = connectionId;
1724 1725 return (0);
1725 1726 }
1726 1727
1727 1728 static int
1728 1729 paging_supported(ns_ldap_cookie_t *cookie)
1729 1730 {
1730 1731 int rc;
1731 1732
1732 1733 cookie->listType = 0;
1733 1734 rc = __s_api_isCtrlSupported(cookie->conn,
1734 1735 LDAP_CONTROL_VLVREQUEST);
1735 1736 if (rc == NS_LDAP_SUCCESS) {
1736 1737 cookie->listType = VLVCTRLFLAG;
1737 1738 return (1);
1738 1739 }
1739 1740 rc = __s_api_isCtrlSupported(cookie->conn,
1740 1741 LDAP_CONTROL_SIMPLE_PAGE);
1741 1742 if (rc == NS_LDAP_SUCCESS) {
1742 1743 cookie->listType = SIMPLEPAGECTRLFLAG;
1743 1744 return (1);
1744 1745 }
1745 1746 return (0);
1746 1747 }
1747 1748
1748 1749 typedef struct servicesorttype {
1749 1750 char *service;
1750 1751 ns_srvsidesort_t type;
1751 1752 } servicesorttype_t;
1752 1753
1753 1754 static servicesorttype_t *sort_type = NULL;
1754 1755 static int sort_type_size = 0;
1755 1756 static int sort_type_hwm = 0;
1756 1757 static mutex_t sort_type_mutex = DEFAULTMUTEX;
1757 1758
1758 1759
1759 1760 static ns_srvsidesort_t
1760 1761 get_srvsidesort_type(char *service)
1761 1762 {
1762 1763 int i;
1763 1764 ns_srvsidesort_t type = SSS_UNKNOWN;
1764 1765
1765 1766 if (service == NULL)
1766 1767 return (type);
1767 1768
1768 1769 (void) mutex_lock(&sort_type_mutex);
1769 1770 if (sort_type != NULL) {
1770 1771 for (i = 0; i < sort_type_hwm; i++) {
1771 1772 if (strcmp(sort_type[i].service, service) == 0) {
1772 1773 type = sort_type[i].type;
1773 1774 break;
1774 1775 }
1775 1776 }
1776 1777 }
1777 1778 (void) mutex_unlock(&sort_type_mutex);
1778 1779 return (type);
1779 1780 }
1780 1781
1781 1782 static void
1782 1783 update_srvsidesort_type(char *service, ns_srvsidesort_t type)
1783 1784 {
1784 1785 int i, size;
1785 1786 servicesorttype_t *tmp;
1786 1787
1787 1788 if (service == NULL)
1788 1789 return;
1789 1790
1790 1791 (void) mutex_lock(&sort_type_mutex);
1791 1792
1792 1793 for (i = 0; i < sort_type_hwm; i++) {
1793 1794 if (strcmp(sort_type[i].service, service) == 0) {
1794 1795 sort_type[i].type = type;
1795 1796 (void) mutex_unlock(&sort_type_mutex);
1796 1797 return;
1797 1798 }
1798 1799 }
1799 1800 if (sort_type == NULL) {
1800 1801 size = 10;
1801 1802 tmp = malloc(size * sizeof (servicesorttype_t));
1802 1803 if (tmp == NULL) {
1803 1804 (void) mutex_unlock(&sort_type_mutex);
1804 1805 return;
1805 1806 }
1806 1807 sort_type = tmp;
1807 1808 sort_type_size = size;
1808 1809 } else if (sort_type_hwm >= sort_type_size) {
1809 1810 size = sort_type_size + 10;
1810 1811 tmp = realloc(sort_type, size * sizeof (servicesorttype_t));
1811 1812 if (tmp == NULL) {
1812 1813 (void) mutex_unlock(&sort_type_mutex);
1813 1814 return;
1814 1815 }
1815 1816 sort_type = tmp;
1816 1817 sort_type_size = size;
1817 1818 }
1818 1819 sort_type[sort_type_hwm].service = strdup(service);
1819 1820 if (sort_type[sort_type_hwm].service == NULL) {
1820 1821 (void) mutex_unlock(&sort_type_mutex);
1821 1822 return;
1822 1823 }
1823 1824 sort_type[sort_type_hwm].type = type;
1824 1825 sort_type_hwm++;
1825 1826
1826 1827 (void) mutex_unlock(&sort_type_mutex);
1827 1828 }
1828 1829
1829 1830 static int
1830 1831 setup_vlv_params(ns_ldap_cookie_t *cookie)
1831 1832 {
1832 1833 LDAPControl **ctrls;
1833 1834 LDAPsortkey **sortkeylist;
1834 1835 LDAPControl *sortctrl = NULL;
1835 1836 LDAPControl *vlvctrl = NULL;
1836 1837 LDAPVirtualList vlist;
1837 1838 char *sortattr;
1838 1839 int rc;
1839 1840 int free_sort = FALSE;
1840 1841
1841 1842 _freeControlList(&cookie->p_serverctrls);
1842 1843
1843 1844 if (cookie->sortTypeTry == SSS_UNKNOWN)
1844 1845 cookie->sortTypeTry = get_srvsidesort_type(cookie->service);
1845 1846 if (cookie->sortTypeTry == SSS_UNKNOWN)
1846 1847 cookie->sortTypeTry = SSS_SINGLE_ATTR;
1847 1848
1848 1849 if (cookie->sortTypeTry == SSS_SINGLE_ATTR) {
1849 1850 if ((cookie->i_flags & NS_LDAP_NOMAP) == 0 &&
1850 1851 cookie->i_sortattr) {
1851 1852 sortattr = __ns_ldap_mapAttribute(cookie->service,
1852 1853 cookie->i_sortattr);
1853 1854 free_sort = TRUE;
1854 1855 } else if (cookie->i_sortattr) {
1855 1856 sortattr = (char *)cookie->i_sortattr;
1856 1857 } else {
1857 1858 sortattr = "cn";
1858 1859 }
1859 1860 } else {
1860 1861 sortattr = "cn uid";
1861 1862 }
1862 1863
1863 1864 rc = ldap_create_sort_keylist(&sortkeylist, sortattr);
1864 1865 if (free_sort)
1865 1866 free(sortattr);
1866 1867 if (rc != LDAP_SUCCESS) {
1867 1868 (void) ldap_get_option(cookie->conn->ld,
1868 1869 LDAP_OPT_ERROR_NUMBER, &rc);
1869 1870 return (rc);
1870 1871 }
1871 1872 rc = ldap_create_sort_control(cookie->conn->ld,
1872 1873 sortkeylist, 1, &sortctrl);
1873 1874 ldap_free_sort_keylist(sortkeylist);
1874 1875 if (rc != LDAP_SUCCESS) {
1875 1876 (void) ldap_get_option(cookie->conn->ld,
1876 1877 LDAP_OPT_ERROR_NUMBER, &rc);
1877 1878 return (rc);
1878 1879 }
1879 1880
1880 1881 vlist.ldvlist_index = cookie->index;
1881 1882 vlist.ldvlist_size = 0;
1882 1883
1883 1884 vlist.ldvlist_before_count = 0;
1884 1885 vlist.ldvlist_after_count = LISTPAGESIZE-1;
1885 1886 vlist.ldvlist_attrvalue = NULL;
1886 1887 vlist.ldvlist_extradata = NULL;
1887 1888
1888 1889 rc = ldap_create_virtuallist_control(cookie->conn->ld,
1889 1890 &vlist, &vlvctrl);
1890 1891 if (rc != LDAP_SUCCESS) {
1891 1892 ldap_control_free(sortctrl);
1892 1893 (void) ldap_get_option(cookie->conn->ld, LDAP_OPT_ERROR_NUMBER,
1893 1894 &rc);
1894 1895 return (rc);
1895 1896 }
1896 1897
1897 1898 ctrls = (LDAPControl **)calloc(3, sizeof (LDAPControl *));
1898 1899 if (ctrls == NULL) {
1899 1900 ldap_control_free(sortctrl);
1900 1901 ldap_control_free(vlvctrl);
1901 1902 return (LDAP_NO_MEMORY);
1902 1903 }
1903 1904
1904 1905 ctrls[0] = sortctrl;
1905 1906 ctrls[1] = vlvctrl;
1906 1907
1907 1908 cookie->p_serverctrls = ctrls;
1908 1909 return (LDAP_SUCCESS);
1909 1910 }
1910 1911
1911 1912 static int
1912 1913 setup_simplepg_params(ns_ldap_cookie_t *cookie)
1913 1914 {
1914 1915 LDAPControl **ctrls;
1915 1916 LDAPControl *pgctrl = NULL;
1916 1917 int rc;
1917 1918
1918 1919 _freeControlList(&cookie->p_serverctrls);
1919 1920
1920 1921 rc = ldap_create_page_control(cookie->conn->ld, LISTPAGESIZE,
1921 1922 cookie->ctrlCookie, (char)0, &pgctrl);
1922 1923 if (rc != LDAP_SUCCESS) {
1923 1924 (void) ldap_get_option(cookie->conn->ld, LDAP_OPT_ERROR_NUMBER,
1924 1925 &rc);
1925 1926 return (rc);
1926 1927 }
1927 1928
1928 1929 ctrls = (LDAPControl **)calloc(2, sizeof (LDAPControl *));
1929 1930 if (ctrls == NULL) {
1930 1931 ldap_control_free(pgctrl);
1931 1932 return (LDAP_NO_MEMORY);
1932 1933 }
1933 1934 ctrls[0] = pgctrl;
1934 1935 cookie->p_serverctrls = ctrls;
1935 1936 return (LDAP_SUCCESS);
1936 1937 }
1937 1938
1938 1939 static void
1939 1940 proc_result_referrals(ns_ldap_cookie_t *cookie)
1940 1941 {
1941 1942 int errCode, i, rc;
1942 1943 char **referrals = NULL;
1943 1944
1944 1945 /*
1945 1946 * Only follow one level of referrals, i.e.
1946 1947 * if already in referral mode, do nothing
1947 1948 */
1948 1949 if (cookie->refpos == NULL) {
1949 1950 cookie->new_state = END_RESULT;
1950 1951 rc = ldap_parse_result(cookie->conn->ld,
1951 1952 cookie->resultMsg,
1952 1953 &errCode, NULL,
1953 1954 NULL, &referrals,
1954 1955 NULL, 0);
1955 1956 if (rc != NS_LDAP_SUCCESS) {
1956 1957 (void) ldap_get_option(cookie->conn->ld,
1957 1958 LDAP_OPT_ERROR_NUMBER,
1958 1959 &cookie->err_rc);
1959 1960 cookie->new_state = LDAP_ERROR;
1960 1961 return;
1961 1962 }
1962 1963 if (errCode == LDAP_REFERRAL) {
1963 1964 for (i = 0; referrals[i] != NULL;
1964 1965 i++) {
1965 1966 /* add to referral list */
1966 1967 rc = __s_api_addRefInfo(
1967 1968 &cookie->reflist,
1968 1969 referrals[i],
1969 1970 cookie->basedn,
1970 1971 &cookie->scope,
1971 1972 cookie->filter,
1972 1973 cookie->conn->ld);
1973 1974 if (rc != NS_LDAP_SUCCESS) {
1974 1975 cookie->new_state =
1975 1976 ERROR;
1976 1977 break;
1977 1978 }
1978 1979 }
1979 1980 ldap_value_free(referrals);
1980 1981 }
1981 1982 }
1982 1983 }
1983 1984
1984 1985 static void
1985 1986 proc_search_references(ns_ldap_cookie_t *cookie)
1986 1987 {
1987 1988 char **refurls = NULL;
1988 1989 int i, rc;
1989 1990
1990 1991 /*
1991 1992 * Only follow one level of referrals, i.e.
1992 1993 * if already in referral mode, do nothing
1993 1994 */
1994 1995 if (cookie->refpos == NULL) {
1995 1996 refurls = ldap_get_reference_urls(
1996 1997 cookie->conn->ld,
1997 1998 cookie->resultMsg);
1998 1999 if (refurls == NULL) {
1999 2000 (void) ldap_get_option(cookie->conn->ld,
2000 2001 LDAP_OPT_ERROR_NUMBER,
2001 2002 &cookie->err_rc);
2002 2003 cookie->new_state = LDAP_ERROR;
2003 2004 return;
2004 2005 }
2005 2006 for (i = 0; refurls[i] != NULL; i++) {
2006 2007 /* add to referral list */
2007 2008 rc = __s_api_addRefInfo(
2008 2009 &cookie->reflist,
2009 2010 refurls[i],
2010 2011 cookie->basedn,
2011 2012 &cookie->scope,
2012 2013 cookie->filter,
2013 2014 cookie->conn->ld);
2014 2015 if (rc != NS_LDAP_SUCCESS) {
2015 2016 cookie->new_state =
2016 2017 ERROR;
2017 2018 break;
2018 2019 }
2019 2020 }
2020 2021 /* free allocated storage */
2021 2022 for (i = 0; refurls[i] != NULL; i++)
2022 2023 free(refurls[i]);
2023 2024 }
2024 2025 }
2025 2026
2026 2027 static ns_state_t
2027 2028 multi_result(ns_ldap_cookie_t *cookie)
2028 2029 {
2029 2030 char errstr[MAXERROR];
2030 2031 char *err;
2031 2032 ns_ldap_error_t **errorp = NULL;
2032 2033 LDAPControl **retCtrls = NULL;
2033 2034 int i, rc;
2034 2035 int errCode;
2035 2036 boolean_t finished = B_FALSE;
2036 2037 unsigned long target_posp = 0;
2037 2038 unsigned long list_size = 0;
2038 2039 unsigned int count = 0;
2039 2040 char **referrals = NULL;
2040 2041
2041 2042 if (cookie->listType == VLVCTRLFLAG) {
2042 2043 rc = ldap_parse_result(cookie->conn->ld, cookie->resultMsg,
2043 2044 &errCode, NULL, NULL, &referrals, &retCtrls, 0);
2044 2045 if (rc != LDAP_SUCCESS) {
2045 2046 (void) ldap_get_option(cookie->conn->ld,
2046 2047 LDAP_OPT_ERROR_NUMBER,
2047 2048 &cookie->err_rc);
2048 2049 (void) sprintf(errstr,
2049 2050 gettext("LDAP ERROR (%d): %s.\n"),
2050 2051 cookie->err_rc,
2051 2052 gettext(ldap_err2string(cookie->err_rc)));
2052 2053 err = strdup(errstr);
2053 2054 MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err,
2054 2055 NS_LDAP_MEMORY);
2055 2056 cookie->err_rc = NS_LDAP_INTERNAL;
2056 2057 cookie->errorp = *errorp;
2057 2058 return (LDAP_ERROR);
2058 2059 }
2059 2060 if (errCode == LDAP_REFERRAL) {
2060 2061 for (i = 0; referrals[i] != NULL;
2061 2062 i++) {
2062 2063 /* add to referral list */
2063 2064 rc = __s_api_addRefInfo(
2064 2065 &cookie->reflist,
2065 2066 referrals[i],
2066 2067 cookie->basedn,
2067 2068 &cookie->scope,
2068 2069 cookie->filter,
2069 2070 cookie->conn->ld);
2070 2071 if (rc != NS_LDAP_SUCCESS) {
2071 2072 ldap_value_free(
2072 2073 referrals);
2073 2074 if (retCtrls)
2074 2075 ldap_controls_free(
2075 2076 retCtrls);
2076 2077 return (ERROR);
2077 2078 }
2078 2079 }
2079 2080 ldap_value_free(referrals);
2080 2081 if (retCtrls)
2081 2082 ldap_controls_free(retCtrls);
2082 2083 return (END_RESULT);
2083 2084 }
2084 2085 if (retCtrls) {
2085 2086 rc = ldap_parse_virtuallist_control(
2086 2087 cookie->conn->ld, retCtrls,
2087 2088 &target_posp, &list_size, &errCode);
2088 2089 if (rc == LDAP_SUCCESS) {
2089 2090 /*
2090 2091 * AD does not return valid target_posp
2091 2092 * and list_size
2092 2093 */
2093 2094 if (target_posp != 0 && list_size != 0) {
2094 2095 cookie->index =
2095 2096 target_posp + LISTPAGESIZE;
2096 2097 if (cookie->index > list_size)
2097 2098 finished = B_TRUE;
2098 2099 } else {
2099 2100 if (cookie->entryCount < LISTPAGESIZE)
2100 2101 finished = B_TRUE;
2101 2102 else
2102 2103 cookie->index +=
2103 2104 cookie->entryCount;
2104 2105 }
2105 2106 }
2106 2107 ldap_controls_free(retCtrls);
2107 2108 retCtrls = NULL;
2108 2109 } else {
2109 2110 finished = B_TRUE;
2110 2111 }
2111 2112 } else if (cookie->listType == SIMPLEPAGECTRLFLAG) {
2112 2113 rc = ldap_parse_result(cookie->conn->ld, cookie->resultMsg,
2113 2114 &errCode, NULL, NULL, &referrals, &retCtrls, 0);
2114 2115 if (rc != LDAP_SUCCESS) {
2115 2116 (void) ldap_get_option(cookie->conn->ld,
2116 2117 LDAP_OPT_ERROR_NUMBER,
2117 2118 &cookie->err_rc);
2118 2119 (void) sprintf(errstr,
2119 2120 gettext("LDAP ERROR (%d): %s.\n"),
2120 2121 cookie->err_rc,
2121 2122 gettext(ldap_err2string(cookie->err_rc)));
2122 2123 err = strdup(errstr);
2123 2124 MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err,
2124 2125 NS_LDAP_MEMORY);
2125 2126 cookie->err_rc = NS_LDAP_INTERNAL;
2126 2127 cookie->errorp = *errorp;
2127 2128 return (LDAP_ERROR);
2128 2129 }
2129 2130 if (errCode == LDAP_REFERRAL) {
2130 2131 for (i = 0; referrals[i] != NULL;
2131 2132 i++) {
2132 2133 /* add to referral list */
2133 2134 rc = __s_api_addRefInfo(
2134 2135 &cookie->reflist,
2135 2136 referrals[i],
2136 2137 cookie->basedn,
2137 2138 &cookie->scope,
2138 2139 cookie->filter,
2139 2140 cookie->conn->ld);
2140 2141 if (rc != NS_LDAP_SUCCESS) {
2141 2142 ldap_value_free(
2142 2143 referrals);
2143 2144 if (retCtrls)
2144 2145 ldap_controls_free(
2145 2146 retCtrls);
2146 2147 return (ERROR);
2147 2148 }
2148 2149 }
2149 2150 ldap_value_free(referrals);
2150 2151 if (retCtrls)
2151 2152 ldap_controls_free(retCtrls);
2152 2153 return (END_RESULT);
2153 2154 }
2154 2155 if (retCtrls) {
2155 2156 if (cookie->ctrlCookie)
2156 2157 ber_bvfree(cookie->ctrlCookie);
2157 2158 cookie->ctrlCookie = NULL;
2158 2159 rc = ldap_parse_page_control(
2159 2160 cookie->conn->ld, retCtrls,
2160 2161 &count, &cookie->ctrlCookie);
2161 2162 if (rc == LDAP_SUCCESS) {
2162 2163 if ((cookie->ctrlCookie == NULL) ||
2163 2164 (cookie->ctrlCookie->bv_val == NULL) ||
2164 2165 (cookie->ctrlCookie->bv_len == 0))
2165 2166 finished = B_TRUE;
2166 2167 }
2167 2168 ldap_controls_free(retCtrls);
2168 2169 retCtrls = NULL;
2169 2170 } else {
2170 2171 finished = B_TRUE;
2171 2172 }
2172 2173 }
2173 2174 if (!finished && cookie->listType == VLVCTRLFLAG)
2174 2175 return (NEXT_VLV);
2175 2176 if (!finished && cookie->listType == SIMPLEPAGECTRLFLAG)
2176 2177 return (NEXT_PAGE);
2177 2178 if (finished)
2178 2179 return (END_RESULT);
2179 2180 return (ERROR);
2180 2181 }
2181 2182
2182 2183 /*
2183 2184 * clear_results(ns_ldap_cookie_t):
2184 2185 *
2185 2186 * Attempt to obtain remnants of ldap responses and free them. If remnants are
2186 2187 * not obtained within a certain time period tell the server we wish to abandon
2187 2188 * the request.
2188 2189 *
2189 2190 * Note that we do not initially tell the server to abandon the request as that
2190 2191 * can be an expensive operation for the server, while it is cheap for us to
2191 2192 * just flush the input.
2192 2193 *
2193 2194 * If something was to remain in libldap queue as a result of some error then
2194 2195 * it would be freed later during drop connection call or when no other
2195 2196 * requests share the connection.
2196 2197 */
2197 2198 static void
2198 2199 clear_results(ns_ldap_cookie_t *cookie)
2199 2200 {
2200 2201 int rc;
2201 2202 if (cookie->conn != NULL && cookie->conn->ld != NULL &&
2202 2203 (cookie->connectionId != -1 ||
2203 2204 (cookie->conn_user != NULL &&
2204 2205 cookie->conn_user->conn_mt != NULL)) &&
2205 2206 cookie->msgId != 0) {
2206 2207 /*
2207 2208 * We need to cleanup the rest of response (if there is such)
2208 2209 * and LDAP abandon is too heavy for LDAP servers, so we will
2209 2210 * wait for the rest of response till timeout and "process" it.
2210 2211 */
2211 2212 rc = ldap_result(cookie->conn->ld, cookie->msgId, LDAP_MSG_ALL,
2212 2213 (struct timeval *)&cookie->search_timeout,
2213 2214 &cookie->resultMsg);
2214 2215 if (rc != -1 && rc != 0 && cookie->resultMsg != NULL) {
2215 2216 (void) ldap_msgfree(cookie->resultMsg);
2216 2217 cookie->resultMsg = NULL;
2217 2218 }
2218 2219
2219 2220 /*
2220 2221 * If there was timeout then we will send ABANDON request to
2221 2222 * LDAP server to decrease load.
2222 2223 */
2223 2224 if (rc == 0)
2224 2225 (void) ldap_abandon_ext(cookie->conn->ld, cookie->msgId,
2225 2226 NULL, NULL);
2226 2227 /* Disassociate cookie with msgId */
2227 2228 cookie->msgId = 0;
2228 2229 }
2229 2230 }
2230 2231
2231 2232 /*
2232 2233 * This state machine performs one or more LDAP searches to a given
2233 2234 * directory server using service search descriptors and schema
2234 2235 * mapping as appropriate. The approximate pseudocode for
2235 2236 * this routine is the following:
2236 2237 * Given the current configuration [set/reset connection etc.]
2237 2238 * and the current service search descriptor list
2238 2239 * or default search filter parameters
2239 2240 * foreach (service search filter) {
2240 2241 * initialize the filter [via filter_init if appropriate]
2241 2242 * get a valid session/connection (preferably the current one)
2242 2243 * Recover if the connection is lost
2243 2244 * perform the search
2244 2245 * foreach (result entry) {
2245 2246 * process result [via callback if appropriate]
2246 2247 * save result for caller if accepted.
2247 2248 * exit and return all collected if allResults found;
2248 2249 * }
2249 2250 * }
2250 2251 * return collected results and exit
2251 2252 */
2252 2253
2253 2254 static
2254 2255 ns_state_t
2255 2256 search_state_machine(ns_ldap_cookie_t *cookie, ns_state_t state, int cycle)
2256 2257 {
2257 2258 char errstr[MAXERROR];
2258 2259 char *err;
2259 2260 int rc, ret;
2260 2261 int rc_save;
2261 2262 ns_ldap_entry_t *nextEntry;
2262 2263 ns_ldap_error_t *error = NULL;
2263 2264 ns_ldap_error_t **errorp;
2264 2265 struct timeval tv;
2265 2266
2266 2267 errorp = &error;
2267 2268 cookie->state = state;
2268 2269 errstr[0] = '\0';
2269 2270
2270 2271 for (;;) {
2271 2272 switch (cookie->state) {
2272 2273 case CLEAR_RESULTS:
2273 2274 clear_results(cookie);
2274 2275 cookie->new_state = EXIT;
2275 2276 break;
2276 2277 case GET_ACCT_MGMT_INFO:
2277 2278 /*
2278 2279 * Set the flag to get ldap account management controls.
2279 2280 */
2280 2281 cookie->nopasswd_acct_mgmt = 1;
2281 2282 cookie->new_state = INIT;
2282 2283 break;
2283 2284 case EXIT:
2284 2285 /* state engine/connection cleaned up in delete */
2285 2286 if (cookie->attribute) {
2286 2287 __s_api_free2dArray(cookie->attribute);
2287 2288 cookie->attribute = NULL;
2288 2289 }
2289 2290 if (cookie->reflist) {
2290 2291 __s_api_deleteRefInfo(cookie->reflist);
2291 2292 cookie->reflist = NULL;
2292 2293 }
2293 2294 return (EXIT);
2294 2295 case INIT:
2295 2296 cookie->sdpos = NULL;
2296 2297 cookie->new_state = NEXT_SEARCH_DESCRIPTOR;
2297 2298 if (cookie->attribute) {
2298 2299 __s_api_free2dArray(cookie->attribute);
2299 2300 cookie->attribute = NULL;
2300 2301 }
2301 2302 if ((cookie->i_flags & NS_LDAP_NOMAP) == 0 &&
2302 2303 cookie->i_attr) {
2303 2304 cookie->attribute =
2304 2305 __ns_ldap_mapAttributeList(
2305 2306 cookie->service,
2306 2307 cookie->i_attr);
2307 2308 }
2308 2309 break;
2309 2310 case REINIT:
2310 2311 /* Check if we've reached MAX retries. */
2311 2312 cookie->retries++;
2312 2313 if (cookie->retries > NS_LIST_TRY_MAX - 1) {
2313 2314 cookie->new_state = LDAP_ERROR;
2314 2315 break;
2315 2316 }
2316 2317
2317 2318 /*
2318 2319 * Even if we still have retries left, check
2319 2320 * if retry is possible.
2320 2321 */
2321 2322 if (cookie->conn_user != NULL) {
2322 2323 int retry;
2323 2324 ns_conn_mgmt_t *cmg;
2324 2325 cmg = cookie->conn_user->conn_mgmt;
2325 2326 retry = cookie->conn_user->retry;
2326 2327 if (cmg != NULL && cmg->cfg_reloaded == 1)
2327 2328 retry = 1;
2328 2329 if (retry == 0) {
2329 2330 cookie->new_state = LDAP_ERROR;
2330 2331 break;
2331 2332 }
2332 2333 }
2333 2334 /*
2334 2335 * Free results if any, reset to the first
2335 2336 * search descriptor and start a new session.
2336 2337 */
2337 2338 if (cookie->resultMsg != NULL) {
2338 2339 (void) ldap_msgfree(cookie->resultMsg);
2339 2340 cookie->resultMsg = NULL;
2340 2341 }
2341 2342 (void) __ns_ldap_freeError(&cookie->errorp);
2342 2343 (void) __ns_ldap_freeResult(&cookie->result);
2343 2344 cookie->sdpos = cookie->sdlist;
2344 2345 cookie->err_from_result = 0;
2345 2346 cookie->err_rc = 0;
2346 2347 cookie->new_state = NEXT_SESSION;
2347 2348 break;
2348 2349 case NEXT_SEARCH_DESCRIPTOR:
2349 2350 /* get next search descriptor */
2350 2351 if (cookie->sdpos == NULL) {
2351 2352 cookie->sdpos = cookie->sdlist;
2352 2353 cookie->new_state = GET_SESSION;
2353 2354 } else {
2354 2355 cookie->sdpos++;
2355 2356 cookie->new_state = NEXT_SEARCH;
2356 2357 }
2357 2358 if (*cookie->sdpos == NULL)
2358 2359 cookie->new_state = EXIT;
2359 2360 break;
2360 2361 case GET_SESSION:
2361 2362 if (get_current_session(cookie) < 0)
2362 2363 cookie->new_state = NEXT_SESSION;
2363 2364 else
2364 2365 cookie->new_state = NEXT_SEARCH;
2365 2366 break;
2366 2367 case NEXT_SESSION:
2367 2368 if (get_next_session(cookie) < 0)
2368 2369 cookie->new_state = RESTART_SESSION;
2369 2370 else
2370 2371 cookie->new_state = NEXT_SEARCH;
2371 2372 break;
2372 2373 case RESTART_SESSION:
2373 2374 if (cookie->i_flags & NS_LDAP_HARD) {
2374 2375 cookie->new_state = NEXT_SESSION;
2375 2376 break;
2376 2377 }
2377 2378 (void) sprintf(errstr,
2378 2379 gettext("Session error no available conn.\n"),
2379 2380 state);
2380 2381 err = strdup(errstr);
2381 2382 MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err,
2382 2383 NS_LDAP_MEMORY);
2383 2384 cookie->err_rc = NS_LDAP_INTERNAL;
2384 2385 cookie->errorp = *errorp;
2385 2386 cookie->new_state = EXIT;
2386 2387 break;
2387 2388 case NEXT_SEARCH:
2388 2389 /* setup referrals search if necessary */
2389 2390 if (cookie->refpos) {
2390 2391 if (setup_referral_search(cookie) < 0) {
2391 2392 cookie->new_state = EXIT;
2392 2393 break;
2393 2394 }
2394 2395 } else if (setup_next_search(cookie) < 0) {
2395 2396 cookie->new_state = EXIT;
2396 2397 break;
2397 2398 }
2398 2399 /* only do VLV/PAGE on scopes onelevel/subtree */
2399 2400 if (paging_supported(cookie)) {
2400 2401 if (cookie->use_paging &&
2401 2402 (cookie->scope != LDAP_SCOPE_BASE)) {
2402 2403 cookie->index = 1;
2403 2404 if (cookie->listType == VLVCTRLFLAG)
2404 2405 cookie->new_state = NEXT_VLV;
2405 2406 else
2406 2407 cookie->new_state = NEXT_PAGE;
2407 2408 break;
2408 2409 }
2409 2410 }
2410 2411 cookie->new_state = ONE_SEARCH;
2411 2412 break;
2412 2413 case NEXT_VLV:
2413 2414 rc = setup_vlv_params(cookie);
2414 2415 if (rc != LDAP_SUCCESS) {
2415 2416 cookie->err_rc = rc;
2416 2417 cookie->new_state = LDAP_ERROR;
2417 2418 break;
2418 2419 }
2419 2420 cookie->next_state = MULTI_RESULT;
2420 2421 cookie->new_state = DO_SEARCH;
2421 2422 break;
2422 2423 case NEXT_PAGE:
2423 2424 rc = setup_simplepg_params(cookie);
2424 2425 if (rc != LDAP_SUCCESS) {
2425 2426 cookie->err_rc = rc;
2426 2427 cookie->new_state = LDAP_ERROR;
2427 2428 break;
2428 2429 }
2429 2430 cookie->next_state = MULTI_RESULT;
2430 2431 cookie->new_state = DO_SEARCH;
2431 2432 break;
2432 2433 case ONE_SEARCH:
2433 2434 cookie->next_state = NEXT_RESULT;
2434 2435 cookie->new_state = DO_SEARCH;
2435 2436 break;
2436 2437 case DO_SEARCH:
2437 2438 cookie->entryCount = 0;
2438 2439 rc = ldap_search_ext(cookie->conn->ld,
2439 2440 cookie->basedn,
2440 2441 cookie->scope,
2441 2442 cookie->filter,
2442 2443 cookie->attribute,
2443 2444 0,
2444 2445 cookie->p_serverctrls,
2445 2446 NULL,
2446 2447 &cookie->search_timeout, 0,
2447 2448 &cookie->msgId);
2448 2449 if (rc != LDAP_SUCCESS) {
2449 2450 if (rc == LDAP_BUSY ||
2450 2451 rc == LDAP_UNAVAILABLE ||
2451 2452 rc == LDAP_UNWILLING_TO_PERFORM ||
2452 2453 rc == LDAP_CONNECT_ERROR ||
2453 2454 rc == LDAP_SERVER_DOWN) {
2454 2455
2455 2456 if (cookie->reinit_on_retriable_err) {
2456 2457 cookie->err_rc = rc;
2457 2458 cookie->new_state = REINIT;
2458 2459 } else {
2459 2460 cookie->new_state =
2460 2461 NEXT_SESSION;
2461 2462 }
2462 2463
2463 2464 /*
2464 2465 * If not able to reach the
2465 2466 * server, inform the ldap
2466 2467 * cache manager that the
2467 2468 * server should be removed
2468 2469 * from it's server list.
2469 2470 * Thus, the manager will not
2470 2471 * return this server on the next
2471 2472 * get-server request and will
2472 2473 * also reduce the server list
2473 2474 * refresh TTL, so that it will
2474 2475 * find out sooner when the server
2475 2476 * is up again.
2476 2477 */
2477 2478 if ((rc == LDAP_CONNECT_ERROR ||
2478 2479 rc == LDAP_SERVER_DOWN) &&
2479 2480 (cookie->conn_user == NULL ||
2480 2481 cookie->conn_user->conn_mt ==
2481 2482 NULL)) {
2482 2483 ret = __s_api_removeServer(
2483 2484 cookie->conn->serverAddr);
2484 2485 if (ret == NS_CACHE_NOSERVER &&
2485 2486 cookie->conn_auth_type
2486 2487 == NS_LDAP_AUTH_NONE) {
2487 2488 /*
2488 2489 * Couldn't remove
2489 2490 * server from server
2490 2491 * list.
2491 2492 * Exit to avoid
2492 2493 * potential infinite
2493 2494 * loop.
2494 2495 */
2495 2496 cookie->err_rc = rc;
2496 2497 cookie->new_state =
2497 2498 LDAP_ERROR;
2498 2499 }
2499 2500 if (cookie->connectionId > -1) {
2500 2501 /*
2501 2502 * NS_LDAP_NEW_CONN
2502 2503 * indicates that the
2503 2504 * connection should
2504 2505 * be deleted, not
2505 2506 * kept alive
2506 2507 */
2507 2508 DropConnection(
2508 2509 cookie->
2509 2510 connectionId,
2510 2511 NS_LDAP_NEW_CONN);
2511 2512 cookie->connectionId =
2512 2513 -1;
2513 2514 }
2514 2515 } else if ((rc == LDAP_CONNECT_ERROR ||
2515 2516 rc == LDAP_SERVER_DOWN) &&
2516 2517 cookie->conn_user != NULL) {
2517 2518 if (cookie->
2518 2519 reinit_on_retriable_err) {
2519 2520 /*
2520 2521 * MT connection not
2521 2522 * usable, close it
2522 2523 * before REINIT.
2523 2524 * rc has already
2524 2525 * been saved in
2525 2526 * cookie->err_rc above.
2526 2527 */
2527 2528 __s_api_conn_mt_close(
2528 2529 cookie->conn_user,
2529 2530 rc,
2530 2531 &cookie->errorp);
2531 2532 } else {
2532 2533 /*
2533 2534 * MT connection not
2534 2535 * usable, close it in
2535 2536 * the LDAP_ERROR state.
2536 2537 * A retry will be done
2537 2538 * next if allowed.
2538 2539 */
2539 2540 cookie->err_rc = rc;
2540 2541 cookie->new_state =
2541 2542 LDAP_ERROR;
2542 2543 }
2543 2544 }
2544 2545 break;
2545 2546 }
2546 2547 cookie->err_rc = rc;
2547 2548 cookie->new_state = LDAP_ERROR;
2548 2549 break;
2549 2550 }
2550 2551 cookie->new_state = cookie->next_state;
2551 2552 break;
2552 2553 case NEXT_RESULT:
2553 2554 /*
2554 2555 * Caller (e.g. __ns_ldap_list_batch_add)
2555 2556 * does not want to block on ldap_result().
2556 2557 * Therefore we execute ldap_result() with
2557 2558 * a zeroed timeval.
2558 2559 */
2559 2560 if (cookie->no_wait == B_TRUE)
2560 2561 (void) memset(&tv, 0, sizeof (tv));
2561 2562 else
2562 2563 tv = cookie->search_timeout;
2563 2564 rc = ldap_result(cookie->conn->ld, cookie->msgId,
2564 2565 LDAP_MSG_ONE,
2565 2566 &tv,
2566 2567 &cookie->resultMsg);
2567 2568 if (rc == LDAP_RES_SEARCH_RESULT) {
2568 2569 cookie->new_state = END_RESULT;
2569 2570 /* check and process referrals info */
2570 2571 if (cookie->followRef)
2571 2572 proc_result_referrals(
2572 2573 cookie);
2573 2574 (void) ldap_msgfree(cookie->resultMsg);
2574 2575 cookie->resultMsg = NULL;
2575 2576 break;
2576 2577 }
2577 2578 /* handle referrals if necessary */
2578 2579 if (rc == LDAP_RES_SEARCH_REFERENCE) {
2579 2580 if (cookie->followRef)
2580 2581 proc_search_references(cookie);
2581 2582 (void) ldap_msgfree(cookie->resultMsg);
2582 2583 cookie->resultMsg = NULL;
2583 2584 break;
2584 2585 }
2585 2586 if (rc != LDAP_RES_SEARCH_ENTRY) {
2586 2587 switch (rc) {
2587 2588 case 0:
2588 2589 if (cookie->no_wait == B_TRUE) {
2589 2590 (void) ldap_msgfree(
2590 2591 cookie->resultMsg);
2591 2592 cookie->resultMsg = NULL;
2592 2593 return (cookie->new_state);
2593 2594 }
2594 2595 rc = LDAP_TIMEOUT;
2595 2596 break;
2596 2597 case -1:
2597 2598 rc = ldap_get_lderrno(cookie->conn->ld,
2598 2599 NULL, NULL);
2599 2600 break;
2600 2601 default:
2601 2602 rc = ldap_result2error(cookie->conn->ld,
2602 2603 cookie->resultMsg, 1);
2603 2604 break;
2604 2605 }
2605 2606 if ((rc == LDAP_TIMEOUT ||
2606 2607 rc == LDAP_SERVER_DOWN) &&
2607 2608 (cookie->conn_user == NULL ||
2608 2609 cookie->conn_user->conn_mt == NULL)) {
2609 2610 if (rc == LDAP_TIMEOUT)
2610 2611 (void) __s_api_removeServer(
2611 2612 cookie->conn->serverAddr);
2612 2613 if (cookie->connectionId > -1) {
2613 2614 DropConnection(
2614 2615 cookie->connectionId,
2615 2616 NS_LDAP_NEW_CONN);
2616 2617 cookie->connectionId = -1;
2617 2618 }
2618 2619 cookie->err_from_result = 1;
2619 2620 }
2620 2621 (void) ldap_msgfree(cookie->resultMsg);
2621 2622 cookie->resultMsg = NULL;
2622 2623 if (rc == LDAP_BUSY ||
2623 2624 rc == LDAP_UNAVAILABLE ||
2624 2625 rc == LDAP_UNWILLING_TO_PERFORM) {
2625 2626 if (cookie->reinit_on_retriable_err) {
2626 2627 cookie->err_rc = rc;
2627 2628 cookie->err_from_result = 1;
2628 2629 cookie->new_state = REINIT;
2629 2630 } else {
2630 2631 cookie->new_state =
2631 2632 NEXT_SESSION;
2632 2633 }
2633 2634 break;
2634 2635 }
2635 2636 if ((rc == LDAP_CONNECT_ERROR ||
2636 2637 rc == LDAP_SERVER_DOWN) &&
2637 2638 cookie->reinit_on_retriable_err) {
2638 2639 ns_ldap_error_t *errorp = NULL;
2639 2640 cookie->err_rc = rc;
2640 2641 cookie->err_from_result = 1;
2641 2642 cookie->new_state = REINIT;
2642 2643 if (cookie->conn_user != NULL)
2643 2644 __s_api_conn_mt_close(
2644 2645 cookie->conn_user,
2645 2646 rc, &errorp);
2646 2647 if (errorp != NULL) {
2647 2648 (void) __ns_ldap_freeError(
2648 2649 &cookie->errorp);
2649 2650 cookie->errorp = errorp;
2650 2651 }
2651 2652 break;
2652 2653 }
2653 2654 cookie->err_rc = rc;
2654 2655 cookie->new_state = LDAP_ERROR;
2655 2656 break;
2656 2657 }
2657 2658 /* else LDAP_RES_SEARCH_ENTRY */
2658 2659 /* get account management response control */
2659 2660 if (cookie->nopasswd_acct_mgmt == 1) {
2660 2661 rc = ldap_get_entry_controls(cookie->conn->ld,
2661 2662 cookie->resultMsg,
2662 2663 &(cookie->resultctrl));
2663 2664 if (rc != LDAP_SUCCESS) {
2664 2665 cookie->new_state = LDAP_ERROR;
2665 2666 cookie->err_rc = rc;
2666 2667 break;
2667 2668 }
2668 2669 }
2669 2670 rc = __s_api_getEntry(cookie);
2670 2671 (void) ldap_msgfree(cookie->resultMsg);
2671 2672 cookie->resultMsg = NULL;
2672 2673 if (rc != NS_LDAP_SUCCESS) {
2673 2674 cookie->new_state = LDAP_ERROR;
2674 2675 break;
2675 2676 }
2676 2677 cookie->new_state = PROCESS_RESULT;
2677 2678 cookie->next_state = NEXT_RESULT;
2678 2679 break;
2679 2680 case MULTI_RESULT:
2680 2681 if (cookie->no_wait == B_TRUE)
2681 2682 (void) memset(&tv, 0, sizeof (tv));
2682 2683 else
2683 2684 tv = cookie->search_timeout;
2684 2685 rc = ldap_result(cookie->conn->ld, cookie->msgId,
2685 2686 LDAP_MSG_ONE,
2686 2687 &tv,
2687 2688 &cookie->resultMsg);
2688 2689 if (rc == LDAP_RES_SEARCH_RESULT) {
2689 2690 rc = ldap_result2error(cookie->conn->ld,
2690 2691 cookie->resultMsg, 0);
2691 2692 if (rc == LDAP_ADMINLIMIT_EXCEEDED &&
2692 2693 cookie->listType == VLVCTRLFLAG &&
2693 2694 cookie->sortTypeTry == SSS_SINGLE_ATTR) {
2694 2695 /* Try old "cn uid" server side sort */
2695 2696 cookie->sortTypeTry = SSS_CN_UID_ATTRS;
2696 2697 cookie->new_state = NEXT_VLV;
2697 2698 (void) ldap_msgfree(cookie->resultMsg);
2698 2699 cookie->resultMsg = NULL;
2699 2700 break;
2700 2701 }
2701 2702 if (rc != LDAP_SUCCESS) {
2702 2703 cookie->err_rc = rc;
2703 2704 cookie->new_state = LDAP_ERROR;
2704 2705 (void) ldap_msgfree(cookie->resultMsg);
2705 2706 cookie->resultMsg = NULL;
2706 2707 break;
2707 2708 }
2708 2709 cookie->new_state = multi_result(cookie);
2709 2710 (void) ldap_msgfree(cookie->resultMsg);
2710 2711 cookie->resultMsg = NULL;
2711 2712 break;
2712 2713 }
2713 2714 /* handle referrals if necessary */
2714 2715 if (rc == LDAP_RES_SEARCH_REFERENCE &&
2715 2716 cookie->followRef) {
2716 2717 proc_search_references(cookie);
2717 2718 (void) ldap_msgfree(cookie->resultMsg);
2718 2719 cookie->resultMsg = NULL;
2719 2720 break;
2720 2721 }
2721 2722 if (rc != LDAP_RES_SEARCH_ENTRY) {
2722 2723 switch (rc) {
2723 2724 case 0:
2724 2725 if (cookie->no_wait == B_TRUE) {
2725 2726 (void) ldap_msgfree(
2726 2727 cookie->resultMsg);
2727 2728 cookie->resultMsg = NULL;
2728 2729 return (cookie->new_state);
2729 2730 }
2730 2731 rc = LDAP_TIMEOUT;
2731 2732 break;
2732 2733 case -1:
2733 2734 rc = ldap_get_lderrno(cookie->conn->ld,
2734 2735 NULL, NULL);
2735 2736 break;
2736 2737 default:
2737 2738 rc = ldap_result2error(cookie->conn->ld,
2738 2739 cookie->resultMsg, 1);
2739 2740 break;
2740 2741 }
2741 2742 if ((rc == LDAP_TIMEOUT ||
2742 2743 rc == LDAP_SERVER_DOWN) &&
2743 2744 (cookie->conn_user == NULL ||
2744 2745 cookie->conn_user->conn_mt == NULL)) {
2745 2746 if (rc == LDAP_TIMEOUT)
2746 2747 (void) __s_api_removeServer(
2747 2748 cookie->conn->serverAddr);
2748 2749 if (cookie->connectionId > -1) {
2749 2750 DropConnection(
2750 2751 cookie->connectionId,
2751 2752 NS_LDAP_NEW_CONN);
2752 2753 cookie->connectionId = -1;
2753 2754 }
2754 2755 cookie->err_from_result = 1;
2755 2756 }
2756 2757 (void) ldap_msgfree(cookie->resultMsg);
2757 2758 cookie->resultMsg = NULL;
2758 2759 if (rc == LDAP_BUSY ||
2759 2760 rc == LDAP_UNAVAILABLE ||
2760 2761 rc == LDAP_UNWILLING_TO_PERFORM) {
2761 2762 if (cookie->reinit_on_retriable_err) {
2762 2763 cookie->err_rc = rc;
2763 2764 cookie->err_from_result = 1;
2764 2765 cookie->new_state = REINIT;
2765 2766 } else {
2766 2767 cookie->new_state =
2767 2768 NEXT_SESSION;
2768 2769 }
2769 2770 break;
2770 2771 }
2771 2772
2772 2773 if ((rc == LDAP_CONNECT_ERROR ||
2773 2774 rc == LDAP_SERVER_DOWN) &&
2774 2775 cookie->reinit_on_retriable_err) {
2775 2776 ns_ldap_error_t *errorp = NULL;
2776 2777 cookie->err_rc = rc;
2777 2778 cookie->err_from_result = 1;
2778 2779 cookie->new_state = REINIT;
2779 2780 if (cookie->conn_user != NULL)
2780 2781 __s_api_conn_mt_close(
2781 2782 cookie->conn_user,
2782 2783 rc, &errorp);
2783 2784 if (errorp != NULL) {
2784 2785 (void) __ns_ldap_freeError(
2785 2786 &cookie->errorp);
2786 2787 cookie->errorp = errorp;
2787 2788 }
2788 2789 break;
2789 2790 }
2790 2791 cookie->err_rc = rc;
2791 2792 cookie->new_state = LDAP_ERROR;
2792 2793 break;
2793 2794 }
2794 2795 /* else LDAP_RES_SEARCH_ENTRY */
2795 2796 cookie->entryCount++;
2796 2797 rc = __s_api_getEntry(cookie);
2797 2798 (void) ldap_msgfree(cookie->resultMsg);
2798 2799 cookie->resultMsg = NULL;
2799 2800 if (rc != NS_LDAP_SUCCESS) {
2800 2801 cookie->new_state = LDAP_ERROR;
2801 2802 break;
2802 2803 }
2803 2804 /*
2804 2805 * If VLV search was successfull save the server
2805 2806 * side sort type tried.
2806 2807 */
2807 2808 if (cookie->listType == VLVCTRLFLAG)
2808 2809 update_srvsidesort_type(cookie->service,
2809 2810 cookie->sortTypeTry);
2810 2811
2811 2812 cookie->new_state = PROCESS_RESULT;
2812 2813 cookie->next_state = MULTI_RESULT;
2813 2814 break;
2814 2815 case PROCESS_RESULT:
2815 2816 /* NOTE THIS STATE MAY BE PROCESSED BY CALLER */
2816 2817 if (cookie->use_usercb && cookie->callback) {
2817 2818 rc = 0;
2818 2819 for (nextEntry = cookie->result->entry;
2819 2820 nextEntry != NULL;
2820 2821 nextEntry = nextEntry->next) {
2821 2822 rc = (*cookie->callback)(nextEntry,
2822 2823 cookie->userdata);
2823 2824
2824 2825 if (rc == NS_LDAP_CB_DONE) {
2825 2826 /* cb doesn't want any more data */
2826 2827 rc = NS_LDAP_PARTIAL;
2827 2828 cookie->err_rc = rc;
2828 2829 break;
2829 2830 } else if (rc != NS_LDAP_CB_NEXT) {
2830 2831 /* invalid return code */
2831 2832 rc = NS_LDAP_OP_FAILED;
2832 2833 cookie->err_rc = rc;
2833 2834 break;
2834 2835 }
2835 2836 }
2836 2837 (void) __ns_ldap_freeResult(&cookie->result);
2837 2838 cookie->result = NULL;
2838 2839 }
2839 2840 if (rc != 0) {
2840 2841 cookie->new_state = EXIT;
2841 2842 break;
2842 2843 }
2843 2844 /* NOTE PREVIOUS STATE SPECIFIES NEXT STATE */
2844 2845 cookie->new_state = cookie->next_state;
2845 2846 break;
2846 2847 case END_PROCESS_RESULT:
2847 2848 cookie->new_state = cookie->next_state;
2848 2849 break;
2849 2850 case END_RESULT:
2850 2851 /*
2851 2852 * XXX DO WE NEED THIS CASE?
2852 2853 * if (search is complete) {
2853 2854 * cookie->new_state = EXIT;
2854 2855 * } else
2855 2856 */
2856 2857 /*
2857 2858 * entering referral mode if necessary
2858 2859 */
2859 2860 if (cookie->followRef && cookie->reflist)
2860 2861 cookie->new_state =
2861 2862 NEXT_REFERRAL;
2862 2863 else
2863 2864 cookie->new_state =
2864 2865 NEXT_SEARCH_DESCRIPTOR;
2865 2866 break;
2866 2867 case NEXT_REFERRAL:
2867 2868 /* get next referral info */
2868 2869 if (cookie->refpos == NULL)
2869 2870 cookie->refpos =
2870 2871 cookie->reflist;
2871 2872 else
2872 2873 cookie->refpos =
2873 2874 cookie->refpos->next;
2874 2875 /* check see if done with all referrals */
2875 2876 if (cookie->refpos != NULL) {
2876 2877 cookie->new_state =
2877 2878 GET_REFERRAL_SESSION;
2878 2879 } else {
2879 2880 __s_api_deleteRefInfo(cookie->reflist);
2880 2881 cookie->reflist = NULL;
2881 2882 cookie->new_state =
2882 2883 NEXT_SEARCH_DESCRIPTOR;
2883 2884 if (cookie->conn_user != NULL)
2884 2885 cookie->conn_user->referral = B_FALSE;
2885 2886 }
2886 2887 break;
2887 2888 case GET_REFERRAL_SESSION:
2888 2889 if (get_referral_session(cookie) < 0) {
2889 2890 cookie->new_state = EXIT;
2890 2891 } else {
2891 2892 cookie->new_state = NEXT_SEARCH;
2892 2893 }
2893 2894 break;
2894 2895 case LDAP_ERROR:
2895 2896 rc_save = cookie->err_rc;
2896 2897 if (cookie->err_from_result) {
2897 2898 if (cookie->err_rc == LDAP_SERVER_DOWN) {
2898 2899 (void) sprintf(errstr,
2899 2900 gettext("LDAP ERROR (%d): "
2900 2901 "Error occurred during"
2901 2902 " receiving results. "
2902 2903 "Connection to server lost."),
2903 2904 cookie->err_rc);
2904 2905 } else if (cookie->err_rc == LDAP_TIMEOUT) {
2905 2906 (void) sprintf(errstr,
2906 2907 gettext("LDAP ERROR (%d): "
2907 2908 "Error occurred during"
2908 2909 " receiving results. %s"
2909 2910 "."), cookie->err_rc,
2910 2911 ldap_err2string(
2911 2912 cookie->err_rc));
2912 2913 }
2913 2914 } else {
2914 2915 (void) sprintf(errstr,
2915 2916 gettext("LDAP ERROR (%d): %s."),
2916 2917 cookie->err_rc,
2917 2918 ldap_err2string(cookie->err_rc));
2918 2919 }
2919 2920 err = strdup(errstr);
2920 2921 if (cookie->err_from_result) {
2921 2922 if (cookie->err_rc == LDAP_SERVER_DOWN) {
2922 2923 MKERROR(LOG_INFO, *errorp,
2923 2924 cookie->err_rc, err,
2924 2925 NS_LDAP_MEMORY);
2925 2926 } else {
2926 2927 MKERROR(LOG_WARNING, *errorp,
2927 2928 cookie->err_rc, err,
2928 2929 NS_LDAP_MEMORY);
2929 2930 }
2930 2931 } else {
2931 2932 MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL,
2932 2933 err, NS_LDAP_MEMORY);
2933 2934 }
2934 2935 cookie->err_rc = NS_LDAP_INTERNAL;
2935 2936 cookie->errorp = *errorp;
2936 2937 if (cookie->conn_user != NULL) {
2937 2938 if (rc_save == LDAP_SERVER_DOWN ||
2938 2939 rc_save == LDAP_CONNECT_ERROR) {
2939 2940 /*
2940 2941 * MT connection is not usable,
2941 2942 * close it.
2942 2943 */
2943 2944 __s_api_conn_mt_close(cookie->conn_user,
2944 2945 rc_save, &cookie->errorp);
2945 2946 return (ERROR);
2946 2947 }
2947 2948 }
2948 2949 return (ERROR);
2949 2950 default:
2950 2951 case ERROR:
2951 2952 (void) sprintf(errstr,
2952 2953 gettext("Internal State machine exit (%d).\n"),
2953 2954 cookie->state);
2954 2955 err = strdup(errstr);
2955 2956 MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err,
2956 2957 NS_LDAP_MEMORY);
2957 2958 cookie->err_rc = NS_LDAP_INTERNAL;
2958 2959 cookie->errorp = *errorp;
2959 2960 return (ERROR);
2960 2961 }
2961 2962
2962 2963 if (cookie->conn_user != NULL &&
2963 2964 cookie->conn_user->bad_mt_conn == B_TRUE) {
2964 2965 __s_api_conn_mt_close(cookie->conn_user, 0, NULL);
2965 2966 cookie->err_rc = cookie->conn_user->ns_rc;
2966 2967 cookie->errorp = cookie->conn_user->ns_error;
2967 2968 cookie->conn_user->ns_error = NULL;
2968 2969 return (ERROR);
2969 2970 }
2970 2971
2971 2972 if (cycle == ONE_STEP) {
2972 2973 return (cookie->new_state);
2973 2974 }
2974 2975 cookie->state = cookie->new_state;
2975 2976 }
2976 2977 /*NOTREACHED*/
2977 2978 #if 0
2978 2979 (void) sprintf(errstr,
2979 2980 gettext("Unexpected State machine error.\n"));
2980 2981 err = strdup(errstr);
2981 2982 MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err, NS_LDAP_MEMORY);
2982 2983 cookie->err_rc = NS_LDAP_INTERNAL;
2983 2984 cookie->errorp = *errorp;
2984 2985 return (ERROR);
2985 2986 #endif
2986 2987 }
2987 2988
2988 2989 /*
2989 2990 * For a lookup of shadow data, if shadow update is enabled,
2990 2991 * check the calling process' privilege to ensure it's
2991 2992 * allowed to perform such operation.
2992 2993 */
2993 2994 static int
2994 2995 check_shadow(ns_ldap_cookie_t *cookie, const char *service)
2995 2996 {
2996 2997 char errstr[MAXERROR];
2997 2998 char *err;
2998 2999 boolean_t priv;
2999 3000 /* caller */
3000 3001 priv_set_t *ps;
3001 3002 /* zone */
3002 3003 priv_set_t *zs;
3003 3004
3004 3005 /*
3005 3006 * If service is "shadow", we may need
3006 3007 * to use privilege credentials.
3007 3008 */
3008 3009 if ((strcmp(service, "shadow") == 0) &&
3009 3010 __ns_ldap_is_shadow_update_enabled()) {
3010 3011 /*
3011 3012 * Since we release admin credentials after
3012 3013 * connection is closed and we do not cache
3013 3014 * them, we allow any root or all zone
3014 3015 * privilege process to read shadow data.
3015 3016 */
3016 3017 priv = (geteuid() == 0);
3017 3018 if (!priv) {
3018 3019 /* caller */
3019 3020 ps = priv_allocset();
3020 3021
3021 3022 (void) getppriv(PRIV_EFFECTIVE, ps);
3022 3023 zs = priv_str_to_set("zone", ",", NULL);
3023 3024 priv = priv_isequalset(ps, zs);
3024 3025 priv_freeset(ps);
3025 3026 priv_freeset(zs);
3026 3027 }
3027 3028 if (!priv) {
3028 3029 (void) sprintf(errstr,
3029 3030 gettext("Permission denied"));
3030 3031 err = strdup(errstr);
3031 3032 if (err == NULL)
3032 3033 return (NS_LDAP_MEMORY);
3033 3034 MKERROR(LOG_INFO, cookie->errorp, NS_LDAP_INTERNAL, err,
3034 3035 NS_LDAP_MEMORY);
3035 3036 return (NS_LDAP_INTERNAL);
3036 3037 }
3037 3038 cookie->i_flags |= NS_LDAP_READ_SHADOW;
3038 3039 /*
3039 3040 * We do not want to reuse connection (hence
3040 3041 * keep it open) with admin credentials.
3041 3042 * If NS_LDAP_KEEP_CONN is set, reject the
3042 3043 * request.
3043 3044 */
3044 3045 if (cookie->i_flags & NS_LDAP_KEEP_CONN)
3045 3046 return (NS_LDAP_INVALID_PARAM);
3046 3047 cookie->i_flags |= NS_LDAP_NEW_CONN;
3047 3048 }
3048 3049
3049 3050 return (NS_LDAP_SUCCESS);
3050 3051 }
3051 3052
3052 3053 /*
3053 3054 * internal function for __ns_ldap_list
3054 3055 */
3055 3056 static int
3056 3057 ldap_list(
3057 3058 ns_ldap_list_batch_t *batch,
3058 3059 const char *service,
3059 3060 const char *filter,
3060 3061 const char *sortattr,
3061 3062 int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
3062 3063 char **realfilter, const void *userdata),
3063 3064 const char * const *attribute,
3064 3065 const ns_cred_t *auth,
3065 3066 const int flags,
3066 3067 ns_ldap_result_t **rResult, /* return result entries */
3067 3068 ns_ldap_error_t **errorp,
3068 3069 int *rcp,
3069 3070 int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
3070 3071 const void *userdata, ns_conn_user_t *conn_user)
3071 3072 {
3072 3073 ns_ldap_cookie_t *cookie;
3073 3074 ns_ldap_search_desc_t **sdlist = NULL;
3074 3075 ns_ldap_search_desc_t *dptr;
3075 3076 ns_ldap_error_t *error = NULL;
3076 3077 char **dns = NULL;
3077 3078 int scope;
3078 3079 int rc;
3079 3080 int from_result;
3080 3081
3081 3082 *errorp = NULL;
3082 3083 *rResult = NULL;
3083 3084 *rcp = NS_LDAP_SUCCESS;
3084 3085
3085 3086 /*
3086 3087 * Sanity check - NS_LDAP_READ_SHADOW is for our
3087 3088 * own internal use.
3088 3089 */
3089 3090 if (flags & NS_LDAP_READ_SHADOW)
3090 3091 return (NS_LDAP_INVALID_PARAM);
3091 3092
3092 3093 /* Initialize State machine cookie */
3093 3094 cookie = init_search_state_machine();
3094 3095 if (cookie == NULL) {
3095 3096 *rcp = NS_LDAP_MEMORY;
3096 3097 return (NS_LDAP_MEMORY);
3097 3098 }
3098 3099 cookie->conn_user = conn_user;
3099 3100
3100 3101 /* see if need to follow referrals */
3101 3102 rc = __s_api_toFollowReferrals(flags,
3102 3103 &cookie->followRef, errorp);
3103 3104 if (rc != NS_LDAP_SUCCESS) {
3104 3105 delete_search_cookie(cookie);
3105 3106 *rcp = rc;
3106 3107 return (rc);
3107 3108 }
3108 3109
3109 3110 /* get the service descriptor - or create a default one */
3110 3111 rc = __s_api_get_SSD_from_SSDtoUse_service(service,
3111 3112 &sdlist, &error);
3112 3113 if (rc != NS_LDAP_SUCCESS) {
3113 3114 delete_search_cookie(cookie);
3114 3115 *errorp = error;
3115 3116 *rcp = rc;
3116 3117 return (rc);
3117 3118 }
3118 3119
3119 3120 if (sdlist == NULL) {
3120 3121 /* Create default service Desc */
3121 3122 sdlist = (ns_ldap_search_desc_t **)calloc(2,
3122 3123 sizeof (ns_ldap_search_desc_t *));
3123 3124 if (sdlist == NULL) {
3124 3125 delete_search_cookie(cookie);
3125 3126 cookie = NULL;
3126 3127 *rcp = NS_LDAP_MEMORY;
3127 3128 return (NS_LDAP_MEMORY);
3128 3129 }
3129 3130 dptr = (ns_ldap_search_desc_t *)
3130 3131 calloc(1, sizeof (ns_ldap_search_desc_t));
3131 3132 if (dptr == NULL) {
3132 3133 free(sdlist);
3133 3134 delete_search_cookie(cookie);
3134 3135 cookie = NULL;
3135 3136 *rcp = NS_LDAP_MEMORY;
3136 3137 return (NS_LDAP_MEMORY);
3137 3138 }
3138 3139 sdlist[0] = dptr;
3139 3140
3140 3141 /* default base */
3141 3142 rc = __s_api_getDNs(&dns, service, &cookie->errorp);
3142 3143 if (rc != NS_LDAP_SUCCESS) {
3143 3144 if (dns) {
3144 3145 __s_api_free2dArray(dns);
3145 3146 dns = NULL;
3146 3147 }
3147 3148 *errorp = cookie->errorp;
3148 3149 cookie->errorp = NULL;
3149 3150 delete_search_cookie(cookie);
3150 3151 cookie = NULL;
3151 3152 *rcp = rc;
3152 3153 return (rc);
3153 3154 }
3154 3155 dptr->basedn = strdup(dns[0]);
3155 3156 __s_api_free2dArray(dns);
3156 3157 dns = NULL;
3157 3158
3158 3159 /* default scope */
3159 3160 scope = 0;
3160 3161 rc = __s_api_getSearchScope(&scope, &cookie->errorp);
3161 3162 dptr->scope = scope;
3162 3163 }
3163 3164
3164 3165 cookie->sdlist = sdlist;
3165 3166
3166 3167 /*
3167 3168 * use VLV/PAGE control only if NS_LDAP_PAGE_CTRL is set
3168 3169 */
3169 3170 if (flags & NS_LDAP_PAGE_CTRL)
3170 3171 cookie->use_paging = TRUE;
3171 3172 else
3172 3173 cookie->use_paging = FALSE;
3173 3174
3174 3175 /* Set up other arguments */
3175 3176 cookie->userdata = userdata;
3176 3177 if (init_filter_cb != NULL) {
3177 3178 cookie->init_filter_cb = init_filter_cb;
3178 3179 cookie->use_filtercb = 1;
3179 3180 }
3180 3181 if (callback != NULL) {
3181 3182 cookie->callback = callback;
3182 3183 cookie->use_usercb = 1;
3183 3184 }
3184 3185
3185 3186 /* check_shadow() may add extra value to cookie->i_flags */
3186 3187 cookie->i_flags = flags;
3187 3188 if (service) {
3188 3189 cookie->service = strdup(service);
3189 3190 if (cookie->service == NULL) {
3190 3191 delete_search_cookie(cookie);
3191 3192 cookie = NULL;
3192 3193 *rcp = NS_LDAP_MEMORY;
3193 3194 return (NS_LDAP_MEMORY);
3194 3195 }
3195 3196
3196 3197 /*
3197 3198 * If given, use the credential given by the caller, and
3198 3199 * skip the credential check required for shadow update.
3199 3200 */
3200 3201 if (auth == NULL) {
3201 3202 rc = check_shadow(cookie, service);
3202 3203 if (rc != NS_LDAP_SUCCESS) {
3203 3204 *errorp = cookie->errorp;
3204 3205 cookie->errorp = NULL;
3205 3206 delete_search_cookie(cookie);
3206 3207 cookie = NULL;
3207 3208 *rcp = rc;
3208 3209 return (rc);
3209 3210 }
3210 3211 }
3211 3212 }
3212 3213
3213 3214 cookie->i_filter = strdup(filter);
3214 3215 cookie->i_attr = attribute;
3215 3216 cookie->i_auth = auth;
3216 3217 cookie->i_sortattr = sortattr;
3217 3218
3218 3219 if (batch != NULL) {
3219 3220 cookie->batch = batch;
3220 3221 cookie->reinit_on_retriable_err = B_TRUE;
3221 3222 cookie->no_wait = B_TRUE;
3222 3223 (void) search_state_machine(cookie, INIT, 0);
3223 3224 cookie->no_wait = B_FALSE;
3224 3225 rc = cookie->err_rc;
3225 3226
3226 3227 if (rc == NS_LDAP_SUCCESS) {
3227 3228 /*
3228 3229 * Here rc == NS_LDAP_SUCCESS means that the state
3229 3230 * machine init'ed successfully. The actual status
3230 3231 * of the search will be determined by
3231 3232 * __ns_ldap_list_batch_end(). Add the cookie to our
3232 3233 * batch.
3233 3234 */
3234 3235 cookie->caller_result = rResult;
3235 3236 cookie->caller_errorp = errorp;
3236 3237 cookie->caller_rc = rcp;
3237 3238 cookie->next_cookie_in_batch = batch->cookie_list;
3238 3239 batch->cookie_list = cookie;
3239 3240 batch->nactive++;
3240 3241 return (rc);
3241 3242 }
3242 3243 /*
3243 3244 * If state machine init failed then copy error to the caller
3244 3245 * and delete the cookie.
3245 3246 */
3246 3247 } else {
3247 3248 (void) search_state_machine(cookie, INIT, 0);
3248 3249 }
3249 3250
3250 3251 /* Copy results back to user */
3251 3252 rc = cookie->err_rc;
3252 3253 if (rc != NS_LDAP_SUCCESS) {
3253 3254 if (conn_user != NULL && conn_user->ns_error != NULL) {
3254 3255 *errorp = conn_user->ns_error;
3255 3256 conn_user->ns_error = NULL;
3256 3257 } else {
3257 3258 *errorp = cookie->errorp;
3258 3259 }
3259 3260 }
3260 3261 *rResult = cookie->result;
3261 3262 from_result = cookie->err_from_result;
3262 3263
3263 3264 cookie->errorp = NULL;
3264 3265 cookie->result = NULL;
3265 3266 delete_search_cookie(cookie);
3266 3267 cookie = NULL;
3267 3268
3268 3269 if (from_result == 0 && *rResult == NULL)
3269 3270 rc = NS_LDAP_NOTFOUND;
3270 3271 *rcp = rc;
3271 3272 return (rc);
3272 3273 }
3273 3274
3274 3275
3275 3276 /*
3276 3277 * __ns_ldap_list performs one or more LDAP searches to a given
3277 3278 * directory server using service search descriptors and schema
3278 3279 * mapping as appropriate. The operation may be retried a
3279 3280 * couple of times in error situations.
3280 3281 */
3281 3282 int
3282 3283 __ns_ldap_list(
3283 3284 const char *service,
3284 3285 const char *filter,
3285 3286 int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
3286 3287 char **realfilter, const void *userdata),
3287 3288 const char * const *attribute,
3288 3289 const ns_cred_t *auth,
3289 3290 const int flags,
3290 3291 ns_ldap_result_t **rResult, /* return result entries */
3291 3292 ns_ldap_error_t **errorp,
3292 3293 int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
3293 3294 const void *userdata)
3294 3295 {
3295 3296 int mod_flags;
3296 3297 /*
3297 3298 * Strip the NS_LDAP_PAGE_CTRL option as this interface does not
3298 3299 * support this. If you want to use this option call the API
3299 3300 * __ns_ldap_list_sort() with has the sort attribute.
3300 3301 */
3301 3302 mod_flags = flags & (~NS_LDAP_PAGE_CTRL);
3302 3303
3303 3304 return (__ns_ldap_list_sort(service, filter, NULL, init_filter_cb,
3304 3305 attribute, auth, mod_flags, rResult, errorp,
3305 3306 callback, userdata));
3306 3307 }
3307 3308
3308 3309 /*
3309 3310 * __ns_ldap_list_sort performs one or more LDAP searches to a given
3310 3311 * directory server using service search descriptors and schema
3311 3312 * mapping as appropriate. The operation may be retried a
3312 3313 * couple of times in error situations.
3313 3314 */
3314 3315 int
3315 3316 __ns_ldap_list_sort(
3316 3317 const char *service,
3317 3318 const char *filter,
3318 3319 const char *sortattr,
3319 3320 int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
3320 3321 char **realfilter, const void *userdata),
3321 3322 const char * const *attribute,
3322 3323 const ns_cred_t *auth,
3323 3324 const int flags,
3324 3325 ns_ldap_result_t **rResult, /* return result entries */
3325 3326 ns_ldap_error_t **errorp,
3326 3327 int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
3327 3328 const void *userdata)
3328 3329 {
3329 3330 ns_conn_user_t *cu = NULL;
3330 3331 int try_cnt = 0;
3331 3332 int rc = NS_LDAP_SUCCESS, trc;
3332 3333
3333 3334 for (;;) {
3334 3335 if (__s_api_setup_retry_search(&cu, NS_CONN_USER_SEARCH,
3335 3336 &try_cnt, &rc, errorp) == 0)
3336 3337 break;
3337 3338 rc = ldap_list(NULL, service, filter, sortattr, init_filter_cb,
3338 3339 attribute, auth, flags, rResult, errorp, &trc, callback,
3339 3340 userdata, cu);
3340 3341 }
3341 3342
3342 3343 return (rc);
3343 3344 }
3344 3345
3345 3346 /*
3346 3347 * Create and initialize batch for native LDAP lookups
3347 3348 */
3348 3349 int
3349 3350 __ns_ldap_list_batch_start(ns_ldap_list_batch_t **batch)
3350 3351 {
3351 3352 *batch = calloc(1, sizeof (ns_ldap_list_batch_t));
3352 3353 if (*batch == NULL)
3353 3354 return (NS_LDAP_MEMORY);
3354 3355 return (NS_LDAP_SUCCESS);
3355 3356 }
3356 3357
3357 3358
3358 3359 /*
3359 3360 * Add a LDAP search request to the batch.
3360 3361 */
3361 3362 int
3362 3363 __ns_ldap_list_batch_add(
3363 3364 ns_ldap_list_batch_t *batch,
3364 3365 const char *service,
3365 3366 const char *filter,
3366 3367 int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
3367 3368 char **realfilter, const void *userdata),
3368 3369 const char * const *attribute,
3369 3370 const ns_cred_t *auth,
3370 3371 const int flags,
3371 3372 ns_ldap_result_t **rResult, /* return result entries */
3372 3373 ns_ldap_error_t **errorp,
3373 3374 int *rcp,
3374 3375 int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
3375 3376 const void *userdata)
3376 3377 {
3377 3378 ns_conn_user_t *cu;
3378 3379 int rc;
3379 3380 int mod_flags;
3380 3381
3381 3382 cu = __s_api_conn_user_init(NS_CONN_USER_SEARCH, NULL, 0);
3382 3383 if (cu == NULL) {
3383 3384 if (rcp != NULL)
3384 3385 *rcp = NS_LDAP_MEMORY;
3385 3386 return (NS_LDAP_MEMORY);
3386 3387 }
3387 3388
3388 3389 /*
3389 3390 * Strip the NS_LDAP_PAGE_CTRL option as the batch interface does not
3390 3391 * support this.
3391 3392 */
3392 3393 mod_flags = flags & (~NS_LDAP_PAGE_CTRL);
3393 3394
3394 3395 rc = ldap_list(batch, service, filter, NULL, init_filter_cb, attribute,
3395 3396 auth, mod_flags, rResult, errorp, rcp, callback, userdata, cu);
3396 3397
3397 3398 /*
3398 3399 * Free the conn_user if the cookie was not batched. If the cookie
3399 3400 * was batched then __ns_ldap_list_batch_end or release will free the
3400 3401 * conn_user. The batch API instructs the search_state_machine
3401 3402 * to reinit and retry (max 3 times) on retriable LDAP errors.
3402 3403 */
3403 3404 if (rc != NS_LDAP_SUCCESS && cu != NULL) {
3404 3405 if (cu->conn_mt != NULL)
3405 3406 __s_api_conn_mt_return(cu);
3406 3407 __s_api_conn_user_free(cu);
3407 3408 }
3408 3409 return (rc);
3409 3410 }
3410 3411
3411 3412
3412 3413 /*
3413 3414 * Free batch.
3414 3415 */
3415 3416 void
3416 3417 __ns_ldap_list_batch_release(ns_ldap_list_batch_t *batch)
3417 3418 {
3418 3419 ns_ldap_cookie_t *c, *next;
3419 3420
3420 3421 for (c = batch->cookie_list; c != NULL; c = next) {
3421 3422 next = c->next_cookie_in_batch;
3422 3423 if (c->conn_user != NULL) {
3423 3424 if (c->conn_user->conn_mt != NULL)
3424 3425 __s_api_conn_mt_return(c->conn_user);
3425 3426 __s_api_conn_user_free(c->conn_user);
3426 3427 c->conn_user = NULL;
3427 3428 }
3428 3429 delete_search_cookie(c);
3429 3430 }
3430 3431 free(batch);
3431 3432 }
3432 3433
3433 3434 #define LD_USING_STATE(st) \
3434 3435 ((st == DO_SEARCH) || (st == MULTI_RESULT) || (st == NEXT_RESULT))
3435 3436
3436 3437 /*
3437 3438 * Process batch. Everytime this function is called it selects an
3438 3439 * active cookie from the batch and single steps through the
3439 3440 * search_state_machine for the selected cookie. If lookup associated
3440 3441 * with the cookie is complete (success or error) then the cookie is
3441 3442 * removed from the batch and its memory freed.
3442 3443 *
3443 3444 * Returns 1 (if batch still has active cookies)
3444 3445 * 0 (if batch has no more active cookies)
3445 3446 * -1 (on errors, *rcp will contain the error code)
3446 3447 *
3447 3448 * The caller should call this function in a loop as long as it returns 1
3448 3449 * to process all the requests added to the batch. The results (and errors)
3449 3450 * will be available in the locations provided by the caller at the time of
3450 3451 * __ns_ldap_list_batch_add().
3451 3452 */
3452 3453 static
3453 3454 int
3454 3455 __ns_ldap_list_batch_process(ns_ldap_list_batch_t *batch, int *rcp)
3455 3456 {
3456 3457 ns_ldap_cookie_t *c, *ptr, **prev;
3457 3458 ns_state_t state;
3458 3459 ns_ldap_error_t *errorp = NULL;
3459 3460 int rc;
3460 3461
3461 3462 /* Check if are already done */
3462 3463 if (batch->nactive == 0)
3463 3464 return (0);
3464 3465
3465 3466 /* Get the next cookie from the batch */
3466 3467 c = (batch->next_cookie == NULL) ?
3467 3468 batch->cookie_list : batch->next_cookie;
3468 3469
3469 3470 batch->next_cookie = c->next_cookie_in_batch;
3470 3471
3471 3472 /*
3472 3473 * Checks the status of the cookie's connection if it needs
3473 3474 * to use that connection for ldap_search_ext or ldap_result.
3474 3475 * If the connection is no longer good but worth retrying
3475 3476 * then reinit the search_state_machine for this cookie
3476 3477 * starting from the first search descriptor. REINIT will
3477 3478 * clear any leftover results if max retries have not been
3478 3479 * reached and redo the search (which may also involve
3479 3480 * following referrals again).
3480 3481 *
3481 3482 * Note that each cookie in the batch will make this
3482 3483 * determination when it reaches one of the LD_USING_STATES.
3483 3484 */
3484 3485 if (LD_USING_STATE(c->new_state) && c->conn_user != NULL) {
3485 3486 rc = __s_api_setup_getnext(c->conn_user, &c->err_rc, &errorp);
3486 3487 if (rc == LDAP_BUSY || rc == LDAP_UNAVAILABLE ||
3487 3488 rc == LDAP_UNWILLING_TO_PERFORM) {
3488 3489 if (errorp != NULL) {
3489 3490 (void) __ns_ldap_freeError(&c->errorp);
3490 3491 c->errorp = errorp;
3491 3492 }
3492 3493 c->new_state = REINIT;
3493 3494 } else if (rc == LDAP_CONNECT_ERROR ||
3494 3495 rc == LDAP_SERVER_DOWN) {
3495 3496 if (errorp != NULL) {
3496 3497 (void) __ns_ldap_freeError(&c->errorp);
3497 3498 c->errorp = errorp;
3498 3499 }
3499 3500 c->new_state = REINIT;
3500 3501 /*
3501 3502 * MT connection is not usable,
3502 3503 * close it before REINIT.
3503 3504 */
3504 3505 __s_api_conn_mt_close(
3505 3506 c->conn_user, rc, NULL);
3506 3507 } else if (rc != NS_LDAP_SUCCESS) {
3507 3508 if (rcp != NULL)
3508 3509 *rcp = rc;
3509 3510 *c->caller_result = NULL;
3510 3511 *c->caller_errorp = errorp;
3511 3512 *c->caller_rc = rc;
3512 3513 return (-1);
3513 3514 }
3514 3515 }
3515 3516
3516 3517 for (;;) {
3517 3518 /* Single step through the search_state_machine */
3518 3519 state = search_state_machine(c, c->new_state, ONE_STEP);
3519 3520 switch (state) {
3520 3521 case LDAP_ERROR:
3521 3522 (void) search_state_machine(c, state, ONE_STEP);
3522 3523 (void) search_state_machine(c, CLEAR_RESULTS, ONE_STEP);
3523 3524 /* FALLTHROUGH */
3524 3525 case ERROR:
3525 3526 case EXIT:
3526 3527 *c->caller_result = c->result;
3527 3528 *c->caller_errorp = c->errorp;
3528 3529 *c->caller_rc =
3529 3530 (c->result == NULL && c->err_from_result == 0)
3530 3531 ? NS_LDAP_NOTFOUND : c->err_rc;
3531 3532 c->result = NULL;
3532 3533 c->errorp = NULL;
3533 3534 /* Remove the cookie from the batch */
3534 3535 ptr = batch->cookie_list;
3535 3536 prev = &batch->cookie_list;
3536 3537 while (ptr != NULL) {
3537 3538 if (ptr == c) {
3538 3539 *prev = ptr->next_cookie_in_batch;
3539 3540 break;
3540 3541 }
3541 3542 prev = &ptr->next_cookie_in_batch;
3542 3543 ptr = ptr->next_cookie_in_batch;
3543 3544 }
3544 3545 /* Delete cookie and decrement active cookie count */
3545 3546 if (c->conn_user != NULL) {
3546 3547 if (c->conn_user->conn_mt != NULL)
3547 3548 __s_api_conn_mt_return(c->conn_user);
3548 3549 __s_api_conn_user_free(c->conn_user);
3549 3550 c->conn_user = NULL;
3550 3551 }
3551 3552 delete_search_cookie(c);
3552 3553 batch->nactive--;
3553 3554 break;
3554 3555 case NEXT_RESULT:
3555 3556 case MULTI_RESULT:
3556 3557 /*
3557 3558 * This means that search_state_machine needs to do
3558 3559 * another ldap_result() for the cookie in question.
3559 3560 * We only do at most one ldap_result() per call in
3560 3561 * this function and therefore we return. This allows
3561 3562 * the caller to process results from other cookies
3562 3563 * in the batch without getting tied up on just one
3563 3564 * cookie.
3564 3565 */
3565 3566 break;
3566 3567 default:
3567 3568 /*
3568 3569 * This includes states that follow NEXT_RESULT or
3569 3570 * MULTI_RESULT such as PROCESS_RESULT and
3570 3571 * END_PROCESS_RESULT. We continue processing
3571 3572 * this cookie till we reach either the error, exit
3572 3573 * or the result states.
3573 3574 */
3574 3575 continue;
3575 3576 }
3576 3577 break;
3577 3578 }
3578 3579
3579 3580 /* Return 0 if no more cookies left otherwise 1 */
3580 3581 return ((batch->nactive > 0) ? 1 : 0);
3581 3582 }
3582 3583
3583 3584
3584 3585 /*
3585 3586 * Process all the active cookies in the batch and when none
3586 3587 * remains finalize the batch.
3587 3588 */
↓ open down ↓ |
3554 lines elided |
↑ open up ↑ |
3588 3589 int
3589 3590 __ns_ldap_list_batch_end(ns_ldap_list_batch_t *batch)
3590 3591 {
3591 3592 int rc = NS_LDAP_SUCCESS;
3592 3593 while (__ns_ldap_list_batch_process(batch, &rc) > 0)
3593 3594 ;
3594 3595 __ns_ldap_list_batch_release(batch);
3595 3596 return (rc);
3596 3597 }
3597 3598
3599 +typedef struct lookup_data {
3600 + const char *lkd_dn;
3601 + const char *lkd_service;
3602 + const char *lkd_filter;
3603 + const ns_cred_t *lkd_cred;
3604 + ns_conn_user_t *lkd_user;
3605 +} lookup_data_t;
3606 +
3598 3607 /*
3599 - * find_domainname performs one or more LDAP searches to
3600 - * find the value of the nisdomain attribute associated with
3601 - * the input DN (with no retry).
3608 + * This creates a service search descriptor that can be used to
3609 + * retrieve a specific DN by using the DN as the basedn with a search
3610 + * scope of 'base'. We don't use any service SSDs in this instance since
3611 + * they are intended to search specific locations/subtrees and filter the
3612 + * results, while here we are wanting to retrieve a specific entry.
3602 3613 */
3603 -
3604 3614 static int
3605 -find_domainname(const char *dn, char **domainname, const ns_cred_t *cred,
3606 - ns_ldap_error_t **errorp, ns_conn_user_t *conn_user)
3615 +lookup_create_ssd(lookup_data_t *dn_data, ns_ldap_search_desc_t **descpp)
3607 3616 {
3617 + ns_ldap_search_desc_t *dptr;
3608 3618
3619 + *descpp = NULL;
3620 +
3621 + dptr = calloc(1, sizeof (ns_ldap_search_desc_t));
3622 + if (dptr == NULL)
3623 + return (NS_LDAP_MEMORY);
3624 +
3625 + dptr->basedn = strdup(dn_data->lkd_dn);
3626 + dptr->scope = NS_LDAP_SCOPE_BASE;
3627 + dptr->filter = strdup(UIDFILTER);
3628 +
3629 + if (dptr->basedn == NULL || dptr->filter == NULL) {
3630 + __ns_ldap_freeASearchDesc(dptr);
3631 + return (NS_LDAP_MEMORY);
3632 + }
3633 +
3634 + *descpp = dptr;
3635 + return (NS_LDAP_SUCCESS);
3636 +}
3637 +
3638 +static int
3639 +lookup_dn(lookup_data_t *dn_data, const char **attrs,
3640 + ns_ldap_result_t **resultp, ns_ldap_error_t **errorp)
3641 +{
3609 3642 ns_ldap_cookie_t *cookie;
3610 - ns_ldap_search_desc_t **sdlist;
3611 - ns_ldap_search_desc_t *dptr;
3612 - int rc;
3613 - char **value;
3643 + int rc = 0;
3614 3644 int flags = 0;
3615 3645
3616 - *domainname = NULL;
3617 3646 *errorp = NULL;
3647 + *resultp = NULL;
3618 3648
3619 - /* Initialize State machine cookie */
3649 + if (dn_data == NULL || dn_data->lkd_dn == NULL ||
3650 + dn_data->lkd_dn[0] == '\0' || dn_data->lkd_filter == NULL)
3651 + return (NS_LDAP_INVALID_PARAM);
3652 +
3620 3653 cookie = init_search_state_machine();
3621 - if (cookie == NULL) {
3654 + if (cookie == NULL)
3622 3655 return (NS_LDAP_MEMORY);
3623 - }
3624 - cookie->conn_user = conn_user;
3625 3656
3626 - /* see if need to follow referrals */
3627 - rc = __s_api_toFollowReferrals(flags,
3628 - &cookie->followRef, errorp);
3629 - if (rc != NS_LDAP_SUCCESS) {
3630 - delete_search_cookie(cookie);
3631 - return (rc);
3632 - }
3657 + rc = __s_api_toFollowReferrals(flags, &cookie->followRef, errorp);
3658 + if (rc != NS_LDAP_SUCCESS)
3659 + goto out;
3633 3660
3634 - /* Create default service Desc */
3635 - sdlist = (ns_ldap_search_desc_t **)calloc(2,
3636 - sizeof (ns_ldap_search_desc_t *));
3637 - if (sdlist == NULL) {
3638 - delete_search_cookie(cookie);
3639 - cookie = NULL;
3640 - return (NS_LDAP_MEMORY);
3661 + /* 1 for SSD, 1 for terminating NULL */
3662 + cookie->sdlist = calloc(2, sizeof (ns_ldap_search_desc_t *));
3663 + if (cookie->sdlist == NULL) {
3664 + rc = NS_LDAP_MEMORY;
3665 + goto out;
3641 3666 }
3642 - dptr = (ns_ldap_search_desc_t *)
3643 - calloc(1, sizeof (ns_ldap_search_desc_t));
3644 - if (dptr == NULL) {
3645 - free(sdlist);
3646 - delete_search_cookie(cookie);
3647 - cookie = NULL;
3648 - return (NS_LDAP_MEMORY);
3649 - }
3650 - sdlist[0] = dptr;
3651 3667
3652 - /* search base is dn */
3653 - dptr->basedn = strdup(dn);
3668 + rc = lookup_create_ssd(dn_data, &cookie->sdlist[0]);
3669 + if (rc != NS_LDAP_SUCCESS)
3670 + goto out;
3654 3671
3655 - /* search scope is base */
3656 - dptr->scope = NS_LDAP_SCOPE_BASE;
3672 + if (dn_data->lkd_service != NULL) {
3673 + /*
3674 + * If a service was specified, set that on the cookie so
3675 + * that search_state_machine() will properly map
3676 + * attributes and objectclasses.
3677 + */
3678 + cookie->service = strdup(dn_data->lkd_service);
3679 + if (cookie->service == NULL) {
3680 + rc = NS_LDAP_MEMORY;
3681 + goto out;
3682 + }
3683 + }
3657 3684
3658 - /* search filter is "nisdomain=*" */
3659 - dptr->filter = strdup(_NIS_FILTER);
3660 -
3661 - cookie->sdlist = sdlist;
3662 - cookie->i_filter = strdup(dptr->filter);
3663 - cookie->i_attr = nis_domain_attrs;
3664 - cookie->i_auth = cred;
3685 + cookie->i_attr = attrs;
3686 + cookie->i_auth = dn_data->lkd_cred;
3665 3687 cookie->i_flags = 0;
3688 + cookie->i_filter = strdup(dn_data->lkd_filter);
3689 + if (cookie->i_filter == NULL) {
3690 + rc = NS_LDAP_MEMORY;
3691 + goto out;
3692 + }
3666 3693
3667 - /* Process search */
3668 - rc = search_state_machine(cookie, INIT, 0);
3669 -
3670 - /* Copy domain name if found */
3694 + /*
3695 + * Actually perform the search. The return value is only used when
3696 + * iterating through multiple results. Since we are searching with
3697 + * a scope of base, we will always get at most one result entry,
3698 + * we ignore the return value and look at err_rc to determine if
3699 + * there were any errors.
3700 + */
3701 + (void) search_state_machine(cookie, INIT, 0);
3671 3702 rc = cookie->err_rc;
3703 +
3672 3704 if (rc != NS_LDAP_SUCCESS) {
3673 - if (conn_user != NULL && conn_user->ns_error != NULL) {
3674 - *errorp = conn_user->ns_error;
3675 - conn_user->ns_error = NULL;
3705 + ns_conn_user_t *user = dn_data->lkd_user;
3706 +
3707 + if (user != NULL && user->ns_error != NULL) {
3708 + *errorp = user->ns_error;
3709 + user->ns_error = NULL;
3676 3710 } else {
3677 3711 *errorp = cookie->errorp;
3712 + cookie->errorp = NULL;
3678 3713 }
3679 - }
3680 - if (cookie->result == NULL)
3714 + } else if (cookie->result != NULL) {
3715 + *resultp = cookie->result;
3716 + cookie->result = NULL;
3717 + } else {
3681 3718 rc = NS_LDAP_NOTFOUND;
3682 - if (rc == NS_LDAP_SUCCESS) {
3683 - value = __ns_ldap_getAttr(cookie->result->entry,
3684 - _NIS_DOMAIN);
3685 - if (value[0])
3686 - *domainname = strdup(value[0]);
3687 - else
3688 - rc = NS_LDAP_NOTFOUND;
3689 3719 }
3690 - if (cookie->result != NULL)
3691 - (void) __ns_ldap_freeResult(&cookie->result);
3692 - cookie->errorp = NULL;
3720 +
3721 +out:
3693 3722 delete_search_cookie(cookie);
3694 - cookie = NULL;
3695 3723 return (rc);
3696 3724 }
3697 3725
3698 3726 /*
3727 + * find_domainname performs one or more LDAP searches to
3728 + * find the value of the nisdomain attribute associated with
3729 + * the input DN (with no retry).
3730 + */
3731 +
3732 +static int
3733 +find_domainname(const char *dn, char **domainname, const ns_cred_t *cred,
3734 + ns_ldap_error_t **errorp, ns_conn_user_t *conn_user)
3735 +{
3736 + lookup_data_t ldata;
3737 + ns_ldap_result_t *result;
3738 + char **value;
3739 + int rc;
3740 +
3741 + *domainname = NULL;
3742 + *errorp = NULL;
3743 +
3744 + ldata.lkd_dn = dn;
3745 + ldata.lkd_service = NULL;
3746 + ldata.lkd_filter = _NIS_FILTER;
3747 + ldata.lkd_cred = cred;
3748 + ldata.lkd_user = conn_user;
3749 +
3750 + rc = lookup_dn(&ldata, nis_domain_attrs, &result, errorp);
3751 + if (rc != NS_LDAP_SUCCESS)
3752 + return (rc);
3753 +
3754 + value = __ns_ldap_getAttr(result->entry, _NIS_DOMAIN);
3755 +
3756 + if (value != NULL && value[0] != NULL) {
3757 + *domainname = strdup(value[0]);
3758 + if (*domainname == NULL)
3759 + rc = NS_LDAP_MEMORY;
3760 + } else {
3761 + rc = NS_LDAP_NOTFOUND;
3762 + }
3763 +
3764 + (void) __ns_ldap_freeResult(&result);
3765 + return (rc);
3766 +}
3767 +
3768 +/*
3699 3769 * __s_api_find_domainname performs one or more LDAP searches to
3700 3770 * find the value of the nisdomain attribute associated with
3701 3771 * the input DN (with retry).
3702 3772 */
3703 3773
3704 3774 static int
3705 3775 __s_api_find_domainname(const char *dn, char **domainname,
3706 3776 const ns_cred_t *cred, ns_ldap_error_t **errorp)
3707 3777 {
3708 3778 ns_conn_user_t *cu = NULL;
3709 3779 int try_cnt = 0;
3710 3780 int rc = NS_LDAP_SUCCESS;
3711 3781
3712 3782 for (;;) {
3713 3783 if (__s_api_setup_retry_search(&cu, NS_CONN_USER_SEARCH,
3714 3784 &try_cnt, &rc, errorp) == 0)
3715 3785 break;
3716 3786 rc = find_domainname(dn, domainname, cred, errorp, cu);
3717 3787 }
3718 3788
3719 3789 return (rc);
3720 3790 }
3721 3791
3722 3792 static int
3723 3793 firstEntry(
3724 3794 const char *service,
3725 3795 const char *filter,
3726 3796 const char *sortattr,
3727 3797 int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
3728 3798 char **realfilter, const void *userdata),
3729 3799 const char * const *attribute,
3730 3800 const ns_cred_t *auth,
3731 3801 const int flags,
3732 3802 void **vcookie,
3733 3803 ns_ldap_result_t **result,
3734 3804 ns_ldap_error_t ** errorp,
3735 3805 const void *userdata,
3736 3806 ns_conn_user_t *conn_user)
3737 3807 {
3738 3808 ns_ldap_cookie_t *cookie = NULL;
3739 3809 ns_ldap_error_t *error = NULL;
3740 3810 ns_state_t state;
3741 3811 ns_ldap_search_desc_t **sdlist;
3742 3812 ns_ldap_search_desc_t *dptr;
3743 3813 char **dns = NULL;
3744 3814 int scope;
3745 3815 int rc;
3746 3816
3747 3817 *errorp = NULL;
3748 3818 *result = NULL;
3749 3819
3750 3820 /*
3751 3821 * Sanity check - NS_LDAP_READ_SHADOW is for our
3752 3822 * own internal use.
3753 3823 */
3754 3824 if (flags & NS_LDAP_READ_SHADOW)
3755 3825 return (NS_LDAP_INVALID_PARAM);
3756 3826
3757 3827 /* get the service descriptor - or create a default one */
3758 3828 rc = __s_api_get_SSD_from_SSDtoUse_service(service,
3759 3829 &sdlist, &error);
3760 3830 if (rc != NS_LDAP_SUCCESS) {
3761 3831 *errorp = error;
3762 3832 return (rc);
3763 3833 }
3764 3834 if (sdlist == NULL) {
3765 3835 /* Create default service Desc */
3766 3836 sdlist = (ns_ldap_search_desc_t **)calloc(2,
3767 3837 sizeof (ns_ldap_search_desc_t *));
3768 3838 if (sdlist == NULL) {
3769 3839 return (NS_LDAP_MEMORY);
3770 3840 }
3771 3841 dptr = (ns_ldap_search_desc_t *)
3772 3842 calloc(1, sizeof (ns_ldap_search_desc_t));
3773 3843 if (dptr == NULL) {
3774 3844 free(sdlist);
3775 3845 return (NS_LDAP_MEMORY);
3776 3846 }
3777 3847 sdlist[0] = dptr;
3778 3848
3779 3849 /* default base */
3780 3850 rc = __s_api_getDNs(&dns, service, &error);
3781 3851 if (rc != NS_LDAP_SUCCESS) {
3782 3852 if (dns) {
3783 3853 __s_api_free2dArray(dns);
3784 3854 dns = NULL;
3785 3855 }
3786 3856 if (sdlist) {
3787 3857 (void) __ns_ldap_freeSearchDescriptors(
3788 3858 &sdlist);
3789 3859
3790 3860 sdlist = NULL;
3791 3861 }
3792 3862 *errorp = error;
3793 3863 return (rc);
3794 3864 }
3795 3865 dptr->basedn = strdup(dns[0]);
3796 3866 __s_api_free2dArray(dns);
3797 3867 dns = NULL;
3798 3868
3799 3869 /* default scope */
3800 3870 scope = 0;
3801 3871 cookie = init_search_state_machine();
3802 3872 if (cookie == NULL) {
3803 3873 if (sdlist) {
3804 3874 (void) __ns_ldap_freeSearchDescriptors(&sdlist);
3805 3875 sdlist = NULL;
3806 3876 }
3807 3877 return (NS_LDAP_MEMORY);
3808 3878 }
3809 3879 rc = __s_api_getSearchScope(&scope, &cookie->errorp);
3810 3880 dptr->scope = scope;
3811 3881 }
3812 3882
3813 3883 /* Initialize State machine cookie */
3814 3884 if (cookie == NULL)
3815 3885 cookie = init_search_state_machine();
3816 3886 if (cookie == NULL) {
3817 3887 if (sdlist) {
3818 3888 (void) __ns_ldap_freeSearchDescriptors(&sdlist);
3819 3889 sdlist = NULL;
3820 3890 }
3821 3891 return (NS_LDAP_MEMORY);
3822 3892 }
3823 3893
3824 3894 /* identify self as a getent user */
3825 3895 cookie->conn_user = conn_user;
3826 3896
3827 3897 cookie->sdlist = sdlist;
3828 3898
3829 3899 /* see if need to follow referrals */
3830 3900 rc = __s_api_toFollowReferrals(flags,
3831 3901 &cookie->followRef, errorp);
3832 3902 if (rc != NS_LDAP_SUCCESS) {
3833 3903 delete_search_cookie(cookie);
3834 3904 return (rc);
3835 3905 }
3836 3906
3837 3907 /*
3838 3908 * use VLV/PAGE control only if NS_LDAP_NO_PAGE_CTRL is not set
3839 3909 */
3840 3910 if (flags & NS_LDAP_NO_PAGE_CTRL)
3841 3911 cookie->use_paging = FALSE;
3842 3912 else
3843 3913 cookie->use_paging = TRUE;
3844 3914
3845 3915 /* Set up other arguments */
3846 3916 cookie->userdata = userdata;
3847 3917 if (init_filter_cb != NULL) {
3848 3918 cookie->init_filter_cb = init_filter_cb;
3849 3919 cookie->use_filtercb = 1;
3850 3920 }
3851 3921 cookie->use_usercb = 0;
3852 3922 /* check_shadow() may add extra value to cookie->i_flags */
3853 3923 cookie->i_flags = flags;
3854 3924 if (service) {
3855 3925 cookie->service = strdup(service);
3856 3926 if (cookie->service == NULL) {
3857 3927 delete_search_cookie(cookie);
3858 3928 return (NS_LDAP_MEMORY);
3859 3929 }
3860 3930
3861 3931 /*
3862 3932 * If given, use the credential given by the caller, and
3863 3933 * skip the credential check required for shadow update.
3864 3934 */
3865 3935 if (auth == NULL) {
3866 3936 rc = check_shadow(cookie, service);
3867 3937 if (rc != NS_LDAP_SUCCESS) {
3868 3938 *errorp = cookie->errorp;
3869 3939 cookie->errorp = NULL;
3870 3940 delete_search_cookie(cookie);
3871 3941 cookie = NULL;
3872 3942 return (rc);
3873 3943 }
3874 3944 }
3875 3945 }
3876 3946
3877 3947 cookie->i_filter = strdup(filter);
3878 3948 cookie->i_attr = attribute;
3879 3949 cookie->i_sortattr = sortattr;
3880 3950 cookie->i_auth = auth;
3881 3951
3882 3952 state = INIT;
3883 3953 for (;;) {
3884 3954 state = search_state_machine(cookie, state, ONE_STEP);
3885 3955 switch (state) {
3886 3956 case PROCESS_RESULT:
3887 3957 *result = cookie->result;
3888 3958 cookie->result = NULL;
3889 3959 *vcookie = (void *)cookie;
3890 3960 return (NS_LDAP_SUCCESS);
3891 3961 case LDAP_ERROR:
3892 3962 state = search_state_machine(cookie, state, ONE_STEP);
3893 3963 state = search_state_machine(cookie, CLEAR_RESULTS,
3894 3964 ONE_STEP);
3895 3965 /* FALLTHROUGH */
3896 3966 case ERROR:
3897 3967 rc = cookie->err_rc;
3898 3968 if (conn_user != NULL && conn_user->ns_error != NULL) {
3899 3969 *errorp = conn_user->ns_error;
3900 3970 conn_user->ns_error = NULL;
3901 3971 } else {
3902 3972 *errorp = cookie->errorp;
3903 3973 cookie->errorp = NULL;
3904 3974 }
3905 3975 delete_search_cookie(cookie);
3906 3976 return (rc);
3907 3977 case EXIT:
3908 3978 rc = cookie->err_rc;
3909 3979 if (rc != NS_LDAP_SUCCESS) {
3910 3980 *errorp = cookie->errorp;
3911 3981 cookie->errorp = NULL;
3912 3982 } else {
3913 3983 rc = NS_LDAP_NOTFOUND;
3914 3984 }
3915 3985
3916 3986 delete_search_cookie(cookie);
3917 3987 return (rc);
3918 3988
3919 3989 default:
3920 3990 break;
3921 3991 }
3922 3992 }
3923 3993 }
3924 3994
3925 3995 int
3926 3996 __ns_ldap_firstEntry(
3927 3997 const char *service,
3928 3998 const char *filter,
3929 3999 const char *vlv_sort,
3930 4000 int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
3931 4001 char **realfilter, const void *userdata),
3932 4002 const char * const *attribute,
3933 4003 const ns_cred_t *auth,
3934 4004 const int flags,
3935 4005 void **vcookie,
3936 4006 ns_ldap_result_t **result,
3937 4007 ns_ldap_error_t ** errorp,
3938 4008 const void *userdata)
3939 4009 {
3940 4010 ns_conn_user_t *cu = NULL;
3941 4011 int try_cnt = 0;
3942 4012 int rc = NS_LDAP_SUCCESS;
3943 4013
3944 4014 for (;;) {
3945 4015 if (__s_api_setup_retry_search(&cu, NS_CONN_USER_GETENT,
3946 4016 &try_cnt, &rc, errorp) == 0)
3947 4017 break;
3948 4018 rc = firstEntry(service, filter, vlv_sort, init_filter_cb,
3949 4019 attribute, auth, flags, vcookie, result, errorp, userdata,
3950 4020 cu);
3951 4021 }
3952 4022 return (rc);
3953 4023 }
3954 4024
3955 4025 /*ARGSUSED2*/
3956 4026 int
3957 4027 __ns_ldap_nextEntry(void *vcookie, ns_ldap_result_t **result,
3958 4028 ns_ldap_error_t ** errorp)
3959 4029 {
3960 4030 ns_ldap_cookie_t *cookie;
3961 4031 ns_state_t state;
3962 4032 int rc;
3963 4033
3964 4034 cookie = (ns_ldap_cookie_t *)vcookie;
3965 4035 cookie->result = NULL;
3966 4036 *result = NULL;
3967 4037
3968 4038 if (cookie->conn_user != NULL) {
3969 4039 rc = __s_api_setup_getnext(cookie->conn_user,
3970 4040 &cookie->err_rc, errorp);
3971 4041 if (rc != NS_LDAP_SUCCESS)
3972 4042 return (rc);
3973 4043 }
3974 4044
3975 4045 state = END_PROCESS_RESULT;
3976 4046 for (;;) {
3977 4047 state = search_state_machine(cookie, state, ONE_STEP);
3978 4048 switch (state) {
3979 4049 case PROCESS_RESULT:
3980 4050 *result = cookie->result;
3981 4051 cookie->result = NULL;
3982 4052 return (NS_LDAP_SUCCESS);
3983 4053 case LDAP_ERROR:
3984 4054 state = search_state_machine(cookie, state, ONE_STEP);
3985 4055 state = search_state_machine(cookie, CLEAR_RESULTS,
3986 4056 ONE_STEP);
3987 4057 /* FALLTHROUGH */
3988 4058 case ERROR:
3989 4059 rc = cookie->err_rc;
3990 4060 *errorp = cookie->errorp;
3991 4061 cookie->errorp = NULL;
3992 4062 return (rc);
3993 4063 case EXIT:
3994 4064 return (NS_LDAP_SUCCESS);
3995 4065 }
3996 4066 }
3997 4067 }
3998 4068
3999 4069 int
4000 4070 __ns_ldap_endEntry(
4001 4071 void **vcookie,
4002 4072 ns_ldap_error_t ** errorp)
4003 4073 {
4004 4074 ns_ldap_cookie_t *cookie;
4005 4075 int rc;
4006 4076
4007 4077 if (*vcookie == NULL)
4008 4078 return (NS_LDAP_INVALID_PARAM);
4009 4079
4010 4080 cookie = (ns_ldap_cookie_t *)(*vcookie);
4011 4081 cookie->result = NULL;
4012 4082
4013 4083 /* Complete search */
4014 4084 rc = search_state_machine(cookie, CLEAR_RESULTS, 0);
4015 4085
4016 4086 /* Copy results back to user */
4017 4087 rc = cookie->err_rc;
4018 4088 if (rc != NS_LDAP_SUCCESS)
4019 4089 *errorp = cookie->errorp;
4020 4090
4021 4091 cookie->errorp = NULL;
4022 4092 if (cookie->conn_user != NULL) {
4023 4093 if (cookie->conn_user->conn_mt != NULL)
4024 4094 __s_api_conn_mt_return(cookie->conn_user);
4025 4095 __s_api_conn_user_free(cookie->conn_user);
4026 4096 }
4027 4097 delete_search_cookie(cookie);
4028 4098 cookie = NULL;
4029 4099 *vcookie = NULL;
4030 4100
4031 4101 return (rc);
4032 4102 }
4033 4103
4034 4104
4035 4105 int
4036 4106 __ns_ldap_freeResult(ns_ldap_result_t **result)
4037 4107 {
4038 4108
4039 4109 ns_ldap_entry_t *curEntry = NULL;
4040 4110 ns_ldap_entry_t *delEntry = NULL;
4041 4111 int i;
4042 4112 ns_ldap_result_t *res = *result;
4043 4113
4044 4114 #ifdef DEBUG
4045 4115 (void) fprintf(stderr, "__ns_ldap_freeResult START\n");
4046 4116 #endif
4047 4117 if (res == NULL)
4048 4118 return (NS_LDAP_INVALID_PARAM);
4049 4119
4050 4120 if (res->entry != NULL)
4051 4121 curEntry = res->entry;
4052 4122
4053 4123 for (i = 0; i < res->entries_count; i++) {
4054 4124 if (curEntry != NULL) {
4055 4125 delEntry = curEntry;
4056 4126 curEntry = curEntry->next;
4057 4127 __ns_ldap_freeEntry(delEntry);
4058 4128 }
4059 4129 }
4060 4130
4061 4131 free(res);
4062 4132 *result = NULL;
4063 4133 return (NS_LDAP_SUCCESS);
4064 4134 }
4065 4135
4066 4136 int
4067 4137 __ns_ldap_auth(const ns_cred_t *auth, const int flags, ns_ldap_error_t **errorp,
4068 4138 LDAPControl **serverctrls __unused, LDAPControl **clientctrls __unused)
4069 4139 {
4070 4140
4071 4141 ConnectionID connectionId = -1;
4072 4142 Connection *conp;
4073 4143 int rc = 0;
4074 4144 int do_not_fail_if_new_pwd_reqd = 0;
4075 4145 int nopasswd_acct_mgmt = 0;
4076 4146 ns_conn_user_t *conn_user;
4077 4147
4078 4148
4079 4149 #ifdef DEBUG
4080 4150 (void) fprintf(stderr, "__ns_ldap_auth START\n");
4081 4151 #endif
4082 4152
4083 4153 *errorp = NULL;
4084 4154 if (auth == NULL)
4085 4155 return (NS_LDAP_INVALID_PARAM);
4086 4156
4087 4157 conn_user = __s_api_conn_user_init(NS_CONN_USER_AUTH,
4088 4158 NULL, B_FALSE);
4089 4159
4090 4160 rc = __s_api_getConnection(NULL, flags | NS_LDAP_NEW_CONN,
4091 4161 auth, &connectionId, &conp, errorp,
4092 4162 do_not_fail_if_new_pwd_reqd, nopasswd_acct_mgmt,
4093 4163 conn_user);
4094 4164
4095 4165 if (conn_user != NULL)
4096 4166 __s_api_conn_user_free(conn_user);
4097 4167
4098 4168 if (rc == NS_LDAP_OP_FAILED && *errorp)
4099 4169 (void) __ns_ldap_freeError(errorp);
4100 4170
4101 4171 if (connectionId > -1)
4102 4172 DropConnection(connectionId, flags);
4103 4173 return (rc);
4104 4174 }
4105 4175
4106 4176 char **
4107 4177 __ns_ldap_getAttr(const ns_ldap_entry_t *entry, const char *attrname)
4108 4178 {
4109 4179 int i;
4110 4180
4111 4181 if (entry == NULL)
4112 4182 return (NULL);
4113 4183 for (i = 0; i < entry->attr_count; i++) {
4114 4184 if (strcasecmp(entry->attr_pair[i]->attrname, attrname) == 0)
4115 4185 return (entry->attr_pair[i]->attrvalue);
4116 4186 }
4117 4187 return (NULL);
4118 4188 }
4119 4189
4120 4190 ns_ldap_attr_t *
4121 4191 __ns_ldap_getAttrStruct(const ns_ldap_entry_t *entry, const char *attrname)
4122 4192 {
4123 4193 int i;
4124 4194
4125 4195 if (entry == NULL)
4126 4196 return (NULL);
4127 4197 for (i = 0; i < entry->attr_count; i++) {
4128 4198 if (strcasecmp(entry->attr_pair[i]->attrname, attrname) == 0)
4129 4199 return (entry->attr_pair[i]);
4130 4200 }
4131 4201 return (NULL);
4132 4202 }
4133 4203
4134 4204
4135 4205 int
4136 4206 __ns_ldap_uid2dn(const char *uid, char **userDN, const ns_cred_t *cred,
4137 4207 ns_ldap_error_t **errorp)
4138 4208 {
4139 4209 ns_ldap_result_t *result = NULL;
4140 4210 char *filter, *userdata;
4141 4211 char errstr[MAXERROR];
4142 4212 char **value;
4143 4213 int rc = 0;
4144 4214 int i;
4145 4215 size_t len;
4146 4216
4147 4217 *errorp = NULL;
4148 4218 *userDN = NULL;
4149 4219 if ((uid == NULL) || (uid[0] == '\0'))
4150 4220 return (NS_LDAP_INVALID_PARAM);
4151 4221
4152 4222 for (i = 0; uid[i] != '\0'; i++) {
4153 4223 if (uid[i] == '=') {
4154 4224 *userDN = strdup(uid);
4155 4225 return (NS_LDAP_SUCCESS);
4156 4226 }
4157 4227 }
4158 4228 for (i = 0; (uid[i] != '\0') && isdigit(uid[i]); i++)
4159 4229 ;
4160 4230 if (uid[i] == '\0') {
4161 4231 len = strlen(UIDNUMFILTER) + strlen(uid) + 1;
4162 4232 filter = malloc(len);
4163 4233 if (filter == NULL) {
4164 4234 *userDN = NULL;
4165 4235 return (NS_LDAP_MEMORY);
4166 4236 }
4167 4237 (void) snprintf(filter, len, UIDNUMFILTER, uid);
4168 4238
4169 4239 len = strlen(UIDNUMFILTER_SSD) + strlen(uid) + 1;
4170 4240 userdata = malloc(len);
4171 4241 if (userdata == NULL) {
4172 4242 *userDN = NULL;
4173 4243 free(filter);
4174 4244 return (NS_LDAP_MEMORY);
4175 4245 }
4176 4246 (void) snprintf(userdata, len, UIDNUMFILTER_SSD, uid);
4177 4247 } else {
4178 4248 len = strlen(UIDFILTER) + strlen(uid) + 1;
4179 4249 filter = malloc(len);
4180 4250 if (filter == NULL) {
4181 4251 *userDN = NULL;
4182 4252 return (NS_LDAP_MEMORY);
4183 4253 }
4184 4254 (void) snprintf(filter, len, UIDFILTER, uid);
4185 4255
4186 4256 len = strlen(UIDFILTER_SSD) + strlen(uid) + 1;
4187 4257 userdata = malloc(len);
4188 4258 if (userdata == NULL) {
4189 4259 *userDN = NULL;
4190 4260 free(filter);
4191 4261 return (NS_LDAP_MEMORY);
4192 4262 }
4193 4263 (void) snprintf(userdata, len, UIDFILTER_SSD, uid);
4194 4264 }
4195 4265
4196 4266 /*
4197 4267 * we want to retrieve the DN as it appears in LDAP
4198 4268 * hence the use of NS_LDAP_NOT_CVT_DN in flags
4199 4269 */
4200 4270 rc = __ns_ldap_list("passwd", filter,
4201 4271 __s_api_merge_SSD_filter,
4202 4272 NULL, cred, NS_LDAP_NOT_CVT_DN,
4203 4273 &result, errorp, NULL,
4204 4274 userdata);
4205 4275 free(filter);
4206 4276 filter = NULL;
4207 4277 free(userdata);
4208 4278 userdata = NULL;
4209 4279 if (rc != NS_LDAP_SUCCESS) {
4210 4280 if (result) {
4211 4281 (void) __ns_ldap_freeResult(&result);
4212 4282 result = NULL;
4213 4283 }
4214 4284 return (rc);
4215 4285 }
4216 4286 if (result->entries_count > 1) {
4217 4287 (void) __ns_ldap_freeResult(&result);
4218 4288 result = NULL;
4219 4289 *userDN = NULL;
4220 4290 (void) sprintf(errstr,
4221 4291 gettext("Too many entries are returned for %s"), uid);
4222 4292 MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, strdup(errstr),
4223 4293 NS_LDAP_MEMORY);
4224 4294 return (NS_LDAP_INTERNAL);
4225 4295 }
4226 4296
4227 4297 value = __ns_ldap_getAttr(result->entry, "dn");
4228 4298 *userDN = strdup(value[0]);
4229 4299 (void) __ns_ldap_freeResult(&result);
4230 4300 result = NULL;
4231 4301 return (NS_LDAP_SUCCESS);
↓ open down ↓ |
523 lines elided |
↑ open up ↑ |
4232 4302 }
4233 4303
4234 4304 #define _P_UID "uid"
4235 4305 static const char *dn2uid_attrs[] = {
4236 4306 _P_CN,
4237 4307 _P_UID,
4238 4308 (char *)NULL
4239 4309 };
4240 4310
4241 4311 int
4242 -__ns_ldap_dn2uid(const char *dn, char **userID, const ns_cred_t *cred,
4312 +__ns_ldap_dn2uid(const char *dn, char **userIDp, const ns_cred_t *cred,
4243 4313 ns_ldap_error_t **errorp)
4244 4314 {
4245 - ns_ldap_result_t *result = NULL;
4246 - char *filter, *userdata;
4247 - char errstr[MAXERROR];
4248 - char **value;
4249 - int rc = 0;
4250 - size_t len;
4315 + lookup_data_t ldata;
4316 + ns_ldap_result_t *result;
4317 + char **value;
4318 + int rc;
4251 4319
4252 4320 *errorp = NULL;
4253 - *userID = NULL;
4321 + *userIDp = NULL;
4254 4322 if ((dn == NULL) || (dn[0] == '\0'))
4255 4323 return (NS_LDAP_INVALID_PARAM);
4256 4324
4257 - len = strlen(UIDDNFILTER) + strlen(dn) + 1;
4258 - filter = malloc(len);
4259 - if (filter == NULL) {
4260 - return (NS_LDAP_MEMORY);
4261 - }
4262 - (void) snprintf(filter, len, UIDDNFILTER, dn);
4325 + /*
4326 + * Many LDAP servers do not support using the dn in a search
4327 + * filter. As a result, we unfortunately cannot use __ns_ldap_list()
4328 + * to lookup the DN. Instead we perform a search with the baseDN
4329 + * being the DN we are looking for with a scope of 'base' to
4330 + * return the entry, as this should be supported by all LDAP servers.
4331 + */
4332 + ldata.lkd_dn = dn;
4263 4333
4264 - len = strlen(UIDDNFILTER_SSD) + strlen(dn) + 1;
4265 - userdata = malloc(len);
4266 - if (userdata == NULL) {
4267 - free(filter);
4268 - return (NS_LDAP_MEMORY);
4269 - }
4270 - (void) snprintf(userdata, len, UIDDNFILTER_SSD, dn);
4271 -
4272 4334 /*
4273 - * Unlike uid2dn, we DO want attribute mapping, so that
4274 - * "uid" is mapped to/from samAccountName, for example.
4335 + * Since we are looking up a user account by its DN, use the attribute
4336 + * and objectclass mappings (if present) for the passwd service.
4275 4337 */
4276 - rc = __ns_ldap_list("passwd", filter,
4277 - __s_api_merge_SSD_filter,
4278 - dn2uid_attrs, cred, 0,
4279 - &result, errorp, NULL,
4280 - userdata);
4281 - free(filter);
4282 - filter = NULL;
4283 - free(userdata);
4284 - userdata = NULL;
4338 + ldata.lkd_service = "passwd";
4339 + ldata.lkd_filter = UIDDNFILTER;
4340 + ldata.lkd_cred = cred;
4341 + ldata.lkd_user = NULL;
4342 +
4343 + rc = lookup_dn(&ldata, dn2uid_attrs, &result, errorp);
4285 4344 if (rc != NS_LDAP_SUCCESS)
4286 - goto out;
4345 + return (rc);
4287 4346
4288 - if (result->entries_count > 1) {
4289 - (void) sprintf(errstr,
4290 - gettext("Too many entries are returned for %s"), dn);
4291 - MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, strdup(errstr),
4292 - NS_LDAP_MEMORY);
4293 - rc = NS_LDAP_INTERNAL;
4294 - goto out;
4295 - }
4296 -
4297 4347 value = __ns_ldap_getAttr(result->entry, _P_UID);
4298 - if (value == NULL || value[0] == NULL) {
4348 + if (value != NULL && value[0] != NULL) {
4349 + *userIDp = strdup(value[0]);
4350 + if (*userIDp == NULL)
4351 + rc = NS_LDAP_MEMORY;
4352 + } else {
4299 4353 rc = NS_LDAP_NOTFOUND;
4300 - goto out;
4301 4354 }
4302 4355
4303 - *userID = strdup(value[0]);
4304 - rc = NS_LDAP_SUCCESS;
4305 -
4306 -out:
4307 4356 (void) __ns_ldap_freeResult(&result);
4308 - result = NULL;
4309 4357 return (rc);
4310 4358 }
4311 4359
4312 4360 int
4313 4361 __ns_ldap_host2dn(const char *host, const char *domain, char **hostDN,
4314 4362 const ns_cred_t *cred, ns_ldap_error_t **errorp)
4315 4363 {
4316 4364 ns_ldap_result_t *result = NULL;
4317 4365 char *filter, *userdata;
4318 4366 char errstr[MAXERROR];
4319 4367 char **value;
4320 4368 int rc;
4321 4369 size_t len;
4322 4370
4323 4371 /*
4324 4372 * XXX
4325 4373 * the domain parameter needs to be used in case domain is not local,
4326 4374 * if this routine is to support multi domain setups, it needs lots
4327 4375 * of work...
4328 4376 */
4329 4377 *errorp = NULL;
4330 4378 *hostDN = NULL;
4331 4379 if ((host == NULL) || (host[0] == '\0'))
4332 4380 return (NS_LDAP_INVALID_PARAM);
4333 4381
4334 4382 len = strlen(HOSTFILTER) + strlen(host) + 1;
4335 4383 filter = malloc(len);
4336 4384 if (filter == NULL) {
4337 4385 return (NS_LDAP_MEMORY);
4338 4386 }
4339 4387 (void) snprintf(filter, len, HOSTFILTER, host);
4340 4388
4341 4389 len = strlen(HOSTFILTER_SSD) + strlen(host) + 1;
4342 4390 userdata = malloc(len);
4343 4391 if (userdata == NULL) {
4344 4392 free(filter);
4345 4393 return (NS_LDAP_MEMORY);
4346 4394 }
4347 4395 (void) snprintf(userdata, len, HOSTFILTER_SSD, host);
4348 4396
4349 4397 /*
4350 4398 * we want to retrieve the DN as it appears in LDAP
4351 4399 * hence the use of NS_LDAP_NOT_CVT_DN in flags
4352 4400 */
4353 4401 rc = __ns_ldap_list("hosts", filter,
4354 4402 __s_api_merge_SSD_filter,
4355 4403 NULL, cred, NS_LDAP_NOT_CVT_DN, &result,
4356 4404 errorp, NULL,
4357 4405 userdata);
4358 4406 free(filter);
4359 4407 filter = NULL;
4360 4408 free(userdata);
4361 4409 userdata = NULL;
4362 4410 if (rc != NS_LDAP_SUCCESS) {
4363 4411 if (result) {
4364 4412 (void) __ns_ldap_freeResult(&result);
4365 4413 result = NULL;
4366 4414 }
4367 4415 return (rc);
4368 4416 }
4369 4417
4370 4418 if (result->entries_count > 1) {
4371 4419 (void) __ns_ldap_freeResult(&result);
4372 4420 result = NULL;
4373 4421 *hostDN = NULL;
4374 4422 (void) sprintf(errstr,
4375 4423 gettext("Too many entries are returned for %s"), host);
4376 4424 MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, strdup(errstr),
4377 4425 NS_LDAP_MEMORY);
4378 4426 return (NS_LDAP_INTERNAL);
4379 4427 }
4380 4428
4381 4429 value = __ns_ldap_getAttr(result->entry, "dn");
4382 4430 *hostDN = strdup(value[0]);
4383 4431 (void) __ns_ldap_freeResult(&result);
4384 4432 result = NULL;
4385 4433 return (NS_LDAP_SUCCESS);
4386 4434 }
4387 4435
4388 4436 int
4389 4437 __ns_ldap_dn2domain(const char *dn, char **domain, const ns_cred_t *cred,
4390 4438 ns_ldap_error_t **errorp)
4391 4439 {
4392 4440 int rc, pnum, i, j, len = 0;
4393 4441 char *newdn, **rdns = NULL;
4394 4442 char **dns, *dn1;
4395 4443
4396 4444 *errorp = NULL;
4397 4445
4398 4446 if (domain == NULL)
4399 4447 return (NS_LDAP_INVALID_PARAM);
4400 4448 else
4401 4449 *domain = NULL;
4402 4450
4403 4451 if ((dn == NULL) || (dn[0] == '\0'))
4404 4452 return (NS_LDAP_INVALID_PARAM);
4405 4453
4406 4454 /*
4407 4455 * break dn into rdns
4408 4456 */
4409 4457 dn1 = strdup(dn);
4410 4458 if (dn1 == NULL)
4411 4459 return (NS_LDAP_MEMORY);
4412 4460 rdns = ldap_explode_dn(dn1, 0);
4413 4461 free(dn1);
4414 4462 if (rdns == NULL || *rdns == NULL)
4415 4463 return (NS_LDAP_INVALID_PARAM);
4416 4464
4417 4465 for (i = 0; rdns[i]; i++)
4418 4466 len += strlen(rdns[i]) + 1;
4419 4467 pnum = i;
4420 4468
4421 4469 newdn = (char *)malloc(len + 1);
4422 4470 dns = (char **)calloc(pnum, sizeof (char *));
4423 4471 if (newdn == NULL || dns == NULL) {
4424 4472 if (newdn)
4425 4473 free(newdn);
4426 4474 ldap_value_free(rdns);
4427 4475 return (NS_LDAP_MEMORY);
4428 4476 }
4429 4477
4430 4478 /* construct a semi-normalized dn, newdn */
4431 4479 *newdn = '\0';
4432 4480 for (i = 0; rdns[i]; i++) {
4433 4481 dns[i] = newdn + strlen(newdn);
4434 4482 (void) strcat(newdn,
4435 4483 __s_api_remove_rdn_space(rdns[i]));
4436 4484 (void) strcat(newdn, ",");
4437 4485 }
4438 4486 /* remove the last ',' */
4439 4487 newdn[strlen(newdn) - 1] = '\0';
4440 4488 ldap_value_free(rdns);
4441 4489
4442 4490 /*
4443 4491 * loop and find the domain name associated with newdn,
4444 4492 * removing rdn one by one from left to right
4445 4493 */
4446 4494 for (i = 0; i < pnum; i++) {
4447 4495
4448 4496 if (*errorp)
4449 4497 (void) __ns_ldap_freeError(errorp);
4450 4498
4451 4499 /*
4452 4500 * try cache manager first
4453 4501 */
4454 4502 rc = __s_api_get_cachemgr_data(NS_CACHE_DN2DOMAIN,
4455 4503 dns[i], domain);
4456 4504 if (rc != NS_LDAP_SUCCESS) {
4457 4505 /*
4458 4506 * try ldap server second
4459 4507 */
4460 4508 rc = __s_api_find_domainname(dns[i], domain,
4461 4509 cred, errorp);
4462 4510 } else {
4463 4511 /*
4464 4512 * skip the last one,
4465 4513 * since it is already cached by ldap_cachemgr
4466 4514 */
4467 4515 i--;
4468 4516 }
4469 4517 if (rc == NS_LDAP_SUCCESS) {
4470 4518 if (__s_api_nscd_proc()) {
4471 4519 /*
4472 4520 * If it's nscd, ask cache manager to save the
4473 4521 * dn to domain mapping(s)
4474 4522 */
4475 4523 for (j = 0; j <= i; j++) {
4476 4524 (void) __s_api_set_cachemgr_data(
4477 4525 NS_CACHE_DN2DOMAIN,
4478 4526 dns[j],
4479 4527 *domain);
4480 4528 }
4481 4529 }
4482 4530 break;
4483 4531 }
4484 4532 }
4485 4533
4486 4534 free(dns);
4487 4535 free(newdn);
4488 4536 if (rc != NS_LDAP_SUCCESS)
4489 4537 rc = NS_LDAP_NOTFOUND;
4490 4538 return (rc);
4491 4539 }
4492 4540
4493 4541 int
4494 4542 __ns_ldap_getServiceAuthMethods(const char *service, ns_auth_t ***auth,
4495 4543 ns_ldap_error_t **errorp)
4496 4544 {
4497 4545 char errstr[MAXERROR];
4498 4546 int rc, i;
4499 4547 boolean_t done = B_FALSE;
4500 4548 int slen;
4501 4549 void **param;
4502 4550 char **sam, *srv, *send;
4503 4551 ns_auth_t **authpp = NULL, *ap;
4504 4552 int cnt, max;
4505 4553 ns_config_t *cfg;
4506 4554 ns_ldap_error_t *error = NULL;
4507 4555
4508 4556 if (errorp == NULL)
4509 4557 return (NS_LDAP_INVALID_PARAM);
4510 4558 *errorp = NULL;
4511 4559
4512 4560 if ((service == NULL) || (service[0] == '\0') ||
4513 4561 (auth == NULL))
4514 4562 return (NS_LDAP_INVALID_PARAM);
4515 4563
4516 4564 *auth = NULL;
4517 4565 rc = __ns_ldap_getParam(NS_LDAP_SERVICE_AUTH_METHOD_P, ¶m, &error);
4518 4566 if (rc != NS_LDAP_SUCCESS || param == NULL) {
4519 4567 *errorp = error;
4520 4568 return (rc);
4521 4569 }
4522 4570 sam = (char **)param;
4523 4571
4524 4572 cfg = __s_api_get_default_config();
4525 4573 cnt = 0;
4526 4574
4527 4575 slen = strlen(service);
4528 4576
4529 4577 for (; *sam; sam++) {
4530 4578 srv = *sam;
4531 4579 if (strncasecmp(service, srv, slen) != 0)
4532 4580 continue;
4533 4581 srv += slen;
4534 4582 if (*srv != COLONTOK)
4535 4583 continue;
4536 4584 send = srv;
4537 4585 srv++;
4538 4586 for (max = 1; (send = strchr(++send, SEMITOK)) != NULL; max++)
4539 4587 ;
4540 4588 authpp = (ns_auth_t **)calloc(++max, sizeof (ns_auth_t *));
4541 4589 if (authpp == NULL) {
4542 4590 (void) __ns_ldap_freeParam(¶m);
4543 4591 __s_api_release_config(cfg);
4544 4592 return (NS_LDAP_MEMORY);
4545 4593 }
4546 4594 while (!done) {
4547 4595 send = strchr(srv, SEMITOK);
4548 4596 if (send != NULL) {
4549 4597 *send = '\0';
4550 4598 send++;
4551 4599 }
4552 4600 i = __s_get_enum_value(cfg, srv, NS_LDAP_AUTH_P);
4553 4601 if (i == -1) {
4554 4602 (void) __ns_ldap_freeParam(¶m);
4555 4603 (void) sprintf(errstr,
4556 4604 gettext("Unsupported "
4557 4605 "serviceAuthenticationMethod: %s.\n"), srv);
4558 4606 MKERROR(LOG_WARNING, *errorp, NS_CONFIG_SYNTAX,
4559 4607 strdup(errstr), NS_LDAP_MEMORY);
4560 4608 __s_api_release_config(cfg);
4561 4609 return (NS_LDAP_CONFIG);
4562 4610 }
4563 4611 ap = __s_api_AuthEnumtoStruct((EnumAuthType_t)i);
4564 4612 if (ap == NULL) {
4565 4613 (void) __ns_ldap_freeParam(¶m);
4566 4614 __s_api_release_config(cfg);
4567 4615 return (NS_LDAP_MEMORY);
4568 4616 }
4569 4617 authpp[cnt++] = ap;
4570 4618 if (send == NULL)
4571 4619 done = B_TRUE;
4572 4620 else
4573 4621 srv = send;
4574 4622 }
4575 4623 }
4576 4624
4577 4625 *auth = authpp;
4578 4626 (void) __ns_ldap_freeParam(¶m);
4579 4627 __s_api_release_config(cfg);
4580 4628 return (NS_LDAP_SUCCESS);
4581 4629 }
4582 4630
4583 4631 /*
4584 4632 * This routine is called when certain scenario occurs
4585 4633 * e.g.
4586 4634 * service == auto_home
4587 4635 * SSD = automount: ou = mytest,
4588 4636 * NS_LDAP_MAPATTRIBUTE= auto_home: automountMapName=AAA
4589 4637 * NS_LDAP_OBJECTCLASSMAP= auto_home:automountMap=MynisMap
4590 4638 * NS_LDAP_OBJECTCLASSMAP= auto_home:automount=MynisObject
4591 4639 *
4592 4640 * The automountMapName is prepended implicitely but is mapped
4593 4641 * to AAA. So dn could appers as
4594 4642 * dn: AAA=auto_home,ou=bar,dc=foo,dc=com
4595 4643 * dn: automountKey=user_01,AAA=auto_home,ou=bar,dc=foo,dc=com
4596 4644 * dn: automountKey=user_02,AAA=auto_home,ou=bar,dc=foo,dc=com
4597 4645 * in the directory.
4598 4646 * This function is called to covert the mapped attr back to
4599 4647 * orig attr when the entries are searched and returned
4600 4648 */
4601 4649
4602 4650 int
4603 4651 __s_api_convert_automountmapname(const char *service, char **dn,
4604 4652 ns_ldap_error_t **errp)
4605 4653 {
4606 4654
4607 4655 char **mapping = NULL;
4608 4656 char *mapped_attr = NULL;
4609 4657 char *automountmapname = "automountMapName";
4610 4658 char *buffer = NULL;
4611 4659 int rc = NS_LDAP_SUCCESS;
4612 4660 char errstr[MAXERROR];
4613 4661
4614 4662 /*
4615 4663 * dn is an input/out parameter, check it first
4616 4664 */
4617 4665
4618 4666 if (service == NULL || dn == NULL || *dn == NULL)
4619 4667 return (NS_LDAP_INVALID_PARAM);
4620 4668
4621 4669 /*
4622 4670 * Check to see if there is a mapped attribute for auto_xxx
4623 4671 */
4624 4672
4625 4673 mapping = __ns_ldap_getMappedAttributes(service, automountmapname);
4626 4674
4627 4675 /*
4628 4676 * if no mapped attribute for auto_xxx, try automount
4629 4677 */
4630 4678
4631 4679 if (mapping == NULL) {
4632 4680 mapping = __ns_ldap_getMappedAttributes(
4633 4681 "automount", automountmapname);
4634 4682 }
4635 4683
4636 4684 /*
4637 4685 * if no mapped attribute is found, return SUCCESS (no op)
4638 4686 */
4639 4687
4640 4688 if (mapping == NULL)
4641 4689 return (NS_LDAP_SUCCESS);
4642 4690
4643 4691 /*
4644 4692 * if the mapped attribute is found and attr is not empty,
4645 4693 * copy it
4646 4694 */
4647 4695
4648 4696 if (mapping[0] != NULL) {
4649 4697 mapped_attr = strdup(mapping[0]);
4650 4698 __s_api_free2dArray(mapping);
4651 4699 if (mapped_attr == NULL) {
4652 4700 return (NS_LDAP_MEMORY);
4653 4701 }
4654 4702 } else {
4655 4703 __s_api_free2dArray(mapping);
4656 4704
4657 4705 (void) snprintf(errstr, (2 * MAXERROR),
4658 4706 gettext("Attribute nisMapName is mapped to an "
4659 4707 "empty string.\n"));
4660 4708
4661 4709 MKERROR(LOG_ERR, *errp, NS_CONFIG_SYNTAX,
4662 4710 strdup(errstr), NS_LDAP_MEMORY);
4663 4711
4664 4712 return (NS_LDAP_CONFIG);
4665 4713 }
4666 4714
4667 4715 /*
4668 4716 * Locate the mapped attribute in the dn
4669 4717 * and replace it if it exists
4670 4718 */
4671 4719
4672 4720 rc = __s_api_replace_mapped_attr_in_dn(
4673 4721 (const char *) automountmapname, (const char *) mapped_attr,
4674 4722 (const char *) *dn, &buffer);
4675 4723
4676 4724 /* clean up */
4677 4725
4678 4726 free(mapped_attr);
4679 4727
4680 4728 /*
4681 4729 * If mapped attr is found(buffer != NULL)
4682 4730 * a new dn is returned
4683 4731 * If no mapped attribute is in dn,
4684 4732 * return NS_LDAP_SUCCESS (no op)
4685 4733 * If no memory,
4686 4734 * return NS_LDAP_MEMORY (no op)
4687 4735 */
4688 4736
4689 4737 if (buffer != NULL) {
4690 4738 free(*dn);
4691 4739 *dn = buffer;
4692 4740 }
4693 4741
4694 4742 return (rc);
4695 4743 }
4696 4744
4697 4745 /*
4698 4746 * If the mapped attr is found in the dn,
4699 4747 * return NS_LDAP_SUCCESS and a new_dn.
4700 4748 * If no mapped attr is found,
4701 4749 * return NS_LDAP_SUCCESS and *new_dn == NULL
4702 4750 * If there is not enough memory,
4703 4751 * return NS_LDAP_MEMORY and *new_dn == NULL
4704 4752 */
4705 4753
4706 4754 int
4707 4755 __s_api_replace_mapped_attr_in_dn(const char *orig_attr,
4708 4756 const char *mapped_attr, const char *dn, char **new_dn)
4709 4757 {
4710 4758
4711 4759 char **dnArray = NULL;
4712 4760 char *cur = NULL, *start = NULL;
4713 4761 int i = 0;
4714 4762 boolean_t found = B_FALSE;
4715 4763 int len = 0, orig_len = 0, mapped_len = 0;
4716 4764 int dn_len = 0, tmp_len = 0;
4717 4765
4718 4766 *new_dn = NULL;
4719 4767
4720 4768 /*
4721 4769 * seperate dn into individual componets
4722 4770 * e.g.
4723 4771 * "automountKey=user_01" , "automountMapName_test=auto_home", ...
4724 4772 */
4725 4773 dnArray = ldap_explode_dn(dn, 0);
4726 4774
4727 4775 /*
4728 4776 * This will find "mapped attr=value" in dn.
4729 4777 * It won't find match if mapped attr appears
4730 4778 * in the value.
4731 4779 */
4732 4780 for (i = 0; dnArray[i] != NULL; i++) {
4733 4781 /*
4734 4782 * This function is called when reading from
4735 4783 * the directory so assume each component has "=".
4736 4784 * Any ill formatted dn should be rejected
4737 4785 * before adding to the directory
4738 4786 */
4739 4787 cur = strchr(dnArray[i], '=');
4740 4788 *cur = '\0';
4741 4789 if (strcasecmp(mapped_attr, dnArray[i]) == 0)
4742 4790 found = B_TRUE;
4743 4791 *cur = '=';
4744 4792 if (found)
4745 4793 break;
4746 4794 }
4747 4795
4748 4796 if (!found) {
4749 4797 __s_api_free2dArray(dnArray);
4750 4798 *new_dn = NULL;
4751 4799 return (NS_LDAP_SUCCESS);
4752 4800 }
4753 4801 /*
4754 4802 * The new length is *dn length + (difference between
4755 4803 * orig attr and mapped attr) + 1 ;
4756 4804 * e.g.
4757 4805 * automountKey=aa,automountMapName_test=auto_home,dc=foo,dc=com
4758 4806 * ==>
4759 4807 * automountKey=aa,automountMapName=auto_home,dc=foo,dc=com
4760 4808 */
4761 4809 mapped_len = strlen(mapped_attr);
4762 4810 orig_len = strlen(orig_attr);
4763 4811 dn_len = strlen(dn);
4764 4812 len = dn_len + orig_len - mapped_len + 1;
4765 4813 *new_dn = (char *)calloc(1, len);
4766 4814 if (*new_dn == NULL) {
4767 4815 __s_api_free2dArray(dnArray);
4768 4816 return (NS_LDAP_MEMORY);
4769 4817 }
4770 4818
4771 4819 /*
4772 4820 * Locate the mapped attr in the dn.
4773 4821 * Use dnArray[i] instead of mapped_attr
4774 4822 * because mapped_attr could appear in
4775 4823 * the value
4776 4824 */
4777 4825
4778 4826 cur = strstr(dn, dnArray[i]);
4779 4827 __s_api_free2dArray(dnArray);
4780 4828 /* copy the portion before mapped attr in dn */
4781 4829 start = *new_dn;
4782 4830 tmp_len = cur - dn;
4783 4831 (void) memcpy(start, dn, tmp_len);
4784 4832
4785 4833 /*
4786 4834 * Copy the orig_attr. e.g. automountMapName
4787 4835 * This replaces mapped attr with orig attr
4788 4836 */
4789 4837 start = start + (cur - dn); /* move cursor in buffer */
4790 4838 (void) memcpy(start, orig_attr, orig_len);
4791 4839
4792 4840 /*
4793 4841 * Copy the portion after mapped attr in dn
4794 4842 */
4795 4843 cur = cur + mapped_len; /* move cursor in dn */
4796 4844 start = start + orig_len; /* move cursor in buffer */
4797 4845 (void) strcpy(start, cur);
4798 4846
4799 4847 return (NS_LDAP_SUCCESS);
4800 4848 }
4801 4849
4802 4850 /*
4803 4851 * Validate Filter functions
4804 4852 */
4805 4853
4806 4854 /* ***** Start of modified libldap.so.5 filter parser ***** */
4807 4855
4808 4856 /* filter parsing routine forward references */
4809 4857 static int adj_filter_list(char *str);
4810 4858 static int adj_simple_filter(char *str);
4811 4859 static int unescape_filterval(char *val);
4812 4860 static int hexchar2int(char c);
4813 4861 static int adj_substring_filter(char *val);
4814 4862
4815 4863
4816 4864 /*
4817 4865 * assumes string manipulation is in-line
4818 4866 * and all strings are sufficient in size
4819 4867 * return value is the position after 'c'
4820 4868 */
4821 4869
4822 4870 static char *
4823 4871 resync_str(char *str, char *next, char c)
4824 4872 {
4825 4873 char *ret;
4826 4874
4827 4875 ret = str + strlen(str);
4828 4876 *next = c;
4829 4877 if (ret == next)
4830 4878 return (ret);
4831 4879 (void) strcat(str, next);
4832 4880 return (ret);
4833 4881 }
4834 4882
4835 4883 static char *
4836 4884 find_right_paren(char *s)
4837 4885 {
4838 4886 int balance;
4839 4887 boolean_t escape;
4840 4888
4841 4889 balance = 1;
4842 4890 escape = B_FALSE;
4843 4891 while (*s && balance) {
4844 4892 if (escape == B_FALSE) {
4845 4893 if (*s == '(')
4846 4894 balance++;
4847 4895 else if (*s == ')')
4848 4896 balance--;
4849 4897 }
4850 4898 if (*s == '\\' && !escape)
4851 4899 escape = B_TRUE;
4852 4900 else
4853 4901 escape = B_FALSE;
4854 4902 if (balance)
4855 4903 s++;
4856 4904 }
4857 4905
4858 4906 return (*s ? s : NULL);
4859 4907 }
4860 4908
4861 4909 static char *
4862 4910 adj_complex_filter(char *str)
4863 4911 {
4864 4912 char *next;
4865 4913
4866 4914 /*
4867 4915 * We have (x(filter)...) with str sitting on
4868 4916 * the x. We have to find the paren matching
4869 4917 * the one before the x and put the intervening
4870 4918 * filters by calling adj_filter_list().
4871 4919 */
4872 4920
4873 4921 str++;
4874 4922 if ((next = find_right_paren(str)) == NULL)
4875 4923 return (NULL);
4876 4924
4877 4925 *next = '\0';
4878 4926 if (adj_filter_list(str) == -1)
4879 4927 return (NULL);
4880 4928 next = resync_str(str, next, ')');
4881 4929 next++;
4882 4930
4883 4931 return (next);
4884 4932 }
4885 4933
4886 4934 static int
4887 4935 adj_filter(char *str)
4888 4936 {
4889 4937 char *next;
4890 4938 int parens, balance;
4891 4939 boolean_t escape;
4892 4940 char *np, *cp, *dp;
4893 4941
4894 4942 parens = 0;
4895 4943 while (*str) {
4896 4944 switch (*str) {
4897 4945 case '(':
4898 4946 str++;
4899 4947 parens++;
4900 4948 switch (*str) {
4901 4949 case '&':
4902 4950 if ((str = adj_complex_filter(str)) == NULL)
4903 4951 return (-1);
4904 4952
4905 4953 parens--;
4906 4954 break;
4907 4955
4908 4956 case '|':
4909 4957 if ((str = adj_complex_filter(str)) == NULL)
4910 4958 return (-1);
4911 4959
4912 4960 parens--;
4913 4961 break;
4914 4962
4915 4963 case '!':
4916 4964 if ((str = adj_complex_filter(str)) == NULL)
4917 4965 return (-1);
4918 4966
4919 4967 parens--;
4920 4968 break;
4921 4969
4922 4970 case '(':
4923 4971 /* illegal ((case - generated by conversion */
4924 4972
4925 4973 /* find missing close) */
4926 4974 np = find_right_paren(str+1);
4927 4975
4928 4976 /* error if not found */
4929 4977 if (np == NULL)
4930 4978 return (-1);
4931 4979
4932 4980 /* remove redundant (and) */
4933 4981 for (dp = str, cp = str+1; cp < np; ) {
4934 4982 *dp++ = *cp++;
4935 4983 }
4936 4984 cp++;
4937 4985 while (*cp)
4938 4986 *dp++ = *cp++;
4939 4987 *dp = '\0';
4940 4988
4941 4989 /* re-start test at original ( */
4942 4990 parens--;
4943 4991 str--;
4944 4992 break;
4945 4993
4946 4994 default:
4947 4995 balance = 1;
4948 4996 escape = B_FALSE;
4949 4997 next = str;
4950 4998 while (*next && balance) {
4951 4999 if (escape == B_FALSE) {
4952 5000 if (*next == '(')
4953 5001 balance++;
4954 5002 else if (*next == ')')
4955 5003 balance--;
4956 5004 }
4957 5005 if (*next == '\\' && !escape)
4958 5006 escape = B_TRUE;
4959 5007 else
4960 5008 escape = B_FALSE;
4961 5009 if (balance)
4962 5010 next++;
4963 5011 }
4964 5012 if (balance != 0)
4965 5013 return (-1);
4966 5014
4967 5015 *next = '\0';
4968 5016 if (adj_simple_filter(str) == -1) {
4969 5017 return (-1);
4970 5018 }
4971 5019 next = resync_str(str, next, ')');
4972 5020 next++;
4973 5021 str = next;
4974 5022 parens--;
4975 5023 break;
4976 5024 }
4977 5025 break;
4978 5026
4979 5027 case ')':
4980 5028 str++;
4981 5029 parens--;
4982 5030 break;
4983 5031
4984 5032 case ' ':
4985 5033 str++;
4986 5034 break;
4987 5035
4988 5036 default: /* assume it's a simple type=value filter */
4989 5037 next = strchr(str, '\0');
4990 5038 if (adj_simple_filter(str) == -1) {
4991 5039 return (-1);
4992 5040 }
4993 5041 str = next;
4994 5042 break;
4995 5043 }
4996 5044 }
4997 5045
4998 5046 return (parens ? -1 : 0);
4999 5047 }
5000 5048
5001 5049
5002 5050 /*
5003 5051 * Put a list of filters like this "(filter1)(filter2)..."
5004 5052 */
5005 5053
5006 5054 static int
5007 5055 adj_filter_list(char *str)
5008 5056 {
5009 5057 char *next;
5010 5058 char save;
5011 5059
5012 5060 while (*str) {
5013 5061 while (*str && isspace(*str))
5014 5062 str++;
5015 5063 if (*str == '\0')
5016 5064 break;
5017 5065
5018 5066 if ((next = find_right_paren(str + 1)) == NULL)
5019 5067 return (-1);
5020 5068 save = *++next;
5021 5069
5022 5070 /* now we have "(filter)" with str pointing to it */
5023 5071 *next = '\0';
5024 5072 if (adj_filter(str) == -1)
5025 5073 return (-1);
5026 5074 next = resync_str(str, next, save);
5027 5075
5028 5076 str = next;
5029 5077 }
5030 5078
5031 5079 return (0);
5032 5080 }
5033 5081
5034 5082
5035 5083 /*
5036 5084 * is_valid_attr - returns 1 if a is a syntactically valid left-hand side
5037 5085 * of a filter expression, 0 otherwise. A valid string may contain only
5038 5086 * letters, numbers, hyphens, semi-colons, colons and periods. examples:
5039 5087 * cn
5040 5088 * cn;lang-fr
5041 5089 * 1.2.3.4;binary;dynamic
5042 5090 * mail;dynamic
5043 5091 * cn:dn:1.2.3.4
5044 5092 *
5045 5093 * For compatibility with older servers, we also allow underscores in
5046 5094 * attribute types, even through they are not allowed by the LDAPv3 RFCs.
5047 5095 */
5048 5096 static int
5049 5097 is_valid_attr(char *a)
5050 5098 {
5051 5099 for (; *a; a++) {
5052 5100 if (!isascii(*a)) {
5053 5101 return (0);
5054 5102 } else if (!isalnum(*a)) {
5055 5103 switch (*a) {
5056 5104 case '-':
5057 5105 case '.':
5058 5106 case ';':
5059 5107 case ':':
5060 5108 case '_':
5061 5109 break; /* valid */
5062 5110 default:
5063 5111 return (0);
5064 5112 }
5065 5113 }
5066 5114 }
5067 5115 return (1);
5068 5116 }
5069 5117
5070 5118 static char *
5071 5119 find_star(char *s)
5072 5120 {
5073 5121 for (; *s; ++s) {
5074 5122 switch (*s) {
5075 5123 case '*':
5076 5124 return (s);
5077 5125 case '\\':
5078 5126 ++s;
5079 5127 if (hexchar2int(s[0]) >= 0 && hexchar2int(s[1]) >= 0)
5080 5128 ++s;
5081 5129 default:
5082 5130 break;
5083 5131 }
5084 5132 }
5085 5133 return (NULL);
5086 5134 }
5087 5135
5088 5136 static int
5089 5137 adj_simple_filter(char *str)
5090 5138 {
5091 5139 char *s, *s2, *s3, filterop;
5092 5140 char *value;
5093 5141 int ftype = 0;
5094 5142 int rc;
5095 5143
5096 5144 rc = -1; /* pessimistic */
5097 5145
5098 5146 if ((str = strdup(str)) == NULL) {
5099 5147 return (rc);
5100 5148 }
5101 5149
5102 5150 if ((s = strchr(str, '=')) == NULL) {
5103 5151 goto free_and_return;
5104 5152 }
5105 5153 value = s + 1;
5106 5154 *s-- = '\0';
5107 5155 filterop = *s;
5108 5156 if (filterop == '<' || filterop == '>' || filterop == '~' ||
5109 5157 filterop == ':') {
5110 5158 *s = '\0';
5111 5159 }
5112 5160
5113 5161 if (!is_valid_attr(str)) {
5114 5162 goto free_and_return;
5115 5163 }
5116 5164
5117 5165 switch (filterop) {
5118 5166 case '<': /* LDAP_FILTER_LE */
5119 5167 case '>': /* LDAP_FILTER_GE */
5120 5168 case '~': /* LDAP_FILTER_APPROX */
5121 5169 break;
5122 5170 case ':': /* extended filter - v3 only */
5123 5171 /*
5124 5172 * extended filter looks like this:
5125 5173 *
5126 5174 * [type][':dn'][':'oid]':='value
5127 5175 *
5128 5176 * where one of type or :oid is required.
5129 5177 *
5130 5178 */
5131 5179 s2 = s3 = NULL;
5132 5180 if ((s2 = strrchr(str, ':')) == NULL) {
5133 5181 goto free_and_return;
5134 5182 }
5135 5183 if (strcasecmp(s2, ":dn") == 0) {
5136 5184 *s2 = '\0';
5137 5185 } else {
5138 5186 *s2 = '\0';
5139 5187 if ((s3 = strrchr(str, ':')) != NULL) {
5140 5188 if (strcasecmp(s3, ":dn") != 0) {
5141 5189 goto free_and_return;
5142 5190 }
5143 5191 *s3 = '\0';
5144 5192 }
5145 5193 }
5146 5194 if (unescape_filterval(value) < 0) {
5147 5195 goto free_and_return;
5148 5196 }
5149 5197 rc = 0;
5150 5198 goto free_and_return;
5151 5199 /* break; */
5152 5200 default:
5153 5201 if (find_star(value) == NULL) {
5154 5202 ftype = 0; /* LDAP_FILTER_EQUALITY */
5155 5203 } else if (strcmp(value, "*") == 0) {
5156 5204 ftype = 1; /* LDAP_FILTER_PRESENT */
5157 5205 } else {
5158 5206 rc = adj_substring_filter(value);
5159 5207 goto free_and_return;
5160 5208 }
5161 5209 break;
5162 5210 }
5163 5211
5164 5212 if (ftype != 0) { /* == LDAP_FILTER_PRESENT */
5165 5213 rc = 0;
5166 5214 } else if (unescape_filterval(value) >= 0) {
5167 5215 rc = 0;
5168 5216 }
5169 5217 if (rc != -1) {
5170 5218 rc = 0;
5171 5219 }
5172 5220
5173 5221 free_and_return:
5174 5222 free(str);
5175 5223 return (rc);
5176 5224 }
5177 5225
5178 5226
5179 5227 /*
5180 5228 * Check in place both LDAPv2 (RFC-1960) and LDAPv3 (hexadecimal) escape
5181 5229 * sequences within the null-terminated string 'val'.
5182 5230 *
5183 5231 * If 'val' contains invalid escape sequences we return -1.
5184 5232 * Otherwise return 1
5185 5233 */
5186 5234 static int
5187 5235 unescape_filterval(char *val)
5188 5236 {
5189 5237 boolean_t escape, firstdigit;
5190 5238 char *s;
5191 5239
5192 5240 firstdigit = B_FALSE;
5193 5241 escape = B_FALSE;
5194 5242 for (s = val; *s; s++) {
5195 5243 if (escape) {
5196 5244 /*
5197 5245 * first try LDAPv3 escape (hexadecimal) sequence
5198 5246 */
5199 5247 if (hexchar2int(*s) < 0) {
5200 5248 if (firstdigit) {
5201 5249 /*
5202 5250 * LDAPv2 (RFC1960) escape sequence
5203 5251 */
5204 5252 escape = B_FALSE;
5205 5253 } else {
5206 5254 return (-1);
5207 5255 }
5208 5256 }
5209 5257 if (firstdigit) {
5210 5258 firstdigit = B_FALSE;
5211 5259 } else {
5212 5260 escape = B_FALSE;
5213 5261 }
5214 5262
5215 5263 } else if (*s != '\\') {
5216 5264 escape = B_FALSE;
5217 5265
5218 5266 } else {
5219 5267 escape = B_TRUE;
5220 5268 firstdigit = B_TRUE;
5221 5269 }
5222 5270 }
5223 5271
5224 5272 return (1);
5225 5273 }
5226 5274
5227 5275
5228 5276 /*
5229 5277 * convert character 'c' that represents a hexadecimal digit to an integer.
5230 5278 * if 'c' is not a hexidecimal digit [0-9A-Fa-f], -1 is returned.
5231 5279 * otherwise the converted value is returned.
5232 5280 */
5233 5281 static int
5234 5282 hexchar2int(char c)
5235 5283 {
5236 5284 if (c >= '0' && c <= '9') {
5237 5285 return (c - '0');
5238 5286 }
5239 5287 if (c >= 'A' && c <= 'F') {
5240 5288 return (c - 'A' + 10);
5241 5289 }
5242 5290 if (c >= 'a' && c <= 'f') {
5243 5291 return (c - 'a' + 10);
5244 5292 }
5245 5293 return (-1);
5246 5294 }
5247 5295
5248 5296 static int
5249 5297 adj_substring_filter(char *val)
5250 5298 {
5251 5299 char *nextstar;
5252 5300
5253 5301 for (; val != NULL; val = nextstar) {
5254 5302 if ((nextstar = find_star(val)) != NULL) {
5255 5303 *nextstar++ = '\0';
5256 5304 }
5257 5305
5258 5306 if (*val != '\0') {
5259 5307 if (unescape_filterval(val) < 0) {
5260 5308 return (-1);
5261 5309 }
5262 5310 }
5263 5311 }
5264 5312
5265 5313 return (0);
5266 5314 }
5267 5315
5268 5316 /* ***** End of modified libldap.so.5 filter parser ***** */
5269 5317
5270 5318
5271 5319 /*
5272 5320 * Walk filter, remove redundant parentheses in-line
5273 5321 * verify that the filter is reasonable
5274 5322 */
5275 5323 static int
5276 5324 validate_filter(ns_ldap_cookie_t *cookie)
5277 5325 {
5278 5326 char *filter = cookie->filter;
5279 5327 int rc;
5280 5328
5281 5329 /* Parse filter looking for illegal values */
5282 5330
5283 5331 rc = adj_filter(filter);
5284 5332 if (rc != 0) {
5285 5333 return (NS_LDAP_OP_FAILED);
5286 5334 }
5287 5335
5288 5336 /* end of filter checking */
5289 5337
5290 5338 return (NS_LDAP_SUCCESS);
5291 5339 }
5292 5340
5293 5341 /*
5294 5342 * Set the account management request control that needs to be sent to server.
5295 5343 * This control is required to get the account management information of
5296 5344 * a user to do local account checking.
5297 5345 */
5298 5346 static int
5299 5347 setup_acctmgmt_params(ns_ldap_cookie_t *cookie)
5300 5348 {
5301 5349 LDAPControl *req, **requestctrls;
5302 5350
5303 5351 req = calloc(1, sizeof (LDAPControl));
5304 5352
5305 5353 if (req == NULL)
5306 5354 return (NS_LDAP_MEMORY);
5307 5355
5308 5356 /* fill in the fields of this new control */
5309 5357 req->ldctl_iscritical = 1;
5310 5358 req->ldctl_oid = strdup(NS_LDAP_ACCOUNT_USABLE_CONTROL);
5311 5359 if (req->ldctl_oid == NULL) {
5312 5360 free(req);
5313 5361 return (NS_LDAP_MEMORY);
5314 5362 }
5315 5363
5316 5364 requestctrls = (LDAPControl **)calloc(2, sizeof (LDAPControl *));
5317 5365 if (requestctrls == NULL) {
5318 5366 ldap_control_free(req);
5319 5367 return (NS_LDAP_MEMORY);
5320 5368 }
5321 5369
5322 5370 requestctrls[0] = req;
5323 5371
5324 5372 cookie->p_serverctrls = requestctrls;
5325 5373
5326 5374 return (NS_LDAP_SUCCESS);
5327 5375 }
5328 5376
5329 5377 /*
5330 5378 * int get_new_acct_more_info(BerElement *ber,
5331 5379 * AcctUsableResponse_t *acctResp)
5332 5380 *
5333 5381 * Decode the more_info data from an Account Management control response,
5334 5382 * when the account is not usable and when code style is from recent LDAP
5335 5383 * servers (see below comments for parse_acct_cont_resp_msg() to get more
5336 5384 * details on coding styles and ASN1 description).
5337 5385 *
5338 5386 * Expected BER encoding: {tbtbtbtiti}
5339 5387 * +t: tag is 0
5340 5388 * +b: TRUE if inactive due to account inactivation
5341 5389 * +t: tag is 1
5342 5390 * +b: TRUE if password has been reset
5343 5391 * +t: tag is 2
5344 5392 * +b: TRUE if password is expired
5345 5393 * +t: tag is 3
5346 5394 * +i: contains num of remaining grace, 0 means no grace
5347 5395 * +t: tag is 4
5348 5396 * +i: contains num of seconds before auto-unlock. -1 means acct is locked
5349 5397 * forever (i.e. until reset)
5350 5398 *
5351 5399 * Asumptions:
5352 5400 * - ber is not null
5353 5401 * - acctResp is not null and is initialized with default values for the
5354 5402 * fields in its AcctUsableResp.more_info structure
5355 5403 * - the ber stream is received in the correct order, per the ASN1 description.
5356 5404 * We do not check this order and make the asumption that it is correct.
5357 5405 * Note that the ber stream may not (and will not in most cases) contain
5358 5406 * all fields.
5359 5407 */
5360 5408 static int
5361 5409 get_new_acct_more_info(BerElement *ber, AcctUsableResponse_t *acctResp)
5362 5410 {
5363 5411 int rc = NS_LDAP_SUCCESS;
5364 5412 char errstr[MAXERROR];
5365 5413 ber_tag_t rTag = LBER_DEFAULT;
5366 5414 ber_len_t rLen = 0;
5367 5415 ber_int_t rValue;
5368 5416 char *last;
5369 5417 int berRC = 0;
5370 5418
5371 5419 /*
5372 5420 * Look at what more_info BER element is/are left to be decoded.
5373 5421 * look at each of them 1 by 1, without checking on their order
5374 5422 * and possible multi values.
5375 5423 */
5376 5424 for (rTag = ber_first_element(ber, &rLen, &last);
5377 5425 rTag != LBER_END_OF_SEQORSET;
5378 5426 rTag = ber_next_element(ber, &rLen, last)) {
5379 5427
5380 5428 berRC = 0;
5381 5429 switch (rTag) {
5382 5430 case 0 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE:
5383 5431 /* inactive */
5384 5432 berRC = ber_scanf(ber, "b", &rValue);
5385 5433 if (berRC != LBER_ERROR) {
5386 5434 (acctResp->AcctUsableResp).more_info.
5387 5435 inactive = (rValue != 0) ? 1 : 0;
5388 5436 }
5389 5437 break;
5390 5438
5391 5439 case 1 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE:
5392 5440 /* reset */
5393 5441 berRC = ber_scanf(ber, "b", &rValue);
5394 5442 if (berRC != LBER_ERROR) {
5395 5443 (acctResp->AcctUsableResp).more_info.reset
5396 5444 = (rValue != 0) ? 1 : 0;
5397 5445 }
5398 5446 break;
5399 5447
5400 5448 case 2 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE:
5401 5449 /* expired */
5402 5450 berRC = ber_scanf(ber, "b", &rValue);
5403 5451 if (berRC != LBER_ERROR) {
5404 5452 (acctResp->AcctUsableResp).more_info.expired
5405 5453 = (rValue != 0) ? 1 : 0;
5406 5454 }
5407 5455 break;
5408 5456
5409 5457 case 3 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE:
5410 5458 /* remaining grace */
5411 5459 berRC = ber_scanf(ber, "i", &rValue);
5412 5460 if (berRC != LBER_ERROR) {
5413 5461 (acctResp->AcctUsableResp).more_info.rem_grace
5414 5462 = rValue;
5415 5463 }
5416 5464 break;
5417 5465
5418 5466 case 4 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE:
5419 5467 /* seconds before unlock */
5420 5468 berRC = ber_scanf(ber, "i", &rValue);
5421 5469 if (berRC != LBER_ERROR) {
5422 5470 (acctResp->AcctUsableResp).more_info.
5423 5471 sec_b4_unlock = rValue;
5424 5472 }
5425 5473 break;
5426 5474
5427 5475 default :
5428 5476 (void) sprintf(errstr,
5429 5477 gettext("invalid reason tag 0x%x"), rTag);
5430 5478 syslog(LOG_DEBUG, "libsldap: %s", errstr);
5431 5479 rc = NS_LDAP_INTERNAL;
5432 5480 break;
5433 5481 }
5434 5482 if (berRC == LBER_ERROR) {
5435 5483 (void) sprintf(errstr,
5436 5484 gettext("error 0x%x decoding value for "
5437 5485 "tag 0x%x"), berRC, rTag);
5438 5486 syslog(LOG_DEBUG, "libsldap: %s", errstr);
5439 5487 rc = NS_LDAP_INTERNAL;
5440 5488 }
5441 5489 if (rc != NS_LDAP_SUCCESS) {
5442 5490 /* exit the for loop */
5443 5491 break;
5444 5492 }
5445 5493 }
5446 5494
5447 5495 return (rc);
5448 5496 }
5449 5497
5450 5498 /*
5451 5499 * int get_old_acct_opt_more_info(BerElement *ber,
5452 5500 * AcctUsableResponse_t *acctResp)
5453 5501 *
5454 5502 * Decode the optional more_info data from an Account Management control
5455 5503 * response, when the account is not usable and when code style is from LDAP
5456 5504 * server 5.2p4 (see below comments for parse_acct_cont_resp_msg() to get more
5457 5505 * details on coding styles and ASN1 description).
5458 5506 *
5459 5507 * Expected BER encoding: titi}
5460 5508 * +t: tag is 2
5461 5509 * +i: contains num of remaining grace, 0 means no grace
5462 5510 * +t: tag is 3
5463 5511 * +i: contains num of seconds before auto-unlock. -1 means acct is locked
5464 5512 * forever (i.e. until reset)
5465 5513 *
5466 5514 * Asumptions:
5467 5515 * - ber is a valid BER element
5468 5516 * - acctResp is initialized for the fields in its AcctUsableResp.more_info
5469 5517 * structure
5470 5518 */
5471 5519 static int
5472 5520 get_old_acct_opt_more_info(ber_tag_t tag, BerElement *ber,
5473 5521 AcctUsableResponse_t *acctResp)
5474 5522 {
5475 5523 int rc = NS_LDAP_SUCCESS;
5476 5524 char errstr[MAXERROR];
5477 5525 ber_len_t len;
5478 5526 int rem_grace, sec_b4_unlock;
5479 5527
5480 5528 switch (tag) {
5481 5529 case 2:
5482 5530 /* decode and maybe 3 is following */
5483 5531 if ((tag = ber_scanf(ber, "i", &rem_grace)) == LBER_ERROR) {
5484 5532 (void) sprintf(errstr, gettext("Can not get "
5485 5533 "rem_grace"));
5486 5534 syslog(LOG_DEBUG, "libsldap: %s", errstr);
5487 5535 rc = NS_LDAP_INTERNAL;
5488 5536 break;
5489 5537 }
5490 5538 (acctResp->AcctUsableResp).more_info.rem_grace = rem_grace;
5491 5539
5492 5540 if ((tag = ber_peek_tag(ber, &len)) == LBER_ERROR) {
5493 5541 /* this is a success case, break to exit */
5494 5542 (void) sprintf(errstr, gettext("No more "
5495 5543 "optional data"));
5496 5544 syslog(LOG_DEBUG, "libsldap: %s", errstr);
5497 5545 break;
5498 5546 }
5499 5547
5500 5548 if (tag == 3) {
5501 5549 if (ber_scanf(ber, "i", &sec_b4_unlock) == LBER_ERROR) {
5502 5550 (void) sprintf(errstr,
5503 5551 gettext("Can not get sec_b4_unlock "
5504 5552 "- 1st case"));
5505 5553 syslog(LOG_DEBUG, "libsldap: %s", errstr);
5506 5554 rc = NS_LDAP_INTERNAL;
5507 5555 break;
5508 5556 }
5509 5557 (acctResp->AcctUsableResp).more_info.sec_b4_unlock =
5510 5558 sec_b4_unlock;
5511 5559 } else { /* unknown tag */
5512 5560 (void) sprintf(errstr, gettext("Unknown tag "
5513 5561 "- 1st case"));
5514 5562 syslog(LOG_DEBUG, "libsldap: %s", errstr);
5515 5563 rc = NS_LDAP_INTERNAL;
5516 5564 break;
5517 5565 }
5518 5566 break;
5519 5567
5520 5568 case 3:
5521 5569 if (ber_scanf(ber, "i", &sec_b4_unlock) == LBER_ERROR) {
5522 5570 (void) sprintf(errstr, gettext("Can not get "
5523 5571 "sec_b4_unlock - 2nd case"));
5524 5572 syslog(LOG_DEBUG, "libsldap: %s", errstr);
5525 5573 rc = NS_LDAP_INTERNAL;
5526 5574 break;
5527 5575 }
5528 5576 (acctResp->AcctUsableResp).more_info.sec_b4_unlock =
5529 5577 sec_b4_unlock;
5530 5578 break;
5531 5579
5532 5580 default: /* unknown tag */
5533 5581 (void) sprintf(errstr, gettext("Unknown tag - 2nd case"));
5534 5582 syslog(LOG_DEBUG, "libsldap: %s", errstr);
5535 5583 rc = NS_LDAP_INTERNAL;
5536 5584 break;
5537 5585 }
5538 5586
5539 5587 return (rc);
5540 5588 }
5541 5589
5542 5590 /*
5543 5591 * **** This function needs to be moved to libldap library ****
5544 5592 * parse_acct_cont_resp_msg() parses the message received by server according to
5545 5593 * following format (ASN1 notation):
5546 5594 *
5547 5595 * ACCOUNT_USABLE_RESPONSE::= CHOICE {
5548 5596 * is_available [0] INTEGER,
5549 5597 * ** seconds before expiration **
5550 5598 * is_not_available [1] more_info
5551 5599 * }
5552 5600 * more_info::= SEQUENCE {
5553 5601 * inactive [0] BOOLEAN DEFAULT FALSE,
5554 5602 * reset [1] BOOLEAN DEFAULT FALSE,
5555 5603 * expired [2] BOOLEAN DEFAULT FALSE,
5556 5604 * remaining_grace [3] INTEGER OPTIONAL,
5557 5605 * seconds_before_unlock [4] INTEGER OPTIONAL
5558 5606 * }
5559 5607 */
5560 5608 /*
5561 5609 * #define used to make the difference between coding style as done
5562 5610 * by LDAP server 5.2p4 and newer LDAP servers. There are 4 values:
5563 5611 * - DS52p4_USABLE: 5.2p4 coding style, account is usable
5564 5612 * - DS52p4_NOT_USABLE: 5.2p4 coding style, account is not usable
5565 5613 * - NEW_USABLE: newer LDAP servers coding style, account is usable
5566 5614 * - NEW_NOT_USABLE: newer LDAP servers coding style, account is not usable
5567 5615 *
5568 5616 * An account would be considered not usable if for instance:
5569 5617 * - it's been made inactive in the LDAP server
5570 5618 * - or its password was reset in the LDAP server database
5571 5619 * - or its password expired
5572 5620 * - or the account has been locked, possibly forever
5573 5621 */
5574 5622 #define DS52p4_USABLE 0x00
5575 5623 #define DS52p4_NOT_USABLE 0x01
5576 5624 #define NEW_USABLE 0x00 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE
5577 5625 #define NEW_NOT_USABLE 0x01 | LBER_CLASS_CONTEXT | LBER_CONSTRUCTED
5578 5626 static int
5579 5627 parse_acct_cont_resp_msg(LDAPControl **ectrls, AcctUsableResponse_t *acctResp)
5580 5628 {
5581 5629 int rc = NS_LDAP_SUCCESS;
5582 5630 BerElement *ber;
5583 5631 ber_tag_t tag;
5584 5632 ber_len_t len;
5585 5633 int i;
5586 5634 char errstr[MAXERROR];
5587 5635 /* used for any coding style when account is usable */
5588 5636 int seconds_before_expiry;
5589 5637 /* used for 5.2p4 coding style when account is not usable */
5590 5638 int inactive, reset, expired;
5591 5639
5592 5640 if (ectrls == NULL) {
5593 5641 (void) sprintf(errstr, gettext("Invalid ectrls parameter"));
5594 5642 syslog(LOG_DEBUG, "libsldap: %s", errstr);
5595 5643 return (NS_LDAP_INVALID_PARAM);
5596 5644 }
5597 5645
5598 5646 for (i = 0; ectrls[i] != NULL; i++) {
5599 5647 if (strcmp(ectrls[i]->ldctl_oid, NS_LDAP_ACCOUNT_USABLE_CONTROL)
5600 5648 == 0) {
5601 5649 break;
5602 5650 }
5603 5651 }
5604 5652
5605 5653 if (ectrls[i] == NULL) {
5606 5654 /* Ldap control is not found */
5607 5655 (void) sprintf(errstr, gettext("Account Usable Control "
5608 5656 "not found"));
5609 5657 syslog(LOG_DEBUG, "libsldap: %s", errstr);
5610 5658 return (NS_LDAP_NOTFOUND);
5611 5659 }
5612 5660
5613 5661 /* Allocate a BER element from the control value and parse it. */
5614 5662 if ((ber = ber_init(&ectrls[i]->ldctl_value)) == NULL)
5615 5663 return (NS_LDAP_MEMORY);
5616 5664
5617 5665 if ((tag = ber_peek_tag(ber, &len)) == LBER_ERROR) {
5618 5666 /* Ldap decoding error */
5619 5667 (void) sprintf(errstr, gettext("Error decoding 1st tag"));
5620 5668 syslog(LOG_DEBUG, "libsldap: %s", errstr);
5621 5669 ber_free(ber, 1);
5622 5670 return (NS_LDAP_INTERNAL);
5623 5671 }
5624 5672
5625 5673 switch (tag) {
5626 5674 case DS52p4_USABLE:
5627 5675 case NEW_USABLE:
5628 5676 acctResp->choice = 0;
5629 5677 if (ber_scanf(ber, "i", &seconds_before_expiry)
5630 5678 == LBER_ERROR) {
5631 5679 /* Ldap decoding error */
5632 5680 (void) sprintf(errstr, gettext("Can not get "
5633 5681 "seconds_before_expiry"));
5634 5682 syslog(LOG_DEBUG, "libsldap: %s", errstr);
5635 5683 rc = NS_LDAP_INTERNAL;
5636 5684 break;
5637 5685 }
5638 5686 /* ber_scanf() succeeded */
5639 5687 (acctResp->AcctUsableResp).seconds_before_expiry =
5640 5688 seconds_before_expiry;
5641 5689 break;
5642 5690
5643 5691 case DS52p4_NOT_USABLE:
5644 5692 acctResp->choice = 1;
5645 5693 if (ber_scanf(ber, "{bbb", &inactive, &reset, &expired)
5646 5694 == LBER_ERROR) {
5647 5695 /* Ldap decoding error */
5648 5696 (void) sprintf(errstr, gettext("Can not get "
5649 5697 "inactive/reset/expired"));
5650 5698 syslog(LOG_DEBUG, "libsldap: %s", errstr);
5651 5699 rc = NS_LDAP_INTERNAL;
5652 5700 break;
5653 5701 }
5654 5702 /* ber_scanf() succeeded */
5655 5703 (acctResp->AcctUsableResp).more_info.inactive =
5656 5704 ((inactive == 0) ? 0 : 1);
5657 5705 (acctResp->AcctUsableResp).more_info.reset =
5658 5706 ((reset == 0) ? 0 : 1);
5659 5707 (acctResp->AcctUsableResp).more_info.expired =
5660 5708 ((expired == 0) ? 0 : 1);
5661 5709 (acctResp->AcctUsableResp).more_info.rem_grace = 0;
5662 5710 (acctResp->AcctUsableResp).more_info.sec_b4_unlock = 0;
5663 5711
5664 5712 if ((tag = ber_peek_tag(ber, &len)) == LBER_ERROR) {
5665 5713 /* this is a success case, break to exit */
5666 5714 (void) sprintf(errstr, gettext("No optional data"));
5667 5715 syslog(LOG_DEBUG, "libsldap: %s", errstr);
5668 5716 break;
5669 5717 }
5670 5718
5671 5719 /*
5672 5720 * Look at what optional more_info BER element is/are
5673 5721 * left to be decoded.
5674 5722 */
5675 5723 rc = get_old_acct_opt_more_info(tag, ber, acctResp);
5676 5724 break;
5677 5725
5678 5726 case NEW_NOT_USABLE:
5679 5727 acctResp->choice = 1;
5680 5728 /*
5681 5729 * Recent LDAP servers won't code more_info data for default
5682 5730 * values (see above comments on ASN1 description for what
5683 5731 * fields have default values & what fields are optional).
5684 5732 */
5685 5733 (acctResp->AcctUsableResp).more_info.inactive = 0;
5686 5734 (acctResp->AcctUsableResp).more_info.reset = 0;
5687 5735 (acctResp->AcctUsableResp).more_info.expired = 0;
5688 5736 (acctResp->AcctUsableResp).more_info.rem_grace = 0;
5689 5737 (acctResp->AcctUsableResp).more_info.sec_b4_unlock = 0;
5690 5738
5691 5739 if (len == 0) {
5692 5740 /*
5693 5741 * Nothing else to decode; this is valid and we
5694 5742 * use default values set above.
5695 5743 */
5696 5744 (void) sprintf(errstr, gettext("more_info is "
5697 5745 "empty, using default values"));
5698 5746 syslog(LOG_DEBUG, "libsldap: %s", errstr);
5699 5747 break;
5700 5748 }
5701 5749
5702 5750 /*
5703 5751 * Look at what more_info BER element is/are left to
5704 5752 * be decoded.
5705 5753 */
5706 5754 rc = get_new_acct_more_info(ber, acctResp);
5707 5755 break;
5708 5756
5709 5757 default:
5710 5758 (void) sprintf(errstr, gettext("unknwon coding style "
5711 5759 "(tag: 0x%x)"), tag);
5712 5760 syslog(LOG_DEBUG, "libsldap: %s", errstr);
5713 5761 rc = NS_LDAP_INTERNAL;
5714 5762 break;
5715 5763 }
5716 5764
5717 5765 ber_free(ber, 1);
5718 5766 return (rc);
5719 5767 }
5720 5768
5721 5769 /*
5722 5770 * internal function for __ns_ldap_getAcctMgmt()
5723 5771 */
5724 5772 static int
5725 5773 getAcctMgmt(const char *user, AcctUsableResponse_t *acctResp,
5726 5774 ns_conn_user_t *conn_user)
5727 5775 {
5728 5776 int scope, rc;
5729 5777 ns_ldap_cookie_t *cookie;
5730 5778 ns_ldap_search_desc_t **sdlist = NULL;
5731 5779 ns_ldap_search_desc_t *dptr;
5732 5780 ns_ldap_error_t *error = NULL;
5733 5781 char **dns = NULL;
5734 5782 char service[] = "shadow";
5735 5783
5736 5784 if (user == NULL || acctResp == NULL)
5737 5785 return (NS_LDAP_INVALID_PARAM);
5738 5786
5739 5787 /* Initialize State machine cookie */
5740 5788 cookie = init_search_state_machine();
5741 5789 if (cookie == NULL)
5742 5790 return (NS_LDAP_MEMORY);
5743 5791 cookie->conn_user = conn_user;
5744 5792
5745 5793 /* see if need to follow referrals */
5746 5794 rc = __s_api_toFollowReferrals(0,
5747 5795 &cookie->followRef, &error);
5748 5796 if (rc != NS_LDAP_SUCCESS) {
5749 5797 (void) __ns_ldap_freeError(&error);
5750 5798 goto out;
5751 5799 }
5752 5800
5753 5801 /* get the service descriptor - or create a default one */
5754 5802 rc = __s_api_get_SSD_from_SSDtoUse_service(service,
5755 5803 &sdlist, &error);
5756 5804 if (rc != NS_LDAP_SUCCESS) {
5757 5805 (void) __ns_ldap_freeError(&error);
5758 5806 goto out;
5759 5807 }
5760 5808
5761 5809 if (sdlist == NULL) {
5762 5810 /* Create default service Desc */
5763 5811 sdlist = (ns_ldap_search_desc_t **)calloc(2,
5764 5812 sizeof (ns_ldap_search_desc_t *));
5765 5813 if (sdlist == NULL) {
5766 5814 rc = NS_LDAP_MEMORY;
5767 5815 goto out;
5768 5816 }
5769 5817 dptr = (ns_ldap_search_desc_t *)
5770 5818 calloc(1, sizeof (ns_ldap_search_desc_t));
5771 5819 if (dptr == NULL) {
5772 5820 free(sdlist);
5773 5821 rc = NS_LDAP_MEMORY;
5774 5822 goto out;
5775 5823 }
5776 5824 sdlist[0] = dptr;
5777 5825
5778 5826 /* default base */
5779 5827 rc = __s_api_getDNs(&dns, service, &cookie->errorp);
5780 5828 if (rc != NS_LDAP_SUCCESS) {
5781 5829 if (dns) {
5782 5830 __s_api_free2dArray(dns);
5783 5831 dns = NULL;
5784 5832 }
5785 5833 (void) __ns_ldap_freeError(&(cookie->errorp));
5786 5834 cookie->errorp = NULL;
5787 5835 goto out;
5788 5836 }
5789 5837 dptr->basedn = strdup(dns[0]);
5790 5838 if (dptr->basedn == NULL) {
5791 5839 free(sdlist);
5792 5840 free(dptr);
5793 5841 if (dns) {
5794 5842 __s_api_free2dArray(dns);
5795 5843 dns = NULL;
5796 5844 }
5797 5845 rc = NS_LDAP_MEMORY;
5798 5846 goto out;
5799 5847 }
5800 5848 __s_api_free2dArray(dns);
5801 5849 dns = NULL;
5802 5850
5803 5851 /* default scope */
5804 5852 scope = 0;
5805 5853 rc = __s_api_getSearchScope(&scope, &cookie->errorp);
5806 5854 dptr->scope = scope;
5807 5855 }
5808 5856
5809 5857 cookie->sdlist = sdlist;
5810 5858
5811 5859 cookie->service = strdup(service);
5812 5860 if (cookie->service == NULL) {
5813 5861 rc = NS_LDAP_MEMORY;
5814 5862 goto out;
5815 5863 }
5816 5864
5817 5865 /* search for entries for this particular uid */
5818 5866 (void) asprintf(&cookie->i_filter, "(uid=%s)", user);
5819 5867 if (cookie->i_filter == NULL) {
5820 5868 rc = NS_LDAP_MEMORY;
5821 5869 goto out;
5822 5870 }
5823 5871
5824 5872 /* create the control request */
5825 5873 if ((rc = setup_acctmgmt_params(cookie)) != NS_LDAP_SUCCESS)
5826 5874 goto out;
5827 5875
5828 5876 /* Process search */
5829 5877 rc = search_state_machine(cookie, GET_ACCT_MGMT_INFO, 0);
5830 5878
5831 5879 /* Copy results back to user */
5832 5880 rc = cookie->err_rc;
5833 5881 if (rc != NS_LDAP_SUCCESS)
5834 5882 (void) __ns_ldap_freeError(&(cookie->errorp));
5835 5883
5836 5884 if (cookie->result == NULL)
5837 5885 goto out;
5838 5886
5839 5887 if ((rc = parse_acct_cont_resp_msg(cookie->resultctrl, acctResp))
5840 5888 != NS_LDAP_SUCCESS)
5841 5889 goto out;
5842 5890
5843 5891 rc = NS_LDAP_SUCCESS;
5844 5892
5845 5893 out:
5846 5894 delete_search_cookie(cookie);
5847 5895
5848 5896 return (rc);
5849 5897 }
5850 5898
5851 5899 /*
5852 5900 * __ns_ldap_getAcctMgmt() is called from pam account management stack
5853 5901 * for retrieving accounting information of users with no user password -
5854 5902 * eg. rlogin, rsh, etc. This function uses the account management control
5855 5903 * request to do a search on the server for the user in question. The
5856 5904 * response control returned from the server is got from the cookie.
5857 5905 * Input params: username of whose account mgmt information is to be got
5858 5906 * pointer to hold the parsed account management information
5859 5907 * Return values: NS_LDAP_SUCCESS on success or appropriate error
5860 5908 * code on failure
5861 5909 */
5862 5910 int
5863 5911 __ns_ldap_getAcctMgmt(const char *user, AcctUsableResponse_t *acctResp)
5864 5912 {
5865 5913 ns_conn_user_t *cu = NULL;
5866 5914 int try_cnt = 0;
5867 5915 int rc = NS_LDAP_SUCCESS;
5868 5916 ns_ldap_error_t *error = NULL;
5869 5917
5870 5918 for (;;) {
5871 5919 if (__s_api_setup_retry_search(&cu, NS_CONN_USER_SEARCH,
5872 5920 &try_cnt, &rc, &error) == 0)
5873 5921 break;
5874 5922 rc = getAcctMgmt(user, acctResp, cu);
5875 5923 }
5876 5924 return (rc);
5877 5925 }
↓ open down ↓ |
1559 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX