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