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