1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 #include <stdio.h> 27 #include <sys/types.h> 28 #include <stdlib.h> 29 #include <libintl.h> 30 31 #include <sys/stat.h> 32 #include <fcntl.h> 33 #include <unistd.h> 34 #include <string.h> 35 #include <strings.h> 36 #include <lber.h> 37 #include <ldap.h> 38 #include <syslog.h> 39 #include <stddef.h> 40 #include <sys/mman.h> 41 42 #include "ns_sldap.h" 43 #include "ns_internal.h" 44 #include "ns_connmgmt.h" 45 #include "ns_cache_door.h" 46 47 /* Additional headers for addTypedEntry Conversion routines */ 48 #include <pwd.h> 49 #include <project.h> 50 #include <shadow.h> 51 #include <grp.h> 52 #include <netinet/in.h> 53 #include <arpa/inet.h> 54 #include <netdb.h> 55 #include <rpc/rpcent.h> 56 #include <auth_attr.h> 57 #include <exec_attr.h> 58 #include <prof_attr.h> 59 #include <user_attr.h> 60 #include <bsm/libbsm.h> 61 #include <sys/tsol/tndb.h> 62 #include <tsol/label.h> 63 64 static int send_to_cachemgr(const char *, 65 ns_ldap_attr_t **, ns_ldap_error_t **); 66 67 static int escape_str(char *, char *); 68 69 /* 70 * If the rdn is a mapped attr: 71 * return NS_LDAP_SUCCESS and a new_dn. 72 * If no mapped attr is found in the rdn: 73 * return NS_LDAP_SUCCESS and *new_dn == NULL 74 * For example: 75 * service = abc 76 * dn = cn=foo,dc=bar,dc=com 77 * attributeMapping: abc:cn=sn 78 * Then: 79 * new_dn = sn=foo,dc=bar,dc=com 80 * 81 */ 82 static int 83 replace_mapped_attr_in_dn( 84 const char *service, const char *dn, char **new_dn) 85 { 86 char **mappedattr; 87 char **dnArray = NULL; 88 char *rservice; 89 char *cur = NULL; 90 int len = 0, orig_len = 0, mapped_len = 0; 91 int dn_len = 0; 92 93 *new_dn = NULL; 94 95 /* 96 * separate dn into individual componets 97 * e.g. 98 * "automountKey=user_01" , "automountMapName_test=auto_home", ... 99 */ 100 dnArray = ldap_explode_dn(dn, 0); 101 if (!dnArray || !*dnArray) 102 return (NS_LDAP_INVALID_PARAM); 103 104 cur = strchr(dnArray[0], '='); 105 if (!cur) { 106 __s_api_free2dArray(dnArray); 107 return (NS_LDAP_INVALID_PARAM); 108 } 109 *cur = '\0'; 110 111 /* we only check schema mapping for automount, not for auto_* */ 112 if (strncasecmp(service, NS_LDAP_TYPE_AUTOMOUNT, 113 sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0) 114 rservice = "automount"; 115 else 116 rservice = (char *)service; 117 118 mappedattr = __ns_ldap_getMappedAttributes(rservice, dnArray[0]); 119 if (!mappedattr || !mappedattr[0]) { 120 __s_api_free2dArray(dnArray); 121 if (mappedattr) 122 __s_api_free2dArray(mappedattr); 123 return (NS_LDAP_SUCCESS); 124 } 125 orig_len = strlen(dnArray[0]); 126 127 /* 128 * The new length is *dn length + (difference between 129 * orig attr and mapped attr) + 1 ; 130 * e.g. 131 * automountKey=aa,automountMapName=auto_home,dc=foo,dc=com 132 * ==> 133 * cn=aa,automountMapName=auto_home,dc=foo,dc=com 134 */ 135 mapped_len = strlen(mappedattr[0]); 136 dn_len = strlen(dn); 137 len = dn_len - orig_len + mapped_len + 1; 138 *new_dn = (char *)calloc(1, len); 139 if (*new_dn == NULL) { 140 __s_api_free2dArray(dnArray); 141 __s_api_free2dArray(mappedattr); 142 return (NS_LDAP_MEMORY); 143 } 144 145 (void) snprintf(*new_dn, len, "%s=%s", mappedattr[0], dn + orig_len +1); 146 __s_api_free2dArray(dnArray); 147 __s_api_free2dArray(mappedattr); 148 149 return (NS_LDAP_SUCCESS); 150 } 151 152 153 /* 154 * The following function is only used by the 155 * "gecos" 1 to N attribute mapping code. It expects 156 * and handle only one data/length pair. 157 */ 158 static int 159 init_bval_mod( 160 LDAPMod *mod, 161 int mop, 162 char *mtype, 163 char *mvptr, 164 int mvlen) 165 { 166 167 struct berval **bmodval; 168 169 /* dup attribute name */ 170 mod->mod_type = strdup(mtype); 171 if (mod->mod_type == NULL) 172 return (-1); 173 174 /* 175 * assume single value, 176 * since only one value/length pair passed in 177 */ 178 bmodval = (struct berval **)calloc(2, sizeof (struct berval *)); 179 if (bmodval == NULL) { 180 free(mod->mod_type); 181 mod->mod_type = NULL; 182 return (-1); 183 } 184 bmodval[0] = (struct berval *)calloc(1, sizeof (struct berval)); 185 if (bmodval[0] == NULL) { 186 free(mod->mod_type); 187 mod->mod_type = NULL; 188 free(bmodval); 189 return (-1); 190 } 191 192 /* set pointer to data */ 193 bmodval[0]->bv_val = mvptr; 194 195 /* set length */ 196 bmodval[0]->bv_len = mvlen; 197 198 /* 199 * turn on the BVALUE bit to indicate 200 * that the length of data is supplied 201 */ 202 mod->mod_op = mop | LDAP_MOD_BVALUES; 203 204 mod->mod_bvalues = bmodval; 205 206 return (0); 207 } 208 209 static void 210 freeModList(LDAPMod **mods) 211 { 212 int i, j; 213 int name_is_oc; 214 215 if (mods == NULL) 216 return; 217 218 for (i = 0; mods[i]; i++) { 219 220 /* free attribute name */ 221 name_is_oc = FALSE; 222 if (mods[i]->mod_type) { 223 if (strcasecmp(mods[i]->mod_type, "objectclass") == 0) 224 name_is_oc = TRUE; 225 free(mods[i]->mod_type); 226 } 227 228 if (mods[i]->mod_bvalues == NULL) 229 continue; 230 /* 231 * LDAP_MOD_BVALUES is only set by 232 * the "gecos" 1 to N attribute mapping 233 * code, and the attribute is single valued. 234 */ 235 if (mods[i]->mod_op & LDAP_MOD_BVALUES) { 236 if (mods[i]->mod_bvalues[0]) 237 free(mods[i]->mod_bvalues[0]); 238 } else { 239 if (name_is_oc) { 240 /* 241 * only values for the "objectclass" 242 * were dupped using strdup. 243 * other attribute values were 244 * not dupped, but via pointer 245 * assignment. So here the 246 * values for "objectclass" 247 * is freed one by one, 248 * but the values for other 249 * attributes need not be freed. 250 */ 251 for (j = 0; mods[i]->mod_values[j]; j++) 252 free(mods[i]->mod_values[j]); 253 } 254 255 } 256 free(mods[i]->mod_bvalues); 257 } 258 259 /* modlist */ 260 free((char *)(mods[0])); 261 free(mods); 262 } 263 264 static LDAPMod ** 265 __s_api_makeModListCount( 266 const char *service, 267 const ns_ldap_attr_t * const *attr, 268 const int mod_op, 269 const int count, 270 const int flags) 271 { 272 LDAPMod **mods, *modlist; 273 char **modval; 274 char **mapping; 275 int i; 276 int j; 277 int k, rc, vlen; 278 char *c, *comma1 = NULL, *comma2 = NULL; 279 int schema_mapping_existed = FALSE; 280 int auto_service = FALSE; 281 282 283 /* 284 * add 2 for "gecos" 1 to up to 3 attribute mapping 285 */ 286 mods = (LDAPMod **)calloc((count + 3), sizeof (LDAPMod *)); 287 if (mods == NULL) { 288 return (NULL); 289 } 290 /* 291 * add 2 for "gecos" 1 to up to 3 attribute mapping 292 */ 293 modlist = (LDAPMod *)calloc(count + 2, sizeof (LDAPMod)); 294 if (modlist == NULL) { 295 free(mods); 296 return (NULL); 297 } 298 299 if (service != NULL && strncasecmp(service, NS_LDAP_TYPE_AUTOMOUNT, 300 sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0) 301 auto_service = TRUE; 302 303 /* 304 * see if schema mapping existed for the given service 305 */ 306 mapping = __ns_ldap_getOrigAttribute(service, 307 NS_HASH_SCHEMA_MAPPING_EXISTED); 308 if (mapping) { 309 schema_mapping_existed = TRUE; 310 __s_api_free2dArray(mapping); 311 mapping = NULL; 312 } 313 314 for (i = 0, k = 0; k < count && attr[k] != NULL; i++, k++) { 315 mods[i] = &modlist[i]; 316 mods[i]->mod_op = mod_op; 317 /* 318 * Perform attribute mapping if necessary. 319 */ 320 if (schema_mapping_existed && (flags & NS_LDAP_NOMAP) == 0) { 321 mapping = __ns_ldap_getMappedAttributes(service, 322 attr[k]->attrname); 323 } else 324 mapping = NULL; 325 326 if (mapping == NULL && auto_service && 327 (flags & NS_LDAP_NOMAP) == 0) { 328 /* 329 * if service == auto_xxx and 330 * no mapped attribute is found 331 * and NS_LDAP_NOMAP is not set 332 * then try automount's mapped attribute 333 */ 334 mapping = __ns_ldap_getMappedAttributes("automount", 335 attr[k]->attrname); 336 } 337 338 if (mapping == NULL) { 339 mods[i]->mod_type = strdup(attr[k]->attrname); 340 if (mods[i]->mod_type == NULL) 341 goto free_memory; 342 } else { 343 /* 344 * 1 to N attribute mapping is only done for "gecos", 345 * and only 1 to 3 mapping. 346 * nine cases here: 347 * 348 * A. attrMap=passwd:gecos=a 349 * 1. gecos="xx,yy,zz" -> a="xx,yy,zz" 350 * 2. gecos="xx,yy" -> a="xx,yy" 351 * 3. gecos="xx" -> a="xx" 352 * 353 * B. attrMap=passwd:gecos=a b 354 * 4. gecos="xx,yy,zz" -> a="xx" b="yy,zz" 355 * 5. gecos="xx,yy" -> a="xx" b="yy" 356 * 6. gecos="xx" -> a="xx" 357 * 358 * C. attrMap=passwd:gecos=a b c 359 * 7. gecos="xx,yy,zz" -> a="xx" b="yy" c="zz" 360 * 8. gecos="xx,yy" -> a="xx" b="yy" 361 * 9. gecos="xx" -> a="xx" 362 * 363 * This can be grouped as: 364 * 365 * c1 cases: 1,2,3,6,9 366 * if ((attrMap=passwd:gecos=a) || 367 * (no "," in gecos value)) 368 * same as other no-mapping attributes, 369 * no special processing needed 370 * else 371 * 372 * c2 cases: 4,5,8 373 * if ((attrMap=passwd:gecos=a b) || 374 * (only one "," in gecos value)) 375 * a=xx b=yy[,...] 376 * else 377 * 378 * c3 case: 7 379 * a=xx b=yy c=... 380 * 381 * notes: in case c2 and c3, ... could still contain "," 382 */ 383 if (strcasecmp(service, "passwd") == 0 && 384 strcasecmp(attr[k]->attrname, "gecos") == 0 && 385 mapping[1] && attr[k]->attrvalue[0] && 386 (comma1 = strchr(attr[k]->attrvalue[0], 387 COMMATOK)) != NULL) { 388 389 /* is there a second comma? */ 390 if (*(comma1 + 1) != '\0') 391 comma2 = strchr(comma1 + 1, COMMATOK); 392 393 /* 394 * Process case c2 or c3. 395 * case c2: mapped to two attributes or just 396 * one comma 397 */ 398 if (mapping[2] == NULL || comma2 == NULL) { 399 /* case c2 */ 400 401 /* 402 * int mod structure for the first attribute 403 */ 404 vlen = comma1 - attr[k]->attrvalue[0]; 405 c = attr[k]->attrvalue[0]; 406 407 if (vlen > 0 && c) { 408 rc = init_bval_mod(mods[i], mod_op, 409 mapping[0], c, vlen); 410 if (rc != 0) 411 goto free_memory; 412 } else { 413 /* don't leave a hole in mods array */ 414 mods[i] = NULL; 415 i--; 416 } 417 418 419 /* 420 * init mod structure for the 2nd attribute 421 */ 422 if (*(comma1 + 1) == '\0') { 423 __s_api_free2dArray(mapping); 424 mapping = NULL; 425 continue; 426 } 427 428 i++; 429 mods[i] = &modlist[i]; 430 431 /* 432 * get pointer to data. 433 * Skip leading spaces. 434 */ 435 for (c = comma1 + 1; *c == SPACETOK; c++) { 436 /* empty */ 437 } 438 439 /* get data length */ 440 vlen = strlen(attr[k]->attrvalue[0]) - 441 (c - attr[k]->attrvalue[0]); 442 443 if (vlen > 0 && c) { 444 rc = init_bval_mod(mods[i], mod_op, 445 mapping[1], c, vlen); 446 if (rc != 0) 447 goto free_memory; 448 } else { 449 /* don't leave a hole in mods array */ 450 mods[i] = NULL; 451 i--; 452 } 453 454 /* done with the mapping array */ 455 __s_api_free2dArray(mapping); 456 mapping = NULL; 457 458 continue; 459 } else { 460 /* case c3 */ 461 462 /* 463 * int mod structure for the first attribute 464 */ 465 vlen = comma1 - attr[k]->attrvalue[0]; 466 c = attr[k]->attrvalue[0]; 467 468 if (vlen > 0 && c) { 469 rc = init_bval_mod(mods[i], mod_op, 470 mapping[0], c, vlen); 471 if (rc != 0) 472 goto free_memory; 473 } else { 474 /* don't leave a hole in mods array */ 475 mods[i] = NULL; 476 i--; 477 } 478 479 /* 480 * init mod structure for the 2nd attribute 481 */ 482 i++; 483 mods[i] = &modlist[i]; 484 485 /* 486 * get pointer to data. 487 * Skip leading spaces. 488 */ 489 for (c = comma1 + 1; *c == SPACETOK; c++) { 490 /* empty */ 491 }; 492 493 /* get data length */ 494 vlen = comma2 - c; 495 496 if (vlen > 0 && c) { 497 rc = init_bval_mod(mods[i], mod_op, 498 mapping[1], c, vlen); 499 if (rc != 0) 500 goto free_memory; 501 } else { 502 /* don't leave a hole in mods array */ 503 mods[i] = NULL; 504 i--; 505 } 506 507 /* 508 * init mod structure for the 3rd attribute 509 */ 510 if (*(comma2 + 1) == '\0') { 511 __s_api_free2dArray(mapping); 512 mapping = NULL; 513 continue; 514 } 515 516 i++; 517 mods[i] = &modlist[i]; 518 /* 519 * get pointer to data. 520 * Skip leading spaces. 521 */ 522 for (c = comma2 + 1; *c == SPACETOK; c++) { 523 /* empty */ 524 } 525 526 /* get data length */ 527 vlen = strlen(attr[k]->attrvalue[0]) - 528 (c - attr[k]->attrvalue[0]); 529 530 if (vlen > 0 && c) { 531 rc = init_bval_mod(mods[i], mod_op, 532 mapping[2], c, vlen); 533 if (rc != 0) 534 goto free_memory; 535 } else { 536 /* don't leave a hole in mods array */ 537 mods[i] = NULL; 538 i--; 539 } 540 541 /* done with the mapping array */ 542 __s_api_free2dArray(mapping); 543 mapping = NULL; 544 545 continue; 546 } 547 } 548 549 /* case c1 */ 550 mods[i]->mod_type = strdup(mapping[0]); 551 if (mods[i]->mod_type == NULL) { 552 goto free_memory; 553 } 554 __s_api_free2dArray(mapping); 555 mapping = NULL; 556 } 557 558 modval = (char **)calloc(attr[k]->value_count+1, 559 sizeof (char *)); 560 if (modval == NULL) 561 goto free_memory; 562 /* 563 * Perform objectclass mapping. 564 * Note that the values for the "objectclass" attribute 565 * will be dupped using strdup. Values for other 566 * attributes will be referenced via pointer 567 * assignments. 568 */ 569 if (strcasecmp(mods[i]->mod_type, "objectclass") == 0) { 570 for (j = 0; j < attr[k]->value_count; j++) { 571 if (schema_mapping_existed && 572 (flags & NS_LDAP_NOMAP) == 0) 573 mapping = 574 __ns_ldap_getMappedObjectClass( 575 service, attr[k]->attrvalue[j]); 576 else 577 mapping = NULL; 578 579 if (mapping == NULL && auto_service && 580 (flags & NS_LDAP_NOMAP) == 0) 581 /* 582 * if service == auto_xxx and 583 * no mapped objectclass is found 584 * then try automount 585 */ 586 mapping = 587 __ns_ldap_getMappedObjectClass( 588 "automount", attr[k]->attrvalue[j]); 589 590 if (mapping && mapping[0]) { 591 /* assume single mapping */ 592 modval[j] = strdup(mapping[0]); 593 } else { 594 modval[j] = strdup(attr[k]-> 595 attrvalue[j]); 596 } 597 if (modval[j] == NULL) 598 goto free_memory; 599 } 600 } else { 601 for (j = 0; j < attr[k]->value_count; j++) { 602 /* ASSIGN NOT COPY */ 603 modval[j] = attr[k]->attrvalue[j]; 604 } 605 } 606 mods[i]->mod_values = modval; 607 } 608 609 return (mods); 610 611 free_memory: 612 freeModList(mods); 613 if (mapping) 614 __s_api_free2dArray(mapping); 615 616 return (NULL); 617 618 } 619 620 static LDAPMod ** 621 __s_api_makeModList( 622 const char *service, 623 const ns_ldap_attr_t * const *attr, 624 const int mod_op, 625 const int flags) 626 { 627 ns_ldap_attr_t **aptr = (ns_ldap_attr_t **)attr; 628 int count = 0; 629 630 if (aptr == NULL) 631 return (NULL); 632 633 /* count number of attributes */ 634 while (*aptr++) 635 count++; 636 637 return (__s_api_makeModListCount(service, attr, mod_op, count, flags)); 638 } 639 640 static void 641 __s_cvt_freeEntryRdn(ns_ldap_entry_t **entry, char **rdn) 642 { 643 if (*entry != NULL) { 644 __ns_ldap_freeEntry(*entry); 645 *entry = NULL; 646 } 647 if (*rdn != NULL) { 648 free(*rdn); 649 *rdn = NULL; 650 } 651 } 652 653 /* 654 * This state machine performs one or more LDAP add/delete/modify 655 * operations to configured LDAP servers. 656 */ 657 static int 658 write_state_machine( 659 int ldap_op, 660 char *dn, 661 LDAPMod **mods, 662 const ns_cred_t *cred, 663 const int flags, 664 ns_ldap_error_t ** errorp) 665 { 666 ConnectionID connectionId = -1; 667 Connection *conp = NULL; 668 LDAPMessage *res; 669 char *target_dn = NULL; 670 char errstr[MAXERROR]; 671 int rc = NS_LDAP_SUCCESS; 672 int return_rc = NS_LDAP_SUCCESS; 673 int followRef = FALSE; 674 int target_dn_allocated = FALSE; 675 int len; 676 int msgid; 677 int Errno; 678 boolean_t from_get_lderrno = B_FALSE; 679 int always = 1; 680 char *err, *errmsg = NULL; 681 /* referrals returned by the LDAP operation */ 682 char **referrals = NULL; 683 /* 684 * list of referrals used by the state machine, built from 685 * the referrals variable above 686 */ 687 ns_referral_info_t *ref_list = NULL; 688 /* current referral */ 689 ns_referral_info_t *current_ref = NULL; 690 ns_write_state_t state = W_INIT, new_state, err_state = W_INIT; 691 int do_not_fail_if_new_pwd_reqd = 0; 692 ns_ldap_passwd_status_t pwd_status = NS_PASSWD_GOOD; 693 int passwd_mgmt = 0; 694 int i = 0; 695 int ldap_error; 696 int nopasswd_acct_mgmt = 0; 697 ns_conn_user_t *conn_user = NULL; 698 699 while (always) { 700 switch (state) { 701 case W_EXIT: 702 /* return the MT connection and free the conn user */ 703 if (conn_user != NULL) { 704 if (conn_user->use_mt_conn == B_TRUE) { 705 if (conn_user->ns_error != NULL) { 706 *errorp = conn_user->ns_error; 707 conn_user->ns_error = NULL; 708 return_rc = conn_user->ns_rc; 709 } 710 if (conn_user->conn_mt != NULL) 711 __s_api_conn_mt_return( 712 conn_user); 713 } 714 __s_api_conn_user_free(conn_user); 715 } 716 717 if (connectionId > -1) 718 DropConnection(connectionId, NS_LDAP_NEW_CONN); 719 if (ref_list) 720 __s_api_deleteRefInfo(ref_list); 721 if (target_dn && target_dn_allocated) 722 free(target_dn); 723 return (return_rc); 724 case W_INIT: 725 /* see if need to follow referrals */ 726 rc = __s_api_toFollowReferrals(flags, 727 &followRef, errorp); 728 if (rc != NS_LDAP_SUCCESS) { 729 return_rc = rc; 730 new_state = W_ERROR; 731 break; 732 } 733 len = strlen(dn); 734 if (dn[len-1] == COMMATOK) 735 rc = __s_api_append_default_basedn( 736 dn, &target_dn, &target_dn_allocated, 737 errorp); 738 else 739 target_dn = dn; 740 if (rc != NS_LDAP_SUCCESS) { 741 return_rc = rc; 742 new_state = W_ERROR; 743 } 744 else 745 new_state = GET_CONNECTION; 746 break; 747 case GET_CONNECTION: 748 /* identify self as a write user */ 749 conn_user = __s_api_conn_user_init(NS_CONN_USER_WRITE, 750 NULL, B_FALSE); 751 rc = __s_api_getConnection(NULL, 752 flags, cred, &connectionId, &conp, errorp, 753 do_not_fail_if_new_pwd_reqd, nopasswd_acct_mgmt, 754 conn_user); 755 756 /* 757 * If password control attached 758 * in *errorp, 759 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO, 760 * free the error structure (we do not need 761 * the password management info). 762 * Reset rc to NS_LDAP_SUCCESS. 763 */ 764 if (rc == NS_LDAP_SUCCESS_WITH_INFO) { 765 (void) __ns_ldap_freeError(errorp); 766 *errorp = NULL; 767 rc = NS_LDAP_SUCCESS; 768 } 769 770 if (rc != NS_LDAP_SUCCESS) { 771 return_rc = rc; 772 new_state = W_ERROR; 773 break; 774 } 775 if (followRef) 776 new_state = SELECT_OPERATION_ASYNC; 777 else 778 new_state = SELECT_OPERATION_SYNC; 779 break; 780 case SELECT_OPERATION_SYNC: 781 if (ldap_op == LDAP_REQ_ADD) 782 new_state = DO_ADD_SYNC; 783 else if (ldap_op == LDAP_REQ_DELETE) 784 new_state = DO_DELETE_SYNC; 785 else if (ldap_op == LDAP_REQ_MODIFY) 786 new_state = DO_MODIFY_SYNC; 787 break; 788 case SELECT_OPERATION_ASYNC: 789 if (ldap_op == LDAP_REQ_ADD) 790 new_state = DO_ADD_ASYNC; 791 else if (ldap_op == LDAP_REQ_DELETE) 792 new_state = DO_DELETE_ASYNC; 793 else if (ldap_op == LDAP_REQ_MODIFY) 794 new_state = DO_MODIFY_ASYNC; 795 break; 796 case DO_ADD_SYNC: 797 rc = ldap_add_ext_s(conp->ld, target_dn, 798 mods, NULL, NULL); 799 new_state = GET_RESULT_SYNC; 800 break; 801 case DO_DELETE_SYNC: 802 rc = ldap_delete_ext_s(conp->ld, target_dn, 803 NULL, NULL); 804 new_state = GET_RESULT_SYNC; 805 break; 806 case DO_MODIFY_SYNC: 807 rc = ldap_modify_ext_s(conp->ld, target_dn, 808 mods, NULL, NULL); 809 new_state = GET_RESULT_SYNC; 810 break; 811 case DO_ADD_ASYNC: 812 rc = ldap_add_ext(conp->ld, target_dn, 813 mods, NULL, NULL, &msgid); 814 new_state = GET_RESULT_ASYNC; 815 break; 816 case DO_DELETE_ASYNC: 817 rc = ldap_delete_ext(conp->ld, target_dn, 818 NULL, NULL, &msgid); 819 new_state = GET_RESULT_ASYNC; 820 break; 821 case DO_MODIFY_ASYNC: 822 rc = ldap_modify_ext(conp->ld, target_dn, 823 mods, NULL, NULL, &msgid); 824 new_state = GET_RESULT_ASYNC; 825 break; 826 case GET_RESULT_SYNC: 827 if (rc != LDAP_SUCCESS) { 828 Errno = rc; 829 (void) ldap_get_lderrno(conp->ld, 830 NULL, &errmsg); 831 832 /* 833 * No need to deal with the error message if 834 * it's an empty string. 835 */ 836 if (errmsg != NULL && *errmsg == '\0') 837 errmsg = NULL; 838 839 if (errmsg != NULL) { 840 /* 841 * ldap_get_lderrno does not expect 842 * errmsg to be freed after use, while 843 * ldap_parse_result below does, so set 844 * a flag to indicate source. 845 */ 846 from_get_lderrno = B_TRUE; 847 } 848 849 new_state = W_LDAP_ERROR; 850 } else { 851 return_rc = NS_LDAP_SUCCESS; 852 new_state = W_EXIT; 853 } 854 break; 855 case GET_RESULT_ASYNC: 856 rc = ldap_result(conp->ld, msgid, 1, 857 (struct timeval *)NULL, &res); 858 /* if no server response, set Errno */ 859 if (rc == -1) { 860 (void) ldap_get_option(conp->ld, 861 LDAP_OPT_ERROR_NUMBER, &Errno); 862 new_state = W_LDAP_ERROR; 863 break; 864 } 865 if (rc == LDAP_RES_ADD || rc == LDAP_RES_MODIFY || 866 rc == LDAP_RES_DELETE) { 867 new_state = PARSE_RESULT; 868 break; 869 } else { 870 return_rc = rc; 871 new_state = W_ERROR; 872 } 873 break; 874 case PARSE_RESULT: 875 /* 876 * need Errno, referrals, error msg, 877 * and the last "1" is to free 878 * the result (res) 879 */ 880 rc = ldap_parse_result(conp->ld, res, &Errno, 881 NULL, &errmsg, &referrals, NULL, 1); 882 /* 883 * free errmsg if it is an empty string 884 */ 885 if (errmsg && *errmsg == '\0') { 886 ldap_memfree(errmsg); 887 errmsg = NULL; 888 } 889 /* 890 * If we received referral data, process 891 * it if: 892 * - we are configured to follow referrals 893 * - and not already in referral mode (to keep 894 * consistency with search_state_machine() 895 * which follows 1 level of referrals only; 896 * see proc_result_referrals() and 897 * proc_search_references(). 898 */ 899 if (Errno == LDAP_REFERRAL && followRef && !ref_list) { 900 for (i = 0; referrals[i] != NULL; i++) { 901 /* add to referral list */ 902 rc = __s_api_addRefInfo(&ref_list, 903 referrals[i], NULL, NULL, NULL, 904 conp->ld); 905 if (rc != NS_LDAP_SUCCESS) { 906 __s_api_deleteRefInfo(ref_list); 907 ref_list = NULL; 908 break; 909 } 910 } 911 ldap_value_free(referrals); 912 if (ref_list == NULL) { 913 if (rc != NS_LDAP_MEMORY) 914 rc = NS_LDAP_INTERNAL; 915 return_rc = rc; 916 new_state = W_ERROR; 917 } else { 918 new_state = GET_REFERRAL_CONNECTION; 919 current_ref = ref_list; 920 } 921 if (errmsg) { 922 ldap_memfree(errmsg); 923 errmsg = NULL; 924 } 925 break; 926 } 927 if (Errno != LDAP_SUCCESS) { 928 new_state = W_LDAP_ERROR; 929 } else { 930 return_rc = NS_LDAP_SUCCESS; 931 new_state = W_EXIT; 932 } 933 break; 934 case GET_REFERRAL_CONNECTION: 935 /* 936 * since we are starting over, 937 * discard the old error info 938 */ 939 return_rc = NS_LDAP_SUCCESS; 940 if (*errorp) 941 (void) __ns_ldap_freeError(errorp); 942 if (connectionId > -1) 943 DropConnection(connectionId, NS_LDAP_NEW_CONN); 944 945 /* set it up to use a referral connection */ 946 if (conn_user != NULL) { 947 /* 948 * If an MT connection is being used, 949 * return it to the pool. 950 */ 951 if (conn_user->conn_mt != NULL) 952 __s_api_conn_mt_return(conn_user); 953 954 conn_user->referral = B_TRUE; 955 } 956 rc = __s_api_getConnection(current_ref->refHost, 957 0, cred, &connectionId, &conp, errorp, 958 do_not_fail_if_new_pwd_reqd, 959 nopasswd_acct_mgmt, conn_user); 960 961 /* 962 * If password control attached 963 * in errorp, 964 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO, 965 * free the error structure (we do not need 966 * the password management info). 967 * Reset rc to NS_LDAP_SUCCESS. 968 */ 969 if (rc == NS_LDAP_SUCCESS_WITH_INFO) { 970 (void) __ns_ldap_freeError(errorp); 971 *errorp = NULL; 972 rc = NS_LDAP_SUCCESS; 973 } 974 975 if (rc != NS_LDAP_SUCCESS) { 976 return_rc = rc; 977 /* 978 * If current referral is not 979 * available for some reason, 980 * try next referral in the list. 981 * Get LDAP error code from errorp. 982 */ 983 if (*errorp != NULL) { 984 ns_write_state_t get_ref = 985 GET_REFERRAL_CONNECTION; 986 987 ldap_error = (*errorp)->status; 988 if (ldap_error == LDAP_BUSY || 989 ldap_error == LDAP_UNAVAILABLE || 990 ldap_error == 991 LDAP_UNWILLING_TO_PERFORM || 992 ldap_error == LDAP_CONNECT_ERROR || 993 ldap_error == LDAP_SERVER_DOWN) { 994 current_ref = current_ref->next; 995 if (current_ref == NULL) { 996 /* no more referral to follow */ 997 new_state = W_ERROR; 998 } else 999 new_state = get_ref; 1000 /* 1001 * free errorp before going to 1002 * next referral 1003 */ 1004 (void) __ns_ldap_freeError( 1005 errorp); 1006 *errorp = NULL; 1007 break; 1008 } 1009 /* 1010 * free errorp before going to W_ERROR 1011 */ 1012 (void) __ns_ldap_freeError(errorp); 1013 *errorp = NULL; 1014 } 1015 /* else, exit */ 1016 __s_api_deleteRefInfo(ref_list); 1017 ref_list = NULL; 1018 new_state = W_ERROR; 1019 if (conn_user != NULL) 1020 conn_user->referral = B_FALSE; 1021 break; 1022 } 1023 /* target DN may changed due to referrals */ 1024 if (current_ref->refDN) { 1025 if (target_dn && target_dn_allocated) { 1026 free(target_dn); 1027 target_dn = NULL; 1028 target_dn_allocated = FALSE; 1029 } 1030 target_dn = current_ref->refDN; 1031 } 1032 new_state = SELECT_OPERATION_SYNC; 1033 break; 1034 case W_LDAP_ERROR: 1035 /* 1036 * map error code and error message 1037 * to password status if necessary. 1038 * This is to see if password updates 1039 * failed due to password policy or 1040 * password syntax checking. 1041 */ 1042 if (errmsg) { 1043 /* 1044 * check if server supports 1045 * password management 1046 */ 1047 passwd_mgmt = 1048 __s_api_contain_passwd_control_oid( 1049 conp->controls); 1050 if (passwd_mgmt) 1051 pwd_status = 1052 __s_api_set_passwd_status( 1053 Errno, errmsg); 1054 /* 1055 * free only if not returned by ldap_get_lderrno 1056 */ 1057 if (!from_get_lderrno) 1058 ldap_memfree(errmsg); 1059 errmsg = NULL; 1060 from_get_lderrno = B_FALSE; 1061 } 1062 1063 (void) snprintf(errstr, sizeof (errstr), 1064 "%s", ldap_err2string(Errno)); 1065 err = strdup(errstr); 1066 if (pwd_status != NS_PASSWD_GOOD) { 1067 MKERROR_PWD_MGMT(*errorp, Errno, err, 1068 pwd_status, 0, NULL); 1069 } else { 1070 MKERROR(LOG_INFO, *errorp, Errno, err, NULL); 1071 } 1072 if (conn_user != NULL && 1073 (Errno == LDAP_SERVER_DOWN || 1074 Errno == LDAP_CONNECT_ERROR)) { 1075 __s_api_conn_mt_close(conn_user, Errno, errorp); 1076 } 1077 return_rc = NS_LDAP_INTERNAL; 1078 new_state = W_EXIT; 1079 break; 1080 case W_ERROR: 1081 default: 1082 (void) sprintf(errstr, 1083 gettext("Internal write State machine exit" 1084 " (state = %d, rc = %d)."), 1085 err_state, return_rc); 1086 err = strdup(errstr); 1087 MKERROR(LOG_WARNING, *errorp, return_rc, err, NULL); 1088 new_state = W_EXIT; 1089 break; 1090 } 1091 1092 if (new_state == W_ERROR) 1093 err_state = state; 1094 1095 if (conn_user != NULL && conn_user->bad_mt_conn == B_TRUE) { 1096 __s_api_conn_mt_close(conn_user, 0, NULL); 1097 new_state = W_EXIT; 1098 } 1099 1100 state = new_state; 1101 } 1102 1103 /* 1104 * should never be here, the next line is to eliminating 1105 * lint message 1106 */ 1107 return (NS_LDAP_INTERNAL); 1108 } 1109 1110 1111 /*ARGSUSED*/ 1112 int 1113 __ns_ldap_addAttr( 1114 const char *service, 1115 const char *dn, 1116 const ns_ldap_attr_t * const *attr, 1117 const ns_cred_t *cred, 1118 const int flags, 1119 ns_ldap_error_t ** errorp) 1120 { 1121 LDAPMod **mods; 1122 int rc = 0; 1123 1124 #ifdef DEBUG 1125 (void) fprintf(stderr, "__ns_ldap_addAttr START\n"); 1126 #endif 1127 *errorp = NULL; 1128 1129 /* Sanity check */ 1130 if ((attr == NULL) || (*attr == NULL) || 1131 (dn == NULL) || (cred == NULL)) 1132 return (NS_LDAP_INVALID_PARAM); 1133 1134 mods = __s_api_makeModList(service, attr, LDAP_MOD_ADD, flags); 1135 if (mods == NULL) { 1136 return (NS_LDAP_MEMORY); 1137 } 1138 1139 rc = write_state_machine(LDAP_REQ_MODIFY, 1140 (char *)dn, mods, cred, flags, errorp); 1141 freeModList(mods); 1142 1143 return (rc); 1144 } 1145 1146 1147 /*ARGSUSED*/ 1148 int 1149 __ns_ldap_delAttr( 1150 const char *service, 1151 const char *dn, 1152 const ns_ldap_attr_t * const *attr, 1153 const ns_cred_t *cred, 1154 const int flags, 1155 ns_ldap_error_t ** errorp) 1156 { 1157 LDAPMod **mods; 1158 int rc = 0; 1159 1160 #ifdef DEBUG 1161 (void) fprintf(stderr, "__ns_ldap_delAttr START\n"); 1162 #endif 1163 *errorp = NULL; 1164 1165 /* Sanity check */ 1166 if ((attr == NULL) || (*attr == NULL) || 1167 (dn == NULL) || (cred == NULL)) 1168 return (NS_LDAP_INVALID_PARAM); 1169 1170 mods = __s_api_makeModList(service, attr, LDAP_MOD_DELETE, flags); 1171 if (mods == NULL) { 1172 return (NS_LDAP_MEMORY); 1173 } 1174 1175 rc = write_state_machine(LDAP_REQ_MODIFY, 1176 (char *)dn, mods, cred, flags, errorp); 1177 1178 freeModList(mods); 1179 return (rc); 1180 } 1181 1182 /* Retrieve the admin bind password from the configuration, if allowed. */ 1183 static int 1184 get_admin_passwd(ns_cred_t *cred, ns_ldap_error_t **errorp) 1185 { 1186 void **paramVal = NULL; 1187 int rc, ldaprc; 1188 char *modparamVal = NULL; 1189 1190 /* 1191 * For GSSAPI/Kerberos, host credential is used, no need to get 1192 * admin bind password 1193 */ 1194 if (cred->auth.saslmech == NS_LDAP_SASL_GSSAPI) 1195 return (NS_LDAP_SUCCESS); 1196 1197 /* 1198 * Retrieve admin bind password. 1199 * The admin bind password is available 1200 * only in the ldap_cachemgr process as 1201 * they are not exposed outside of that 1202 * process. 1203 */ 1204 paramVal = NULL; 1205 if ((ldaprc = __ns_ldap_getParam(NS_LDAP_ADMIN_BINDPASSWD_P, 1206 ¶mVal, errorp)) != NS_LDAP_SUCCESS) 1207 return (ldaprc); 1208 if (paramVal == NULL || *paramVal == NULL) { 1209 rc = NS_LDAP_CONFIG; 1210 *errorp = __s_api_make_error(NS_CONFIG_NODEFAULT, 1211 gettext("Admin bind password not configured")); 1212 if (*errorp == NULL) 1213 rc = NS_LDAP_MEMORY; 1214 return (rc); 1215 } 1216 modparamVal = dvalue((char *)*paramVal); 1217 (void) memset(*paramVal, 0, strlen((char *)*paramVal)); 1218 (void) __ns_ldap_freeParam(¶mVal); 1219 if (modparamVal == NULL || *((char *)modparamVal) == '\0') { 1220 if (modparamVal != NULL) 1221 free(modparamVal); 1222 rc = NS_LDAP_CONFIG; 1223 *errorp = __s_api_make_error(NS_CONFIG_SYNTAX, 1224 gettext("bind password not valid")); 1225 if (*errorp == NULL) 1226 rc = NS_LDAP_MEMORY; 1227 return (rc); 1228 } 1229 1230 cred->cred.unix_cred.passwd = modparamVal; 1231 return (NS_LDAP_SUCCESS); 1232 } 1233 1234 boolean_t 1235 __ns_ldap_is_shadow_update_enabled(void) 1236 { 1237 int **enable_shadow = NULL; 1238 ns_ldap_error_t *errorp = NULL; 1239 1240 if (__ns_ldap_getParam(NS_LDAP_ENABLE_SHADOW_UPDATE_P, 1241 (void ***)&enable_shadow, &errorp) != NS_LDAP_SUCCESS) { 1242 if (errorp) 1243 (void) __ns_ldap_freeError(&errorp); 1244 return (B_FALSE); 1245 } 1246 if ((enable_shadow != NULL && *enable_shadow != NULL) && 1247 (*enable_shadow[0] == NS_LDAP_ENABLE_SHADOW_UPDATE_TRUE)) { 1248 (void) __ns_ldap_freeParam((void ***)&enable_shadow); 1249 return (B_TRUE); 1250 } 1251 if (enable_shadow != NULL) 1252 (void) __ns_ldap_freeParam((void ***)&enable_shadow); 1253 return (B_FALSE); 1254 } 1255 1256 /* 1257 * __ns_ldap_repAttr modifies ldap attributes of the 'dn' entry stored 1258 * on the LDAP server. 'service' indicates the type of database entries 1259 * to modify. When the Native LDAP client is configured with 'shadow update 1260 * enabled', Shadowshadow(4) entries can only be modified by privileged users. 1261 * Such users use the NS_LDAP_UPDATE_SHADOW flag to indicate the call is 1262 * for such a shadow(4) update, which would be forwarded to ldap_cachemgr 1263 * for performing the LDAP modify operation. ldap_cachemgr would call 1264 * this function again and use the special service NS_ADMIN_SHADOW_UPDATE 1265 * to identify itself, so that admin credential would be obtained and 1266 * the actual LDAP modify operation be done. 1267 */ 1268 /*ARGSUSED*/ 1269 int 1270 __ns_ldap_repAttr( 1271 const char *service, 1272 const char *dn, 1273 const ns_ldap_attr_t * const *attr, 1274 const ns_cred_t *cred, 1275 const int flags, 1276 ns_ldap_error_t ** errorp) 1277 { 1278 LDAPMod **mods; 1279 int rc = 0; 1280 boolean_t priv; 1281 boolean_t shadow_update_enabled = B_FALSE; 1282 1283 #ifdef DEBUG 1284 (void) fprintf(stderr, "__ns_ldap_repAttr START\n"); 1285 #endif 1286 *errorp = NULL; 1287 1288 /* Sanity check */ 1289 if (attr == NULL || *attr == NULL || dn == NULL) 1290 return (NS_LDAP_INVALID_PARAM); 1291 1292 /* Privileged shadow modify? */ 1293 if ((flags & NS_LDAP_UPDATE_SHADOW) != 0 && 1294 strcmp(service, "shadow") == 0) { 1295 1296 /* Shadow update enabled ? If not, error out */ 1297 shadow_update_enabled = __ns_ldap_is_shadow_update_enabled(); 1298 if (!shadow_update_enabled) { 1299 *errorp = __s_api_make_error(NS_CONFIG_NOTALLOW, 1300 gettext("Shadow Update is not enabled")); 1301 return (NS_LDAP_CONFIG); 1302 } 1303 1304 /* privileged shadow modify requires euid 0 or all zone privs */ 1305 priv = (geteuid() == 0); 1306 if (!priv) { 1307 priv_set_t *ps = priv_allocset(); /* caller */ 1308 priv_set_t *zs; /* zone */ 1309 1310 (void) getppriv(PRIV_EFFECTIVE, ps); 1311 zs = priv_str_to_set("zone", ",", NULL); 1312 priv = priv_isequalset(ps, zs); 1313 priv_freeset(ps); 1314 priv_freeset(zs); 1315 } 1316 if (!priv) 1317 return (NS_LDAP_OP_FAILED); 1318 1319 rc = send_to_cachemgr(dn, (ns_ldap_attr_t **)attr, errorp); 1320 return (rc); 1321 } 1322 1323 if (cred == NULL) 1324 return (NS_LDAP_INVALID_PARAM); 1325 1326 /* 1327 * If service is NS_ADMIN_SHADOW_UPDATE, the caller should be 1328 * ldap_cachemgr. We need to get the admin cred to do work. 1329 * If the caller is not ldap_cachemgr, but use the service 1330 * NS_ADMIN_SHADOW_UPDATE, get_admin_passwd() will fail, 1331 * as the admin cred is not available to the caller. 1332 */ 1333 if (strcmp(service, NS_ADMIN_SHADOW_UPDATE) == 0) { 1334 if ((rc = get_admin_passwd((ns_cred_t *)cred, errorp)) != 1335 NS_LDAP_SUCCESS) 1336 return (rc); 1337 } 1338 1339 mods = __s_api_makeModList(service, attr, LDAP_MOD_REPLACE, flags); 1340 if (mods == NULL) 1341 return (NS_LDAP_MEMORY); 1342 1343 rc = write_state_machine(LDAP_REQ_MODIFY, 1344 (char *)dn, mods, cred, flags, errorp); 1345 1346 freeModList(mods); 1347 return (rc); 1348 } 1349 1350 /*ARGSUSED*/ 1351 int 1352 __ns_ldap_addEntry( 1353 const char *service, 1354 const char *dn, 1355 const ns_ldap_entry_t *entry, 1356 const ns_cred_t *cred, 1357 const int flags, 1358 ns_ldap_error_t ** errorp) 1359 { 1360 char *new_dn = NULL; 1361 LDAPMod **mods = NULL; 1362 const ns_ldap_attr_t * const *attr; 1363 int nAttr = 0; 1364 int rc = 0; 1365 1366 #ifdef DEBUG 1367 (void) fprintf(stderr, "__ns_ldap_addEntry START\n"); 1368 #endif 1369 1370 if ((entry == NULL) || (dn == NULL) || (cred == NULL)) 1371 return (NS_LDAP_INVALID_PARAM); 1372 *errorp = NULL; 1373 1374 /* Construct array of LDAPMod representing attributes of new entry. */ 1375 1376 nAttr = entry->attr_count; 1377 attr = (const ns_ldap_attr_t * const *)(entry->attr_pair); 1378 mods = __s_api_makeModListCount(service, attr, LDAP_MOD_ADD, 1379 nAttr, flags); 1380 if (mods == NULL) { 1381 return (NS_LDAP_MEMORY); 1382 } 1383 1384 rc = replace_mapped_attr_in_dn(service, dn, &new_dn); 1385 if (rc != NS_LDAP_SUCCESS) { 1386 freeModList(mods); 1387 return (rc); 1388 } 1389 1390 rc = write_state_machine(LDAP_REQ_ADD, 1391 new_dn ? new_dn : (char *)dn, mods, cred, flags, errorp); 1392 1393 if (new_dn) 1394 free(new_dn); 1395 freeModList(mods); 1396 return (rc); 1397 } 1398 1399 1400 /*ARGSUSED*/ 1401 int 1402 __ns_ldap_delEntry( 1403 const char *service, 1404 const char *dn, 1405 const ns_cred_t *cred, 1406 const int flags, 1407 ns_ldap_error_t ** errorp) 1408 { 1409 int rc; 1410 1411 #ifdef DEBUG 1412 (void) fprintf(stderr, "__ns_ldap_delEntry START\n"); 1413 #endif 1414 if ((dn == NULL) || (cred == NULL)) 1415 return (NS_LDAP_INVALID_PARAM); 1416 1417 *errorp = NULL; 1418 1419 rc = write_state_machine(LDAP_REQ_DELETE, 1420 (char *)dn, NULL, cred, flags, errorp); 1421 1422 return (rc); 1423 } 1424 1425 /* 1426 * Add Typed Entry Helper routines 1427 */ 1428 1429 /* 1430 * Add Typed Entry Conversion routines 1431 */ 1432 1433 static int 1434 __s_add_attr(ns_ldap_entry_t *e, char *attrname, char *value) 1435 { 1436 ns_ldap_attr_t *a; 1437 char *v; 1438 1439 a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t)); 1440 if (a == NULL) 1441 return (NS_LDAP_MEMORY); 1442 a->attrname = strdup(attrname); 1443 if (a->attrname == NULL) 1444 return (NS_LDAP_MEMORY); 1445 a->attrvalue = (char **)calloc(1, sizeof (char **)); 1446 if (a->attrvalue == NULL) 1447 return (NS_LDAP_MEMORY); 1448 a->value_count = 1; 1449 a->attrvalue[0] = NULL; 1450 v = strdup(value); 1451 if (v == NULL) 1452 return (NS_LDAP_MEMORY); 1453 a->attrvalue[0] = v; 1454 e->attr_pair[e->attr_count] = a; 1455 e->attr_count++; 1456 return (NS_LDAP_SUCCESS); 1457 } 1458 1459 static int 1460 __s_add_attrlist(ns_ldap_entry_t *e, char *attrname, char **argv) 1461 { 1462 ns_ldap_attr_t *a; 1463 char *v; 1464 char **av; 1465 int i, j; 1466 1467 a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t)); 1468 if (a == NULL) 1469 return (NS_LDAP_MEMORY); 1470 a->attrname = strdup(attrname); 1471 if (a->attrname == NULL) 1472 return (NS_LDAP_MEMORY); 1473 1474 for (i = 0, av = argv; *av != NULL; av++, i++) 1475 ; 1476 1477 a->attrvalue = (char **)calloc(i, sizeof (char *)); 1478 1479 if (a->attrvalue == NULL) 1480 return (NS_LDAP_MEMORY); 1481 1482 a->value_count = i; 1483 for (j = 0; j < i; j++) { 1484 v = strdup(argv[j]); 1485 if (v == NULL) 1486 return (NS_LDAP_MEMORY); 1487 a->attrvalue[j] = v; 1488 } 1489 e->attr_pair[e->attr_count] = a; 1490 e->attr_count++; 1491 return (NS_LDAP_SUCCESS); 1492 } 1493 1494 static ns_ldap_entry_t * 1495 __s_mk_entry(char **objclass, int max_attr) 1496 { 1497 ns_ldap_entry_t *e; 1498 e = (ns_ldap_entry_t *)calloc(1, sizeof (ns_ldap_entry_t)); 1499 if (e == NULL) 1500 return (NULL); 1501 /* allocate attributes, +1 for objectclass, +1 for NULL terminator */ 1502 e->attr_pair = (ns_ldap_attr_t **) 1503 calloc(max_attr + 2, sizeof (ns_ldap_attr_t *)); 1504 if (e->attr_pair == NULL) { 1505 free(e); 1506 return (NULL); 1507 } 1508 e->attr_count = 0; 1509 if (__s_add_attrlist(e, "objectClass", objclass) != NS_LDAP_SUCCESS) { 1510 free(e->attr_pair); 1511 free(e); 1512 return (NULL); 1513 } 1514 return (e); 1515 } 1516 1517 1518 /* 1519 * Conversion: passwd 1520 * Input format: struct passwd 1521 * Exported objectclass: posixAccount 1522 */ 1523 static int 1524 __s_cvt_passwd(const void *data, char **rdn, 1525 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 1526 { 1527 ns_ldap_entry_t *e; 1528 int rc; 1529 char trdn[RDNSIZE]; 1530 /* routine specific */ 1531 struct passwd *ptr; 1532 int max_attr = 9; 1533 char ibuf[10]; 1534 static char *oclist[] = { 1535 "posixAccount", 1536 "shadowAccount", 1537 "account", 1538 "top", 1539 NULL 1540 }; 1541 1542 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 1543 return (NS_LDAP_OP_FAILED); 1544 *entry = e = __s_mk_entry(oclist, max_attr); 1545 if (e == NULL) 1546 return (NS_LDAP_MEMORY); 1547 1548 /* Convert the structure */ 1549 ptr = (struct passwd *)data; 1550 1551 if (ptr->pw_name == NULL || ptr->pw_uid > MAXUID || 1552 ptr->pw_gid > MAXUID || ptr->pw_dir == NULL) { 1553 __ns_ldap_freeEntry(e); 1554 *entry = NULL; 1555 return (NS_LDAP_INVALID_PARAM); 1556 } 1557 1558 /* Create an appropriate rdn */ 1559 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->pw_name); 1560 *rdn = strdup(trdn); 1561 if (*rdn == NULL) { 1562 __ns_ldap_freeEntry(e); 1563 *entry = NULL; 1564 return (NS_LDAP_MEMORY); 1565 } 1566 1567 /* Error check the data and add the attributes */ 1568 rc = __s_add_attr(e, "uid", ptr->pw_name); 1569 if (rc != NS_LDAP_SUCCESS) { 1570 __s_cvt_freeEntryRdn(entry, rdn); 1571 return (rc); 1572 } 1573 rc = __s_add_attr(e, "cn", ptr->pw_name); 1574 if (rc != NS_LDAP_SUCCESS) { 1575 __s_cvt_freeEntryRdn(entry, rdn); 1576 return (rc); 1577 } 1578 1579 if (ptr->pw_passwd != NULL && 1580 ptr->pw_passwd[0] != '\0') { 1581 rc = __s_add_attr(e, "userPassword", ptr->pw_passwd); 1582 if (rc != NS_LDAP_SUCCESS) { 1583 __s_cvt_freeEntryRdn(entry, rdn); 1584 return (rc); 1585 } 1586 } 1587 1588 (void) sprintf(ibuf, "%u", ptr->pw_uid); 1589 rc = __s_add_attr(e, "uidNumber", ibuf); 1590 if (rc != NS_LDAP_SUCCESS) { 1591 __s_cvt_freeEntryRdn(entry, rdn); 1592 return (rc); 1593 } 1594 1595 (void) sprintf(ibuf, "%u", ptr->pw_gid); 1596 rc = __s_add_attr(e, "gidNumber", ibuf); 1597 if (rc != NS_LDAP_SUCCESS) { 1598 __s_cvt_freeEntryRdn(entry, rdn); 1599 return (rc); 1600 } 1601 if (ptr->pw_gecos != NULL && 1602 ptr->pw_gecos[0] != '\0') { 1603 rc = __s_add_attr(e, "gecos", ptr->pw_gecos); 1604 if (rc != NS_LDAP_SUCCESS) { 1605 __s_cvt_freeEntryRdn(entry, rdn); 1606 return (rc); 1607 } 1608 } 1609 1610 rc = __s_add_attr(e, "homeDirectory", ptr->pw_dir); 1611 if (rc != NS_LDAP_SUCCESS) { 1612 __s_cvt_freeEntryRdn(entry, rdn); 1613 return (rc); 1614 } 1615 if (ptr->pw_shell != NULL && 1616 ptr->pw_shell[0] != '\0') { 1617 rc = __s_add_attr(e, "loginShell", ptr->pw_shell); 1618 if (rc != NS_LDAP_SUCCESS) { 1619 __s_cvt_freeEntryRdn(entry, rdn); 1620 return (rc); 1621 } 1622 } 1623 1624 return (NS_LDAP_SUCCESS); 1625 } 1626 1627 /* 1628 * escape_str function escapes special characters in str and 1629 * copies to escstr string. 1630 * 1631 * return 0 for successful 1632 * 1 for fail 1633 */ 1634 static int escape_str(char *escstr, char *str) 1635 { 1636 int index = 0; 1637 1638 while ((*str != '\0') && (index < (RDNSIZE - 1))) { 1639 if (*str == '+' || *str == ';' || *str == '>' || 1640 *str == '<' || *str == ',' || *str == '"' || 1641 *str == '\\' || *str == '=' || 1642 (*str == '#' && index == 0)) { 1643 *escstr++ = '\\'; 1644 *escstr++ = *str++; 1645 index += 2; 1646 } else { 1647 *escstr++ = *str++; 1648 index++; 1649 } 1650 } 1651 1652 if (*str == '\0') { 1653 *escstr = '\0'; 1654 return (0); 1655 } else { 1656 return (1); 1657 } 1658 } 1659 1660 /* 1661 * Conversion: project 1662 * Input format: struct project 1663 * Exported objectclass: SolarisProject 1664 */ 1665 static int 1666 __s_cvt_project(const void *data, char **rdn, 1667 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 1668 { 1669 ns_ldap_entry_t *e; 1670 int rc; 1671 char trdn[RDNSIZE]; 1672 1673 /* routine specific */ 1674 struct project *ptr; 1675 int max_attr = 9; 1676 char ibuf[11]; 1677 static char *oclist[] = { 1678 "SolarisProject", 1679 "top", 1680 NULL 1681 }; 1682 1683 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 1684 return (NS_LDAP_OP_FAILED); 1685 1686 *entry = e = __s_mk_entry(oclist, max_attr); 1687 if (e == NULL) 1688 return (NS_LDAP_MEMORY); 1689 1690 /* Convert the structure */ 1691 ptr = (struct project *)data; 1692 1693 if (ptr->pj_name == NULL || ptr->pj_projid > MAXUID) { 1694 __ns_ldap_freeEntry(e); 1695 *entry = NULL; 1696 return (NS_LDAP_INVALID_PARAM); 1697 } 1698 1699 /* Create an appropriate rdn */ 1700 (void) snprintf(trdn, RDNSIZE, "SolarisProjectName=%s", ptr->pj_name); 1701 *rdn = strdup(trdn); 1702 if (*rdn == NULL) { 1703 __ns_ldap_freeEntry(e); 1704 *entry = NULL; 1705 return (NS_LDAP_MEMORY); 1706 } 1707 1708 /* Error check the data and add the attributes */ 1709 1710 /* Project name */ 1711 rc = __s_add_attr(e, "SolarisProjectName", ptr->pj_name); 1712 if (rc != NS_LDAP_SUCCESS) { 1713 __s_cvt_freeEntryRdn(entry, rdn); 1714 return (rc); 1715 } 1716 1717 /* 1718 * Project ID: 1719 * ibuf is 11 chars big, which should be enough for string 1720 * representation of 32bit number + nul-car 1721 */ 1722 if (snprintf(ibuf, sizeof (ibuf), "%u", ptr->pj_projid) < 0) { 1723 __s_cvt_freeEntryRdn(entry, rdn); 1724 return (NS_LDAP_INVALID_PARAM); 1725 } 1726 rc = __s_add_attr(e, "SolarisProjectID", ibuf); 1727 if (rc != NS_LDAP_SUCCESS) { 1728 __s_cvt_freeEntryRdn(entry, rdn); 1729 return (rc); 1730 } 1731 1732 /* Comment/Description */ 1733 if (ptr->pj_comment != NULL && ptr->pj_comment[0] != '\0') { 1734 rc = __s_add_attr(e, "description", ptr->pj_comment); 1735 if (rc != NS_LDAP_SUCCESS) { 1736 __s_cvt_freeEntryRdn(entry, rdn); 1737 return (rc); 1738 } 1739 } 1740 1741 /* Attributes */ 1742 if (ptr->pj_attr != NULL && ptr->pj_attr[0] != '\0') { 1743 rc = __s_add_attr(e, "SolarisProjectAttr", ptr->pj_attr); 1744 if (rc != NS_LDAP_SUCCESS) { 1745 __s_cvt_freeEntryRdn(entry, rdn); 1746 return (rc); 1747 } 1748 } 1749 1750 /* Users */ 1751 if (ptr->pj_users != NULL) { 1752 rc = __s_add_attrlist(e, "memberUid", ptr->pj_users); 1753 if (rc != NS_LDAP_SUCCESS) { 1754 __s_cvt_freeEntryRdn(entry, rdn); 1755 return (rc); 1756 } 1757 } 1758 1759 /* Groups */ 1760 if (ptr->pj_groups != NULL) { 1761 rc = __s_add_attrlist(e, "memberGid", ptr->pj_groups); 1762 if (rc != NS_LDAP_SUCCESS) { 1763 __s_cvt_freeEntryRdn(entry, rdn); 1764 return (rc); 1765 } 1766 } 1767 1768 1769 1770 return (NS_LDAP_SUCCESS); 1771 } 1772 /* 1773 * Conversion: shadow 1774 * Input format: struct shadow 1775 * Exported objectclass: shadowAccount 1776 */ 1777 static int 1778 __s_cvt_shadow(const void *data, char **rdn, 1779 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 1780 { 1781 ns_ldap_entry_t *e; 1782 int rc; 1783 char trdn[RDNSIZE]; 1784 /* routine specific */ 1785 struct spwd *ptr; 1786 int max_attr = 10; 1787 char ibuf[10]; 1788 static char *oclist[] = { 1789 "posixAccount", 1790 "shadowAccount", 1791 "account", 1792 "top", 1793 NULL 1794 }; 1795 1796 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 1797 return (NS_LDAP_OP_FAILED); 1798 *entry = e = __s_mk_entry(oclist, max_attr); 1799 if (e == NULL) 1800 return (NS_LDAP_MEMORY); 1801 1802 /* Convert the structure */ 1803 ptr = (struct spwd *)data; 1804 1805 if (ptr->sp_namp == NULL) { 1806 __ns_ldap_freeEntry(e); 1807 *entry = NULL; 1808 return (NS_LDAP_INVALID_PARAM); 1809 } 1810 1811 /* Create an appropriate rdn */ 1812 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->sp_namp); 1813 *rdn = strdup(trdn); 1814 if (*rdn == NULL) { 1815 __ns_ldap_freeEntry(e); 1816 *entry = NULL; 1817 return (NS_LDAP_MEMORY); 1818 } 1819 1820 /* Error check the data and add the attributes */ 1821 rc = __s_add_attr(e, "uid", ptr->sp_namp); 1822 if (rc != NS_LDAP_SUCCESS) { 1823 __s_cvt_freeEntryRdn(entry, rdn); 1824 return (rc); 1825 } 1826 1827 if (ptr->sp_pwdp == NULL) { 1828 __s_cvt_freeEntryRdn(entry, rdn); 1829 return (NS_LDAP_INVALID_PARAM); 1830 } else { 1831 rc = __s_add_attr(e, "userPassword", ptr->sp_pwdp); 1832 if (rc != NS_LDAP_SUCCESS) { 1833 __s_cvt_freeEntryRdn(entry, rdn); 1834 return (rc); 1835 } 1836 } 1837 if (ptr->sp_lstchg >= 0) { 1838 (void) sprintf(ibuf, "%d", ptr->sp_lstchg); 1839 rc = __s_add_attr(e, "shadowLastChange", ibuf); 1840 if (rc != NS_LDAP_SUCCESS) { 1841 __s_cvt_freeEntryRdn(entry, rdn); 1842 return (rc); 1843 } 1844 } 1845 if (ptr->sp_min >= 0) { 1846 (void) sprintf(ibuf, "%d", ptr->sp_min); 1847 rc = __s_add_attr(e, "shadowMin", ibuf); 1848 if (rc != NS_LDAP_SUCCESS) { 1849 __s_cvt_freeEntryRdn(entry, rdn); 1850 return (rc); 1851 } 1852 } 1853 if (ptr->sp_max >= 0) { 1854 (void) sprintf(ibuf, "%d", ptr->sp_max); 1855 rc = __s_add_attr(e, "shadowMax", ibuf); 1856 if (rc != NS_LDAP_SUCCESS) { 1857 __s_cvt_freeEntryRdn(entry, rdn); 1858 return (rc); 1859 } 1860 } 1861 if (ptr->sp_warn >= 0) { 1862 (void) sprintf(ibuf, "%d", ptr->sp_warn); 1863 rc = __s_add_attr(e, "shadowWarning", ibuf); 1864 if (rc != NS_LDAP_SUCCESS) { 1865 __s_cvt_freeEntryRdn(entry, rdn); 1866 return (rc); 1867 } 1868 } 1869 if (ptr->sp_inact >= 0) { 1870 (void) sprintf(ibuf, "%d", ptr->sp_inact); 1871 rc = __s_add_attr(e, "shadowInactive", ibuf); 1872 if (rc != NS_LDAP_SUCCESS) { 1873 __s_cvt_freeEntryRdn(entry, rdn); 1874 return (rc); 1875 } 1876 } 1877 if (ptr->sp_expire >= 0) { 1878 (void) sprintf(ibuf, "%d", ptr->sp_expire); 1879 rc = __s_add_attr(e, "shadowExpire", ibuf); 1880 if (rc != NS_LDAP_SUCCESS) { 1881 __s_cvt_freeEntryRdn(entry, rdn); 1882 return (rc); 1883 } 1884 } 1885 (void) sprintf(ibuf, "%d", ptr->sp_flag); 1886 rc = __s_add_attr(e, "shadowFlag", ibuf); 1887 if (rc != NS_LDAP_SUCCESS) { 1888 __s_cvt_freeEntryRdn(entry, rdn); 1889 return (rc); 1890 } 1891 1892 return (NS_LDAP_SUCCESS); 1893 } 1894 1895 1896 /* 1897 * Conversion: group 1898 * Input format: struct group 1899 * Exported objectclass: posixGroup 1900 */ 1901 static int 1902 __s_cvt_group(const void *data, char **rdn, 1903 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 1904 { 1905 ns_ldap_entry_t *e; 1906 int rc; 1907 char trdn[RDNSIZE]; 1908 /* routine specific */ 1909 struct group *ptr; 1910 int i, j, k; 1911 char **nm, **lm; 1912 int max_attr = 4; 1913 char ibuf[10]; 1914 static char *oclist[] = { 1915 "posixGroup", 1916 "top", 1917 NULL 1918 }; 1919 1920 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 1921 return (NS_LDAP_OP_FAILED); 1922 *entry = e = __s_mk_entry(oclist, max_attr); 1923 if (e == NULL) 1924 return (NS_LDAP_MEMORY); 1925 1926 /* Convert the structure */ 1927 ptr = (struct group *)data; 1928 1929 if (ptr->gr_name == NULL || ptr->gr_gid > MAXUID) { 1930 __ns_ldap_freeEntry(e); 1931 *entry = NULL; 1932 return (NS_LDAP_INVALID_PARAM); 1933 } 1934 1935 /* Create an appropriate rdn */ 1936 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->gr_name); 1937 *rdn = strdup(trdn); 1938 if (*rdn == NULL) { 1939 __ns_ldap_freeEntry(e); 1940 *entry = NULL; 1941 return (NS_LDAP_MEMORY); 1942 } 1943 1944 /* Error check the data and add the attributes */ 1945 rc = __s_add_attr(e, "cn", ptr->gr_name); 1946 if (rc != NS_LDAP_SUCCESS) { 1947 __s_cvt_freeEntryRdn(entry, rdn); 1948 return (rc); 1949 } 1950 1951 (void) sprintf(ibuf, "%u", ptr->gr_gid); 1952 rc = __s_add_attr(e, "gidNumber", ibuf); 1953 if (rc != NS_LDAP_SUCCESS) { 1954 __s_cvt_freeEntryRdn(entry, rdn); 1955 return (rc); 1956 } 1957 if (ptr->gr_passwd && ptr->gr_passwd[0] != '\0') { 1958 rc = __s_add_attr(e, "userPassword", ptr->gr_passwd); 1959 if (rc != NS_LDAP_SUCCESS) { 1960 __s_cvt_freeEntryRdn(entry, rdn); 1961 return (rc); 1962 } 1963 } 1964 1965 if (ptr->gr_mem && ptr->gr_mem[0]) { 1966 lm = ptr->gr_mem; 1967 for (i = 0; *lm; i++, lm++) 1968 ; 1969 lm = ptr->gr_mem; 1970 nm = (char **)calloc(i+2, sizeof (char *)); 1971 if (nm == NULL) { 1972 __s_cvt_freeEntryRdn(entry, rdn); 1973 return (NS_LDAP_MEMORY); 1974 } 1975 for (j = 0; j < i; j++) { 1976 nm[j] = strdup(lm[j]); 1977 if (nm[j] == NULL) { 1978 for (k = 0; k < j; k++) 1979 free(nm[k]); 1980 free(nm); 1981 __s_cvt_freeEntryRdn(entry, rdn); 1982 return (NS_LDAP_MEMORY); 1983 } 1984 } 1985 rc = __s_add_attrlist(e, "memberUid", nm); 1986 for (j = 0; j < i; j++) { 1987 free(nm[j]); 1988 } 1989 free(nm); 1990 nm = NULL; 1991 if (rc != NS_LDAP_SUCCESS) { 1992 __s_cvt_freeEntryRdn(entry, rdn); 1993 return (rc); 1994 } 1995 } 1996 1997 return (NS_LDAP_SUCCESS); 1998 } 1999 2000 /* 2001 * Conversion: hosts 2002 * Input format: struct hostent 2003 * Exported objectclass: ipHost 2004 */ 2005 static int 2006 __s_cvt_hosts(const void *data, char **rdn, 2007 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2008 { 2009 ns_ldap_entry_t *e; 2010 int rc; 2011 char trdn[RDNSIZE]; 2012 /* routine specific */ 2013 struct hostent *ptr; 2014 int max_attr = 6; 2015 int i, j, k; 2016 char **nm, **lm; 2017 static char *oclist[] = { 2018 "ipHost", 2019 "device", 2020 "top", 2021 NULL 2022 }; 2023 2024 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2025 return (NS_LDAP_OP_FAILED); 2026 *entry = e = __s_mk_entry(oclist, max_attr); 2027 if (e == NULL) 2028 return (NS_LDAP_MEMORY); 2029 2030 /* Convert the structure */ 2031 ptr = (struct hostent *)data; 2032 2033 if (ptr->h_name == NULL || 2034 ptr->h_addr_list == NULL || ptr->h_addr_list[0] == '\0') { 2035 __ns_ldap_freeEntry(e); 2036 *entry = NULL; 2037 return (NS_LDAP_INVALID_PARAM); 2038 } 2039 2040 /* Create an appropriate rdn */ 2041 (void) snprintf(trdn, RDNSIZE, "cn=%s+ipHostNumber=%s", 2042 ptr->h_name, ptr->h_addr_list[0]); 2043 *rdn = strdup(trdn); 2044 if (*rdn == NULL) { 2045 __ns_ldap_freeEntry(e); 2046 *entry = NULL; 2047 return (NS_LDAP_MEMORY); 2048 } 2049 2050 /* Error check the data and add the attributes */ 2051 if (ptr->h_aliases && ptr->h_aliases[0]) { 2052 lm = ptr->h_aliases; 2053 /* 2054 * If there is a description, 'i' will contain 2055 * the index of the description in the aliases list 2056 */ 2057 for (i = 0; *lm && (*lm)[0] != '#'; i++, lm++) 2058 ; 2059 lm = ptr->h_aliases; 2060 nm = (char **)calloc(i+2, sizeof (char *)); 2061 if (nm == NULL) { 2062 __s_cvt_freeEntryRdn(entry, rdn); 2063 return (NS_LDAP_MEMORY); 2064 } 2065 nm[0] = ptr->h_name; 2066 for (j = 0; j < i; j++) 2067 nm[j+1] = ptr->h_aliases[j]; 2068 2069 rc = __s_add_attrlist(e, "cn", nm); 2070 2071 if (rc != NS_LDAP_SUCCESS) { 2072 __s_cvt_freeEntryRdn(entry, rdn); 2073 free(nm); 2074 return (rc); 2075 } 2076 2077 if (lm[i] && lm[i][0] == '#') { 2078 nm[0] = &(lm[i][1]); 2079 nm[1] = NULL; 2080 rc = __s_add_attrlist(e, "description", nm); 2081 } 2082 free(nm); 2083 nm = NULL; 2084 if (rc != NS_LDAP_SUCCESS) { 2085 __s_cvt_freeEntryRdn(entry, rdn); 2086 return (rc); 2087 } 2088 } else { 2089 rc = __s_add_attr(e, "cn", ptr->h_name); 2090 if (rc != NS_LDAP_SUCCESS) { 2091 __s_cvt_freeEntryRdn(entry, rdn); 2092 return (rc); 2093 } 2094 } 2095 2096 if (ptr->h_addr_list && ptr->h_addr_list[0]) { 2097 lm = ptr->h_addr_list; 2098 for (i = 0; *lm; i++, lm++) 2099 ; 2100 lm = ptr->h_addr_list; 2101 nm = (char **)calloc(i+2, sizeof (char *)); 2102 if (nm == NULL) { 2103 __s_cvt_freeEntryRdn(entry, rdn); 2104 return (NS_LDAP_MEMORY); 2105 } 2106 for (j = 0; j < i; j++) { 2107 nm[j] = strdup(lm[j]); 2108 if (nm[j] == NULL) { 2109 for (k = 0; k < j; k++) 2110 free(nm[k]); 2111 free(nm); 2112 __s_cvt_freeEntryRdn(entry, rdn); 2113 return (NS_LDAP_MEMORY); 2114 } 2115 } 2116 rc = __s_add_attrlist(e, "ipHostNumber", nm); 2117 for (j = 0; j < i; j++) { 2118 free(nm[j]); 2119 } 2120 free(nm); 2121 nm = NULL; 2122 if (rc != NS_LDAP_SUCCESS) { 2123 __s_cvt_freeEntryRdn(entry, rdn); 2124 return (rc); 2125 } 2126 } else { 2127 __s_cvt_freeEntryRdn(entry, rdn); 2128 return (NS_LDAP_INVALID_PARAM); 2129 } 2130 2131 return (NS_LDAP_SUCCESS); 2132 } 2133 2134 /* 2135 * Conversion: rpc 2136 * Input format: struct rpcent 2137 * Exported objectclass: oncRpc 2138 */ 2139 static int 2140 __s_cvt_rpc(const void *data, char **rdn, 2141 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2142 { 2143 ns_ldap_entry_t *e; 2144 int rc; 2145 char trdn[RDNSIZE]; 2146 /* routine specific */ 2147 struct rpcent *ptr; 2148 int max_attr = 3; 2149 int i, j; 2150 char **nm; 2151 char ibuf[10]; 2152 static char *oclist[] = { 2153 "oncRpc", 2154 "top", 2155 NULL 2156 }; 2157 2158 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2159 return (NS_LDAP_OP_FAILED); 2160 *entry = e = __s_mk_entry(oclist, max_attr); 2161 if (e == NULL) 2162 return (NS_LDAP_MEMORY); 2163 2164 /* Convert the structure */ 2165 ptr = (struct rpcent *)data; 2166 2167 if (ptr->r_name == NULL || ptr->r_number < 0) { 2168 __ns_ldap_freeEntry(e); 2169 *entry = NULL; 2170 return (NS_LDAP_INVALID_PARAM); 2171 } 2172 2173 /* Create an appropriate rdn */ 2174 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->r_name); 2175 *rdn = strdup(trdn); 2176 if (*rdn == NULL) { 2177 __ns_ldap_freeEntry(e); 2178 *entry = NULL; 2179 return (NS_LDAP_MEMORY); 2180 } 2181 2182 /* Error check the data and add the attributes */ 2183 if (ptr->r_aliases && ptr->r_aliases[0]) { 2184 nm = ptr->r_aliases; 2185 for (i = 0; *nm; i++, nm++) 2186 ; 2187 nm = (char **)calloc(i+2, sizeof (char *)); 2188 if (nm == NULL) { 2189 __s_cvt_freeEntryRdn(entry, rdn); 2190 return (NS_LDAP_MEMORY); 2191 } 2192 nm[0] = ptr->r_name; 2193 for (j = 0; j < i; j++) 2194 nm[j+1] = ptr->r_aliases[j]; 2195 2196 rc = __s_add_attrlist(e, "cn", nm); 2197 free(nm); 2198 nm = NULL; 2199 if (rc != NS_LDAP_SUCCESS) { 2200 __s_cvt_freeEntryRdn(entry, rdn); 2201 return (rc); 2202 } 2203 } else { 2204 rc = __s_add_attr(e, "cn", ptr->r_name); 2205 if (rc != NS_LDAP_SUCCESS) { 2206 __s_cvt_freeEntryRdn(entry, rdn); 2207 return (rc); 2208 } 2209 } 2210 2211 if (ptr->r_number >= 0) { 2212 (void) sprintf(ibuf, "%d", ptr->r_number); 2213 rc = __s_add_attr(e, "oncRpcNumber", ibuf); 2214 if (rc != NS_LDAP_SUCCESS) { 2215 __s_cvt_freeEntryRdn(entry, rdn); 2216 return (rc); 2217 } 2218 } 2219 2220 return (NS_LDAP_SUCCESS); 2221 2222 } 2223 2224 /* 2225 * Conversion: protocols 2226 * Input format: struct protoent 2227 * Exported objectclass: ipProtocol 2228 */ 2229 static int 2230 __s_cvt_protocols(const void *data, char **rdn, 2231 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2232 { 2233 ns_ldap_entry_t *e; 2234 int rc; 2235 char trdn[RDNSIZE]; 2236 /* routine specific */ 2237 struct protoent *ptr; 2238 int max_attr = 3; 2239 int i, j; 2240 char ibuf[10]; 2241 char **nm; 2242 static char *oclist[] = { 2243 "ipProtocol", 2244 "top", 2245 NULL 2246 }; 2247 2248 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2249 return (NS_LDAP_OP_FAILED); 2250 *entry = e = __s_mk_entry(oclist, max_attr); 2251 if (e == NULL) 2252 return (NS_LDAP_MEMORY); 2253 2254 /* Convert the structure */ 2255 ptr = (struct protoent *)data; 2256 2257 if (ptr->p_name == NULL || ptr->p_proto < 0) { 2258 __ns_ldap_freeEntry(e); 2259 *entry = NULL; 2260 return (NS_LDAP_INVALID_PARAM); 2261 } 2262 2263 /* Create an appropriate rdn */ 2264 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->p_name); 2265 *rdn = strdup(trdn); 2266 if (*rdn == NULL) { 2267 __ns_ldap_freeEntry(e); 2268 *entry = NULL; 2269 return (NS_LDAP_MEMORY); 2270 } 2271 2272 /* Error check the data and add the attributes */ 2273 if (ptr->p_aliases && ptr->p_aliases[0]) { 2274 nm = ptr->p_aliases; 2275 for (i = 0; *nm; i++, nm++) 2276 ; 2277 nm = (char **)calloc(i+2, sizeof (char *)); 2278 if (nm == NULL) { 2279 __s_cvt_freeEntryRdn(entry, rdn); 2280 return (NS_LDAP_MEMORY); 2281 } 2282 nm[0] = ptr->p_name; 2283 for (j = 0; j < i; j++) 2284 nm[j+1] = ptr->p_aliases[j]; 2285 2286 rc = __s_add_attrlist(e, "cn", nm); 2287 free(nm); 2288 nm = NULL; 2289 if (rc != NS_LDAP_SUCCESS) { 2290 __s_cvt_freeEntryRdn(entry, rdn); 2291 return (rc); 2292 } 2293 } else { 2294 rc = __s_add_attr(e, "cn", ptr->p_name); 2295 if (rc != NS_LDAP_SUCCESS) { 2296 __s_cvt_freeEntryRdn(entry, rdn); 2297 return (rc); 2298 } 2299 } 2300 2301 (void) sprintf(ibuf, "%d", ptr->p_proto); 2302 rc = __s_add_attr(e, "ipProtocolNumber", ibuf); 2303 if (rc != NS_LDAP_SUCCESS) { 2304 __s_cvt_freeEntryRdn(entry, rdn); 2305 return (rc); 2306 } 2307 2308 return (NS_LDAP_SUCCESS); 2309 2310 } 2311 2312 /* 2313 * Conversion: services 2314 * Input format: struct servent 2315 * Exported objectclass: ipService 2316 */ 2317 static int 2318 __s_cvt_services(const void *data, char **rdn, 2319 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2320 { 2321 ns_ldap_entry_t *e; 2322 int rc; 2323 char trdn[RDNSIZE]; 2324 char esc_str[RDNSIZE]; 2325 /* routine specific */ 2326 struct servent *ptr; 2327 int max_attr = 4; 2328 int i, j; 2329 char ibuf[10]; 2330 char **nm; 2331 static char *oclist[] = { 2332 "ipService", 2333 "top", 2334 NULL 2335 }; 2336 2337 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2338 return (NS_LDAP_OP_FAILED); 2339 *entry = e = __s_mk_entry(oclist, max_attr); 2340 if (e == NULL) 2341 return (NS_LDAP_MEMORY); 2342 2343 /* Convert the structure */ 2344 ptr = (struct servent *)data; 2345 2346 if (ptr->s_name == NULL || ptr->s_port < 0 || ptr->s_proto == '\0') { 2347 __ns_ldap_freeEntry(e); 2348 *entry = NULL; 2349 return (NS_LDAP_INVALID_PARAM); 2350 } 2351 2352 /* 2353 * Escape special characters in service name. 2354 */ 2355 if (escape_str(esc_str, ptr->s_name) != 0) { 2356 __ns_ldap_freeEntry(e); 2357 *entry = NULL; 2358 return (NS_LDAP_INVALID_PARAM); 2359 } 2360 2361 /* Create an appropriate rdn */ 2362 (void) snprintf(trdn, RDNSIZE, "cn=%s+ipServiceProtocol=%s", 2363 esc_str, ptr->s_proto); 2364 2365 *rdn = strdup(trdn); 2366 if (*rdn == NULL) { 2367 __ns_ldap_freeEntry(e); 2368 *entry = NULL; 2369 return (NS_LDAP_MEMORY); 2370 } 2371 2372 /* Error check the data and add the attributes */ 2373 if (ptr->s_aliases && ptr->s_aliases[0]) { 2374 nm = ptr->s_aliases; 2375 for (i = 0; *nm; i++, nm++) 2376 ; 2377 nm = (char **)calloc(i+2, sizeof (char *)); 2378 if (nm == NULL) { 2379 __s_cvt_freeEntryRdn(entry, rdn); 2380 return (NS_LDAP_MEMORY); 2381 } 2382 nm[0] = ptr->s_name; 2383 for (j = 0; j < i; j++) 2384 nm[j+1] = ptr->s_aliases[j]; 2385 2386 rc = __s_add_attrlist(e, "cn", nm); 2387 free(nm); 2388 nm = NULL; 2389 if (rc != NS_LDAP_SUCCESS) { 2390 __s_cvt_freeEntryRdn(entry, rdn); 2391 return (rc); 2392 } 2393 } else { 2394 rc = __s_add_attr(e, "cn", ptr->s_name); 2395 if (rc != NS_LDAP_SUCCESS) { 2396 __s_cvt_freeEntryRdn(entry, rdn); 2397 return (rc); 2398 } 2399 } 2400 2401 (void) sprintf(ibuf, "%d", ptr->s_port); 2402 rc = __s_add_attr(e, "ipServicePort", ibuf); 2403 if (rc != NS_LDAP_SUCCESS) { 2404 __s_cvt_freeEntryRdn(entry, rdn); 2405 return (rc); 2406 } 2407 rc = __s_add_attr(e, "ipServiceProtocol", ptr->s_proto); 2408 if (rc != NS_LDAP_SUCCESS) { 2409 __s_cvt_freeEntryRdn(entry, rdn); 2410 return (rc); 2411 } 2412 2413 return (NS_LDAP_SUCCESS); 2414 } 2415 2416 /* 2417 * Conversion: networks 2418 * Input format: struct netent 2419 * Exported objectclass: ipNetwork 2420 */ 2421 static int 2422 __s_cvt_networks(const void *data, char **rdn, 2423 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2424 { 2425 ns_ldap_entry_t *e; 2426 int rc; 2427 char trdn[RDNSIZE]; 2428 /* routine specific */ 2429 struct netent *ptr; 2430 int max_attr = 4; 2431 int i, j; 2432 char cp[64]; 2433 char **nm; 2434 static char *oclist[] = { 2435 "ipNetwork", 2436 "top", 2437 NULL 2438 }; 2439 2440 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2441 return (NS_LDAP_OP_FAILED); 2442 *entry = e = __s_mk_entry(oclist, max_attr); 2443 if (e == NULL) 2444 return (NS_LDAP_MEMORY); 2445 2446 /* Convert the structure */ 2447 ptr = (struct netent *)data; 2448 2449 if (ptr->n_name == NULL || ptr->n_net == 0) { 2450 __ns_ldap_freeEntry(e); 2451 *entry = NULL; 2452 return (NS_LDAP_INVALID_PARAM); 2453 } 2454 2455 (void) snprintf(cp, sizeof (cp), "%d.%d.%d.%d", 2456 (ptr->n_net & 0xFF000000) >> 24, 2457 (ptr->n_net & 0x00FF0000) >> 16, 2458 (ptr->n_net & 0x0000FF00) >> 8, 2459 (ptr->n_net & 0x000000FF)); 2460 2461 /* Create an appropriate rdn */ 2462 (void) snprintf(trdn, RDNSIZE, "ipNetworkNumber=%s", cp); 2463 *rdn = strdup(trdn); 2464 if (*rdn == NULL) { 2465 __ns_ldap_freeEntry(e); 2466 *entry = NULL; 2467 return (NS_LDAP_MEMORY); 2468 } 2469 2470 /* Error check the data and add the attributes */ 2471 if (ptr->n_aliases && ptr->n_aliases[0]) { 2472 nm = ptr->n_aliases; 2473 for (i = 0; *nm; i++, nm++) 2474 ; 2475 nm = (char **)calloc(i+2, sizeof (char *)); 2476 if (nm == NULL) { 2477 __s_cvt_freeEntryRdn(entry, rdn); 2478 return (NS_LDAP_MEMORY); 2479 } 2480 nm[0] = ptr->n_name; 2481 for (j = 0; j < i; j++) 2482 nm[j+1] = ptr->n_aliases[j]; 2483 2484 rc = __s_add_attrlist(e, "cn", nm); 2485 free(nm); 2486 nm = NULL; 2487 if (rc != NS_LDAP_SUCCESS) { 2488 __s_cvt_freeEntryRdn(entry, rdn); 2489 return (rc); 2490 } 2491 } else { 2492 rc = __s_add_attr(e, "cn", ptr->n_name); 2493 if (rc != NS_LDAP_SUCCESS) { 2494 __s_cvt_freeEntryRdn(entry, rdn); 2495 return (rc); 2496 } 2497 } 2498 2499 rc = __s_add_attr(e, "ipNetworkNumber", cp); 2500 if (rc != NS_LDAP_SUCCESS) { 2501 __s_cvt_freeEntryRdn(entry, rdn); 2502 return (rc); 2503 } 2504 2505 return (NS_LDAP_SUCCESS); 2506 2507 } 2508 /* 2509 * Conversion: netmasks 2510 * Input format: struct _ns_netmasks 2511 * Exported objectclass: ipNetwork 2512 */ 2513 static int 2514 __s_cvt_netmasks(const void *data, char **rdn, 2515 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2516 { 2517 ns_ldap_entry_t *e; 2518 int rc; 2519 char trdn[RDNSIZE]; 2520 /* routine specific */ 2521 struct _ns_netmasks *ptr; 2522 int max_attr = 4; 2523 static char *oclist[] = { 2524 "ipNetwork", 2525 "top", 2526 NULL 2527 }; 2528 2529 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2530 return (NS_LDAP_OP_FAILED); 2531 *entry = e = __s_mk_entry(oclist, max_attr); 2532 if (e == NULL) 2533 return (NS_LDAP_MEMORY); 2534 2535 /* Convert the structure */ 2536 ptr = (struct _ns_netmasks *)data; 2537 2538 if (ptr->netnumber == NULL) { 2539 __ns_ldap_freeEntry(e); 2540 *entry = NULL; 2541 return (NS_LDAP_INVALID_PARAM); 2542 } 2543 2544 /* Create an appropriate rdn */ 2545 (void) snprintf(trdn, RDNSIZE, "ipNetworkNumber=%s", ptr->netnumber); 2546 *rdn = strdup(trdn); 2547 if (*rdn == NULL) { 2548 __ns_ldap_freeEntry(e); 2549 *entry = NULL; 2550 return (NS_LDAP_MEMORY); 2551 } 2552 2553 /* Error check the data and add the attributes */ 2554 rc = __s_add_attr(e, "ipNetworkNumber", ptr->netnumber); 2555 if (rc != NS_LDAP_SUCCESS) { 2556 __s_cvt_freeEntryRdn(entry, rdn); 2557 return (rc); 2558 } 2559 2560 if (ptr->netmask != '\0') { 2561 rc = __s_add_attr(e, "ipNetmaskNumber", ptr->netmask); 2562 if (rc != NS_LDAP_SUCCESS) { 2563 __s_cvt_freeEntryRdn(entry, rdn); 2564 return (rc); 2565 } 2566 } 2567 2568 return (NS_LDAP_SUCCESS); 2569 2570 } 2571 /* 2572 * Conversion: netgroups 2573 * Input format: struct _ns_netgroups 2574 * Exported objectclass: nisNetgroup 2575 */ 2576 static int 2577 __s_cvt_netgroups(const void *data, char **rdn, 2578 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2579 { 2580 ns_ldap_entry_t *e; 2581 int rc; 2582 char trdn[RDNSIZE]; 2583 /* routine specific */ 2584 struct _ns_netgroups *ptr; 2585 int max_attr = 6; 2586 int i, j; 2587 char **nm; 2588 static char *oclist[] = { 2589 "nisNetgroup", 2590 "top", 2591 NULL 2592 }; 2593 2594 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2595 return (NS_LDAP_OP_FAILED); 2596 *entry = e = __s_mk_entry(oclist, max_attr); 2597 if (e == NULL) 2598 return (NS_LDAP_MEMORY); 2599 2600 /* Convert the structure */ 2601 ptr = (struct _ns_netgroups *)data; 2602 2603 if (ptr->name == NULL) { 2604 __ns_ldap_freeEntry(e); 2605 *entry = NULL; 2606 return (NS_LDAP_INVALID_PARAM); 2607 } 2608 2609 /* Create an appropriate rdn */ 2610 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name); 2611 *rdn = strdup(trdn); 2612 if (*rdn == NULL) { 2613 __ns_ldap_freeEntry(e); 2614 *entry = NULL; 2615 return (NS_LDAP_MEMORY); 2616 } 2617 2618 if (ptr->name != '\0') { 2619 rc = __s_add_attr(e, "cn", ptr->name); 2620 if (rc != NS_LDAP_SUCCESS) { 2621 __s_cvt_freeEntryRdn(entry, rdn); 2622 return (rc); 2623 } 2624 } 2625 2626 /* Error check the data and add the attributes */ 2627 if (ptr->triplet && ptr->triplet[0]) { 2628 nm = ptr->triplet; 2629 for (i = 0; *nm; i++, nm++) 2630 ; 2631 nm = (char **)calloc(i+2, sizeof (char *)); 2632 if (nm == NULL) { 2633 __s_cvt_freeEntryRdn(entry, rdn); 2634 return (NS_LDAP_MEMORY); 2635 } 2636 for (j = 0; j < i; j++) 2637 nm[j] = ptr->triplet[j]; 2638 2639 rc = __s_add_attrlist(e, "nisNetgroupTriple", nm); 2640 free(nm); 2641 nm = NULL; 2642 if (rc != NS_LDAP_SUCCESS) { 2643 __s_cvt_freeEntryRdn(entry, rdn); 2644 return (rc); 2645 } 2646 } 2647 if (ptr->netgroup && ptr->netgroup[0]) { 2648 nm = ptr->netgroup; 2649 for (i = 0; *nm; i++, nm++) 2650 ; 2651 nm = (char **)calloc(i+2, sizeof (char *)); 2652 if (nm == NULL) { 2653 __s_cvt_freeEntryRdn(entry, rdn); 2654 return (NS_LDAP_MEMORY); 2655 } 2656 for (j = 0; j < i; j++) 2657 nm[j] = ptr->netgroup[j]; 2658 2659 rc = __s_add_attrlist(e, "memberNisNetgroup", nm); 2660 free(nm); 2661 nm = NULL; 2662 if (rc != NS_LDAP_SUCCESS) { 2663 __s_cvt_freeEntryRdn(entry, rdn); 2664 return (rc); 2665 } 2666 } 2667 return (NS_LDAP_SUCCESS); 2668 } 2669 /* 2670 * Conversion: bootparams 2671 * Input format: struct _ns_bootp 2672 * Exported objectclass: bootableDevice, device 2673 */ 2674 static int 2675 __s_cvt_bootparams(const void *data, char **rdn, 2676 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2677 { 2678 ns_ldap_entry_t *e; 2679 int rc; 2680 char trdn[RDNSIZE]; 2681 /* routine specific */ 2682 struct _ns_bootp *ptr; 2683 int max_attr = 4; 2684 int i, j; 2685 char **nm; 2686 static char *oclist[] = { 2687 "bootableDevice", 2688 "device", 2689 "top", 2690 NULL 2691 }; 2692 2693 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2694 return (NS_LDAP_OP_FAILED); 2695 *entry = e = __s_mk_entry(oclist, max_attr); 2696 if (e == NULL) 2697 return (NS_LDAP_MEMORY); 2698 2699 /* Convert the structure */ 2700 ptr = (struct _ns_bootp *)data; 2701 2702 if (ptr->name == NULL) { 2703 __ns_ldap_freeEntry(e); 2704 *entry = NULL; 2705 return (NS_LDAP_INVALID_PARAM); 2706 } 2707 2708 /* Create an appropriate rdn */ 2709 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name); 2710 *rdn = strdup(trdn); 2711 if (*rdn == NULL) { 2712 __ns_ldap_freeEntry(e); 2713 *entry = NULL; 2714 return (NS_LDAP_MEMORY); 2715 } 2716 2717 if (ptr->name != '\0') { 2718 rc = __s_add_attr(e, "cn", ptr->name); 2719 if (rc != NS_LDAP_SUCCESS) { 2720 __s_cvt_freeEntryRdn(entry, rdn); 2721 return (rc); 2722 } 2723 } 2724 2725 /* Error check the data and add the attributes */ 2726 if (ptr->param && ptr->param[0]) { 2727 nm = ptr->param; 2728 for (i = 0; *nm; i++, nm++) 2729 ; 2730 nm = (char **)calloc(i+2, sizeof (char *)); 2731 if (nm == NULL) { 2732 __s_cvt_freeEntryRdn(entry, rdn); 2733 return (NS_LDAP_MEMORY); 2734 } 2735 for (j = 0; j < i; j++) 2736 nm[j] = ptr->param[j]; 2737 2738 rc = __s_add_attrlist(e, "bootParameter", nm); 2739 free(nm); 2740 nm = NULL; 2741 if (rc != NS_LDAP_SUCCESS) { 2742 __s_cvt_freeEntryRdn(entry, rdn); 2743 return (rc); 2744 } 2745 } 2746 2747 return (NS_LDAP_SUCCESS); 2748 2749 } 2750 /* 2751 * Conversion: ethers 2752 * Input format: struct _ns_ethers 2753 * Exported objectclass: ieee802Device, device 2754 */ 2755 static int 2756 __s_cvt_ethers(const void *data, char **rdn, 2757 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2758 { 2759 ns_ldap_entry_t *e; 2760 int rc; 2761 char trdn[RDNSIZE]; 2762 /* routine specific */ 2763 struct _ns_ethers *ptr; 2764 int max_attr = 4; 2765 static char *oclist[] = { 2766 "ieee802Device", 2767 "device", 2768 "top", 2769 NULL 2770 }; 2771 2772 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2773 return (NS_LDAP_OP_FAILED); 2774 *entry = e = __s_mk_entry(oclist, max_attr); 2775 if (e == NULL) 2776 return (NS_LDAP_MEMORY); 2777 2778 /* Convert the structure */ 2779 ptr = (struct _ns_ethers *)data; 2780 2781 if (ptr->name == NULL || ptr->ether == '\0') { 2782 __ns_ldap_freeEntry(e); 2783 *entry = NULL; 2784 return (NS_LDAP_INVALID_PARAM); 2785 } 2786 2787 /* Create an appropriate rdn */ 2788 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name); 2789 *rdn = strdup(trdn); 2790 if (*rdn == NULL) { 2791 __ns_ldap_freeEntry(e); 2792 *entry = NULL; 2793 return (NS_LDAP_MEMORY); 2794 } 2795 2796 /* Error check the data and add the attributes */ 2797 rc = __s_add_attr(e, "cn", ptr->name); 2798 if (rc != NS_LDAP_SUCCESS) { 2799 __s_cvt_freeEntryRdn(entry, rdn); 2800 return (rc); 2801 } 2802 2803 rc = __s_add_attr(e, "macAddress", ptr->ether); 2804 if (rc != NS_LDAP_SUCCESS) { 2805 __s_cvt_freeEntryRdn(entry, rdn); 2806 return (rc); 2807 } 2808 2809 return (NS_LDAP_SUCCESS); 2810 } 2811 /* 2812 * This function is used when processing an ethers (objectclass: ieee802Device) 2813 * or a bootparams (objectclass: bootableDevice) entry, and the entry is 2814 * already found in LDAP. Since both ethers and bootparams share the same 2815 * LDAP container, we want to check that the entry found in LDAP is: 2816 * - either the same entry (same cn, same objectclass): we don't do anything 2817 * in this case 2818 * - or an entry which does not have the objectclass we are interesting in: 2819 * in this case, we modify the existing entry by adding the relevant 2820 * objectclass (ieee802Device or bootableDevice) and the relevant attribute(s) 2821 * from the attribute list previously computing by the relevant conversion 2822 * function. 2823 * Note: from conversion functions __s_cvt_ethers() and __s_cvt_bootparams() 2824 * we know that there is only 1 more attribute today to add (macAddress 2825 * or bootParameter) 2826 */ 2827 #define _MAX_ATTR_ETHBOOTP 2 2828 static int 2829 modify_ethers_bootp( 2830 const char *service, 2831 const char *rdn, 2832 const char *fulldn, 2833 const ns_ldap_attr_t * const *attrlist, 2834 const ns_cred_t *cred, 2835 const int flags, 2836 ns_ldap_error_t **errorp) 2837 { 2838 char filter[BUFSIZ]; 2839 ns_ldap_result_t *resultp; 2840 int rc = 0; 2841 int i; 2842 ns_ldap_attr_t *new_attrlist[_MAX_ATTR_ETHBOOTP+1]; 2843 ns_ldap_attr_t new_attrlist0; 2844 char *new_attrvalue0[1]; 2845 const ns_ldap_attr_t * const *aptr = attrlist; 2846 ns_ldap_attr_t *aptr2; 2847 ns_ldap_error_t *new_errorp = NULL; 2848 2849 if (rdn == NULL || fulldn == NULL || attrlist == NULL || 2850 errorp == NULL || service == NULL) 2851 return (NS_LDAP_OP_FAILED); 2852 2853 bzero(&new_attrlist, sizeof (new_attrlist)); 2854 bzero(&new_attrlist0, sizeof (new_attrlist0)); 2855 new_attrlist[0] = &new_attrlist0; 2856 new_attrlist[0]->attrvalue = new_attrvalue0; 2857 2858 new_attrlist[0]->attrname = "objectclass"; 2859 new_attrlist[0]->value_count = 1; 2860 if (strcasecmp(service, "ethers") == NULL) { 2861 (void) snprintf(&filter[0], sizeof (filter), 2862 "(&(objectClass=ieee802Device)(%s))", rdn); 2863 new_attrlist[0]->attrvalue[0] = "ieee802Device"; 2864 } else { 2865 (void) snprintf(&filter[0], sizeof (filter), 2866 "(&(objectClass=bootableDevice)(%s))", rdn); 2867 new_attrlist[0]->attrvalue[0] = "bootableDevice"; 2868 } 2869 2870 rc = __ns_ldap_list(service, filter, NULL, (const char **)NULL, 2871 NULL, NS_LDAP_SCOPE_SUBTREE, &resultp, &new_errorp, 2872 NULL, NULL); 2873 2874 switch (rc) { 2875 case NS_LDAP_SUCCESS: 2876 /* 2877 * entry already exists for this service 2878 * return NS_LDAP_INTERNAL and do not modify the incoming errorp 2879 */ 2880 rc = NS_LDAP_INTERNAL; 2881 break; 2882 case NS_LDAP_NOTFOUND: 2883 /* 2884 * entry not found with the given objectclasss but entry exists 2885 * hence add the relevant attribute (macAddress or bootparams). 2886 */ 2887 i = 1; 2888 while (*aptr && (i < _MAX_ATTR_ETHBOOTP)) { 2889 /* aptr2 needed here to avoid lint warning */ 2890 aptr2 = (ns_ldap_attr_t *)*aptr++; 2891 if ((strcasecmp(aptr2->attrname, "cn") != 0) && 2892 (strcasecmp(aptr2->attrname, 2893 "objectclass") != 0)) { 2894 new_attrlist[i++] = (ns_ldap_attr_t *)aptr2; 2895 } 2896 } 2897 2898 if (i != _MAX_ATTR_ETHBOOTP) { 2899 /* we haven't found all expected attributes */ 2900 rc = NS_LDAP_OP_FAILED; 2901 break; 2902 } 2903 2904 aptr = (const ns_ldap_attr_t * const *) new_attrlist; 2905 /* clean errorp first */ 2906 (void) __ns_ldap_freeError(errorp); 2907 rc = __ns_ldap_addAttr(service, fulldn, aptr, cred, flags, 2908 errorp); 2909 break; 2910 default: 2911 /* 2912 * unexpected error happenned 2913 * returning relevant error 2914 */ 2915 (void) __ns_ldap_freeError(errorp); 2916 *errorp = new_errorp; 2917 break; 2918 } 2919 2920 return (rc); 2921 } 2922 2923 /* 2924 * Conversion: publickey 2925 * Input format: struct _ns_pubkey 2926 * Exported objectclass: NisKeyObject 2927 */ 2928 static int 2929 __s_cvt_publickey(const void *data, char **rdn, 2930 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2931 { 2932 ns_ldap_entry_t *e; 2933 int rc; 2934 char trdn[RDNSIZE]; 2935 /* routine specific */ 2936 struct _ns_pubkey *ptr; 2937 int max_attr = 3; 2938 static char *oclist[] = { 2939 "NisKeyObject", 2940 NULL 2941 }; 2942 2943 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2944 return (NS_LDAP_OP_FAILED); 2945 *entry = e = __s_mk_entry(oclist, max_attr); 2946 if (e == NULL) 2947 return (NS_LDAP_MEMORY); 2948 2949 /* Convert the structure */ 2950 ptr = (struct _ns_pubkey *)data; 2951 2952 if (ptr->name == NULL || ptr->pubkey == '\0' || ptr->privkey == '\0') { 2953 __ns_ldap_freeEntry(e); 2954 *entry = NULL; 2955 return (NS_LDAP_INVALID_PARAM); 2956 } 2957 2958 /* Create an appropriate rdn */ 2959 if (ptr->hostcred == NS_HOSTCRED_FALSE) 2960 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->name); 2961 else 2962 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name); 2963 *rdn = strdup(trdn); 2964 if (*rdn == NULL) { 2965 __ns_ldap_freeEntry(e); 2966 *entry = NULL; 2967 return (NS_LDAP_MEMORY); 2968 } 2969 2970 /* Error check the data and add the attributes */ 2971 2972 rc = __s_add_attr(e, "nisPublickey", ptr->pubkey); 2973 if (rc != NS_LDAP_SUCCESS) { 2974 __s_cvt_freeEntryRdn(entry, rdn); 2975 return (rc); 2976 } 2977 2978 rc = __s_add_attr(e, "nisSecretkey", ptr->privkey); 2979 if (rc != NS_LDAP_SUCCESS) { 2980 __s_cvt_freeEntryRdn(entry, rdn); 2981 return (rc); 2982 } 2983 2984 return (NS_LDAP_SUCCESS); 2985 } 2986 /* 2987 * Conversion: aliases 2988 * Input format: struct _ns_alias 2989 * Exported objectclass: mailGroup 2990 */ 2991 static int 2992 __s_cvt_aliases(const void *data, char **rdn, 2993 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2994 { 2995 ns_ldap_entry_t *e; 2996 int rc; 2997 char trdn[RDNSIZE]; 2998 /* routine specific */ 2999 struct _ns_alias *ptr; 3000 int max_attr = 4; 3001 int i, j; 3002 char **nm; 3003 static char *oclist[] = { 3004 "mailGroup", 3005 "top", 3006 NULL 3007 }; 3008 3009 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3010 return (NS_LDAP_OP_FAILED); 3011 *entry = e = __s_mk_entry(oclist, max_attr); 3012 if (e == NULL) 3013 return (NS_LDAP_MEMORY); 3014 3015 /* Convert the structure */ 3016 ptr = (struct _ns_alias *)data; 3017 3018 if (ptr->alias == NULL) { 3019 __ns_ldap_freeEntry(e); 3020 *entry = NULL; 3021 return (NS_LDAP_INVALID_PARAM); 3022 } 3023 3024 /* Create an appropriate rdn */ 3025 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->alias); 3026 *rdn = strdup(trdn); 3027 if (*rdn == NULL) { 3028 __ns_ldap_freeEntry(e); 3029 *entry = NULL; 3030 return (NS_LDAP_MEMORY); 3031 } 3032 3033 if (ptr->alias != '\0') { 3034 rc = __s_add_attr(e, "mail", (char *)ptr->alias); 3035 if (rc != NS_LDAP_SUCCESS) { 3036 __s_cvt_freeEntryRdn(entry, rdn); 3037 return (rc); 3038 } 3039 } 3040 3041 /* Error check the data and add the attributes */ 3042 if (ptr->member && ptr->member[0]) { 3043 nm = ptr->member; 3044 for (i = 0; *nm; i++, nm++) 3045 ; 3046 nm = (char **)calloc(i+2, sizeof (char *)); 3047 if (nm == NULL) { 3048 __s_cvt_freeEntryRdn(entry, rdn); 3049 return (NS_LDAP_MEMORY); 3050 } 3051 for (j = 0; j < i; j++) 3052 nm[j] = ptr->member[j]; 3053 3054 rc = __s_add_attrlist(e, "mgrpRFC822MailMember", nm); 3055 free(nm); 3056 nm = NULL; 3057 if (rc != NS_LDAP_SUCCESS) { 3058 __s_cvt_freeEntryRdn(entry, rdn); 3059 return (rc); 3060 } 3061 } 3062 3063 return (NS_LDAP_SUCCESS); 3064 3065 } 3066 /* 3067 * Conversion: automount 3068 * Input format: struct _ns_automount 3069 * Exported objectclass: automount 3070 */ 3071 static int 3072 __s_cvt_auto_mount(const void *data, char **rdn, 3073 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3074 { 3075 ns_ldap_entry_t *e; 3076 int rc; 3077 char trdn[RDNSIZE]; 3078 /* routine specific */ 3079 struct _ns_automount *ptr; 3080 int max_attr = 6; 3081 void **paramVal = NULL; 3082 char **mappedschema = NULL; 3083 int version1 = 0; 3084 static char *oclist[] = { 3085 NULL, 3086 "top", 3087 NULL 3088 }; 3089 3090 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3091 return (NS_LDAP_OP_FAILED); 3092 3093 /* determine profile version number */ 3094 rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, ¶mVal, errorp); 3095 if (paramVal && *paramVal && 3096 strcasecmp(*paramVal, NS_LDAP_VERSION_1) == 0) 3097 version1 = 1; 3098 if (paramVal) 3099 (void) __ns_ldap_freeParam(¶mVal); 3100 if (rc && errorp) 3101 (void) __ns_ldap_freeError(errorp); 3102 3103 /* use old schema for version 1 profiles */ 3104 if (version1) 3105 oclist[0] = "nisObject"; 3106 else 3107 oclist[0] = "automount"; 3108 3109 *entry = e = __s_mk_entry(oclist, max_attr); 3110 if (e == NULL) 3111 return (NS_LDAP_MEMORY); 3112 3113 /* Convert the structure */ 3114 ptr = (struct _ns_automount *)data; 3115 3116 if (ptr->key == NULL || ptr->value == '\0' || ptr->mapname == '\0') { 3117 __ns_ldap_freeEntry(e); 3118 *entry = NULL; 3119 return (NS_LDAP_INVALID_PARAM); 3120 } 3121 3122 /* Create an appropriate rdn */ 3123 (void) snprintf(trdn, RDNSIZE, version1 ? "cn=%s" : "automountKey=%s", 3124 ptr->key); 3125 *rdn = strdup(trdn); 3126 if (*rdn == NULL) { 3127 __ns_ldap_freeEntry(e); 3128 *entry = NULL; 3129 return (NS_LDAP_MEMORY); 3130 } 3131 3132 if (ptr->key != '\0') { 3133 rc = __s_add_attr(e, version1 ? "cn" : "automountKey", 3134 (char *)ptr->key); 3135 if (rc != NS_LDAP_SUCCESS) { 3136 __s_cvt_freeEntryRdn(entry, rdn); 3137 return (rc); 3138 } 3139 } 3140 3141 rc = __s_add_attr(e, version1 ? "nisMapEntry" : "automountInformation", 3142 (char *)ptr->value); 3143 if (rc != NS_LDAP_SUCCESS) { 3144 __s_cvt_freeEntryRdn(entry, rdn); 3145 return (rc); 3146 } 3147 3148 /* 3149 * even for version 2, if automount is mapped to nisObject we 3150 * still need 'nisMapName' attribute 3151 */ 3152 mappedschema = __ns_ldap_getMappedObjectClass("automount", "automount"); 3153 if (mappedschema && mappedschema[0] && 3154 strcasecmp(mappedschema[0], "nisObject") == 0) 3155 version1 = 1; 3156 if (mappedschema) 3157 __s_api_free2dArray(mappedschema); 3158 3159 if (version1) { 3160 rc = __s_add_attr(e, "nisMapName", (char *)ptr->mapname); 3161 if (rc != NS_LDAP_SUCCESS) { 3162 __s_cvt_freeEntryRdn(entry, rdn); 3163 return (rc); 3164 } 3165 } 3166 3167 return (NS_LDAP_SUCCESS); 3168 } 3169 /* 3170 * Conversion: auth_attr 3171 * Input format: authstr_t 3172 * Exported objectclass: SolarisAuthAttr 3173 */ 3174 static int 3175 __s_cvt_authattr(const void *data, char **rdn, 3176 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3177 { 3178 ns_ldap_entry_t *e; 3179 int rc; 3180 char trdn[RDNSIZE]; 3181 /* routine specific */ 3182 authstr_t *ptr; 3183 int max_attr = 6; 3184 static char *oclist[] = { 3185 "SolarisAuthAttr", 3186 "top", 3187 NULL 3188 }; 3189 3190 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3191 return (NS_LDAP_OP_FAILED); 3192 3193 *entry = e = __s_mk_entry(oclist, max_attr); 3194 if (e == NULL) 3195 return (NS_LDAP_MEMORY); 3196 3197 /* Convert the structure */ 3198 ptr = (authstr_t *)data; 3199 3200 if (ptr->name == NULL || ptr->name[0] == '\0' || ptr->attr == NULL) { 3201 __ns_ldap_freeEntry(e); 3202 *entry = NULL; 3203 return (NS_LDAP_INVALID_PARAM); 3204 } 3205 3206 /* Create an appropriate rdn */ 3207 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name); 3208 *rdn = strdup(trdn); 3209 if (*rdn == NULL) { 3210 __ns_ldap_freeEntry(e); 3211 *entry = NULL; 3212 return (NS_LDAP_MEMORY); 3213 } 3214 3215 rc = __s_add_attr(e, "cn", ptr->name); 3216 if (rc != NS_LDAP_SUCCESS) { 3217 __s_cvt_freeEntryRdn(entry, rdn); 3218 return (rc); 3219 } 3220 3221 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr); 3222 if (rc != NS_LDAP_SUCCESS) { 3223 __s_cvt_freeEntryRdn(entry, rdn); 3224 return (rc); 3225 } 3226 3227 if (ptr->res1 != NULL) { 3228 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1); 3229 if (rc != NS_LDAP_SUCCESS) { 3230 __s_cvt_freeEntryRdn(entry, rdn); 3231 return (rc); 3232 } 3233 } 3234 3235 if (ptr->res2 != NULL) { 3236 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2); 3237 if (rc != NS_LDAP_SUCCESS) { 3238 __s_cvt_freeEntryRdn(entry, rdn); 3239 return (rc); 3240 } 3241 } 3242 3243 if (ptr->short_desc != NULL) { 3244 rc = __s_add_attr(e, "SolarisAttrShortDesc", ptr->short_desc); 3245 if (rc != NS_LDAP_SUCCESS) { 3246 __s_cvt_freeEntryRdn(entry, rdn); 3247 return (rc); 3248 } 3249 } 3250 3251 if (ptr->long_desc != NULL) { 3252 rc = __s_add_attr(e, "SolarisAttrLongDesc", ptr->long_desc); 3253 if (rc != NS_LDAP_SUCCESS) { 3254 __s_cvt_freeEntryRdn(entry, rdn); 3255 return (rc); 3256 } 3257 } 3258 3259 return (NS_LDAP_SUCCESS); 3260 } 3261 /* 3262 * Conversion: exec_attr 3263 * Input format: execstr_t 3264 * Exported objectclass: SolarisExecAttr 3265 */ 3266 static int 3267 __s_cvt_execattr(const void *data, char **rdn, 3268 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3269 { 3270 ns_ldap_entry_t *e; 3271 int rc; 3272 char trdn[RDNSIZE]; 3273 char esc_str[RDNSIZE]; 3274 /* routine specific */ 3275 execstr_t *ptr; 3276 int max_attr = 7; 3277 static char *oclist[] = { 3278 "SolarisExecAttr", 3279 "SolarisProfAttr", 3280 "top", 3281 NULL 3282 }; 3283 3284 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3285 return (NS_LDAP_OP_FAILED); 3286 3287 *entry = e = __s_mk_entry(oclist, max_attr); 3288 if (e == NULL) 3289 return (NS_LDAP_MEMORY); 3290 3291 /* Convert the structure */ 3292 ptr = (execstr_t *)data; 3293 3294 if (ptr->name == NULL || ptr->name[0] == '\0' || 3295 ptr->policy == NULL || ptr->policy[0] == '\0' || 3296 ptr->type == NULL || ptr->type[0] == '\0' || 3297 ptr->id == NULL || ptr->id[0] == '\0') { 3298 __ns_ldap_freeEntry(e); 3299 *entry = NULL; 3300 return (NS_LDAP_INVALID_PARAM); 3301 } 3302 3303 /* 3304 * Escape special characters in ProfileID. 3305 */ 3306 if (escape_str(esc_str, ptr->id) != 0) { 3307 __ns_ldap_freeEntry(e); 3308 *entry = NULL; 3309 return (NS_LDAP_INVALID_PARAM); 3310 } 3311 3312 /* Create an appropriate rdn */ 3313 (void) snprintf(trdn, RDNSIZE, "cn=%s+SolarisKernelSecurityPolicy=%s" 3314 "+SolarisProfileType=%s+SolarisProfileId=%s", 3315 ptr->name, ptr->policy, ptr->type, esc_str); 3316 3317 *rdn = strdup(trdn); 3318 if (*rdn == NULL) { 3319 __ns_ldap_freeEntry(e); 3320 *entry = NULL; 3321 return (NS_LDAP_MEMORY); 3322 } 3323 3324 rc = __s_add_attr(e, "cn", ptr->name); 3325 if (rc != NS_LDAP_SUCCESS) { 3326 __s_cvt_freeEntryRdn(entry, rdn); 3327 return (rc); 3328 } 3329 3330 rc = __s_add_attr(e, "SolarisKernelSecurityPolicy", ptr->policy); 3331 if (rc != NS_LDAP_SUCCESS) { 3332 __s_cvt_freeEntryRdn(entry, rdn); 3333 return (rc); 3334 } 3335 3336 rc = __s_add_attr(e, "SolarisProfileType", ptr->type); 3337 if (rc != NS_LDAP_SUCCESS) { 3338 __s_cvt_freeEntryRdn(entry, rdn); 3339 return (rc); 3340 } 3341 3342 rc = __s_add_attr(e, "SolarisProfileId", ptr->id); 3343 if (rc != NS_LDAP_SUCCESS) { 3344 __s_cvt_freeEntryRdn(entry, rdn); 3345 return (rc); 3346 } 3347 3348 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr); 3349 if (rc != NS_LDAP_SUCCESS) { 3350 __s_cvt_freeEntryRdn(entry, rdn); 3351 return (rc); 3352 } 3353 3354 if (ptr->res1 != NULL) { 3355 rc = __s_add_attr(e, "SolarisAttrRes1", ptr->res1); 3356 if (rc != NS_LDAP_SUCCESS) { 3357 __s_cvt_freeEntryRdn(entry, rdn); 3358 return (rc); 3359 } 3360 } 3361 3362 if (ptr->res2 != NULL) { 3363 rc = __s_add_attr(e, "SolarisAttrRes2", ptr->res2); 3364 if (rc != NS_LDAP_SUCCESS) { 3365 __s_cvt_freeEntryRdn(entry, rdn); 3366 return (rc); 3367 } 3368 } 3369 3370 return (NS_LDAP_SUCCESS); 3371 } 3372 /* 3373 * Conversion: prof_attr 3374 * Input format: profstr_t 3375 * Exported objectclass: SolarisProfAttr 3376 */ 3377 static int 3378 __s_cvt_profattr(const void *data, char **rdn, 3379 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3380 { 3381 ns_ldap_entry_t *e; 3382 int rc; 3383 char trdn[RDNSIZE]; 3384 /* routine specific */ 3385 profstr_t *ptr; 3386 int max_attr = 5; 3387 static char *oclist[] = { 3388 "SolarisProfAttr", 3389 "top", 3390 NULL 3391 }; 3392 3393 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3394 return (NS_LDAP_OP_FAILED); 3395 3396 *entry = e = __s_mk_entry(oclist, max_attr); 3397 if (e == NULL) 3398 return (NS_LDAP_MEMORY); 3399 3400 /* Convert the structure */ 3401 ptr = (profstr_t *)data; 3402 3403 if (ptr->name == NULL || ptr->name[0] == '\0' || ptr->attr == NULL) { 3404 __ns_ldap_freeEntry(e); 3405 *entry = NULL; 3406 return (NS_LDAP_INVALID_PARAM); 3407 } 3408 3409 /* Create an appropriate rdn */ 3410 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name); 3411 *rdn = strdup(trdn); 3412 if (*rdn == NULL) { 3413 __ns_ldap_freeEntry(e); 3414 *entry = NULL; 3415 return (NS_LDAP_MEMORY); 3416 } 3417 3418 rc = __s_add_attr(e, "cn", ptr->name); 3419 if (rc != NS_LDAP_SUCCESS) { 3420 __s_cvt_freeEntryRdn(entry, rdn); 3421 return (rc); 3422 } 3423 3424 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr); 3425 if (rc != NS_LDAP_SUCCESS) { 3426 __s_cvt_freeEntryRdn(entry, rdn); 3427 return (rc); 3428 } 3429 3430 if (ptr->res1 != NULL) { 3431 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1); 3432 if (rc != NS_LDAP_SUCCESS) { 3433 __s_cvt_freeEntryRdn(entry, rdn); 3434 return (rc); 3435 } 3436 } 3437 3438 if (ptr->res2 != NULL) { 3439 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2); 3440 if (rc != NS_LDAP_SUCCESS) { 3441 __s_cvt_freeEntryRdn(entry, rdn); 3442 return (rc); 3443 } 3444 } 3445 3446 if (ptr->desc != NULL) { 3447 rc = __s_add_attr(e, "SolarisAttrLongDesc", ptr->desc); 3448 if (rc != NS_LDAP_SUCCESS) { 3449 __s_cvt_freeEntryRdn(entry, rdn); 3450 return (rc); 3451 } 3452 } 3453 3454 return (NS_LDAP_SUCCESS); 3455 } 3456 /* 3457 * Conversion: user_attr 3458 * Input format: userstr_t 3459 * Exported objectclass: SolarisUserAttr 3460 */ 3461 static int 3462 __s_cvt_userattr(const void *data, char **rdn, 3463 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3464 { 3465 ns_ldap_entry_t *e; 3466 int rc; 3467 char trdn[RDNSIZE]; 3468 /* routine specific */ 3469 userstr_t *ptr; 3470 int max_attr = 5; 3471 static char *oclist[] = { 3472 "SolarisUserAttr", 3473 NULL 3474 }; 3475 3476 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3477 return (NS_LDAP_OP_FAILED); 3478 3479 *entry = e = __s_mk_entry(oclist, max_attr); 3480 if (e == NULL) 3481 return (NS_LDAP_MEMORY); 3482 3483 /* Convert the structure */ 3484 ptr = (userstr_t *)data; 3485 3486 if (ptr->name == NULL || ptr->name[0] == '\0' || 3487 ptr->attr == NULL) { 3488 __ns_ldap_freeEntry(e); 3489 *entry = NULL; 3490 return (NS_LDAP_INVALID_PARAM); 3491 } 3492 3493 /* Create an appropriate rdn */ 3494 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->name); 3495 *rdn = strdup(trdn); 3496 if (*rdn == NULL) { 3497 __ns_ldap_freeEntry(e); 3498 *entry = NULL; 3499 return (NS_LDAP_MEMORY); 3500 } 3501 3502 /* 3503 * SolarisUserAttr has no uid attribute 3504 */ 3505 3506 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr); 3507 if (rc != NS_LDAP_SUCCESS) { 3508 __s_cvt_freeEntryRdn(entry, rdn); 3509 return (rc); 3510 } 3511 3512 if (ptr->qualifier != NULL) { 3513 rc = __s_add_attr(e, "SolarisUserQualifier", ptr->qualifier); 3514 if (rc != NS_LDAP_SUCCESS) { 3515 __s_cvt_freeEntryRdn(entry, rdn); 3516 return (rc); 3517 } 3518 } 3519 3520 if (ptr->res1 != NULL) { 3521 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1); 3522 if (rc != NS_LDAP_SUCCESS) { 3523 __s_cvt_freeEntryRdn(entry, rdn); 3524 return (rc); 3525 } 3526 } 3527 3528 if (ptr->res2 != NULL) { 3529 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2); 3530 if (rc != NS_LDAP_SUCCESS) { 3531 __s_cvt_freeEntryRdn(entry, rdn); 3532 return (rc); 3533 } 3534 } 3535 3536 return (NS_LDAP_SUCCESS); 3537 } 3538 /* 3539 * Conversion: audit_user 3540 * Input format: au_user_str_t 3541 * Exported objectclass: SolarisAuditUser 3542 */ 3543 static int 3544 __s_cvt_audituser(const void *data, char **rdn, 3545 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3546 { 3547 ns_ldap_entry_t *e; 3548 int rc; 3549 char trdn[RDNSIZE]; 3550 /* routine specific */ 3551 au_user_str_t *ptr; 3552 int max_attr = 3; 3553 static char *oclist[] = { 3554 "SolarisAuditUser", 3555 NULL 3556 }; 3557 3558 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3559 return (NS_LDAP_OP_FAILED); 3560 3561 *entry = e = __s_mk_entry(oclist, max_attr); 3562 if (e == NULL) 3563 return (NS_LDAP_MEMORY); 3564 3565 /* Convert the structure */ 3566 ptr = (au_user_str_t *)data; 3567 3568 if (ptr->au_name == NULL || ptr->au_name[0] == '\0') { 3569 __ns_ldap_freeEntry(e); 3570 *entry = NULL; 3571 return (NS_LDAP_INVALID_PARAM); 3572 } 3573 3574 /* Create an appropriate rdn */ 3575 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->au_name); 3576 *rdn = strdup(trdn); 3577 if (*rdn == NULL) { 3578 __ns_ldap_freeEntry(e); 3579 *entry = NULL; 3580 return (NS_LDAP_MEMORY); 3581 } 3582 3583 /* 3584 * Solaris AuditUser has no uid attribute 3585 */ 3586 3587 if (ptr->au_always != NULL) { 3588 rc = __s_add_attr(e, "SolarisAuditAlways", ptr->au_always); 3589 if (rc != NS_LDAP_SUCCESS) { 3590 __s_cvt_freeEntryRdn(entry, rdn); 3591 return (rc); 3592 } 3593 } 3594 3595 if (ptr->au_never != NULL) { 3596 rc = __s_add_attr(e, "SolarisAuditNever", ptr->au_never); 3597 if (rc != NS_LDAP_SUCCESS) { 3598 __s_cvt_freeEntryRdn(entry, rdn); 3599 return (rc); 3600 } 3601 } 3602 3603 return (NS_LDAP_SUCCESS); 3604 } 3605 /* 3606 * Conversion: tnrhtp 3607 * Input format: tsol_tpstr_t 3608 * Exported objectclass: ipTnetTemplate 3609 */ 3610 static int 3611 __s_cvt_tnrhtp(const void *data, char **rdn, 3612 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3613 { 3614 ns_ldap_entry_t *e; 3615 int rc; 3616 char trdn[RDNSIZE]; 3617 char esc_str[RDNSIZE]; 3618 /* routine specific */ 3619 int max_attr = 2; 3620 tsol_tpstr_t *ptr; 3621 static char *oclist[] = { 3622 "ipTnetTemplate", 3623 "top", 3624 NULL 3625 }; 3626 3627 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3628 return (NS_LDAP_OP_FAILED); 3629 3630 *entry = e = __s_mk_entry(oclist, max_attr); 3631 if (e == NULL) 3632 return (NS_LDAP_MEMORY); 3633 3634 /* Convert the structure */ 3635 ptr = (tsol_tpstr_t *)data; 3636 3637 if (ptr->template == NULL || *ptr->template == '\0') { 3638 __ns_ldap_freeEntry(e); 3639 *entry = NULL; 3640 return (NS_LDAP_INVALID_PARAM); 3641 } 3642 3643 /* 3644 * Escape special characters in Template name. 3645 */ 3646 if (escape_str(esc_str, ptr->template) != 0) { 3647 __ns_ldap_freeEntry(e); 3648 *entry = NULL; 3649 return (NS_LDAP_INVALID_PARAM); 3650 } 3651 3652 /* Create an appropriate rdn */ 3653 (void) snprintf(trdn, RDNSIZE, "ipTnetTemplateName=%s", esc_str); 3654 *rdn = strdup(trdn); 3655 if (*rdn == NULL) { 3656 __ns_ldap_freeEntry(e); 3657 *entry = NULL; 3658 return (NS_LDAP_MEMORY); 3659 } 3660 3661 rc = __s_add_attr(e, "ipTnetTemplateName", ptr->template); 3662 if (rc != NS_LDAP_SUCCESS) { 3663 __s_cvt_freeEntryRdn(entry, rdn); 3664 return (rc); 3665 } 3666 3667 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attrs); 3668 if (rc != NS_LDAP_SUCCESS) { 3669 __s_cvt_freeEntryRdn(entry, rdn); 3670 return (rc); 3671 } 3672 3673 return (NS_LDAP_SUCCESS); 3674 } 3675 /* 3676 * Conversion: tnrhdb 3677 * Input format: tsol_rhstr_t 3678 * Exported objectclass: ipTnetHost 3679 */ 3680 static int 3681 __s_cvt_tnrhdb(const void *data, char **rdn, 3682 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3683 { 3684 ns_ldap_entry_t *e; 3685 int rc; 3686 char trdn[RDNSIZE]; 3687 /* routine specific */ 3688 tsol_rhstr_t *ptr; 3689 int max_attr = 2; 3690 static char *oclist[] = { 3691 "ipTnetHost", 3692 "ipTnetTemplate", 3693 "top", 3694 NULL 3695 }; 3696 3697 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3698 return (NS_LDAP_OP_FAILED); 3699 3700 *entry = e = __s_mk_entry(oclist, max_attr); 3701 if (e == NULL) 3702 return (NS_LDAP_MEMORY); 3703 3704 /* Convert the structure */ 3705 ptr = (tsol_rhstr_t *)data; 3706 3707 if (ptr->address == NULL || *ptr->address == '\0' || 3708 ptr->template == NULL || *ptr->template == '\0') { 3709 __ns_ldap_freeEntry(e); 3710 *entry = NULL; 3711 return (NS_LDAP_INVALID_PARAM); 3712 } 3713 3714 /* Create an appropriate rdn */ 3715 (void) snprintf(trdn, RDNSIZE, "ipTnetNumber=%s", ptr->address); 3716 *rdn = strdup(trdn); 3717 if (*rdn == NULL) { 3718 __ns_ldap_freeEntry(e); 3719 *entry = NULL; 3720 return (NS_LDAP_MEMORY); 3721 } 3722 3723 rc = __s_add_attr(e, "ipTnetNumber", ptr->address); 3724 if (rc != NS_LDAP_SUCCESS) { 3725 __s_cvt_freeEntryRdn(entry, rdn); 3726 return (rc); 3727 } 3728 3729 rc = __s_add_attr(e, "ipTnetTemplateName", ptr->template); 3730 if (rc != NS_LDAP_SUCCESS) { 3731 __s_cvt_freeEntryRdn(entry, rdn); 3732 return (rc); 3733 } 3734 3735 return (NS_LDAP_SUCCESS); 3736 } 3737 /* 3738 * Add Typed Entry Conversion data structures 3739 */ 3740 3741 typedef struct __ns_cvt_type { 3742 const char *service; 3743 int flags; 3744 #define AE 1 /* alway add entries */ 3745 int (*cvt_rtn)(const void *data, 3746 char **rdn, 3747 ns_ldap_entry_t **entry, 3748 ns_ldap_error_t **errorp); 3749 } __ns_cvt_type_t; 3750 3751 static __ns_cvt_type_t __s_cvtlist[] = { 3752 { NS_LDAP_TYPE_PASSWD, 0, __s_cvt_passwd }, 3753 { NS_LDAP_TYPE_GROUP, 0, __s_cvt_group }, 3754 { NS_LDAP_TYPE_HOSTS, 0, __s_cvt_hosts }, 3755 { NS_LDAP_TYPE_IPNODES, 0, __s_cvt_hosts }, 3756 { NS_LDAP_TYPE_RPC, 0, __s_cvt_rpc }, 3757 { NS_LDAP_TYPE_PROTOCOLS, 0, __s_cvt_protocols }, 3758 { NS_LDAP_TYPE_NETWORKS, 0, __s_cvt_networks }, 3759 { NS_LDAP_TYPE_NETGROUP, 0, __s_cvt_netgroups }, 3760 { NS_LDAP_TYPE_ALIASES, 0, __s_cvt_aliases }, 3761 { NS_LDAP_TYPE_SERVICES, 0, __s_cvt_services }, 3762 { NS_LDAP_TYPE_ETHERS, 0, __s_cvt_ethers }, 3763 { NS_LDAP_TYPE_SHADOW, 0, __s_cvt_shadow }, 3764 { NS_LDAP_TYPE_NETMASKS, 0, __s_cvt_netmasks }, 3765 { NS_LDAP_TYPE_BOOTPARAMS, 0, __s_cvt_bootparams }, 3766 { NS_LDAP_TYPE_AUTHATTR, 0, __s_cvt_authattr }, 3767 { NS_LDAP_TYPE_EXECATTR, 0, __s_cvt_execattr }, 3768 { NS_LDAP_TYPE_PROFILE, 0, __s_cvt_profattr }, 3769 { NS_LDAP_TYPE_USERATTR, AE, __s_cvt_userattr }, 3770 { NS_LDAP_TYPE_AUTOMOUNT, 0, __s_cvt_auto_mount }, 3771 { NS_LDAP_TYPE_PUBLICKEY, AE, __s_cvt_publickey }, 3772 { NS_LDAP_TYPE_AUUSER, AE, __s_cvt_audituser }, 3773 { NS_LDAP_TYPE_TNRHTP, 0, __s_cvt_tnrhtp }, 3774 { NS_LDAP_TYPE_TNRHDB, 0, __s_cvt_tnrhdb }, 3775 { NS_LDAP_TYPE_PROJECT, 0, __s_cvt_project }, 3776 { NULL, 0, NULL }, 3777 }; 3778 3779 /* 3780 * Add Typed Entry Routine 3781 */ 3782 3783 /*ARGSUSED*/ 3784 int __ns_ldap_addTypedEntry( 3785 const char *servicetype, 3786 const char *basedn, 3787 const void *data, 3788 const int create, 3789 const ns_cred_t *cred, 3790 const int flags, 3791 ns_ldap_error_t **errorp) 3792 { 3793 char *rdn = NULL, *fulldn = NULL; 3794 void **paramVal = NULL; 3795 ns_ldap_entry_t *entry = NULL; 3796 const ns_ldap_attr_t *const *modattrlist; 3797 ns_ldap_search_desc_t **sdlist; 3798 char **dns = NULL; 3799 char trdn[RDNSIZE]; 3800 char service[BUFSIZE]; 3801 int rc = 0; 3802 int automount = 0; 3803 int i, s; 3804 3805 rc = NS_LDAP_OP_FAILED; 3806 for (s = 0; __s_cvtlist[s].service != NULL; s++) { 3807 if (__s_cvtlist[s].cvt_rtn == NULL) 3808 continue; 3809 if (strcasecmp(__s_cvtlist[s].service, servicetype) == 0) 3810 break; 3811 /* Or, check if the servicetype is auto_ */ 3812 if (strcmp(__s_cvtlist[s].service, 3813 NS_LDAP_TYPE_AUTOMOUNT) == 0 && 3814 strncasecmp(servicetype, NS_LDAP_TYPE_AUTOMOUNT, 3815 sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0) { 3816 automount++; 3817 break; 3818 } 3819 } 3820 if (__s_cvtlist[s].service == NULL) 3821 return (rc); 3822 3823 /* Convert the data */ 3824 rc = (*__s_cvtlist[s].cvt_rtn)(data, &rdn, &entry, errorp); 3825 if (rc != NS_LDAP_SUCCESS) { 3826 __s_cvt_freeEntryRdn(&entry, &rdn); 3827 return (rc); 3828 } 3829 if (rdn == NULL) { 3830 __ns_ldap_freeEntry(entry); 3831 return (NS_LDAP_OP_FAILED); 3832 } 3833 3834 if (strcmp(servicetype, "publickey") == 0) { 3835 struct _ns_pubkey *ptr; 3836 ptr = (struct _ns_pubkey *)data; 3837 if (ptr->hostcred == NS_HOSTCRED_TRUE) 3838 (void) strcpy(service, "hosts"); 3839 else 3840 (void) strcpy(service, "passwd"); 3841 } else 3842 (void) strcpy(service, servicetype); 3843 3844 /* Create the Full DN */ 3845 if (basedn == NULL) { 3846 rc = __s_api_get_SSD_from_SSDtoUse_service(service, 3847 &sdlist, errorp); 3848 if (rc != NS_LDAP_SUCCESS) { 3849 __s_cvt_freeEntryRdn(&entry, &rdn); 3850 return (rc); 3851 } 3852 3853 if (sdlist == NULL) { 3854 rc = __s_api_getDNs(&dns, service, errorp); 3855 if (rc != NS_LDAP_SUCCESS) { 3856 if (dns) { 3857 __s_api_free2dArray(dns); 3858 dns = NULL; 3859 } 3860 __s_cvt_freeEntryRdn(&entry, &rdn); 3861 return (rc); 3862 } 3863 (void) snprintf(trdn, RDNSIZE, "%s,%s", rdn, dns[0]); 3864 __s_api_free2dArray(dns); 3865 } else { 3866 if (sdlist[0]->basedn) { 3867 (void) snprintf(trdn, RDNSIZE, "%s,%s", 3868 rdn, sdlist[0]->basedn); 3869 } else { 3870 __s_cvt_freeEntryRdn(&entry, &rdn); 3871 return (NS_LDAP_OP_FAILED); 3872 } 3873 } 3874 i = strlen(trdn) - 1; 3875 if (trdn[i] == COMMATOK) { 3876 rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P, 3877 ¶mVal, errorp); 3878 if (rc != NS_LDAP_SUCCESS) { 3879 __s_cvt_freeEntryRdn(&entry, &rdn); 3880 return (rc); 3881 } 3882 i = strlen(trdn) + strlen((char *)(paramVal[0])) + 1; 3883 fulldn = (char *)calloc(i, 1); 3884 if (fulldn == NULL) { 3885 (void) __ns_ldap_freeParam(¶mVal); 3886 __s_cvt_freeEntryRdn(&entry, &rdn); 3887 return (NS_LDAP_MEMORY); 3888 } 3889 (void) snprintf(fulldn, i, "%s%s", trdn, 3890 (char *)(paramVal[0])); 3891 (void) __ns_ldap_freeParam(¶mVal); 3892 } else { 3893 fulldn = strdup(trdn); 3894 if (fulldn == NULL) { 3895 __s_cvt_freeEntryRdn(&entry, &rdn); 3896 return (NS_LDAP_MEMORY); 3897 } 3898 } 3899 } else { 3900 i = strlen(rdn) + strlen(basedn) + 2; 3901 fulldn = (char *)calloc(i, 1); 3902 if (fulldn == NULL) { 3903 __s_cvt_freeEntryRdn(&entry, &rdn); 3904 return (NS_LDAP_MEMORY); 3905 } 3906 (void) snprintf(fulldn, i, "%s,%s", rdn, basedn); 3907 } 3908 3909 modattrlist = (const ns_ldap_attr_t * const *)entry->attr_pair; 3910 /* Check to see if the entry exists already */ 3911 /* May need to delete or update first */ 3912 3913 if (create != 1) { 3914 /* Modify the entry */ 3915 /* 3916 * To add a shadow-like entry, the addTypedEntry function 3917 * would call __ns_ldap_repAttr first, and if server says 3918 * LDAP_NO_SUCH_OBJECT, then it tries __ns_ldap_addEntry. 3919 * This is to allow a netmask entry to be added even if the 3920 * base network entry is not in the directory. It would work 3921 * because the difference between the schema for the network 3922 * and netmask data contains only MAY attributes. 3923 * 3924 * But for shadow data, the attributes do not have MUST 3925 * attributes the base entry needs, so if the __ns_ldap_addEntry 3926 * is executed, it would fail. The real reason, however, is that 3927 * the base entry did not exist. So returning 3928 * LDAP_OBJECT_CLASS_VIOLATION would just confused. 3929 */ 3930 if ((__s_cvtlist[s].flags & AE) != 0) 3931 rc = __ns_ldap_addAttr(service, fulldn, modattrlist, 3932 cred, flags, errorp); 3933 else { 3934 rc = __ns_ldap_repAttr(service, fulldn, modattrlist, 3935 cred, flags, errorp); 3936 if (rc == NS_LDAP_INTERNAL && *errorp && 3937 (*errorp)->status == LDAP_NO_SUCH_OBJECT) { 3938 (void) __ns_ldap_freeError(errorp); 3939 rc = __ns_ldap_addEntry(service, fulldn, 3940 entry, cred, flags, errorp); 3941 if (rc == NS_LDAP_INTERNAL && *errorp && 3942 (*errorp)->status == 3943 LDAP_OBJECT_CLASS_VIOLATION) 3944 (*errorp)->status = LDAP_NO_SUCH_OBJECT; 3945 } 3946 } 3947 } else { 3948 /* Add the entry */ 3949 rc = __ns_ldap_addEntry(service, fulldn, entry, 3950 cred, flags, errorp); 3951 if (rc == NS_LDAP_INTERNAL && *errorp && 3952 (*errorp)->status == LDAP_ALREADY_EXISTS && 3953 ((strcmp(service, "ethers") == 0) || 3954 (strcmp(service, "bootparams") == 0))) { 3955 rc = modify_ethers_bootp(service, rdn, fulldn, 3956 modattrlist, cred, flags, errorp); 3957 } 3958 } 3959 3960 /* Free up entry created by conversion routine */ 3961 if (fulldn != NULL) 3962 free(fulldn); 3963 __s_cvt_freeEntryRdn(&entry, &rdn); 3964 return (rc); 3965 } 3966 3967 3968 /* 3969 * Append the default base dn to the dn 3970 * when it ends with ','. 3971 * e.g. 3972 * SSD = service:ou=foo, 3973 */ 3974 int 3975 __s_api_append_default_basedn( 3976 const char *dn, 3977 char **new_dn, 3978 int *allocated, 3979 ns_ldap_error_t **errp) { 3980 3981 int rc = NS_LDAP_SUCCESS, len = 0; 3982 void **param = NULL; 3983 char *str = NULL; 3984 3985 *allocated = FALSE; 3986 *new_dn = NULL; 3987 3988 if (dn == NULL) 3989 return (NS_LDAP_INVALID_PARAM); 3990 3991 rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P, 3992 (void ***)¶m, errp); 3993 3994 if (rc != NS_LDAP_SUCCESS) { 3995 if (param) 3996 (void) __ns_ldap_freeParam(¶m); 3997 return (rc); 3998 } 3999 4000 len = strlen(dn); 4001 str = ((char **)param)[0]; 4002 len = len + strlen(str) +1; 4003 *new_dn = (char *)malloc(len); 4004 if (*new_dn == NULL) { 4005 (void) __ns_ldap_freeParam(¶m); 4006 return (NS_LDAP_MEMORY); 4007 } 4008 *allocated = TRUE; 4009 4010 (void) strcpy(*new_dn, dn); 4011 (void) strcat(*new_dn, str); 4012 4013 (void) __ns_ldap_freeParam(¶m); 4014 return (NS_LDAP_SUCCESS); 4015 } 4016 4017 /* 4018 * Flatten the input ns_ldap_attr_t list, 'attr', and convert it into an 4019 * ldap_strlist_t structure in buffer 'buf', to be used by ldap_cachemgr. 4020 * The output contains a count, a list of offsets, which show where the 4021 * corresponding copied attribute type and attribute value are located. 4022 * For example, for dn=aaaa, userpassword=bbbb, shadowlastchange=cccc, 4023 * the output is the ldap_strlist_t structure with: ldap_count = 6, 4024 * (buf + ldap_offsets[0]) -> "dn" 4025 * (buf + ldap_offsets[1]) -> "aaaa" 4026 * (buf + ldap_offsets[2]) -> "userPassword" 4027 * (buf + ldap_offsets[3]) -> "bbbb" 4028 * (buf + ldap_offsets[4]) -> "shadowlastchange" 4029 * (buf + ldap_offsets[5]) -> "cccc" 4030 * and all the string data shown above copied into the buffer after 4031 * the offset array. The total length of the data will be the return 4032 * value, or -1 if error. 4033 */ 4034 static int 4035 attr2list(const char *dn, ns_ldap_attr_t **attr, 4036 char *buf, int bufsize) 4037 { 4038 int c = 0; 4039 char *ap; 4040 int ao; 4041 ldap_strlist_t *al = (ldap_strlist_t *)buf; 4042 ns_ldap_attr_t *a = (ns_ldap_attr_t *)*attr; 4043 ns_ldap_attr_t **aptr = (ns_ldap_attr_t **)attr; 4044 4045 /* bufsize > strlen(dn) + strlen("dn") + 1 ('\0') */ 4046 if ((strlen(dn) + 2 + 1) >= bufsize) 4047 return (-1); 4048 4049 /* count number of attributes */ 4050 while (*aptr++) 4051 c++; 4052 al->ldap_count = 2 + c * 2; 4053 ao = sizeof (al->ldap_count) + sizeof (al->ldap_offsets[0]) * 4054 al->ldap_count; 4055 if (ao > bufsize) 4056 return (-1); 4057 al->ldap_offsets[0] = ao; 4058 ap = buf + ao; 4059 ao += 3; 4060 4061 /* copy entry DN */ 4062 if (ao > bufsize) 4063 return (-1); 4064 (void) strlcpy(ap, "dn", bufsize); 4065 ap += 3; 4066 4067 al->ldap_offsets[1] = ao; 4068 ao += strlen(dn) + 1; 4069 if (ao > bufsize) 4070 return (-1); 4071 (void) strlcpy(ap, dn, bufsize); 4072 ap = buf + ao; 4073 4074 aptr = attr; 4075 for (c = 2; c < al->ldap_count; c++, aptr++) { 4076 a = *aptr; 4077 if (a->attrname == NULL || a->attrvalue == NULL || 4078 a->value_count != 1 || a->attrvalue[0] == NULL) 4079 return (-1); 4080 al->ldap_offsets[c] = ao; 4081 ao += strlen(a->attrname) + 1; 4082 if (ao > bufsize) 4083 return (-1); 4084 (void) strlcpy(ap, a->attrname, bufsize); 4085 ap = buf + ao; 4086 4087 c++; 4088 al->ldap_offsets[c] = ao; 4089 ao += strlen(a->attrvalue[0]) + 1; 4090 (void) strlcpy(ap, a->attrvalue[0], bufsize); 4091 ap = buf + ao; 4092 }; 4093 4094 return (ao); 4095 } 4096 4097 /* 4098 * Send a modify request to the ldap_cachemgr daemon 4099 * which will use the admin credential to perform the 4100 * operation. 4101 */ 4102 4103 static int 4104 send_to_cachemgr( 4105 const char *dn, 4106 ns_ldap_attr_t **attr, 4107 ns_ldap_error_t **errorp) 4108 { 4109 union { 4110 ldap_data_t s_d; 4111 char s_b[DOORBUFFERSIZE]; 4112 } space; 4113 4114 ldap_data_t *sptr; 4115 int ndata; 4116 int adata; 4117 int len; 4118 int rc; 4119 char errstr[MAXERROR]; 4120 ldap_admin_mod_result_t *admin_result; 4121 4122 *errorp = NULL; 4123 (void) memset(space.s_b, 0, DOORBUFFERSIZE); 4124 len = attr2list(dn, attr, (char *)&space.s_d.ldap_call.ldap_u.strlist, 4125 sizeof (space) - offsetof(ldap_return_t, ldap_u)); 4126 if (len <= 0) 4127 return (NS_LDAP_INVALID_PARAM); 4128 4129 adata = sizeof (ldap_call_t) + len; 4130 ndata = sizeof (space); 4131 space.s_d.ldap_call.ldap_callnumber = ADMINMODIFY; 4132 sptr = &space.s_d; 4133 4134 switch (__ns_ldap_trydoorcall(&sptr, &ndata, &adata)) { 4135 case NS_CACHE_SUCCESS: 4136 break; 4137 case NS_CACHE_NOTFOUND: 4138 (void) snprintf(errstr, sizeof (errstr), 4139 gettext("Door call ADMINMODIFY to " 4140 "ldap_cachemgr failed - error: %d"), 4141 space.s_d.ldap_ret.ldap_errno); 4142 MKERROR(LOG_WARNING, *errorp, NS_CONFIG_CACHEMGR, 4143 strdup(errstr), NULL); 4144 return (NS_LDAP_OP_FAILED); 4145 break; 4146 default: 4147 return (NS_LDAP_OP_FAILED); 4148 } 4149 4150 admin_result = &sptr->ldap_ret.ldap_u.admin_result; 4151 if (admin_result->ns_err == NS_LDAP_SUCCESS) 4152 rc = NS_LDAP_SUCCESS; 4153 else { 4154 rc = admin_result->ns_err; 4155 if (admin_result->msg_size == 0) 4156 *errorp = __s_api_make_error(admin_result->status, 4157 NULL); 4158 else 4159 *errorp = __s_api_make_error(admin_result->status, 4160 admin_result->msg); 4161 } 4162 4163 /* clean up the door call */ 4164 if (sptr != &space.s_d) { 4165 (void) munmap((char *)sptr, ndata); 4166 } 4167 4168 return (rc); 4169 } 4170