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 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 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() { 1236 1237 int **enable_shadow = NULL; 1238 1239 if (__ns_ldap_getParam(NS_LDAP_ENABLE_SHADOW_UPDATE_P, 1240 (void ***)&enable_shadow, NULL) != NS_LDAP_SUCCESS) { 1241 return (B_FALSE); 1242 } 1243 if ((enable_shadow != NULL && *enable_shadow != NULL) && 1244 (*enable_shadow[0] == NS_LDAP_ENABLE_SHADOW_UPDATE_TRUE)) { 1245 (void) __ns_ldap_freeParam((void ***)&enable_shadow); 1246 return (B_TRUE); 1247 } 1248 if (enable_shadow != NULL) 1249 (void) __ns_ldap_freeParam((void ***)&enable_shadow); 1250 return (B_FALSE); 1251 } 1252 1253 /* 1254 * __ns_ldap_repAttr modifies ldap attributes of the 'dn' entry stored 1255 * on the LDAP server. 'service' indicates the type of database entries 1256 * to modify. When the Native LDAP client is configured with 'shadow update 1257 * enabled', Shadowshadow(4) entries can only be modified by privileged users. 1258 * Such users use the NS_LDAP_UPDATE_SHADOW flag to indicate the call is 1259 * for such a shadow(4) update, which would be forwarded to ldap_cachemgr 1260 * for performing the LDAP modify operation. ldap_cachemgr would call 1261 * this function again and use the special service NS_ADMIN_SHADOW_UPDATE 1262 * to identify itself, so that admin credential would be obtained and 1263 * the actual LDAP modify operation be done. 1264 */ 1265 /*ARGSUSED*/ 1266 int 1267 __ns_ldap_repAttr( 1268 const char *service, 1269 const char *dn, 1270 const ns_ldap_attr_t * const *attr, 1271 const ns_cred_t *cred, 1272 const int flags, 1273 ns_ldap_error_t ** errorp) 1274 { 1275 LDAPMod **mods; 1276 int rc = 0; 1277 boolean_t priv; 1278 boolean_t shadow_update_enabled = B_FALSE; 1279 1280 #ifdef DEBUG 1281 (void) fprintf(stderr, "__ns_ldap_repAttr START\n"); 1282 #endif 1283 *errorp = NULL; 1284 1285 /* Sanity check */ 1286 if (attr == NULL || *attr == NULL || dn == NULL) 1287 return (NS_LDAP_INVALID_PARAM); 1288 1289 /* Privileged shadow modify? */ 1290 if ((flags & NS_LDAP_UPDATE_SHADOW) != 0 && 1291 strcmp(service, "shadow") == 0) { 1292 1293 /* Shadow update enabled ? If not, error out */ 1294 shadow_update_enabled = __ns_ldap_is_shadow_update_enabled(); 1295 if (!shadow_update_enabled) { 1296 *errorp = __s_api_make_error(NS_CONFIG_NOTALLOW, 1297 gettext("Shadow Update is not enabled")); 1298 return (NS_LDAP_CONFIG); 1299 } 1300 1301 /* privileged shadow modify requires euid 0 or all zone privs */ 1302 priv = (geteuid() == 0); 1303 if (!priv) { 1304 priv_set_t *ps = priv_allocset(); /* caller */ 1305 priv_set_t *zs; /* zone */ 1306 1307 (void) getppriv(PRIV_EFFECTIVE, ps); 1308 zs = priv_str_to_set("zone", ",", NULL); 1309 priv = priv_isequalset(ps, zs); 1310 priv_freeset(ps); 1311 priv_freeset(zs); 1312 } 1313 if (!priv) 1314 return (NS_LDAP_OP_FAILED); 1315 1316 rc = send_to_cachemgr(dn, (ns_ldap_attr_t **)attr, errorp); 1317 return (rc); 1318 } 1319 1320 if (cred == NULL) 1321 return (NS_LDAP_INVALID_PARAM); 1322 1323 /* 1324 * If service is NS_ADMIN_SHADOW_UPDATE, the caller should be 1325 * ldap_cachemgr. We need to get the admin cred to do work. 1326 * If the caller is not ldap_cachemgr, but use the service 1327 * NS_ADMIN_SHADOW_UPDATE, get_admin_passwd() will fail, 1328 * as the admin cred is not available to the caller. 1329 */ 1330 if (strcmp(service, NS_ADMIN_SHADOW_UPDATE) == 0) { 1331 if ((rc = get_admin_passwd((ns_cred_t *)cred, errorp)) != 1332 NS_LDAP_SUCCESS) 1333 return (rc); 1334 } 1335 1336 mods = __s_api_makeModList(service, attr, LDAP_MOD_REPLACE, flags); 1337 if (mods == NULL) 1338 return (NS_LDAP_MEMORY); 1339 1340 rc = write_state_machine(LDAP_REQ_MODIFY, 1341 (char *)dn, mods, cred, flags, errorp); 1342 1343 freeModList(mods); 1344 return (rc); 1345 } 1346 1347 /*ARGSUSED*/ 1348 int 1349 __ns_ldap_addEntry( 1350 const char *service, 1351 const char *dn, 1352 const ns_ldap_entry_t *entry, 1353 const ns_cred_t *cred, 1354 const int flags, 1355 ns_ldap_error_t ** errorp) 1356 { 1357 char *new_dn = NULL; 1358 LDAPMod **mods = NULL; 1359 const ns_ldap_attr_t * const *attr; 1360 int nAttr = 0; 1361 int rc = 0; 1362 1363 #ifdef DEBUG 1364 (void) fprintf(stderr, "__ns_ldap_addEntry START\n"); 1365 #endif 1366 1367 if ((entry == NULL) || (dn == NULL) || (cred == NULL)) 1368 return (NS_LDAP_INVALID_PARAM); 1369 *errorp = NULL; 1370 1371 /* Construct array of LDAPMod representing attributes of new entry. */ 1372 1373 nAttr = entry->attr_count; 1374 attr = (const ns_ldap_attr_t * const *)(entry->attr_pair); 1375 mods = __s_api_makeModListCount(service, attr, LDAP_MOD_ADD, 1376 nAttr, flags); 1377 if (mods == NULL) { 1378 return (NS_LDAP_MEMORY); 1379 } 1380 1381 rc = replace_mapped_attr_in_dn(service, dn, &new_dn); 1382 if (rc != NS_LDAP_SUCCESS) { 1383 freeModList(mods); 1384 return (rc); 1385 } 1386 1387 rc = write_state_machine(LDAP_REQ_ADD, 1388 new_dn ? new_dn : (char *)dn, mods, cred, flags, errorp); 1389 1390 if (new_dn) 1391 free(new_dn); 1392 freeModList(mods); 1393 return (rc); 1394 } 1395 1396 1397 /*ARGSUSED*/ 1398 int 1399 __ns_ldap_delEntry( 1400 const char *service, 1401 const char *dn, 1402 const ns_cred_t *cred, 1403 const int flags, 1404 ns_ldap_error_t ** errorp) 1405 { 1406 int rc; 1407 1408 #ifdef DEBUG 1409 (void) fprintf(stderr, "__ns_ldap_delEntry START\n"); 1410 #endif 1411 if ((dn == NULL) || (cred == NULL)) 1412 return (NS_LDAP_INVALID_PARAM); 1413 1414 *errorp = NULL; 1415 1416 rc = write_state_machine(LDAP_REQ_DELETE, 1417 (char *)dn, NULL, cred, flags, errorp); 1418 1419 return (rc); 1420 } 1421 1422 /* 1423 * Add Typed Entry Helper routines 1424 */ 1425 1426 /* 1427 * Add Typed Entry Conversion routines 1428 */ 1429 1430 static int 1431 __s_add_attr(ns_ldap_entry_t *e, char *attrname, char *value) 1432 { 1433 ns_ldap_attr_t *a; 1434 char *v; 1435 1436 a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t)); 1437 if (a == NULL) 1438 return (NS_LDAP_MEMORY); 1439 a->attrname = strdup(attrname); 1440 if (a->attrname == NULL) 1441 return (NS_LDAP_MEMORY); 1442 a->attrvalue = (char **)calloc(1, sizeof (char **)); 1443 if (a->attrvalue == NULL) 1444 return (NS_LDAP_MEMORY); 1445 a->value_count = 1; 1446 a->attrvalue[0] = NULL; 1447 v = strdup(value); 1448 if (v == NULL) 1449 return (NS_LDAP_MEMORY); 1450 a->attrvalue[0] = v; 1451 e->attr_pair[e->attr_count] = a; 1452 e->attr_count++; 1453 return (NS_LDAP_SUCCESS); 1454 } 1455 1456 static int 1457 __s_add_attrlist(ns_ldap_entry_t *e, char *attrname, char **argv) 1458 { 1459 ns_ldap_attr_t *a; 1460 char *v; 1461 char **av; 1462 int i, j; 1463 1464 a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t)); 1465 if (a == NULL) 1466 return (NS_LDAP_MEMORY); 1467 a->attrname = strdup(attrname); 1468 if (a->attrname == NULL) 1469 return (NS_LDAP_MEMORY); 1470 1471 for (i = 0, av = argv; *av != NULL; av++, i++) 1472 ; 1473 1474 a->attrvalue = (char **)calloc(i, sizeof (char *)); 1475 1476 if (a->attrvalue == NULL) 1477 return (NS_LDAP_MEMORY); 1478 1479 a->value_count = i; 1480 for (j = 0; j < i; j++) { 1481 v = strdup(argv[j]); 1482 if (v == NULL) 1483 return (NS_LDAP_MEMORY); 1484 a->attrvalue[j] = v; 1485 } 1486 e->attr_pair[e->attr_count] = a; 1487 e->attr_count++; 1488 return (NS_LDAP_SUCCESS); 1489 } 1490 1491 static ns_ldap_entry_t * 1492 __s_mk_entry(char **objclass, int max_attr) 1493 { 1494 ns_ldap_entry_t *e; 1495 e = (ns_ldap_entry_t *)calloc(1, sizeof (ns_ldap_entry_t)); 1496 if (e == NULL) 1497 return (NULL); 1498 /* allocate attributes, +1 for objectclass, +1 for NULL terminator */ 1499 e->attr_pair = (ns_ldap_attr_t **) 1500 calloc(max_attr + 2, sizeof (ns_ldap_attr_t *)); 1501 if (e->attr_pair == NULL) { 1502 free(e); 1503 return (NULL); 1504 } 1505 e->attr_count = 0; 1506 if (__s_add_attrlist(e, "objectClass", objclass) != NS_LDAP_SUCCESS) { 1507 free(e->attr_pair); 1508 free(e); 1509 return (NULL); 1510 } 1511 return (e); 1512 } 1513 1514 1515 /* 1516 * Conversion: passwd 1517 * Input format: struct passwd 1518 * Exported objectclass: posixAccount 1519 */ 1520 static int 1521 __s_cvt_passwd(const void *data, char **rdn, 1522 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 1523 { 1524 ns_ldap_entry_t *e; 1525 int rc; 1526 char trdn[RDNSIZE]; 1527 /* routine specific */ 1528 struct passwd *ptr; 1529 int max_attr = 9; 1530 char ibuf[10]; 1531 static char *oclist[] = { 1532 "posixAccount", 1533 "shadowAccount", 1534 "account", 1535 "top", 1536 NULL 1537 }; 1538 1539 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 1540 return (NS_LDAP_OP_FAILED); 1541 *entry = e = __s_mk_entry(oclist, max_attr); 1542 if (e == NULL) 1543 return (NS_LDAP_MEMORY); 1544 1545 /* Convert the structure */ 1546 ptr = (struct passwd *)data; 1547 1548 if (ptr->pw_name == NULL || ptr->pw_uid > MAXUID || 1549 ptr->pw_gid > MAXUID || ptr->pw_dir == NULL) { 1550 __ns_ldap_freeEntry(e); 1551 *entry = NULL; 1552 return (NS_LDAP_INVALID_PARAM); 1553 } 1554 1555 /* Create an appropriate rdn */ 1556 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->pw_name); 1557 *rdn = strdup(trdn); 1558 if (*rdn == NULL) { 1559 __ns_ldap_freeEntry(e); 1560 *entry = NULL; 1561 return (NS_LDAP_MEMORY); 1562 } 1563 1564 /* Error check the data and add the attributes */ 1565 rc = __s_add_attr(e, "uid", ptr->pw_name); 1566 if (rc != NS_LDAP_SUCCESS) { 1567 __s_cvt_freeEntryRdn(entry, rdn); 1568 return (rc); 1569 } 1570 rc = __s_add_attr(e, "cn", ptr->pw_name); 1571 if (rc != NS_LDAP_SUCCESS) { 1572 __s_cvt_freeEntryRdn(entry, rdn); 1573 return (rc); 1574 } 1575 1576 if (ptr->pw_passwd != NULL && 1577 ptr->pw_passwd[0] != '\0') { 1578 rc = __s_add_attr(e, "userPassword", ptr->pw_passwd); 1579 if (rc != NS_LDAP_SUCCESS) { 1580 __s_cvt_freeEntryRdn(entry, rdn); 1581 return (rc); 1582 } 1583 } 1584 1585 (void) sprintf(ibuf, "%u", ptr->pw_uid); 1586 rc = __s_add_attr(e, "uidNumber", ibuf); 1587 if (rc != NS_LDAP_SUCCESS) { 1588 __s_cvt_freeEntryRdn(entry, rdn); 1589 return (rc); 1590 } 1591 1592 (void) sprintf(ibuf, "%u", ptr->pw_gid); 1593 rc = __s_add_attr(e, "gidNumber", ibuf); 1594 if (rc != NS_LDAP_SUCCESS) { 1595 __s_cvt_freeEntryRdn(entry, rdn); 1596 return (rc); 1597 } 1598 if (ptr->pw_gecos != NULL && 1599 ptr->pw_gecos[0] != '\0') { 1600 rc = __s_add_attr(e, "gecos", ptr->pw_gecos); 1601 if (rc != NS_LDAP_SUCCESS) { 1602 __s_cvt_freeEntryRdn(entry, rdn); 1603 return (rc); 1604 } 1605 } 1606 1607 rc = __s_add_attr(e, "homeDirectory", ptr->pw_dir); 1608 if (rc != NS_LDAP_SUCCESS) { 1609 __s_cvt_freeEntryRdn(entry, rdn); 1610 return (rc); 1611 } 1612 if (ptr->pw_shell != NULL && 1613 ptr->pw_shell[0] != '\0') { 1614 rc = __s_add_attr(e, "loginShell", ptr->pw_shell); 1615 if (rc != NS_LDAP_SUCCESS) { 1616 __s_cvt_freeEntryRdn(entry, rdn); 1617 return (rc); 1618 } 1619 } 1620 1621 return (NS_LDAP_SUCCESS); 1622 } 1623 1624 /* 1625 * escape_str function escapes special characters in str and 1626 * copies to escstr string. 1627 * 1628 * return 0 for successful 1629 * 1 for fail 1630 */ 1631 static int escape_str(char *escstr, char *str) 1632 { 1633 int index = 0; 1634 1635 while ((*str != '\0') && (index < (RDNSIZE - 1))) { 1636 if (*str == '+' || *str == ';' || *str == '>' || 1637 *str == '<' || *str == ',' || *str == '"' || 1638 *str == '\\' || *str == '=' || 1639 (*str == '#' && index == 0)) { 1640 *escstr++ = '\\'; 1641 *escstr++ = *str++; 1642 index += 2; 1643 } else { 1644 *escstr++ = *str++; 1645 index++; 1646 } 1647 } 1648 1649 if (*str == '\0') { 1650 *escstr = '\0'; 1651 return (0); 1652 } else { 1653 return (1); 1654 } 1655 } 1656 1657 /* 1658 * Conversion: project 1659 * Input format: struct project 1660 * Exported objectclass: SolarisProject 1661 */ 1662 static int 1663 __s_cvt_project(const void *data, char **rdn, 1664 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 1665 { 1666 ns_ldap_entry_t *e; 1667 int rc; 1668 char trdn[RDNSIZE]; 1669 1670 /* routine specific */ 1671 struct project *ptr; 1672 int max_attr = 9; 1673 char ibuf[11]; 1674 static char *oclist[] = { 1675 "SolarisProject", 1676 "top", 1677 NULL 1678 }; 1679 1680 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 1681 return (NS_LDAP_OP_FAILED); 1682 1683 *entry = e = __s_mk_entry(oclist, max_attr); 1684 if (e == NULL) 1685 return (NS_LDAP_MEMORY); 1686 1687 /* Convert the structure */ 1688 ptr = (struct project *)data; 1689 1690 if (ptr->pj_name == NULL || ptr->pj_projid > MAXUID) { 1691 __ns_ldap_freeEntry(e); 1692 *entry = NULL; 1693 return (NS_LDAP_INVALID_PARAM); 1694 } 1695 1696 /* Create an appropriate rdn */ 1697 (void) snprintf(trdn, RDNSIZE, "SolarisProjectName=%s", ptr->pj_name); 1698 *rdn = strdup(trdn); 1699 if (*rdn == NULL) { 1700 __ns_ldap_freeEntry(e); 1701 *entry = NULL; 1702 return (NS_LDAP_MEMORY); 1703 } 1704 1705 /* Error check the data and add the attributes */ 1706 1707 /* Project name */ 1708 rc = __s_add_attr(e, "SolarisProjectName", ptr->pj_name); 1709 if (rc != NS_LDAP_SUCCESS) { 1710 __s_cvt_freeEntryRdn(entry, rdn); 1711 return (rc); 1712 } 1713 1714 /* 1715 * Project ID: 1716 * ibuf is 11 chars big, which should be enough for string 1717 * representation of 32bit number + nul-car 1718 */ 1719 if (snprintf(ibuf, sizeof (ibuf), "%u", ptr->pj_projid) < 0) { 1720 __s_cvt_freeEntryRdn(entry, rdn); 1721 return (NS_LDAP_INVALID_PARAM); 1722 } 1723 rc = __s_add_attr(e, "SolarisProjectID", ibuf); 1724 if (rc != NS_LDAP_SUCCESS) { 1725 __s_cvt_freeEntryRdn(entry, rdn); 1726 return (rc); 1727 } 1728 1729 /* Comment/Description */ 1730 if (ptr->pj_comment != NULL && ptr->pj_comment[0] != '\0') { 1731 rc = __s_add_attr(e, "description", ptr->pj_comment); 1732 if (rc != NS_LDAP_SUCCESS) { 1733 __s_cvt_freeEntryRdn(entry, rdn); 1734 return (rc); 1735 } 1736 } 1737 1738 /* Attributes */ 1739 if (ptr->pj_attr != NULL && ptr->pj_attr[0] != '\0') { 1740 rc = __s_add_attr(e, "SolarisProjectAttr", ptr->pj_attr); 1741 if (rc != NS_LDAP_SUCCESS) { 1742 __s_cvt_freeEntryRdn(entry, rdn); 1743 return (rc); 1744 } 1745 } 1746 1747 /* Users */ 1748 if (ptr->pj_users != NULL) { 1749 rc = __s_add_attrlist(e, "memberUid", ptr->pj_users); 1750 if (rc != NS_LDAP_SUCCESS) { 1751 __s_cvt_freeEntryRdn(entry, rdn); 1752 return (rc); 1753 } 1754 } 1755 1756 /* Groups */ 1757 if (ptr->pj_groups != NULL) { 1758 rc = __s_add_attrlist(e, "memberGid", ptr->pj_groups); 1759 if (rc != NS_LDAP_SUCCESS) { 1760 __s_cvt_freeEntryRdn(entry, rdn); 1761 return (rc); 1762 } 1763 } 1764 1765 1766 1767 return (NS_LDAP_SUCCESS); 1768 } 1769 /* 1770 * Conversion: shadow 1771 * Input format: struct shadow 1772 * Exported objectclass: shadowAccount 1773 */ 1774 static int 1775 __s_cvt_shadow(const void *data, char **rdn, 1776 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 1777 { 1778 ns_ldap_entry_t *e; 1779 int rc; 1780 char trdn[RDNSIZE]; 1781 /* routine specific */ 1782 struct spwd *ptr; 1783 int max_attr = 10; 1784 char ibuf[10]; 1785 static char *oclist[] = { 1786 "posixAccount", 1787 "shadowAccount", 1788 "account", 1789 "top", 1790 NULL 1791 }; 1792 1793 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 1794 return (NS_LDAP_OP_FAILED); 1795 *entry = e = __s_mk_entry(oclist, max_attr); 1796 if (e == NULL) 1797 return (NS_LDAP_MEMORY); 1798 1799 /* Convert the structure */ 1800 ptr = (struct spwd *)data; 1801 1802 if (ptr->sp_namp == NULL) { 1803 __ns_ldap_freeEntry(e); 1804 *entry = NULL; 1805 return (NS_LDAP_INVALID_PARAM); 1806 } 1807 1808 /* Create an appropriate rdn */ 1809 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->sp_namp); 1810 *rdn = strdup(trdn); 1811 if (*rdn == NULL) { 1812 __ns_ldap_freeEntry(e); 1813 *entry = NULL; 1814 return (NS_LDAP_MEMORY); 1815 } 1816 1817 /* Error check the data and add the attributes */ 1818 rc = __s_add_attr(e, "uid", ptr->sp_namp); 1819 if (rc != NS_LDAP_SUCCESS) { 1820 __s_cvt_freeEntryRdn(entry, rdn); 1821 return (rc); 1822 } 1823 1824 if (ptr->sp_pwdp == NULL) { 1825 __s_cvt_freeEntryRdn(entry, rdn); 1826 return (NS_LDAP_INVALID_PARAM); 1827 } else { 1828 rc = __s_add_attr(e, "userPassword", ptr->sp_pwdp); 1829 if (rc != NS_LDAP_SUCCESS) { 1830 __s_cvt_freeEntryRdn(entry, rdn); 1831 return (rc); 1832 } 1833 } 1834 if (ptr->sp_lstchg >= 0) { 1835 (void) sprintf(ibuf, "%d", ptr->sp_lstchg); 1836 rc = __s_add_attr(e, "shadowLastChange", ibuf); 1837 if (rc != NS_LDAP_SUCCESS) { 1838 __s_cvt_freeEntryRdn(entry, rdn); 1839 return (rc); 1840 } 1841 } 1842 if (ptr->sp_min >= 0) { 1843 (void) sprintf(ibuf, "%d", ptr->sp_min); 1844 rc = __s_add_attr(e, "shadowMin", ibuf); 1845 if (rc != NS_LDAP_SUCCESS) { 1846 __s_cvt_freeEntryRdn(entry, rdn); 1847 return (rc); 1848 } 1849 } 1850 if (ptr->sp_max >= 0) { 1851 (void) sprintf(ibuf, "%d", ptr->sp_max); 1852 rc = __s_add_attr(e, "shadowMax", ibuf); 1853 if (rc != NS_LDAP_SUCCESS) { 1854 __s_cvt_freeEntryRdn(entry, rdn); 1855 return (rc); 1856 } 1857 } 1858 if (ptr->sp_warn >= 0) { 1859 (void) sprintf(ibuf, "%d", ptr->sp_warn); 1860 rc = __s_add_attr(e, "shadowWarning", ibuf); 1861 if (rc != NS_LDAP_SUCCESS) { 1862 __s_cvt_freeEntryRdn(entry, rdn); 1863 return (rc); 1864 } 1865 } 1866 if (ptr->sp_inact >= 0) { 1867 (void) sprintf(ibuf, "%d", ptr->sp_inact); 1868 rc = __s_add_attr(e, "shadowInactive", ibuf); 1869 if (rc != NS_LDAP_SUCCESS) { 1870 __s_cvt_freeEntryRdn(entry, rdn); 1871 return (rc); 1872 } 1873 } 1874 if (ptr->sp_expire >= 0) { 1875 (void) sprintf(ibuf, "%d", ptr->sp_expire); 1876 rc = __s_add_attr(e, "shadowExpire", ibuf); 1877 if (rc != NS_LDAP_SUCCESS) { 1878 __s_cvt_freeEntryRdn(entry, rdn); 1879 return (rc); 1880 } 1881 } 1882 (void) sprintf(ibuf, "%d", ptr->sp_flag); 1883 rc = __s_add_attr(e, "shadowFlag", ibuf); 1884 if (rc != NS_LDAP_SUCCESS) { 1885 __s_cvt_freeEntryRdn(entry, rdn); 1886 return (rc); 1887 } 1888 1889 return (NS_LDAP_SUCCESS); 1890 } 1891 1892 1893 /* 1894 * Conversion: group 1895 * Input format: struct group 1896 * Exported objectclass: posixGroup 1897 */ 1898 static int 1899 __s_cvt_group(const void *data, char **rdn, 1900 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 1901 { 1902 ns_ldap_entry_t *e; 1903 int rc; 1904 char trdn[RDNSIZE]; 1905 /* routine specific */ 1906 struct group *ptr; 1907 int i, j, k; 1908 char **nm, **lm; 1909 int max_attr = 4; 1910 char ibuf[10]; 1911 static char *oclist[] = { 1912 "posixGroup", 1913 "top", 1914 NULL 1915 }; 1916 1917 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 1918 return (NS_LDAP_OP_FAILED); 1919 *entry = e = __s_mk_entry(oclist, max_attr); 1920 if (e == NULL) 1921 return (NS_LDAP_MEMORY); 1922 1923 /* Convert the structure */ 1924 ptr = (struct group *)data; 1925 1926 if (ptr->gr_name == NULL || ptr->gr_gid > MAXUID) { 1927 __ns_ldap_freeEntry(e); 1928 *entry = NULL; 1929 return (NS_LDAP_INVALID_PARAM); 1930 } 1931 1932 /* Create an appropriate rdn */ 1933 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->gr_name); 1934 *rdn = strdup(trdn); 1935 if (*rdn == NULL) { 1936 __ns_ldap_freeEntry(e); 1937 *entry = NULL; 1938 return (NS_LDAP_MEMORY); 1939 } 1940 1941 /* Error check the data and add the attributes */ 1942 rc = __s_add_attr(e, "cn", ptr->gr_name); 1943 if (rc != NS_LDAP_SUCCESS) { 1944 __s_cvt_freeEntryRdn(entry, rdn); 1945 return (rc); 1946 } 1947 1948 (void) sprintf(ibuf, "%u", ptr->gr_gid); 1949 rc = __s_add_attr(e, "gidNumber", ibuf); 1950 if (rc != NS_LDAP_SUCCESS) { 1951 __s_cvt_freeEntryRdn(entry, rdn); 1952 return (rc); 1953 } 1954 if (ptr->gr_passwd && ptr->gr_passwd[0] != '\0') { 1955 rc = __s_add_attr(e, "userPassword", ptr->gr_passwd); 1956 if (rc != NS_LDAP_SUCCESS) { 1957 __s_cvt_freeEntryRdn(entry, rdn); 1958 return (rc); 1959 } 1960 } 1961 1962 if (ptr->gr_mem && ptr->gr_mem[0]) { 1963 lm = ptr->gr_mem; 1964 for (i = 0; *lm; i++, lm++) 1965 ; 1966 lm = ptr->gr_mem; 1967 nm = (char **)calloc(i+2, sizeof (char *)); 1968 if (nm == NULL) { 1969 __s_cvt_freeEntryRdn(entry, rdn); 1970 return (NS_LDAP_MEMORY); 1971 } 1972 for (j = 0; j < i; j++) { 1973 nm[j] = strdup(lm[j]); 1974 if (nm[j] == NULL) { 1975 for (k = 0; k < j; k++) 1976 free(nm[k]); 1977 free(nm); 1978 __s_cvt_freeEntryRdn(entry, rdn); 1979 return (NS_LDAP_MEMORY); 1980 } 1981 } 1982 rc = __s_add_attrlist(e, "memberUid", nm); 1983 for (j = 0; j < i; j++) { 1984 free(nm[j]); 1985 } 1986 free(nm); 1987 nm = NULL; 1988 if (rc != NS_LDAP_SUCCESS) { 1989 __s_cvt_freeEntryRdn(entry, rdn); 1990 return (rc); 1991 } 1992 } 1993 1994 return (NS_LDAP_SUCCESS); 1995 } 1996 1997 /* 1998 * Conversion: hosts 1999 * Input format: struct hostent 2000 * Exported objectclass: ipHost 2001 */ 2002 static int 2003 __s_cvt_hosts(const void *data, char **rdn, 2004 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2005 { 2006 ns_ldap_entry_t *e; 2007 int rc; 2008 char trdn[RDNSIZE]; 2009 /* routine specific */ 2010 struct hostent *ptr; 2011 int max_attr = 6; 2012 int i, j, k; 2013 char **nm, **lm; 2014 static char *oclist[] = { 2015 "ipHost", 2016 "device", 2017 "top", 2018 NULL 2019 }; 2020 2021 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2022 return (NS_LDAP_OP_FAILED); 2023 *entry = e = __s_mk_entry(oclist, max_attr); 2024 if (e == NULL) 2025 return (NS_LDAP_MEMORY); 2026 2027 /* Convert the structure */ 2028 ptr = (struct hostent *)data; 2029 2030 if (ptr->h_name == NULL || 2031 ptr->h_addr_list == NULL || ptr->h_addr_list[0] == '\0') { 2032 __ns_ldap_freeEntry(e); 2033 *entry = NULL; 2034 return (NS_LDAP_INVALID_PARAM); 2035 } 2036 2037 /* Create an appropriate rdn */ 2038 (void) snprintf(trdn, RDNSIZE, "cn=%s+ipHostNumber=%s", 2039 ptr->h_name, ptr->h_addr_list[0]); 2040 *rdn = strdup(trdn); 2041 if (*rdn == NULL) { 2042 __ns_ldap_freeEntry(e); 2043 *entry = NULL; 2044 return (NS_LDAP_MEMORY); 2045 } 2046 2047 /* Error check the data and add the attributes */ 2048 if (ptr->h_aliases && ptr->h_aliases[0]) { 2049 lm = ptr->h_aliases; 2050 /* 2051 * If there is a description, 'i' will contain 2052 * the index of the description in the aliases list 2053 */ 2054 for (i = 0; *lm && (*lm)[0] != '#'; i++, lm++) 2055 ; 2056 lm = ptr->h_aliases; 2057 nm = (char **)calloc(i+2, sizeof (char *)); 2058 if (nm == NULL) { 2059 __s_cvt_freeEntryRdn(entry, rdn); 2060 return (NS_LDAP_MEMORY); 2061 } 2062 nm[0] = ptr->h_name; 2063 for (j = 0; j < i; j++) 2064 nm[j+1] = ptr->h_aliases[j]; 2065 2066 rc = __s_add_attrlist(e, "cn", nm); 2067 2068 if (rc != NS_LDAP_SUCCESS) { 2069 __s_cvt_freeEntryRdn(entry, rdn); 2070 free(nm); 2071 return (rc); 2072 } 2073 2074 if (lm[i] && lm[i][0] == '#') { 2075 nm[0] = &(lm[i][1]); 2076 nm[1] = NULL; 2077 rc = __s_add_attrlist(e, "description", nm); 2078 } 2079 free(nm); 2080 nm = NULL; 2081 if (rc != NS_LDAP_SUCCESS) { 2082 __s_cvt_freeEntryRdn(entry, rdn); 2083 return (rc); 2084 } 2085 } else { 2086 rc = __s_add_attr(e, "cn", ptr->h_name); 2087 if (rc != NS_LDAP_SUCCESS) { 2088 __s_cvt_freeEntryRdn(entry, rdn); 2089 return (rc); 2090 } 2091 } 2092 2093 if (ptr->h_addr_list && ptr->h_addr_list[0]) { 2094 lm = ptr->h_addr_list; 2095 for (i = 0; *lm; i++, lm++) 2096 ; 2097 lm = ptr->h_addr_list; 2098 nm = (char **)calloc(i+2, sizeof (char *)); 2099 if (nm == NULL) { 2100 __s_cvt_freeEntryRdn(entry, rdn); 2101 return (NS_LDAP_MEMORY); 2102 } 2103 for (j = 0; j < i; j++) { 2104 nm[j] = strdup(lm[j]); 2105 if (nm[j] == NULL) { 2106 for (k = 0; k < j; k++) 2107 free(nm[k]); 2108 free(nm); 2109 __s_cvt_freeEntryRdn(entry, rdn); 2110 return (NS_LDAP_MEMORY); 2111 } 2112 } 2113 rc = __s_add_attrlist(e, "ipHostNumber", nm); 2114 for (j = 0; j < i; j++) { 2115 free(nm[j]); 2116 } 2117 free(nm); 2118 nm = NULL; 2119 if (rc != NS_LDAP_SUCCESS) { 2120 __s_cvt_freeEntryRdn(entry, rdn); 2121 return (rc); 2122 } 2123 } else { 2124 __s_cvt_freeEntryRdn(entry, rdn); 2125 return (NS_LDAP_INVALID_PARAM); 2126 } 2127 2128 return (NS_LDAP_SUCCESS); 2129 } 2130 2131 /* 2132 * Conversion: rpc 2133 * Input format: struct rpcent 2134 * Exported objectclass: oncRpc 2135 */ 2136 static int 2137 __s_cvt_rpc(const void *data, char **rdn, 2138 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2139 { 2140 ns_ldap_entry_t *e; 2141 int rc; 2142 char trdn[RDNSIZE]; 2143 /* routine specific */ 2144 struct rpcent *ptr; 2145 int max_attr = 3; 2146 int i, j; 2147 char **nm; 2148 char ibuf[10]; 2149 static char *oclist[] = { 2150 "oncRpc", 2151 "top", 2152 NULL 2153 }; 2154 2155 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2156 return (NS_LDAP_OP_FAILED); 2157 *entry = e = __s_mk_entry(oclist, max_attr); 2158 if (e == NULL) 2159 return (NS_LDAP_MEMORY); 2160 2161 /* Convert the structure */ 2162 ptr = (struct rpcent *)data; 2163 2164 if (ptr->r_name == NULL || ptr->r_number < 0) { 2165 __ns_ldap_freeEntry(e); 2166 *entry = NULL; 2167 return (NS_LDAP_INVALID_PARAM); 2168 } 2169 2170 /* Create an appropriate rdn */ 2171 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->r_name); 2172 *rdn = strdup(trdn); 2173 if (*rdn == NULL) { 2174 __ns_ldap_freeEntry(e); 2175 *entry = NULL; 2176 return (NS_LDAP_MEMORY); 2177 } 2178 2179 /* Error check the data and add the attributes */ 2180 if (ptr->r_aliases && ptr->r_aliases[0]) { 2181 nm = ptr->r_aliases; 2182 for (i = 0; *nm; i++, nm++) 2183 ; 2184 nm = (char **)calloc(i+2, sizeof (char *)); 2185 if (nm == NULL) { 2186 __s_cvt_freeEntryRdn(entry, rdn); 2187 return (NS_LDAP_MEMORY); 2188 } 2189 nm[0] = ptr->r_name; 2190 for (j = 0; j < i; j++) 2191 nm[j+1] = ptr->r_aliases[j]; 2192 2193 rc = __s_add_attrlist(e, "cn", nm); 2194 free(nm); 2195 nm = NULL; 2196 if (rc != NS_LDAP_SUCCESS) { 2197 __s_cvt_freeEntryRdn(entry, rdn); 2198 return (rc); 2199 } 2200 } else { 2201 rc = __s_add_attr(e, "cn", ptr->r_name); 2202 if (rc != NS_LDAP_SUCCESS) { 2203 __s_cvt_freeEntryRdn(entry, rdn); 2204 return (rc); 2205 } 2206 } 2207 2208 if (ptr->r_number >= 0) { 2209 (void) sprintf(ibuf, "%d", ptr->r_number); 2210 rc = __s_add_attr(e, "oncRpcNumber", ibuf); 2211 if (rc != NS_LDAP_SUCCESS) { 2212 __s_cvt_freeEntryRdn(entry, rdn); 2213 return (rc); 2214 } 2215 } 2216 2217 return (NS_LDAP_SUCCESS); 2218 2219 } 2220 2221 /* 2222 * Conversion: protocols 2223 * Input format: struct protoent 2224 * Exported objectclass: ipProtocol 2225 */ 2226 static int 2227 __s_cvt_protocols(const void *data, char **rdn, 2228 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2229 { 2230 ns_ldap_entry_t *e; 2231 int rc; 2232 char trdn[RDNSIZE]; 2233 /* routine specific */ 2234 struct protoent *ptr; 2235 int max_attr = 3; 2236 int i, j; 2237 char ibuf[10]; 2238 char **nm; 2239 static char *oclist[] = { 2240 "ipProtocol", 2241 "top", 2242 NULL 2243 }; 2244 2245 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2246 return (NS_LDAP_OP_FAILED); 2247 *entry = e = __s_mk_entry(oclist, max_attr); 2248 if (e == NULL) 2249 return (NS_LDAP_MEMORY); 2250 2251 /* Convert the structure */ 2252 ptr = (struct protoent *)data; 2253 2254 if (ptr->p_name == NULL || ptr->p_proto < 0) { 2255 __ns_ldap_freeEntry(e); 2256 *entry = NULL; 2257 return (NS_LDAP_INVALID_PARAM); 2258 } 2259 2260 /* Create an appropriate rdn */ 2261 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->p_name); 2262 *rdn = strdup(trdn); 2263 if (*rdn == NULL) { 2264 __ns_ldap_freeEntry(e); 2265 *entry = NULL; 2266 return (NS_LDAP_MEMORY); 2267 } 2268 2269 /* Error check the data and add the attributes */ 2270 if (ptr->p_aliases && ptr->p_aliases[0]) { 2271 nm = ptr->p_aliases; 2272 for (i = 0; *nm; i++, nm++) 2273 ; 2274 nm = (char **)calloc(i+2, sizeof (char *)); 2275 if (nm == NULL) { 2276 __s_cvt_freeEntryRdn(entry, rdn); 2277 return (NS_LDAP_MEMORY); 2278 } 2279 nm[0] = ptr->p_name; 2280 for (j = 0; j < i; j++) 2281 nm[j+1] = ptr->p_aliases[j]; 2282 2283 rc = __s_add_attrlist(e, "cn", nm); 2284 free(nm); 2285 nm = NULL; 2286 if (rc != NS_LDAP_SUCCESS) { 2287 __s_cvt_freeEntryRdn(entry, rdn); 2288 return (rc); 2289 } 2290 } else { 2291 rc = __s_add_attr(e, "cn", ptr->p_name); 2292 if (rc != NS_LDAP_SUCCESS) { 2293 __s_cvt_freeEntryRdn(entry, rdn); 2294 return (rc); 2295 } 2296 } 2297 2298 (void) sprintf(ibuf, "%d", ptr->p_proto); 2299 rc = __s_add_attr(e, "ipProtocolNumber", ibuf); 2300 if (rc != NS_LDAP_SUCCESS) { 2301 __s_cvt_freeEntryRdn(entry, rdn); 2302 return (rc); 2303 } 2304 2305 return (NS_LDAP_SUCCESS); 2306 2307 } 2308 2309 /* 2310 * Conversion: services 2311 * Input format: struct servent 2312 * Exported objectclass: ipService 2313 */ 2314 static int 2315 __s_cvt_services(const void *data, char **rdn, 2316 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2317 { 2318 ns_ldap_entry_t *e; 2319 int rc; 2320 char trdn[RDNSIZE]; 2321 char esc_str[RDNSIZE]; 2322 /* routine specific */ 2323 struct servent *ptr; 2324 int max_attr = 4; 2325 int i, j; 2326 char ibuf[10]; 2327 char **nm; 2328 static char *oclist[] = { 2329 "ipService", 2330 "top", 2331 NULL 2332 }; 2333 2334 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2335 return (NS_LDAP_OP_FAILED); 2336 *entry = e = __s_mk_entry(oclist, max_attr); 2337 if (e == NULL) 2338 return (NS_LDAP_MEMORY); 2339 2340 /* Convert the structure */ 2341 ptr = (struct servent *)data; 2342 2343 if (ptr->s_name == NULL || ptr->s_port < 0 || ptr->s_proto == '\0') { 2344 __ns_ldap_freeEntry(e); 2345 *entry = NULL; 2346 return (NS_LDAP_INVALID_PARAM); 2347 } 2348 2349 /* 2350 * Escape special characters in service name. 2351 */ 2352 if (escape_str(esc_str, ptr->s_name) != 0) { 2353 __ns_ldap_freeEntry(e); 2354 *entry = NULL; 2355 return (NS_LDAP_INVALID_PARAM); 2356 } 2357 2358 /* Create an appropriate rdn */ 2359 (void) snprintf(trdn, RDNSIZE, "cn=%s+ipServiceProtocol=%s", 2360 esc_str, ptr->s_proto); 2361 2362 *rdn = strdup(trdn); 2363 if (*rdn == NULL) { 2364 __ns_ldap_freeEntry(e); 2365 *entry = NULL; 2366 return (NS_LDAP_MEMORY); 2367 } 2368 2369 /* Error check the data and add the attributes */ 2370 if (ptr->s_aliases && ptr->s_aliases[0]) { 2371 nm = ptr->s_aliases; 2372 for (i = 0; *nm; i++, nm++) 2373 ; 2374 nm = (char **)calloc(i+2, sizeof (char *)); 2375 if (nm == NULL) { 2376 __s_cvt_freeEntryRdn(entry, rdn); 2377 return (NS_LDAP_MEMORY); 2378 } 2379 nm[0] = ptr->s_name; 2380 for (j = 0; j < i; j++) 2381 nm[j+1] = ptr->s_aliases[j]; 2382 2383 rc = __s_add_attrlist(e, "cn", nm); 2384 free(nm); 2385 nm = NULL; 2386 if (rc != NS_LDAP_SUCCESS) { 2387 __s_cvt_freeEntryRdn(entry, rdn); 2388 return (rc); 2389 } 2390 } else { 2391 rc = __s_add_attr(e, "cn", ptr->s_name); 2392 if (rc != NS_LDAP_SUCCESS) { 2393 __s_cvt_freeEntryRdn(entry, rdn); 2394 return (rc); 2395 } 2396 } 2397 2398 (void) sprintf(ibuf, "%d", ptr->s_port); 2399 rc = __s_add_attr(e, "ipServicePort", ibuf); 2400 if (rc != NS_LDAP_SUCCESS) { 2401 __s_cvt_freeEntryRdn(entry, rdn); 2402 return (rc); 2403 } 2404 rc = __s_add_attr(e, "ipServiceProtocol", ptr->s_proto); 2405 if (rc != NS_LDAP_SUCCESS) { 2406 __s_cvt_freeEntryRdn(entry, rdn); 2407 return (rc); 2408 } 2409 2410 return (NS_LDAP_SUCCESS); 2411 } 2412 2413 /* 2414 * Conversion: networks 2415 * Input format: struct netent 2416 * Exported objectclass: ipNetwork 2417 */ 2418 static int 2419 __s_cvt_networks(const void *data, char **rdn, 2420 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2421 { 2422 ns_ldap_entry_t *e; 2423 int rc; 2424 char trdn[RDNSIZE]; 2425 /* routine specific */ 2426 struct netent *ptr; 2427 int max_attr = 4; 2428 int i, j; 2429 char cp[64]; 2430 char **nm; 2431 static char *oclist[] = { 2432 "ipNetwork", 2433 "top", 2434 NULL 2435 }; 2436 2437 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2438 return (NS_LDAP_OP_FAILED); 2439 *entry = e = __s_mk_entry(oclist, max_attr); 2440 if (e == NULL) 2441 return (NS_LDAP_MEMORY); 2442 2443 /* Convert the structure */ 2444 ptr = (struct netent *)data; 2445 2446 if (ptr->n_name == NULL || ptr->n_net == 0) { 2447 __ns_ldap_freeEntry(e); 2448 *entry = NULL; 2449 return (NS_LDAP_INVALID_PARAM); 2450 } 2451 2452 (void) snprintf(cp, sizeof (cp), "%d.%d.%d.%d", 2453 (ptr->n_net & 0xFF000000) >> 24, 2454 (ptr->n_net & 0x00FF0000) >> 16, 2455 (ptr->n_net & 0x0000FF00) >> 8, 2456 (ptr->n_net & 0x000000FF)); 2457 2458 /* Create an appropriate rdn */ 2459 (void) snprintf(trdn, RDNSIZE, "ipNetworkNumber=%s", cp); 2460 *rdn = strdup(trdn); 2461 if (*rdn == NULL) { 2462 __ns_ldap_freeEntry(e); 2463 *entry = NULL; 2464 return (NS_LDAP_MEMORY); 2465 } 2466 2467 /* Error check the data and add the attributes */ 2468 if (ptr->n_aliases && ptr->n_aliases[0]) { 2469 nm = ptr->n_aliases; 2470 for (i = 0; *nm; i++, nm++) 2471 ; 2472 nm = (char **)calloc(i+2, sizeof (char *)); 2473 if (nm == NULL) { 2474 __s_cvt_freeEntryRdn(entry, rdn); 2475 return (NS_LDAP_MEMORY); 2476 } 2477 nm[0] = ptr->n_name; 2478 for (j = 0; j < i; j++) 2479 nm[j+1] = ptr->n_aliases[j]; 2480 2481 rc = __s_add_attrlist(e, "cn", nm); 2482 free(nm); 2483 nm = NULL; 2484 if (rc != NS_LDAP_SUCCESS) { 2485 __s_cvt_freeEntryRdn(entry, rdn); 2486 return (rc); 2487 } 2488 } else { 2489 rc = __s_add_attr(e, "cn", ptr->n_name); 2490 if (rc != NS_LDAP_SUCCESS) { 2491 __s_cvt_freeEntryRdn(entry, rdn); 2492 return (rc); 2493 } 2494 } 2495 2496 rc = __s_add_attr(e, "ipNetworkNumber", cp); 2497 if (rc != NS_LDAP_SUCCESS) { 2498 __s_cvt_freeEntryRdn(entry, rdn); 2499 return (rc); 2500 } 2501 2502 return (NS_LDAP_SUCCESS); 2503 2504 } 2505 /* 2506 * Conversion: netmasks 2507 * Input format: struct _ns_netmasks 2508 * Exported objectclass: ipNetwork 2509 */ 2510 static int 2511 __s_cvt_netmasks(const void *data, char **rdn, 2512 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2513 { 2514 ns_ldap_entry_t *e; 2515 int rc; 2516 char trdn[RDNSIZE]; 2517 /* routine specific */ 2518 struct _ns_netmasks *ptr; 2519 int max_attr = 4; 2520 static char *oclist[] = { 2521 "ipNetwork", 2522 "top", 2523 NULL 2524 }; 2525 2526 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2527 return (NS_LDAP_OP_FAILED); 2528 *entry = e = __s_mk_entry(oclist, max_attr); 2529 if (e == NULL) 2530 return (NS_LDAP_MEMORY); 2531 2532 /* Convert the structure */ 2533 ptr = (struct _ns_netmasks *)data; 2534 2535 if (ptr->netnumber == NULL) { 2536 __ns_ldap_freeEntry(e); 2537 *entry = NULL; 2538 return (NS_LDAP_INVALID_PARAM); 2539 } 2540 2541 /* Create an appropriate rdn */ 2542 (void) snprintf(trdn, RDNSIZE, "ipNetworkNumber=%s", ptr->netnumber); 2543 *rdn = strdup(trdn); 2544 if (*rdn == NULL) { 2545 __ns_ldap_freeEntry(e); 2546 *entry = NULL; 2547 return (NS_LDAP_MEMORY); 2548 } 2549 2550 /* Error check the data and add the attributes */ 2551 rc = __s_add_attr(e, "ipNetworkNumber", ptr->netnumber); 2552 if (rc != NS_LDAP_SUCCESS) { 2553 __s_cvt_freeEntryRdn(entry, rdn); 2554 return (rc); 2555 } 2556 2557 if (ptr->netmask != '\0') { 2558 rc = __s_add_attr(e, "ipNetmaskNumber", ptr->netmask); 2559 if (rc != NS_LDAP_SUCCESS) { 2560 __s_cvt_freeEntryRdn(entry, rdn); 2561 return (rc); 2562 } 2563 } 2564 2565 return (NS_LDAP_SUCCESS); 2566 2567 } 2568 /* 2569 * Conversion: netgroups 2570 * Input format: struct _ns_netgroups 2571 * Exported objectclass: nisNetgroup 2572 */ 2573 static int 2574 __s_cvt_netgroups(const void *data, char **rdn, 2575 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2576 { 2577 ns_ldap_entry_t *e; 2578 int rc; 2579 char trdn[RDNSIZE]; 2580 /* routine specific */ 2581 struct _ns_netgroups *ptr; 2582 int max_attr = 6; 2583 int i, j; 2584 char **nm; 2585 static char *oclist[] = { 2586 "nisNetgroup", 2587 "top", 2588 NULL 2589 }; 2590 2591 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2592 return (NS_LDAP_OP_FAILED); 2593 *entry = e = __s_mk_entry(oclist, max_attr); 2594 if (e == NULL) 2595 return (NS_LDAP_MEMORY); 2596 2597 /* Convert the structure */ 2598 ptr = (struct _ns_netgroups *)data; 2599 2600 if (ptr->name == NULL) { 2601 __ns_ldap_freeEntry(e); 2602 *entry = NULL; 2603 return (NS_LDAP_INVALID_PARAM); 2604 } 2605 2606 /* Create an appropriate rdn */ 2607 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name); 2608 *rdn = strdup(trdn); 2609 if (*rdn == NULL) { 2610 __ns_ldap_freeEntry(e); 2611 *entry = NULL; 2612 return (NS_LDAP_MEMORY); 2613 } 2614 2615 if (ptr->name != '\0') { 2616 rc = __s_add_attr(e, "cn", ptr->name); 2617 if (rc != NS_LDAP_SUCCESS) { 2618 __s_cvt_freeEntryRdn(entry, rdn); 2619 return (rc); 2620 } 2621 } 2622 2623 /* Error check the data and add the attributes */ 2624 if (ptr->triplet && ptr->triplet[0]) { 2625 nm = ptr->triplet; 2626 for (i = 0; *nm; i++, nm++) 2627 ; 2628 nm = (char **)calloc(i+2, sizeof (char *)); 2629 if (nm == NULL) { 2630 __s_cvt_freeEntryRdn(entry, rdn); 2631 return (NS_LDAP_MEMORY); 2632 } 2633 for (j = 0; j < i; j++) 2634 nm[j] = ptr->triplet[j]; 2635 2636 rc = __s_add_attrlist(e, "nisNetgroupTriple", nm); 2637 free(nm); 2638 nm = NULL; 2639 if (rc != NS_LDAP_SUCCESS) { 2640 __s_cvt_freeEntryRdn(entry, rdn); 2641 return (rc); 2642 } 2643 } 2644 if (ptr->netgroup && ptr->netgroup[0]) { 2645 nm = ptr->netgroup; 2646 for (i = 0; *nm; i++, nm++) 2647 ; 2648 nm = (char **)calloc(i+2, sizeof (char *)); 2649 if (nm == NULL) { 2650 __s_cvt_freeEntryRdn(entry, rdn); 2651 return (NS_LDAP_MEMORY); 2652 } 2653 for (j = 0; j < i; j++) 2654 nm[j] = ptr->netgroup[j]; 2655 2656 rc = __s_add_attrlist(e, "memberNisNetgroup", nm); 2657 free(nm); 2658 nm = NULL; 2659 if (rc != NS_LDAP_SUCCESS) { 2660 __s_cvt_freeEntryRdn(entry, rdn); 2661 return (rc); 2662 } 2663 } 2664 return (NS_LDAP_SUCCESS); 2665 } 2666 /* 2667 * Conversion: bootparams 2668 * Input format: struct _ns_bootp 2669 * Exported objectclass: bootableDevice, device 2670 */ 2671 static int 2672 __s_cvt_bootparams(const void *data, char **rdn, 2673 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2674 { 2675 ns_ldap_entry_t *e; 2676 int rc; 2677 char trdn[RDNSIZE]; 2678 /* routine specific */ 2679 struct _ns_bootp *ptr; 2680 int max_attr = 4; 2681 int i, j; 2682 char **nm; 2683 static char *oclist[] = { 2684 "bootableDevice", 2685 "device", 2686 "top", 2687 NULL 2688 }; 2689 2690 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2691 return (NS_LDAP_OP_FAILED); 2692 *entry = e = __s_mk_entry(oclist, max_attr); 2693 if (e == NULL) 2694 return (NS_LDAP_MEMORY); 2695 2696 /* Convert the structure */ 2697 ptr = (struct _ns_bootp *)data; 2698 2699 if (ptr->name == NULL) { 2700 __ns_ldap_freeEntry(e); 2701 *entry = NULL; 2702 return (NS_LDAP_INVALID_PARAM); 2703 } 2704 2705 /* Create an appropriate rdn */ 2706 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name); 2707 *rdn = strdup(trdn); 2708 if (*rdn == NULL) { 2709 __ns_ldap_freeEntry(e); 2710 *entry = NULL; 2711 return (NS_LDAP_MEMORY); 2712 } 2713 2714 if (ptr->name != '\0') { 2715 rc = __s_add_attr(e, "cn", ptr->name); 2716 if (rc != NS_LDAP_SUCCESS) { 2717 __s_cvt_freeEntryRdn(entry, rdn); 2718 return (rc); 2719 } 2720 } 2721 2722 /* Error check the data and add the attributes */ 2723 if (ptr->param && ptr->param[0]) { 2724 nm = ptr->param; 2725 for (i = 0; *nm; i++, nm++) 2726 ; 2727 nm = (char **)calloc(i+2, sizeof (char *)); 2728 if (nm == NULL) { 2729 __s_cvt_freeEntryRdn(entry, rdn); 2730 return (NS_LDAP_MEMORY); 2731 } 2732 for (j = 0; j < i; j++) 2733 nm[j] = ptr->param[j]; 2734 2735 rc = __s_add_attrlist(e, "bootParameter", nm); 2736 free(nm); 2737 nm = NULL; 2738 if (rc != NS_LDAP_SUCCESS) { 2739 __s_cvt_freeEntryRdn(entry, rdn); 2740 return (rc); 2741 } 2742 } 2743 2744 return (NS_LDAP_SUCCESS); 2745 2746 } 2747 /* 2748 * Conversion: ethers 2749 * Input format: struct _ns_ethers 2750 * Exported objectclass: ieee802Device, device 2751 */ 2752 static int 2753 __s_cvt_ethers(const void *data, char **rdn, 2754 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2755 { 2756 ns_ldap_entry_t *e; 2757 int rc; 2758 char trdn[RDNSIZE]; 2759 /* routine specific */ 2760 struct _ns_ethers *ptr; 2761 int max_attr = 4; 2762 static char *oclist[] = { 2763 "ieee802Device", 2764 "device", 2765 "top", 2766 NULL 2767 }; 2768 2769 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2770 return (NS_LDAP_OP_FAILED); 2771 *entry = e = __s_mk_entry(oclist, max_attr); 2772 if (e == NULL) 2773 return (NS_LDAP_MEMORY); 2774 2775 /* Convert the structure */ 2776 ptr = (struct _ns_ethers *)data; 2777 2778 if (ptr->name == NULL || ptr->ether == '\0') { 2779 __ns_ldap_freeEntry(e); 2780 *entry = NULL; 2781 return (NS_LDAP_INVALID_PARAM); 2782 } 2783 2784 /* Create an appropriate rdn */ 2785 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name); 2786 *rdn = strdup(trdn); 2787 if (*rdn == NULL) { 2788 __ns_ldap_freeEntry(e); 2789 *entry = NULL; 2790 return (NS_LDAP_MEMORY); 2791 } 2792 2793 /* Error check the data and add the attributes */ 2794 rc = __s_add_attr(e, "cn", ptr->name); 2795 if (rc != NS_LDAP_SUCCESS) { 2796 __s_cvt_freeEntryRdn(entry, rdn); 2797 return (rc); 2798 } 2799 2800 rc = __s_add_attr(e, "macAddress", ptr->ether); 2801 if (rc != NS_LDAP_SUCCESS) { 2802 __s_cvt_freeEntryRdn(entry, rdn); 2803 return (rc); 2804 } 2805 2806 return (NS_LDAP_SUCCESS); 2807 } 2808 /* 2809 * This function is used when processing an ethers (objectclass: ieee802Device) 2810 * or a bootparams (objectclass: bootableDevice) entry, and the entry is 2811 * already found in LDAP. Since both ethers and bootparams share the same 2812 * LDAP container, we want to check that the entry found in LDAP is: 2813 * - either the same entry (same cn, same objectclass): we don't do anything 2814 * in this case 2815 * - or an entry which does not have the objectclass we are interesting in: 2816 * in this case, we modify the existing entry by adding the relevant 2817 * objectclass (ieee802Device or bootableDevice) and the relevant attribute(s) 2818 * from the attribute list previously computing by the relevant conversion 2819 * function. 2820 * Note: from conversion functions __s_cvt_ethers() and __s_cvt_bootparams() 2821 * we know that there is only 1 more attribute today to add (macAddress 2822 * or bootParameter) 2823 */ 2824 #define _MAX_ATTR_ETHBOOTP 2 2825 static int 2826 modify_ethers_bootp( 2827 const char *service, 2828 const char *rdn, 2829 const char *fulldn, 2830 const ns_ldap_attr_t * const *attrlist, 2831 const ns_cred_t *cred, 2832 const int flags, 2833 ns_ldap_error_t **errorp) 2834 { 2835 char filter[BUFSIZ]; 2836 ns_ldap_result_t *resultp; 2837 int rc = 0; 2838 int i; 2839 ns_ldap_attr_t *new_attrlist[_MAX_ATTR_ETHBOOTP+1]; 2840 ns_ldap_attr_t new_attrlist0; 2841 char *new_attrvalue0[1]; 2842 const ns_ldap_attr_t * const *aptr = attrlist; 2843 ns_ldap_attr_t *aptr2; 2844 ns_ldap_error_t *new_errorp = NULL; 2845 2846 if (rdn == NULL || fulldn == NULL || attrlist == NULL || 2847 errorp == NULL || service == NULL) 2848 return (NS_LDAP_OP_FAILED); 2849 2850 bzero(&new_attrlist, sizeof (new_attrlist)); 2851 bzero(&new_attrlist0, sizeof (new_attrlist0)); 2852 new_attrlist[0] = &new_attrlist0; 2853 new_attrlist[0]->attrvalue = new_attrvalue0; 2854 2855 new_attrlist[0]->attrname = "objectclass"; 2856 new_attrlist[0]->value_count = 1; 2857 if (strcasecmp(service, "ethers") == NULL) { 2858 (void) snprintf(&filter[0], sizeof (filter), 2859 "(&(objectClass=ieee802Device)(%s))", rdn); 2860 new_attrlist[0]->attrvalue[0] = "ieee802Device"; 2861 } else { 2862 (void) snprintf(&filter[0], sizeof (filter), 2863 "(&(objectClass=bootableDevice)(%s))", rdn); 2864 new_attrlist[0]->attrvalue[0] = "bootableDevice"; 2865 } 2866 2867 rc = __ns_ldap_list(service, filter, NULL, (const char **)NULL, 2868 NULL, NS_LDAP_SCOPE_SUBTREE, &resultp, &new_errorp, 2869 NULL, NULL); 2870 2871 switch (rc) { 2872 case NS_LDAP_SUCCESS: 2873 /* 2874 * entry already exists for this service 2875 * return NS_LDAP_INTERNAL and do not modify the incoming errorp 2876 */ 2877 rc = NS_LDAP_INTERNAL; 2878 break; 2879 case NS_LDAP_NOTFOUND: 2880 /* 2881 * entry not found with the given objectclasss but entry exists 2882 * hence add the relevant attribute (macAddress or bootparams). 2883 */ 2884 i = 1; 2885 while (*aptr && (i < _MAX_ATTR_ETHBOOTP)) { 2886 /* aptr2 needed here to avoid lint warning */ 2887 aptr2 = (ns_ldap_attr_t *)*aptr++; 2888 if ((strcasecmp(aptr2->attrname, "cn") != 0) && 2889 (strcasecmp(aptr2->attrname, 2890 "objectclass") != 0)) { 2891 new_attrlist[i++] = (ns_ldap_attr_t *)aptr2; 2892 } 2893 } 2894 2895 if (i != _MAX_ATTR_ETHBOOTP) { 2896 /* we haven't found all expected attributes */ 2897 rc = NS_LDAP_OP_FAILED; 2898 break; 2899 } 2900 2901 aptr = (const ns_ldap_attr_t * const *) new_attrlist; 2902 /* clean errorp first */ 2903 (void) __ns_ldap_freeError(errorp); 2904 rc = __ns_ldap_addAttr(service, fulldn, aptr, cred, flags, 2905 errorp); 2906 break; 2907 default: 2908 /* 2909 * unexpected error happenned 2910 * returning relevant error 2911 */ 2912 (void) __ns_ldap_freeError(errorp); 2913 *errorp = new_errorp; 2914 break; 2915 } 2916 2917 return (rc); 2918 } 2919 2920 /* 2921 * Conversion: publickey 2922 * Input format: struct _ns_pubkey 2923 * Exported objectclass: NisKeyObject 2924 */ 2925 static int 2926 __s_cvt_publickey(const void *data, char **rdn, 2927 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2928 { 2929 ns_ldap_entry_t *e; 2930 int rc; 2931 char trdn[RDNSIZE]; 2932 /* routine specific */ 2933 struct _ns_pubkey *ptr; 2934 int max_attr = 3; 2935 static char *oclist[] = { 2936 "NisKeyObject", 2937 NULL 2938 }; 2939 2940 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2941 return (NS_LDAP_OP_FAILED); 2942 *entry = e = __s_mk_entry(oclist, max_attr); 2943 if (e == NULL) 2944 return (NS_LDAP_MEMORY); 2945 2946 /* Convert the structure */ 2947 ptr = (struct _ns_pubkey *)data; 2948 2949 if (ptr->name == NULL || ptr->pubkey == '\0' || ptr->privkey == '\0') { 2950 __ns_ldap_freeEntry(e); 2951 *entry = NULL; 2952 return (NS_LDAP_INVALID_PARAM); 2953 } 2954 2955 /* Create an appropriate rdn */ 2956 if (ptr->hostcred == NS_HOSTCRED_FALSE) 2957 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->name); 2958 else 2959 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name); 2960 *rdn = strdup(trdn); 2961 if (*rdn == NULL) { 2962 __ns_ldap_freeEntry(e); 2963 *entry = NULL; 2964 return (NS_LDAP_MEMORY); 2965 } 2966 2967 /* Error check the data and add the attributes */ 2968 2969 rc = __s_add_attr(e, "nisPublickey", ptr->pubkey); 2970 if (rc != NS_LDAP_SUCCESS) { 2971 __s_cvt_freeEntryRdn(entry, rdn); 2972 return (rc); 2973 } 2974 2975 rc = __s_add_attr(e, "nisSecretkey", ptr->privkey); 2976 if (rc != NS_LDAP_SUCCESS) { 2977 __s_cvt_freeEntryRdn(entry, rdn); 2978 return (rc); 2979 } 2980 2981 return (NS_LDAP_SUCCESS); 2982 } 2983 /* 2984 * Conversion: aliases 2985 * Input format: struct _ns_alias 2986 * Exported objectclass: mailGroup 2987 */ 2988 static int 2989 __s_cvt_aliases(const void *data, char **rdn, 2990 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2991 { 2992 ns_ldap_entry_t *e; 2993 int rc; 2994 char trdn[RDNSIZE]; 2995 /* routine specific */ 2996 struct _ns_alias *ptr; 2997 int max_attr = 4; 2998 int i, j; 2999 char **nm; 3000 static char *oclist[] = { 3001 "mailGroup", 3002 "top", 3003 NULL 3004 }; 3005 3006 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3007 return (NS_LDAP_OP_FAILED); 3008 *entry = e = __s_mk_entry(oclist, max_attr); 3009 if (e == NULL) 3010 return (NS_LDAP_MEMORY); 3011 3012 /* Convert the structure */ 3013 ptr = (struct _ns_alias *)data; 3014 3015 if (ptr->alias == NULL) { 3016 __ns_ldap_freeEntry(e); 3017 *entry = NULL; 3018 return (NS_LDAP_INVALID_PARAM); 3019 } 3020 3021 /* Create an appropriate rdn */ 3022 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->alias); 3023 *rdn = strdup(trdn); 3024 if (*rdn == NULL) { 3025 __ns_ldap_freeEntry(e); 3026 *entry = NULL; 3027 return (NS_LDAP_MEMORY); 3028 } 3029 3030 if (ptr->alias != '\0') { 3031 rc = __s_add_attr(e, "mail", (char *)ptr->alias); 3032 if (rc != NS_LDAP_SUCCESS) { 3033 __s_cvt_freeEntryRdn(entry, rdn); 3034 return (rc); 3035 } 3036 } 3037 3038 /* Error check the data and add the attributes */ 3039 if (ptr->member && ptr->member[0]) { 3040 nm = ptr->member; 3041 for (i = 0; *nm; i++, nm++) 3042 ; 3043 nm = (char **)calloc(i+2, sizeof (char *)); 3044 if (nm == NULL) { 3045 __s_cvt_freeEntryRdn(entry, rdn); 3046 return (NS_LDAP_MEMORY); 3047 } 3048 for (j = 0; j < i; j++) 3049 nm[j] = ptr->member[j]; 3050 3051 rc = __s_add_attrlist(e, "mgrpRFC822MailMember", nm); 3052 free(nm); 3053 nm = NULL; 3054 if (rc != NS_LDAP_SUCCESS) { 3055 __s_cvt_freeEntryRdn(entry, rdn); 3056 return (rc); 3057 } 3058 } 3059 3060 return (NS_LDAP_SUCCESS); 3061 3062 } 3063 /* 3064 * Conversion: automount 3065 * Input format: struct _ns_automount 3066 * Exported objectclass: automount 3067 */ 3068 static int 3069 __s_cvt_auto_mount(const void *data, char **rdn, 3070 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3071 { 3072 ns_ldap_entry_t *e; 3073 int rc; 3074 char trdn[RDNSIZE]; 3075 /* routine specific */ 3076 struct _ns_automount *ptr; 3077 int max_attr = 6; 3078 void **paramVal = NULL; 3079 char **mappedschema = NULL; 3080 int version1 = 0; 3081 static char *oclist[] = { 3082 NULL, 3083 "top", 3084 NULL 3085 }; 3086 3087 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3088 return (NS_LDAP_OP_FAILED); 3089 3090 /* determine profile version number */ 3091 rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, ¶mVal, errorp); 3092 if (paramVal && *paramVal && 3093 strcasecmp(*paramVal, NS_LDAP_VERSION_1) == 0) 3094 version1 = 1; 3095 if (paramVal) 3096 (void) __ns_ldap_freeParam(¶mVal); 3097 if (rc && errorp) 3098 (void) __ns_ldap_freeError(errorp); 3099 3100 /* use old schema for version 1 profiles */ 3101 if (version1) 3102 oclist[0] = "nisObject"; 3103 else 3104 oclist[0] = "automount"; 3105 3106 *entry = e = __s_mk_entry(oclist, max_attr); 3107 if (e == NULL) 3108 return (NS_LDAP_MEMORY); 3109 3110 /* Convert the structure */ 3111 ptr = (struct _ns_automount *)data; 3112 3113 if (ptr->key == NULL || ptr->value == '\0' || ptr->mapname == '\0') { 3114 __ns_ldap_freeEntry(e); 3115 *entry = NULL; 3116 return (NS_LDAP_INVALID_PARAM); 3117 } 3118 3119 /* Create an appropriate rdn */ 3120 (void) snprintf(trdn, RDNSIZE, version1 ? "cn=%s" : "automountKey=%s", 3121 ptr->key); 3122 *rdn = strdup(trdn); 3123 if (*rdn == NULL) { 3124 __ns_ldap_freeEntry(e); 3125 *entry = NULL; 3126 return (NS_LDAP_MEMORY); 3127 } 3128 3129 if (ptr->key != '\0') { 3130 rc = __s_add_attr(e, version1 ? "cn" : "automountKey", 3131 (char *)ptr->key); 3132 if (rc != NS_LDAP_SUCCESS) { 3133 __s_cvt_freeEntryRdn(entry, rdn); 3134 return (rc); 3135 } 3136 } 3137 3138 rc = __s_add_attr(e, version1 ? "nisMapEntry" : "automountInformation", 3139 (char *)ptr->value); 3140 if (rc != NS_LDAP_SUCCESS) { 3141 __s_cvt_freeEntryRdn(entry, rdn); 3142 return (rc); 3143 } 3144 3145 /* 3146 * even for version 2, if automount is mapped to nisObject we 3147 * still need 'nisMapName' attribute 3148 */ 3149 mappedschema = __ns_ldap_getMappedObjectClass("automount", "automount"); 3150 if (mappedschema && mappedschema[0] && 3151 strcasecmp(mappedschema[0], "nisObject") == 0) 3152 version1 = 1; 3153 if (mappedschema) 3154 __s_api_free2dArray(mappedschema); 3155 3156 if (version1) { 3157 rc = __s_add_attr(e, "nisMapName", (char *)ptr->mapname); 3158 if (rc != NS_LDAP_SUCCESS) { 3159 __s_cvt_freeEntryRdn(entry, rdn); 3160 return (rc); 3161 } 3162 } 3163 3164 return (NS_LDAP_SUCCESS); 3165 } 3166 /* 3167 * Conversion: auth_attr 3168 * Input format: authstr_t 3169 * Exported objectclass: SolarisAuthAttr 3170 */ 3171 static int 3172 __s_cvt_authattr(const void *data, char **rdn, 3173 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3174 { 3175 ns_ldap_entry_t *e; 3176 int rc; 3177 char trdn[RDNSIZE]; 3178 /* routine specific */ 3179 authstr_t *ptr; 3180 int max_attr = 6; 3181 static char *oclist[] = { 3182 "SolarisAuthAttr", 3183 "top", 3184 NULL 3185 }; 3186 3187 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3188 return (NS_LDAP_OP_FAILED); 3189 3190 *entry = e = __s_mk_entry(oclist, max_attr); 3191 if (e == NULL) 3192 return (NS_LDAP_MEMORY); 3193 3194 /* Convert the structure */ 3195 ptr = (authstr_t *)data; 3196 3197 if (ptr->name == NULL || ptr->name[0] == '\0' || ptr->attr == NULL) { 3198 __ns_ldap_freeEntry(e); 3199 *entry = NULL; 3200 return (NS_LDAP_INVALID_PARAM); 3201 } 3202 3203 /* Create an appropriate rdn */ 3204 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name); 3205 *rdn = strdup(trdn); 3206 if (*rdn == NULL) { 3207 __ns_ldap_freeEntry(e); 3208 *entry = NULL; 3209 return (NS_LDAP_MEMORY); 3210 } 3211 3212 rc = __s_add_attr(e, "cn", ptr->name); 3213 if (rc != NS_LDAP_SUCCESS) { 3214 __s_cvt_freeEntryRdn(entry, rdn); 3215 return (rc); 3216 } 3217 3218 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr); 3219 if (rc != NS_LDAP_SUCCESS) { 3220 __s_cvt_freeEntryRdn(entry, rdn); 3221 return (rc); 3222 } 3223 3224 if (ptr->res1 != NULL) { 3225 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1); 3226 if (rc != NS_LDAP_SUCCESS) { 3227 __s_cvt_freeEntryRdn(entry, rdn); 3228 return (rc); 3229 } 3230 } 3231 3232 if (ptr->res2 != NULL) { 3233 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2); 3234 if (rc != NS_LDAP_SUCCESS) { 3235 __s_cvt_freeEntryRdn(entry, rdn); 3236 return (rc); 3237 } 3238 } 3239 3240 if (ptr->short_desc != NULL) { 3241 rc = __s_add_attr(e, "SolarisAttrShortDesc", ptr->short_desc); 3242 if (rc != NS_LDAP_SUCCESS) { 3243 __s_cvt_freeEntryRdn(entry, rdn); 3244 return (rc); 3245 } 3246 } 3247 3248 if (ptr->long_desc != NULL) { 3249 rc = __s_add_attr(e, "SolarisAttrLongDesc", ptr->long_desc); 3250 if (rc != NS_LDAP_SUCCESS) { 3251 __s_cvt_freeEntryRdn(entry, rdn); 3252 return (rc); 3253 } 3254 } 3255 3256 return (NS_LDAP_SUCCESS); 3257 } 3258 /* 3259 * Conversion: exec_attr 3260 * Input format: execstr_t 3261 * Exported objectclass: SolarisExecAttr 3262 */ 3263 static int 3264 __s_cvt_execattr(const void *data, char **rdn, 3265 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3266 { 3267 ns_ldap_entry_t *e; 3268 int rc; 3269 char trdn[RDNSIZE]; 3270 char esc_str[RDNSIZE]; 3271 /* routine specific */ 3272 execstr_t *ptr; 3273 int max_attr = 7; 3274 static char *oclist[] = { 3275 "SolarisExecAttr", 3276 "SolarisProfAttr", 3277 "top", 3278 NULL 3279 }; 3280 3281 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3282 return (NS_LDAP_OP_FAILED); 3283 3284 *entry = e = __s_mk_entry(oclist, max_attr); 3285 if (e == NULL) 3286 return (NS_LDAP_MEMORY); 3287 3288 /* Convert the structure */ 3289 ptr = (execstr_t *)data; 3290 3291 if (ptr->name == NULL || ptr->name[0] == '\0' || 3292 ptr->policy == NULL || ptr->policy[0] == '\0' || 3293 ptr->type == NULL || ptr->type[0] == '\0' || 3294 ptr->id == NULL || ptr->id[0] == '\0') { 3295 __ns_ldap_freeEntry(e); 3296 *entry = NULL; 3297 return (NS_LDAP_INVALID_PARAM); 3298 } 3299 3300 /* 3301 * Escape special characters in ProfileID. 3302 */ 3303 if (escape_str(esc_str, ptr->id) != 0) { 3304 __ns_ldap_freeEntry(e); 3305 *entry = NULL; 3306 return (NS_LDAP_INVALID_PARAM); 3307 } 3308 3309 /* Create an appropriate rdn */ 3310 (void) snprintf(trdn, RDNSIZE, "cn=%s+SolarisKernelSecurityPolicy=%s" 3311 "+SolarisProfileType=%s+SolarisProfileId=%s", 3312 ptr->name, ptr->policy, ptr->type, esc_str); 3313 3314 *rdn = strdup(trdn); 3315 if (*rdn == NULL) { 3316 __ns_ldap_freeEntry(e); 3317 *entry = NULL; 3318 return (NS_LDAP_MEMORY); 3319 } 3320 3321 rc = __s_add_attr(e, "cn", ptr->name); 3322 if (rc != NS_LDAP_SUCCESS) { 3323 __s_cvt_freeEntryRdn(entry, rdn); 3324 return (rc); 3325 } 3326 3327 rc = __s_add_attr(e, "SolarisKernelSecurityPolicy", ptr->policy); 3328 if (rc != NS_LDAP_SUCCESS) { 3329 __s_cvt_freeEntryRdn(entry, rdn); 3330 return (rc); 3331 } 3332 3333 rc = __s_add_attr(e, "SolarisProfileType", ptr->type); 3334 if (rc != NS_LDAP_SUCCESS) { 3335 __s_cvt_freeEntryRdn(entry, rdn); 3336 return (rc); 3337 } 3338 3339 rc = __s_add_attr(e, "SolarisProfileId", ptr->id); 3340 if (rc != NS_LDAP_SUCCESS) { 3341 __s_cvt_freeEntryRdn(entry, rdn); 3342 return (rc); 3343 } 3344 3345 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr); 3346 if (rc != NS_LDAP_SUCCESS) { 3347 __s_cvt_freeEntryRdn(entry, rdn); 3348 return (rc); 3349 } 3350 3351 if (ptr->res1 != NULL) { 3352 rc = __s_add_attr(e, "SolarisAttrRes1", ptr->res1); 3353 if (rc != NS_LDAP_SUCCESS) { 3354 __s_cvt_freeEntryRdn(entry, rdn); 3355 return (rc); 3356 } 3357 } 3358 3359 if (ptr->res2 != NULL) { 3360 rc = __s_add_attr(e, "SolarisAttrRes2", ptr->res2); 3361 if (rc != NS_LDAP_SUCCESS) { 3362 __s_cvt_freeEntryRdn(entry, rdn); 3363 return (rc); 3364 } 3365 } 3366 3367 return (NS_LDAP_SUCCESS); 3368 } 3369 /* 3370 * Conversion: prof_attr 3371 * Input format: profstr_t 3372 * Exported objectclass: SolarisProfAttr 3373 */ 3374 static int 3375 __s_cvt_profattr(const void *data, char **rdn, 3376 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3377 { 3378 ns_ldap_entry_t *e; 3379 int rc; 3380 char trdn[RDNSIZE]; 3381 /* routine specific */ 3382 profstr_t *ptr; 3383 int max_attr = 5; 3384 static char *oclist[] = { 3385 "SolarisProfAttr", 3386 "top", 3387 NULL 3388 }; 3389 3390 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3391 return (NS_LDAP_OP_FAILED); 3392 3393 *entry = e = __s_mk_entry(oclist, max_attr); 3394 if (e == NULL) 3395 return (NS_LDAP_MEMORY); 3396 3397 /* Convert the structure */ 3398 ptr = (profstr_t *)data; 3399 3400 if (ptr->name == NULL || ptr->name[0] == '\0' || ptr->attr == NULL) { 3401 __ns_ldap_freeEntry(e); 3402 *entry = NULL; 3403 return (NS_LDAP_INVALID_PARAM); 3404 } 3405 3406 /* Create an appropriate rdn */ 3407 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name); 3408 *rdn = strdup(trdn); 3409 if (*rdn == NULL) { 3410 __ns_ldap_freeEntry(e); 3411 *entry = NULL; 3412 return (NS_LDAP_MEMORY); 3413 } 3414 3415 rc = __s_add_attr(e, "cn", ptr->name); 3416 if (rc != NS_LDAP_SUCCESS) { 3417 __s_cvt_freeEntryRdn(entry, rdn); 3418 return (rc); 3419 } 3420 3421 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr); 3422 if (rc != NS_LDAP_SUCCESS) { 3423 __s_cvt_freeEntryRdn(entry, rdn); 3424 return (rc); 3425 } 3426 3427 if (ptr->res1 != NULL) { 3428 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1); 3429 if (rc != NS_LDAP_SUCCESS) { 3430 __s_cvt_freeEntryRdn(entry, rdn); 3431 return (rc); 3432 } 3433 } 3434 3435 if (ptr->res2 != NULL) { 3436 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2); 3437 if (rc != NS_LDAP_SUCCESS) { 3438 __s_cvt_freeEntryRdn(entry, rdn); 3439 return (rc); 3440 } 3441 } 3442 3443 if (ptr->desc != NULL) { 3444 rc = __s_add_attr(e, "SolarisAttrLongDesc", ptr->desc); 3445 if (rc != NS_LDAP_SUCCESS) { 3446 __s_cvt_freeEntryRdn(entry, rdn); 3447 return (rc); 3448 } 3449 } 3450 3451 return (NS_LDAP_SUCCESS); 3452 } 3453 /* 3454 * Conversion: user_attr 3455 * Input format: userstr_t 3456 * Exported objectclass: SolarisUserAttr 3457 */ 3458 static int 3459 __s_cvt_userattr(const void *data, char **rdn, 3460 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3461 { 3462 ns_ldap_entry_t *e; 3463 int rc; 3464 char trdn[RDNSIZE]; 3465 /* routine specific */ 3466 userstr_t *ptr; 3467 int max_attr = 5; 3468 static char *oclist[] = { 3469 "SolarisUserAttr", 3470 NULL 3471 }; 3472 3473 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3474 return (NS_LDAP_OP_FAILED); 3475 3476 *entry = e = __s_mk_entry(oclist, max_attr); 3477 if (e == NULL) 3478 return (NS_LDAP_MEMORY); 3479 3480 /* Convert the structure */ 3481 ptr = (userstr_t *)data; 3482 3483 if (ptr->name == NULL || ptr->name[0] == '\0' || 3484 ptr->attr == NULL) { 3485 __ns_ldap_freeEntry(e); 3486 *entry = NULL; 3487 return (NS_LDAP_INVALID_PARAM); 3488 } 3489 3490 /* Create an appropriate rdn */ 3491 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->name); 3492 *rdn = strdup(trdn); 3493 if (*rdn == NULL) { 3494 __ns_ldap_freeEntry(e); 3495 *entry = NULL; 3496 return (NS_LDAP_MEMORY); 3497 } 3498 3499 /* 3500 * SolarisUserAttr has no uid attribute 3501 */ 3502 3503 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr); 3504 if (rc != NS_LDAP_SUCCESS) { 3505 __s_cvt_freeEntryRdn(entry, rdn); 3506 return (rc); 3507 } 3508 3509 if (ptr->qualifier != NULL) { 3510 rc = __s_add_attr(e, "SolarisUserQualifier", ptr->qualifier); 3511 if (rc != NS_LDAP_SUCCESS) { 3512 __s_cvt_freeEntryRdn(entry, rdn); 3513 return (rc); 3514 } 3515 } 3516 3517 if (ptr->res1 != NULL) { 3518 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1); 3519 if (rc != NS_LDAP_SUCCESS) { 3520 __s_cvt_freeEntryRdn(entry, rdn); 3521 return (rc); 3522 } 3523 } 3524 3525 if (ptr->res2 != NULL) { 3526 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2); 3527 if (rc != NS_LDAP_SUCCESS) { 3528 __s_cvt_freeEntryRdn(entry, rdn); 3529 return (rc); 3530 } 3531 } 3532 3533 return (NS_LDAP_SUCCESS); 3534 } 3535 /* 3536 * Conversion: audit_user 3537 * Input format: au_user_str_t 3538 * Exported objectclass: SolarisAuditUser 3539 */ 3540 static int 3541 __s_cvt_audituser(const void *data, char **rdn, 3542 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3543 { 3544 ns_ldap_entry_t *e; 3545 int rc; 3546 char trdn[RDNSIZE]; 3547 /* routine specific */ 3548 au_user_str_t *ptr; 3549 int max_attr = 3; 3550 static char *oclist[] = { 3551 "SolarisAuditUser", 3552 NULL 3553 }; 3554 3555 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3556 return (NS_LDAP_OP_FAILED); 3557 3558 *entry = e = __s_mk_entry(oclist, max_attr); 3559 if (e == NULL) 3560 return (NS_LDAP_MEMORY); 3561 3562 /* Convert the structure */ 3563 ptr = (au_user_str_t *)data; 3564 3565 if (ptr->au_name == NULL || ptr->au_name[0] == '\0') { 3566 __ns_ldap_freeEntry(e); 3567 *entry = NULL; 3568 return (NS_LDAP_INVALID_PARAM); 3569 } 3570 3571 /* Create an appropriate rdn */ 3572 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->au_name); 3573 *rdn = strdup(trdn); 3574 if (*rdn == NULL) { 3575 __ns_ldap_freeEntry(e); 3576 *entry = NULL; 3577 return (NS_LDAP_MEMORY); 3578 } 3579 3580 /* 3581 * Solaris AuditUser has no uid attribute 3582 */ 3583 3584 if (ptr->au_always != NULL) { 3585 rc = __s_add_attr(e, "SolarisAuditAlways", ptr->au_always); 3586 if (rc != NS_LDAP_SUCCESS) { 3587 __s_cvt_freeEntryRdn(entry, rdn); 3588 return (rc); 3589 } 3590 } 3591 3592 if (ptr->au_never != NULL) { 3593 rc = __s_add_attr(e, "SolarisAuditNever", ptr->au_never); 3594 if (rc != NS_LDAP_SUCCESS) { 3595 __s_cvt_freeEntryRdn(entry, rdn); 3596 return (rc); 3597 } 3598 } 3599 3600 return (NS_LDAP_SUCCESS); 3601 } 3602 /* 3603 * Conversion: tnrhtp 3604 * Input format: tsol_tpstr_t 3605 * Exported objectclass: ipTnetTemplate 3606 */ 3607 static int 3608 __s_cvt_tnrhtp(const void *data, char **rdn, 3609 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3610 { 3611 ns_ldap_entry_t *e; 3612 int rc; 3613 char trdn[RDNSIZE]; 3614 char esc_str[RDNSIZE]; 3615 /* routine specific */ 3616 int max_attr = 2; 3617 tsol_tpstr_t *ptr; 3618 static char *oclist[] = { 3619 "ipTnetTemplate", 3620 "top", 3621 NULL 3622 }; 3623 3624 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3625 return (NS_LDAP_OP_FAILED); 3626 3627 *entry = e = __s_mk_entry(oclist, max_attr); 3628 if (e == NULL) 3629 return (NS_LDAP_MEMORY); 3630 3631 /* Convert the structure */ 3632 ptr = (tsol_tpstr_t *)data; 3633 3634 if (ptr->template == NULL || *ptr->template == '\0') { 3635 __ns_ldap_freeEntry(e); 3636 *entry = NULL; 3637 return (NS_LDAP_INVALID_PARAM); 3638 } 3639 3640 /* 3641 * Escape special characters in Template name. 3642 */ 3643 if (escape_str(esc_str, ptr->template) != 0) { 3644 __ns_ldap_freeEntry(e); 3645 *entry = NULL; 3646 return (NS_LDAP_INVALID_PARAM); 3647 } 3648 3649 /* Create an appropriate rdn */ 3650 (void) snprintf(trdn, RDNSIZE, "ipTnetTemplateName=%s", esc_str); 3651 *rdn = strdup(trdn); 3652 if (*rdn == NULL) { 3653 __ns_ldap_freeEntry(e); 3654 *entry = NULL; 3655 return (NS_LDAP_MEMORY); 3656 } 3657 3658 rc = __s_add_attr(e, "ipTnetTemplateName", ptr->template); 3659 if (rc != NS_LDAP_SUCCESS) { 3660 __s_cvt_freeEntryRdn(entry, rdn); 3661 return (rc); 3662 } 3663 3664 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attrs); 3665 if (rc != NS_LDAP_SUCCESS) { 3666 __s_cvt_freeEntryRdn(entry, rdn); 3667 return (rc); 3668 } 3669 3670 return (NS_LDAP_SUCCESS); 3671 } 3672 /* 3673 * Conversion: tnrhdb 3674 * Input format: tsol_rhstr_t 3675 * Exported objectclass: ipTnetHost 3676 */ 3677 static int 3678 __s_cvt_tnrhdb(const void *data, char **rdn, 3679 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3680 { 3681 ns_ldap_entry_t *e; 3682 int rc; 3683 char trdn[RDNSIZE]; 3684 /* routine specific */ 3685 tsol_rhstr_t *ptr; 3686 int max_attr = 2; 3687 static char *oclist[] = { 3688 "ipTnetHost", 3689 "ipTnetTemplate", 3690 "top", 3691 NULL 3692 }; 3693 3694 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3695 return (NS_LDAP_OP_FAILED); 3696 3697 *entry = e = __s_mk_entry(oclist, max_attr); 3698 if (e == NULL) 3699 return (NS_LDAP_MEMORY); 3700 3701 /* Convert the structure */ 3702 ptr = (tsol_rhstr_t *)data; 3703 3704 if (ptr->address == NULL || *ptr->address == '\0' || 3705 ptr->template == NULL || *ptr->template == '\0') { 3706 __ns_ldap_freeEntry(e); 3707 *entry = NULL; 3708 return (NS_LDAP_INVALID_PARAM); 3709 } 3710 3711 /* Create an appropriate rdn */ 3712 (void) snprintf(trdn, RDNSIZE, "ipTnetNumber=%s", ptr->address); 3713 *rdn = strdup(trdn); 3714 if (*rdn == NULL) { 3715 __ns_ldap_freeEntry(e); 3716 *entry = NULL; 3717 return (NS_LDAP_MEMORY); 3718 } 3719 3720 rc = __s_add_attr(e, "ipTnetNumber", ptr->address); 3721 if (rc != NS_LDAP_SUCCESS) { 3722 __s_cvt_freeEntryRdn(entry, rdn); 3723 return (rc); 3724 } 3725 3726 rc = __s_add_attr(e, "ipTnetTemplateName", ptr->template); 3727 if (rc != NS_LDAP_SUCCESS) { 3728 __s_cvt_freeEntryRdn(entry, rdn); 3729 return (rc); 3730 } 3731 3732 return (NS_LDAP_SUCCESS); 3733 } 3734 /* 3735 * Add Typed Entry Conversion data structures 3736 */ 3737 3738 typedef struct __ns_cvt_type { 3739 const char *service; 3740 int flags; 3741 #define AE 1 /* alway add entries */ 3742 int (*cvt_rtn)(const void *data, 3743 char **rdn, 3744 ns_ldap_entry_t **entry, 3745 ns_ldap_error_t **errorp); 3746 } __ns_cvt_type_t; 3747 3748 static __ns_cvt_type_t __s_cvtlist[] = { 3749 { NS_LDAP_TYPE_PASSWD, 0, __s_cvt_passwd }, 3750 { NS_LDAP_TYPE_GROUP, 0, __s_cvt_group }, 3751 { NS_LDAP_TYPE_HOSTS, 0, __s_cvt_hosts }, 3752 { NS_LDAP_TYPE_IPNODES, 0, __s_cvt_hosts }, 3753 { NS_LDAP_TYPE_RPC, 0, __s_cvt_rpc }, 3754 { NS_LDAP_TYPE_PROTOCOLS, 0, __s_cvt_protocols }, 3755 { NS_LDAP_TYPE_NETWORKS, 0, __s_cvt_networks }, 3756 { NS_LDAP_TYPE_NETGROUP, 0, __s_cvt_netgroups }, 3757 { NS_LDAP_TYPE_ALIASES, 0, __s_cvt_aliases }, 3758 { NS_LDAP_TYPE_SERVICES, 0, __s_cvt_services }, 3759 { NS_LDAP_TYPE_ETHERS, 0, __s_cvt_ethers }, 3760 { NS_LDAP_TYPE_SHADOW, 0, __s_cvt_shadow }, 3761 { NS_LDAP_TYPE_NETMASKS, 0, __s_cvt_netmasks }, 3762 { NS_LDAP_TYPE_BOOTPARAMS, 0, __s_cvt_bootparams }, 3763 { NS_LDAP_TYPE_AUTHATTR, 0, __s_cvt_authattr }, 3764 { NS_LDAP_TYPE_EXECATTR, 0, __s_cvt_execattr }, 3765 { NS_LDAP_TYPE_PROFILE, 0, __s_cvt_profattr }, 3766 { NS_LDAP_TYPE_USERATTR, AE, __s_cvt_userattr }, 3767 { NS_LDAP_TYPE_AUTOMOUNT, 0, __s_cvt_auto_mount }, 3768 { NS_LDAP_TYPE_PUBLICKEY, AE, __s_cvt_publickey }, 3769 { NS_LDAP_TYPE_AUUSER, AE, __s_cvt_audituser }, 3770 { NS_LDAP_TYPE_TNRHTP, 0, __s_cvt_tnrhtp }, 3771 { NS_LDAP_TYPE_TNRHDB, 0, __s_cvt_tnrhdb }, 3772 { NS_LDAP_TYPE_PROJECT, 0, __s_cvt_project }, 3773 { NULL, 0, NULL }, 3774 }; 3775 3776 /* 3777 * Add Typed Entry Routine 3778 */ 3779 3780 /*ARGSUSED*/ 3781 int __ns_ldap_addTypedEntry( 3782 const char *servicetype, 3783 const char *basedn, 3784 const void *data, 3785 const int create, 3786 const ns_cred_t *cred, 3787 const int flags, 3788 ns_ldap_error_t **errorp) 3789 { 3790 char *rdn = NULL, *fulldn = NULL; 3791 void **paramVal = NULL; 3792 ns_ldap_entry_t *entry = NULL; 3793 const ns_ldap_attr_t *const *modattrlist; 3794 ns_ldap_search_desc_t **sdlist; 3795 char **dns = NULL; 3796 char trdn[RDNSIZE]; 3797 char service[BUFSIZE]; 3798 int rc = 0; 3799 int automount = 0; 3800 int i, s; 3801 3802 rc = NS_LDAP_OP_FAILED; 3803 for (s = 0; __s_cvtlist[s].service != NULL; s++) { 3804 if (__s_cvtlist[s].cvt_rtn == NULL) 3805 continue; 3806 if (strcasecmp(__s_cvtlist[s].service, servicetype) == 0) 3807 break; 3808 /* Or, check if the servicetype is auto_ */ 3809 if (strcmp(__s_cvtlist[s].service, 3810 NS_LDAP_TYPE_AUTOMOUNT) == 0 && 3811 strncasecmp(servicetype, NS_LDAP_TYPE_AUTOMOUNT, 3812 sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0) { 3813 automount++; 3814 break; 3815 } 3816 } 3817 if (__s_cvtlist[s].service == NULL) 3818 return (rc); 3819 3820 /* Convert the data */ 3821 rc = (*__s_cvtlist[s].cvt_rtn)(data, &rdn, &entry, errorp); 3822 if (rc != NS_LDAP_SUCCESS) { 3823 __s_cvt_freeEntryRdn(&entry, &rdn); 3824 return (rc); 3825 } 3826 if (rdn == NULL) { 3827 __ns_ldap_freeEntry(entry); 3828 return (NS_LDAP_OP_FAILED); 3829 } 3830 3831 if (strcmp(servicetype, "publickey") == 0) { 3832 struct _ns_pubkey *ptr; 3833 ptr = (struct _ns_pubkey *)data; 3834 if (ptr->hostcred == NS_HOSTCRED_TRUE) 3835 (void) strcpy(service, "hosts"); 3836 else 3837 (void) strcpy(service, "passwd"); 3838 } else 3839 (void) strcpy(service, servicetype); 3840 3841 /* Create the Full DN */ 3842 if (basedn == NULL) { 3843 rc = __s_api_get_SSD_from_SSDtoUse_service(service, 3844 &sdlist, errorp); 3845 if (rc != NS_LDAP_SUCCESS) { 3846 __s_cvt_freeEntryRdn(&entry, &rdn); 3847 return (rc); 3848 } 3849 3850 if (sdlist == NULL) { 3851 rc = __s_api_getDNs(&dns, service, errorp); 3852 if (rc != NS_LDAP_SUCCESS) { 3853 if (dns) { 3854 __s_api_free2dArray(dns); 3855 dns = NULL; 3856 } 3857 __s_cvt_freeEntryRdn(&entry, &rdn); 3858 return (rc); 3859 } 3860 (void) snprintf(trdn, RDNSIZE, "%s,%s", rdn, dns[0]); 3861 __s_api_free2dArray(dns); 3862 } else { 3863 if (sdlist[0]->basedn) { 3864 (void) snprintf(trdn, RDNSIZE, "%s,%s", 3865 rdn, sdlist[0]->basedn); 3866 } else { 3867 __s_cvt_freeEntryRdn(&entry, &rdn); 3868 return (NS_LDAP_OP_FAILED); 3869 } 3870 } 3871 i = strlen(trdn) - 1; 3872 if (trdn[i] == COMMATOK) { 3873 rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P, 3874 ¶mVal, errorp); 3875 if (rc != NS_LDAP_SUCCESS) { 3876 __s_cvt_freeEntryRdn(&entry, &rdn); 3877 return (rc); 3878 } 3879 i = strlen(trdn) + strlen((char *)(paramVal[0])) + 1; 3880 fulldn = (char *)calloc(i, 1); 3881 if (fulldn == NULL) { 3882 (void) __ns_ldap_freeParam(¶mVal); 3883 __s_cvt_freeEntryRdn(&entry, &rdn); 3884 return (NS_LDAP_MEMORY); 3885 } 3886 (void) snprintf(fulldn, i, "%s%s", trdn, 3887 (char *)(paramVal[0])); 3888 (void) __ns_ldap_freeParam(¶mVal); 3889 } else { 3890 fulldn = strdup(trdn); 3891 if (fulldn == NULL) { 3892 __s_cvt_freeEntryRdn(&entry, &rdn); 3893 return (NS_LDAP_MEMORY); 3894 } 3895 } 3896 } else { 3897 i = strlen(rdn) + strlen(basedn) + 2; 3898 fulldn = (char *)calloc(i, 1); 3899 if (fulldn == NULL) { 3900 __s_cvt_freeEntryRdn(&entry, &rdn); 3901 return (NS_LDAP_MEMORY); 3902 } 3903 (void) snprintf(fulldn, i, "%s,%s", rdn, basedn); 3904 } 3905 3906 modattrlist = (const ns_ldap_attr_t * const *)entry->attr_pair; 3907 /* Check to see if the entry exists already */ 3908 /* May need to delete or update first */ 3909 3910 if (create != 1) { 3911 /* Modify the entry */ 3912 /* 3913 * To add a shadow-like entry, the addTypedEntry function 3914 * would call __ns_ldap_repAttr first, and if server says 3915 * LDAP_NO_SUCH_OBJECT, then it tries __ns_ldap_addEntry. 3916 * This is to allow a netmask entry to be added even if the 3917 * base network entry is not in the directory. It would work 3918 * because the difference between the schema for the network 3919 * and netmask data contains only MAY attributes. 3920 * 3921 * But for shadow data, the attributes do not have MUST 3922 * attributes the base entry needs, so if the __ns_ldap_addEntry 3923 * is executed, it would fail. The real reason, however, is that 3924 * the base entry did not exist. So returning 3925 * LDAP_OBJECT_CLASS_VIOLATION would just confused. 3926 */ 3927 if ((__s_cvtlist[s].flags & AE) != 0) 3928 rc = __ns_ldap_addAttr(service, fulldn, modattrlist, 3929 cred, flags, errorp); 3930 else { 3931 rc = __ns_ldap_repAttr(service, fulldn, modattrlist, 3932 cred, flags, errorp); 3933 if (rc == NS_LDAP_INTERNAL && *errorp && 3934 (*errorp)->status == LDAP_NO_SUCH_OBJECT) { 3935 (void) __ns_ldap_freeError(errorp); 3936 rc = __ns_ldap_addEntry(service, fulldn, 3937 entry, cred, flags, errorp); 3938 if (rc == NS_LDAP_INTERNAL && *errorp && 3939 (*errorp)->status == 3940 LDAP_OBJECT_CLASS_VIOLATION) 3941 (*errorp)->status = LDAP_NO_SUCH_OBJECT; 3942 } 3943 } 3944 } else { 3945 /* Add the entry */ 3946 rc = __ns_ldap_addEntry(service, fulldn, entry, 3947 cred, flags, errorp); 3948 if (rc == NS_LDAP_INTERNAL && *errorp && 3949 (*errorp)->status == LDAP_ALREADY_EXISTS && 3950 ((strcmp(service, "ethers") == 0) || 3951 (strcmp(service, "bootparams") == 0))) { 3952 rc = modify_ethers_bootp(service, rdn, fulldn, 3953 modattrlist, cred, flags, errorp); 3954 } 3955 } 3956 3957 /* Free up entry created by conversion routine */ 3958 if (fulldn != NULL) 3959 free(fulldn); 3960 __s_cvt_freeEntryRdn(&entry, &rdn); 3961 return (rc); 3962 } 3963 3964 3965 /* 3966 * Append the default base dn to the dn 3967 * when it ends with ','. 3968 * e.g. 3969 * SSD = service:ou=foo, 3970 */ 3971 int 3972 __s_api_append_default_basedn( 3973 const char *dn, 3974 char **new_dn, 3975 int *allocated, 3976 ns_ldap_error_t **errp) { 3977 3978 int rc = NS_LDAP_SUCCESS, len = 0; 3979 void **param = NULL; 3980 char *str = NULL; 3981 3982 *allocated = FALSE; 3983 *new_dn = NULL; 3984 3985 if (dn == NULL) 3986 return (NS_LDAP_INVALID_PARAM); 3987 3988 rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P, 3989 (void ***)¶m, errp); 3990 3991 if (rc != NS_LDAP_SUCCESS) { 3992 if (param) 3993 (void) __ns_ldap_freeParam(¶m); 3994 return (rc); 3995 } 3996 3997 len = strlen(dn); 3998 str = ((char **)param)[0]; 3999 len = len + strlen(str) +1; 4000 *new_dn = (char *)malloc(len); 4001 if (*new_dn == NULL) { 4002 (void) __ns_ldap_freeParam(¶m); 4003 return (NS_LDAP_MEMORY); 4004 } 4005 *allocated = TRUE; 4006 4007 (void) strcpy(*new_dn, dn); 4008 (void) strcat(*new_dn, str); 4009 4010 (void) __ns_ldap_freeParam(¶m); 4011 return (NS_LDAP_SUCCESS); 4012 } 4013 4014 /* 4015 * Flatten the input ns_ldap_attr_t list, 'attr', and convert it into an 4016 * ldap_strlist_t structure in buffer 'buf', to be used by ldap_cachemgr. 4017 * The output contains a count, a list of offsets, which show where the 4018 * corresponding copied attribute type and attribute value are located. 4019 * For example, for dn=aaaa, userpassword=bbbb, shadowlastchange=cccc, 4020 * the output is the ldap_strlist_t structure with: ldap_count = 6, 4021 * (buf + ldap_offsets[0]) -> "dn" 4022 * (buf + ldap_offsets[1]) -> "aaaa" 4023 * (buf + ldap_offsets[2]) -> "userPassword" 4024 * (buf + ldap_offsets[3]) -> "bbbb" 4025 * (buf + ldap_offsets[4]) -> "shadowlastchange" 4026 * (buf + ldap_offsets[5]) -> "cccc" 4027 * and all the string data shown above copied into the buffer after 4028 * the offset array. The total length of the data will be the return 4029 * value, or -1 if error. 4030 */ 4031 static int 4032 attr2list(const char *dn, ns_ldap_attr_t **attr, 4033 char *buf, int bufsize) 4034 { 4035 int c = 0; 4036 char *ap; 4037 int ao; 4038 ldap_strlist_t *al = (ldap_strlist_t *)buf; 4039 ns_ldap_attr_t *a = (ns_ldap_attr_t *)*attr; 4040 ns_ldap_attr_t **aptr = (ns_ldap_attr_t **)attr; 4041 4042 /* bufsize > strlen(dn) + strlen("dn") + 1 ('\0') */ 4043 if ((strlen(dn) + 2 + 1) >= bufsize) 4044 return (-1); 4045 4046 /* count number of attributes */ 4047 while (*aptr++) 4048 c++; 4049 al->ldap_count = 2 + c * 2; 4050 ao = sizeof (al->ldap_count) + sizeof (al->ldap_offsets[0]) * 4051 al->ldap_count; 4052 if (ao > bufsize) 4053 return (-1); 4054 al->ldap_offsets[0] = ao; 4055 ap = buf + ao; 4056 ao += 3; 4057 4058 /* copy entry DN */ 4059 if (ao > bufsize) 4060 return (-1); 4061 (void) strlcpy(ap, "dn", bufsize); 4062 ap += 3; 4063 4064 al->ldap_offsets[1] = ao; 4065 ao += strlen(dn) + 1; 4066 if (ao > bufsize) 4067 return (-1); 4068 (void) strlcpy(ap, dn, bufsize); 4069 ap = buf + ao; 4070 4071 aptr = attr; 4072 for (c = 2; c < al->ldap_count; c++, aptr++) { 4073 a = *aptr; 4074 if (a->attrname == NULL || a->attrvalue == NULL || 4075 a->value_count != 1 || a->attrvalue[0] == NULL) 4076 return (-1); 4077 al->ldap_offsets[c] = ao; 4078 ao += strlen(a->attrname) + 1; 4079 if (ao > bufsize) 4080 return (-1); 4081 (void) strlcpy(ap, a->attrname, bufsize); 4082 ap = buf + ao; 4083 4084 c++; 4085 al->ldap_offsets[c] = ao; 4086 ao += strlen(a->attrvalue[0]) + 1; 4087 (void) strlcpy(ap, a->attrvalue[0], bufsize); 4088 ap = buf + ao; 4089 }; 4090 4091 return (ao); 4092 } 4093 4094 /* 4095 * Send a modify request to the ldap_cachemgr daemon 4096 * which will use the admin credential to perform the 4097 * operation. 4098 */ 4099 4100 static int 4101 send_to_cachemgr( 4102 const char *dn, 4103 ns_ldap_attr_t **attr, 4104 ns_ldap_error_t **errorp) 4105 { 4106 union { 4107 ldap_data_t s_d; 4108 char s_b[DOORBUFFERSIZE]; 4109 } space; 4110 4111 ldap_data_t *sptr; 4112 int ndata; 4113 int adata; 4114 int len; 4115 int rc; 4116 char errstr[MAXERROR]; 4117 ldap_admin_mod_result_t *admin_result; 4118 4119 *errorp = NULL; 4120 (void) memset(space.s_b, 0, DOORBUFFERSIZE); 4121 len = attr2list(dn, attr, (char *)&space.s_d.ldap_call.ldap_u.strlist, 4122 sizeof (space) - offsetof(ldap_return_t, ldap_u)); 4123 if (len <= 0) 4124 return (NS_LDAP_INVALID_PARAM); 4125 4126 adata = sizeof (ldap_call_t) + len; 4127 ndata = sizeof (space); 4128 space.s_d.ldap_call.ldap_callnumber = ADMINMODIFY; 4129 sptr = &space.s_d; 4130 4131 switch (__ns_ldap_trydoorcall(&sptr, &ndata, &adata)) { 4132 case NS_CACHE_SUCCESS: 4133 break; 4134 case NS_CACHE_NOTFOUND: 4135 (void) snprintf(errstr, sizeof (errstr), 4136 gettext("Door call ADMINMODIFY to " 4137 "ldap_cachemgr failed - error: %d"), 4138 space.s_d.ldap_ret.ldap_errno); 4139 MKERROR(LOG_WARNING, *errorp, NS_CONFIG_CACHEMGR, 4140 strdup(errstr), NULL); 4141 return (NS_LDAP_OP_FAILED); 4142 break; 4143 default: 4144 return (NS_LDAP_OP_FAILED); 4145 } 4146 4147 admin_result = &sptr->ldap_ret.ldap_u.admin_result; 4148 if (admin_result->ns_err == NS_LDAP_SUCCESS) 4149 rc = NS_LDAP_SUCCESS; 4150 else { 4151 rc = admin_result->ns_err; 4152 if (admin_result->msg_size == 0) 4153 *errorp = __s_api_make_error(admin_result->status, 4154 NULL); 4155 else 4156 *errorp = __s_api_make_error(admin_result->status, 4157 admin_result->msg); 4158 } 4159 4160 /* clean up the door call */ 4161 if (sptr != &space.s_d) { 4162 (void) munmap((char *)sptr, ndata); 4163 } 4164 4165 return (rc); 4166 } 4167