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] == NULL) { 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 == NULL) { 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 != NULL) { 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 || *ptr->name == '\0') { 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 rc = __s_add_attr(e, "cn", ptr->name); 2620 if (rc != NS_LDAP_SUCCESS) { 2621 __s_cvt_freeEntryRdn(entry, rdn); 2622 return (rc); 2623 } 2624 2625 /* Error check the data and add the attributes */ 2626 if (ptr->triplet && ptr->triplet[0]) { 2627 nm = ptr->triplet; 2628 for (i = 0; *nm; i++, nm++) 2629 ; 2630 nm = (char **)calloc(i+2, sizeof (char *)); 2631 if (nm == NULL) { 2632 __s_cvt_freeEntryRdn(entry, rdn); 2633 return (NS_LDAP_MEMORY); 2634 } 2635 for (j = 0; j < i; j++) 2636 nm[j] = ptr->triplet[j]; 2637 2638 rc = __s_add_attrlist(e, "nisNetgroupTriple", nm); 2639 free(nm); 2640 nm = NULL; 2641 if (rc != NS_LDAP_SUCCESS) { 2642 __s_cvt_freeEntryRdn(entry, rdn); 2643 return (rc); 2644 } 2645 } 2646 if (ptr->netgroup && ptr->netgroup[0]) { 2647 nm = ptr->netgroup; 2648 for (i = 0; *nm; i++, nm++) 2649 ; 2650 nm = (char **)calloc(i+2, sizeof (char *)); 2651 if (nm == NULL) { 2652 __s_cvt_freeEntryRdn(entry, rdn); 2653 return (NS_LDAP_MEMORY); 2654 } 2655 for (j = 0; j < i; j++) 2656 nm[j] = ptr->netgroup[j]; 2657 2658 rc = __s_add_attrlist(e, "memberNisNetgroup", nm); 2659 free(nm); 2660 nm = NULL; 2661 if (rc != NS_LDAP_SUCCESS) { 2662 __s_cvt_freeEntryRdn(entry, rdn); 2663 return (rc); 2664 } 2665 } 2666 return (NS_LDAP_SUCCESS); 2667 } 2668 /* 2669 * Conversion: bootparams 2670 * Input format: struct _ns_bootp 2671 * Exported objectclass: bootableDevice, device 2672 */ 2673 static int 2674 __s_cvt_bootparams(const void *data, char **rdn, 2675 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2676 { 2677 ns_ldap_entry_t *e; 2678 int rc; 2679 char trdn[RDNSIZE]; 2680 /* routine specific */ 2681 struct _ns_bootp *ptr; 2682 int max_attr = 4; 2683 int i, j; 2684 char **nm; 2685 static char *oclist[] = { 2686 "bootableDevice", 2687 "device", 2688 "top", 2689 NULL 2690 }; 2691 2692 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2693 return (NS_LDAP_OP_FAILED); 2694 *entry = e = __s_mk_entry(oclist, max_attr); 2695 if (e == NULL) 2696 return (NS_LDAP_MEMORY); 2697 2698 /* Convert the structure */ 2699 ptr = (struct _ns_bootp *)data; 2700 2701 if (ptr->name == NULL || *ptr->name == '\0') { 2702 __ns_ldap_freeEntry(e); 2703 *entry = NULL; 2704 return (NS_LDAP_INVALID_PARAM); 2705 } 2706 2707 /* Create an appropriate rdn */ 2708 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name); 2709 *rdn = strdup(trdn); 2710 if (*rdn == NULL) { 2711 __ns_ldap_freeEntry(e); 2712 *entry = NULL; 2713 return (NS_LDAP_MEMORY); 2714 } 2715 2716 rc = __s_add_attr(e, "cn", ptr->name); 2717 if (rc != NS_LDAP_SUCCESS) { 2718 __s_cvt_freeEntryRdn(entry, rdn); 2719 return (rc); 2720 } 2721 2722 /* Error check the data and add the attributes */ 2723 if (ptr->param && ptr->param[0]) { 2724 nm = ptr->param; 2725 for (i = 0; *nm; i++, nm++) 2726 ; 2727 nm = (char **)calloc(i+2, sizeof (char *)); 2728 if (nm == NULL) { 2729 __s_cvt_freeEntryRdn(entry, rdn); 2730 return (NS_LDAP_MEMORY); 2731 } 2732 for (j = 0; j < i; j++) 2733 nm[j] = ptr->param[j]; 2734 2735 rc = __s_add_attrlist(e, "bootParameter", nm); 2736 free(nm); 2737 nm = NULL; 2738 if (rc != NS_LDAP_SUCCESS) { 2739 __s_cvt_freeEntryRdn(entry, rdn); 2740 return (rc); 2741 } 2742 } 2743 2744 return (NS_LDAP_SUCCESS); 2745 2746 } 2747 /* 2748 * Conversion: ethers 2749 * Input format: struct _ns_ethers 2750 * Exported objectclass: ieee802Device, device 2751 */ 2752 static int 2753 __s_cvt_ethers(const void *data, char **rdn, 2754 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2755 { 2756 ns_ldap_entry_t *e; 2757 int rc; 2758 char trdn[RDNSIZE]; 2759 /* routine specific */ 2760 struct _ns_ethers *ptr; 2761 int max_attr = 4; 2762 static char *oclist[] = { 2763 "ieee802Device", 2764 "device", 2765 "top", 2766 NULL 2767 }; 2768 2769 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2770 return (NS_LDAP_OP_FAILED); 2771 *entry = e = __s_mk_entry(oclist, max_attr); 2772 if (e == NULL) 2773 return (NS_LDAP_MEMORY); 2774 2775 /* Convert the structure */ 2776 ptr = (struct _ns_ethers *)data; 2777 2778 if (ptr->name == NULL || *ptr->name == '\0' || ptr->ether == NULL) { 2779 __ns_ldap_freeEntry(e); 2780 *entry = NULL; 2781 return (NS_LDAP_INVALID_PARAM); 2782 } 2783 2784 /* Create an appropriate rdn */ 2785 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name); 2786 *rdn = strdup(trdn); 2787 if (*rdn == NULL) { 2788 __ns_ldap_freeEntry(e); 2789 *entry = NULL; 2790 return (NS_LDAP_MEMORY); 2791 } 2792 2793 /* Error check the data and add the attributes */ 2794 rc = __s_add_attr(e, "cn", ptr->name); 2795 if (rc != NS_LDAP_SUCCESS) { 2796 __s_cvt_freeEntryRdn(entry, rdn); 2797 return (rc); 2798 } 2799 2800 rc = __s_add_attr(e, "macAddress", ptr->ether); 2801 if (rc != NS_LDAP_SUCCESS) { 2802 __s_cvt_freeEntryRdn(entry, rdn); 2803 return (rc); 2804 } 2805 2806 return (NS_LDAP_SUCCESS); 2807 } 2808 /* 2809 * This function is used when processing an ethers (objectclass: ieee802Device) 2810 * or a bootparams (objectclass: bootableDevice) entry, and the entry is 2811 * already found in LDAP. Since both ethers and bootparams share the same 2812 * LDAP container, we want to check that the entry found in LDAP is: 2813 * - either the same entry (same cn, same objectclass): we don't do anything 2814 * in this case 2815 * - or an entry which does not have the objectclass we are interesting in: 2816 * in this case, we modify the existing entry by adding the relevant 2817 * objectclass (ieee802Device or bootableDevice) and the relevant attribute(s) 2818 * from the attribute list previously computing by the relevant conversion 2819 * function. 2820 * Note: from conversion functions __s_cvt_ethers() and __s_cvt_bootparams() 2821 * we know that there is only 1 more attribute today to add (macAddress 2822 * or bootParameter) 2823 */ 2824 #define _MAX_ATTR_ETHBOOTP 2 2825 static int 2826 modify_ethers_bootp( 2827 const char *service, 2828 const char *rdn, 2829 const char *fulldn, 2830 const ns_ldap_attr_t * const *attrlist, 2831 const ns_cred_t *cred, 2832 const int flags, 2833 ns_ldap_error_t **errorp) 2834 { 2835 char filter[BUFSIZ]; 2836 ns_ldap_result_t *resultp; 2837 int rc = 0; 2838 int i; 2839 ns_ldap_attr_t *new_attrlist[_MAX_ATTR_ETHBOOTP+1]; 2840 ns_ldap_attr_t new_attrlist0; 2841 char *new_attrvalue0[1]; 2842 const ns_ldap_attr_t * const *aptr = attrlist; 2843 ns_ldap_attr_t *aptr2; 2844 ns_ldap_error_t *new_errorp = NULL; 2845 2846 if (rdn == NULL || fulldn == NULL || attrlist == NULL || 2847 errorp == NULL || service == NULL) 2848 return (NS_LDAP_OP_FAILED); 2849 2850 bzero(&new_attrlist, sizeof (new_attrlist)); 2851 bzero(&new_attrlist0, sizeof (new_attrlist0)); 2852 new_attrlist[0] = &new_attrlist0; 2853 new_attrlist[0]->attrvalue = new_attrvalue0; 2854 2855 new_attrlist[0]->attrname = "objectclass"; 2856 new_attrlist[0]->value_count = 1; 2857 if (strcasecmp(service, "ethers") == NULL) { 2858 (void) snprintf(&filter[0], sizeof (filter), 2859 "(&(objectClass=ieee802Device)(%s))", rdn); 2860 new_attrlist[0]->attrvalue[0] = "ieee802Device"; 2861 } else { 2862 (void) snprintf(&filter[0], sizeof (filter), 2863 "(&(objectClass=bootableDevice)(%s))", rdn); 2864 new_attrlist[0]->attrvalue[0] = "bootableDevice"; 2865 } 2866 2867 rc = __ns_ldap_list(service, filter, NULL, (const char **)NULL, 2868 NULL, NS_LDAP_SCOPE_SUBTREE, &resultp, &new_errorp, 2869 NULL, NULL); 2870 2871 switch (rc) { 2872 case NS_LDAP_SUCCESS: 2873 /* 2874 * entry already exists for this service 2875 * return NS_LDAP_INTERNAL and do not modify the incoming errorp 2876 */ 2877 rc = NS_LDAP_INTERNAL; 2878 break; 2879 case NS_LDAP_NOTFOUND: 2880 /* 2881 * entry not found with the given objectclasss but entry exists 2882 * hence add the relevant attribute (macAddress or bootparams). 2883 */ 2884 i = 1; 2885 while (*aptr && (i < _MAX_ATTR_ETHBOOTP)) { 2886 /* aptr2 needed here to avoid lint warning */ 2887 aptr2 = (ns_ldap_attr_t *)*aptr++; 2888 if ((strcasecmp(aptr2->attrname, "cn") != 0) && 2889 (strcasecmp(aptr2->attrname, 2890 "objectclass") != 0)) { 2891 new_attrlist[i++] = (ns_ldap_attr_t *)aptr2; 2892 } 2893 } 2894 2895 if (i != _MAX_ATTR_ETHBOOTP) { 2896 /* we haven't found all expected attributes */ 2897 rc = NS_LDAP_OP_FAILED; 2898 break; 2899 } 2900 2901 aptr = (const ns_ldap_attr_t * const *) new_attrlist; 2902 /* clean errorp first */ 2903 (void) __ns_ldap_freeError(errorp); 2904 rc = __ns_ldap_addAttr(service, fulldn, aptr, cred, flags, 2905 errorp); 2906 break; 2907 default: 2908 /* 2909 * unexpected error happenned 2910 * returning relevant error 2911 */ 2912 (void) __ns_ldap_freeError(errorp); 2913 *errorp = new_errorp; 2914 break; 2915 } 2916 2917 return (rc); 2918 } 2919 2920 /* 2921 * Conversion: publickey 2922 * Input format: struct _ns_pubkey 2923 * Exported objectclass: NisKeyObject 2924 */ 2925 static int 2926 __s_cvt_publickey(const void *data, char **rdn, 2927 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2928 { 2929 ns_ldap_entry_t *e; 2930 int rc; 2931 char trdn[RDNSIZE]; 2932 /* routine specific */ 2933 struct _ns_pubkey *ptr; 2934 int max_attr = 3; 2935 static char *oclist[] = { 2936 "NisKeyObject", 2937 NULL 2938 }; 2939 2940 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 2941 return (NS_LDAP_OP_FAILED); 2942 *entry = e = __s_mk_entry(oclist, max_attr); 2943 if (e == NULL) 2944 return (NS_LDAP_MEMORY); 2945 2946 /* Convert the structure */ 2947 ptr = (struct _ns_pubkey *)data; 2948 2949 if (ptr->name == NULL || *ptr->name == '\0' || ptr->pubkey == NULL || 2950 ptr->privkey == NULL) { 2951 __ns_ldap_freeEntry(e); 2952 *entry = NULL; 2953 return (NS_LDAP_INVALID_PARAM); 2954 } 2955 2956 /* Create an appropriate rdn */ 2957 if (ptr->hostcred == NS_HOSTCRED_FALSE) 2958 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->name); 2959 else 2960 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name); 2961 *rdn = strdup(trdn); 2962 if (*rdn == NULL) { 2963 __ns_ldap_freeEntry(e); 2964 *entry = NULL; 2965 return (NS_LDAP_MEMORY); 2966 } 2967 2968 /* Error check the data and add the attributes */ 2969 2970 rc = __s_add_attr(e, "nisPublickey", ptr->pubkey); 2971 if (rc != NS_LDAP_SUCCESS) { 2972 __s_cvt_freeEntryRdn(entry, rdn); 2973 return (rc); 2974 } 2975 2976 rc = __s_add_attr(e, "nisSecretkey", ptr->privkey); 2977 if (rc != NS_LDAP_SUCCESS) { 2978 __s_cvt_freeEntryRdn(entry, rdn); 2979 return (rc); 2980 } 2981 2982 return (NS_LDAP_SUCCESS); 2983 } 2984 /* 2985 * Conversion: aliases 2986 * Input format: struct _ns_alias 2987 * Exported objectclass: mailGroup 2988 */ 2989 static int 2990 __s_cvt_aliases(const void *data, char **rdn, 2991 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 2992 { 2993 ns_ldap_entry_t *e; 2994 int rc; 2995 char trdn[RDNSIZE]; 2996 /* routine specific */ 2997 struct _ns_alias *ptr; 2998 int max_attr = 4; 2999 int i, j; 3000 char **nm; 3001 static char *oclist[] = { 3002 "mailGroup", 3003 "top", 3004 NULL 3005 }; 3006 3007 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3008 return (NS_LDAP_OP_FAILED); 3009 *entry = e = __s_mk_entry(oclist, max_attr); 3010 if (e == NULL) 3011 return (NS_LDAP_MEMORY); 3012 3013 /* Convert the structure */ 3014 ptr = (struct _ns_alias *)data; 3015 3016 if (ptr->alias == NULL || *ptr->alias == '\0') { 3017 __ns_ldap_freeEntry(e); 3018 *entry = NULL; 3019 return (NS_LDAP_INVALID_PARAM); 3020 } 3021 3022 /* Create an appropriate rdn */ 3023 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->alias); 3024 *rdn = strdup(trdn); 3025 if (*rdn == NULL) { 3026 __ns_ldap_freeEntry(e); 3027 *entry = NULL; 3028 return (NS_LDAP_MEMORY); 3029 } 3030 3031 rc = __s_add_attr(e, "mail", (char *)ptr->alias); 3032 if (rc != NS_LDAP_SUCCESS) { 3033 __s_cvt_freeEntryRdn(entry, rdn); 3034 return (rc); 3035 } 3036 3037 /* Error check the data and add the attributes */ 3038 if (ptr->member && ptr->member[0]) { 3039 nm = ptr->member; 3040 for (i = 0; *nm; i++, nm++) 3041 ; 3042 nm = (char **)calloc(i+2, sizeof (char *)); 3043 if (nm == NULL) { 3044 __s_cvt_freeEntryRdn(entry, rdn); 3045 return (NS_LDAP_MEMORY); 3046 } 3047 for (j = 0; j < i; j++) 3048 nm[j] = ptr->member[j]; 3049 3050 rc = __s_add_attrlist(e, "mgrpRFC822MailMember", nm); 3051 free(nm); 3052 nm = NULL; 3053 if (rc != NS_LDAP_SUCCESS) { 3054 __s_cvt_freeEntryRdn(entry, rdn); 3055 return (rc); 3056 } 3057 } 3058 3059 return (NS_LDAP_SUCCESS); 3060 3061 } 3062 /* 3063 * Conversion: automount 3064 * Input format: struct _ns_automount 3065 * Exported objectclass: automount 3066 */ 3067 static int 3068 __s_cvt_auto_mount(const void *data, char **rdn, 3069 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3070 { 3071 ns_ldap_entry_t *e; 3072 int rc; 3073 char trdn[RDNSIZE]; 3074 /* routine specific */ 3075 struct _ns_automount *ptr; 3076 int max_attr = 6; 3077 void **paramVal = NULL; 3078 char **mappedschema = NULL; 3079 int version1 = 0; 3080 static char *oclist[] = { 3081 NULL, 3082 "top", 3083 NULL 3084 }; 3085 3086 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3087 return (NS_LDAP_OP_FAILED); 3088 3089 /* determine profile version number */ 3090 rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, ¶mVal, errorp); 3091 if (paramVal && *paramVal && 3092 strcasecmp(*paramVal, NS_LDAP_VERSION_1) == 0) 3093 version1 = 1; 3094 if (paramVal) 3095 (void) __ns_ldap_freeParam(¶mVal); 3096 if (rc && errorp) 3097 (void) __ns_ldap_freeError(errorp); 3098 3099 /* use old schema for version 1 profiles */ 3100 if (version1) 3101 oclist[0] = "nisObject"; 3102 else 3103 oclist[0] = "automount"; 3104 3105 *entry = e = __s_mk_entry(oclist, max_attr); 3106 if (e == NULL) 3107 return (NS_LDAP_MEMORY); 3108 3109 /* Convert the structure */ 3110 ptr = (struct _ns_automount *)data; 3111 3112 if (ptr->key == NULL || *ptr->key == '\0' || ptr->value == NULL || 3113 ptr->mapname == NULL) { 3114 __ns_ldap_freeEntry(e); 3115 *entry = NULL; 3116 return (NS_LDAP_INVALID_PARAM); 3117 } 3118 3119 /* Create an appropriate rdn */ 3120 (void) snprintf(trdn, RDNSIZE, version1 ? "cn=%s" : "automountKey=%s", 3121 ptr->key); 3122 *rdn = strdup(trdn); 3123 if (*rdn == NULL) { 3124 __ns_ldap_freeEntry(e); 3125 *entry = NULL; 3126 return (NS_LDAP_MEMORY); 3127 } 3128 3129 rc = __s_add_attr(e, version1 ? "cn" : "automountKey", 3130 (char *)ptr->key); 3131 if (rc != NS_LDAP_SUCCESS) { 3132 __s_cvt_freeEntryRdn(entry, rdn); 3133 return (rc); 3134 } 3135 3136 rc = __s_add_attr(e, version1 ? "nisMapEntry" : "automountInformation", 3137 (char *)ptr->value); 3138 if (rc != NS_LDAP_SUCCESS) { 3139 __s_cvt_freeEntryRdn(entry, rdn); 3140 return (rc); 3141 } 3142 3143 /* 3144 * even for version 2, if automount is mapped to nisObject we 3145 * still need 'nisMapName' attribute 3146 */ 3147 mappedschema = __ns_ldap_getMappedObjectClass("automount", "automount"); 3148 if (mappedschema && mappedschema[0] && 3149 strcasecmp(mappedschema[0], "nisObject") == 0) 3150 version1 = 1; 3151 if (mappedschema) 3152 __s_api_free2dArray(mappedschema); 3153 3154 if (version1) { 3155 rc = __s_add_attr(e, "nisMapName", (char *)ptr->mapname); 3156 if (rc != NS_LDAP_SUCCESS) { 3157 __s_cvt_freeEntryRdn(entry, rdn); 3158 return (rc); 3159 } 3160 } 3161 3162 return (NS_LDAP_SUCCESS); 3163 } 3164 /* 3165 * Conversion: auth_attr 3166 * Input format: authstr_t 3167 * Exported objectclass: SolarisAuthAttr 3168 */ 3169 static int 3170 __s_cvt_authattr(const void *data, char **rdn, 3171 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3172 { 3173 ns_ldap_entry_t *e; 3174 int rc; 3175 char trdn[RDNSIZE]; 3176 /* routine specific */ 3177 authstr_t *ptr; 3178 int max_attr = 6; 3179 static char *oclist[] = { 3180 "SolarisAuthAttr", 3181 "top", 3182 NULL 3183 }; 3184 3185 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3186 return (NS_LDAP_OP_FAILED); 3187 3188 *entry = e = __s_mk_entry(oclist, max_attr); 3189 if (e == NULL) 3190 return (NS_LDAP_MEMORY); 3191 3192 /* Convert the structure */ 3193 ptr = (authstr_t *)data; 3194 3195 if (ptr->name == NULL || ptr->name[0] == '\0' || ptr->attr == NULL) { 3196 __ns_ldap_freeEntry(e); 3197 *entry = NULL; 3198 return (NS_LDAP_INVALID_PARAM); 3199 } 3200 3201 /* Create an appropriate rdn */ 3202 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name); 3203 *rdn = strdup(trdn); 3204 if (*rdn == NULL) { 3205 __ns_ldap_freeEntry(e); 3206 *entry = NULL; 3207 return (NS_LDAP_MEMORY); 3208 } 3209 3210 rc = __s_add_attr(e, "cn", ptr->name); 3211 if (rc != NS_LDAP_SUCCESS) { 3212 __s_cvt_freeEntryRdn(entry, rdn); 3213 return (rc); 3214 } 3215 3216 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr); 3217 if (rc != NS_LDAP_SUCCESS) { 3218 __s_cvt_freeEntryRdn(entry, rdn); 3219 return (rc); 3220 } 3221 3222 if (ptr->res1 != NULL) { 3223 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1); 3224 if (rc != NS_LDAP_SUCCESS) { 3225 __s_cvt_freeEntryRdn(entry, rdn); 3226 return (rc); 3227 } 3228 } 3229 3230 if (ptr->res2 != NULL) { 3231 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2); 3232 if (rc != NS_LDAP_SUCCESS) { 3233 __s_cvt_freeEntryRdn(entry, rdn); 3234 return (rc); 3235 } 3236 } 3237 3238 if (ptr->short_desc != NULL) { 3239 rc = __s_add_attr(e, "SolarisAttrShortDesc", ptr->short_desc); 3240 if (rc != NS_LDAP_SUCCESS) { 3241 __s_cvt_freeEntryRdn(entry, rdn); 3242 return (rc); 3243 } 3244 } 3245 3246 if (ptr->long_desc != NULL) { 3247 rc = __s_add_attr(e, "SolarisAttrLongDesc", ptr->long_desc); 3248 if (rc != NS_LDAP_SUCCESS) { 3249 __s_cvt_freeEntryRdn(entry, rdn); 3250 return (rc); 3251 } 3252 } 3253 3254 return (NS_LDAP_SUCCESS); 3255 } 3256 /* 3257 * Conversion: exec_attr 3258 * Input format: execstr_t 3259 * Exported objectclass: SolarisExecAttr 3260 */ 3261 static int 3262 __s_cvt_execattr(const void *data, char **rdn, 3263 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3264 { 3265 ns_ldap_entry_t *e; 3266 int rc; 3267 char trdn[RDNSIZE]; 3268 char esc_str[RDNSIZE]; 3269 /* routine specific */ 3270 execstr_t *ptr; 3271 int max_attr = 7; 3272 static char *oclist[] = { 3273 "SolarisExecAttr", 3274 "SolarisProfAttr", 3275 "top", 3276 NULL 3277 }; 3278 3279 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3280 return (NS_LDAP_OP_FAILED); 3281 3282 *entry = e = __s_mk_entry(oclist, max_attr); 3283 if (e == NULL) 3284 return (NS_LDAP_MEMORY); 3285 3286 /* Convert the structure */ 3287 ptr = (execstr_t *)data; 3288 3289 if (ptr->name == NULL || ptr->name[0] == '\0' || 3290 ptr->policy == NULL || ptr->policy[0] == '\0' || 3291 ptr->type == NULL || ptr->type[0] == '\0' || 3292 ptr->id == NULL || ptr->id[0] == '\0') { 3293 __ns_ldap_freeEntry(e); 3294 *entry = NULL; 3295 return (NS_LDAP_INVALID_PARAM); 3296 } 3297 3298 /* 3299 * Escape special characters in ProfileID. 3300 */ 3301 if (escape_str(esc_str, ptr->id) != 0) { 3302 __ns_ldap_freeEntry(e); 3303 *entry = NULL; 3304 return (NS_LDAP_INVALID_PARAM); 3305 } 3306 3307 /* Create an appropriate rdn */ 3308 (void) snprintf(trdn, RDNSIZE, "cn=%s+SolarisKernelSecurityPolicy=%s" 3309 "+SolarisProfileType=%s+SolarisProfileId=%s", 3310 ptr->name, ptr->policy, ptr->type, esc_str); 3311 3312 *rdn = strdup(trdn); 3313 if (*rdn == NULL) { 3314 __ns_ldap_freeEntry(e); 3315 *entry = NULL; 3316 return (NS_LDAP_MEMORY); 3317 } 3318 3319 rc = __s_add_attr(e, "cn", ptr->name); 3320 if (rc != NS_LDAP_SUCCESS) { 3321 __s_cvt_freeEntryRdn(entry, rdn); 3322 return (rc); 3323 } 3324 3325 rc = __s_add_attr(e, "SolarisKernelSecurityPolicy", ptr->policy); 3326 if (rc != NS_LDAP_SUCCESS) { 3327 __s_cvt_freeEntryRdn(entry, rdn); 3328 return (rc); 3329 } 3330 3331 rc = __s_add_attr(e, "SolarisProfileType", ptr->type); 3332 if (rc != NS_LDAP_SUCCESS) { 3333 __s_cvt_freeEntryRdn(entry, rdn); 3334 return (rc); 3335 } 3336 3337 rc = __s_add_attr(e, "SolarisProfileId", ptr->id); 3338 if (rc != NS_LDAP_SUCCESS) { 3339 __s_cvt_freeEntryRdn(entry, rdn); 3340 return (rc); 3341 } 3342 3343 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr); 3344 if (rc != NS_LDAP_SUCCESS) { 3345 __s_cvt_freeEntryRdn(entry, rdn); 3346 return (rc); 3347 } 3348 3349 if (ptr->res1 != NULL) { 3350 rc = __s_add_attr(e, "SolarisAttrRes1", ptr->res1); 3351 if (rc != NS_LDAP_SUCCESS) { 3352 __s_cvt_freeEntryRdn(entry, rdn); 3353 return (rc); 3354 } 3355 } 3356 3357 if (ptr->res2 != NULL) { 3358 rc = __s_add_attr(e, "SolarisAttrRes2", ptr->res2); 3359 if (rc != NS_LDAP_SUCCESS) { 3360 __s_cvt_freeEntryRdn(entry, rdn); 3361 return (rc); 3362 } 3363 } 3364 3365 return (NS_LDAP_SUCCESS); 3366 } 3367 /* 3368 * Conversion: prof_attr 3369 * Input format: profstr_t 3370 * Exported objectclass: SolarisProfAttr 3371 */ 3372 static int 3373 __s_cvt_profattr(const void *data, char **rdn, 3374 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3375 { 3376 ns_ldap_entry_t *e; 3377 int rc; 3378 char trdn[RDNSIZE]; 3379 /* routine specific */ 3380 profstr_t *ptr; 3381 int max_attr = 5; 3382 static char *oclist[] = { 3383 "SolarisProfAttr", 3384 "top", 3385 NULL 3386 }; 3387 3388 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3389 return (NS_LDAP_OP_FAILED); 3390 3391 *entry = e = __s_mk_entry(oclist, max_attr); 3392 if (e == NULL) 3393 return (NS_LDAP_MEMORY); 3394 3395 /* Convert the structure */ 3396 ptr = (profstr_t *)data; 3397 3398 if (ptr->name == NULL || ptr->name[0] == '\0' || ptr->attr == NULL) { 3399 __ns_ldap_freeEntry(e); 3400 *entry = NULL; 3401 return (NS_LDAP_INVALID_PARAM); 3402 } 3403 3404 /* Create an appropriate rdn */ 3405 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name); 3406 *rdn = strdup(trdn); 3407 if (*rdn == NULL) { 3408 __ns_ldap_freeEntry(e); 3409 *entry = NULL; 3410 return (NS_LDAP_MEMORY); 3411 } 3412 3413 rc = __s_add_attr(e, "cn", ptr->name); 3414 if (rc != NS_LDAP_SUCCESS) { 3415 __s_cvt_freeEntryRdn(entry, rdn); 3416 return (rc); 3417 } 3418 3419 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr); 3420 if (rc != NS_LDAP_SUCCESS) { 3421 __s_cvt_freeEntryRdn(entry, rdn); 3422 return (rc); 3423 } 3424 3425 if (ptr->res1 != NULL) { 3426 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1); 3427 if (rc != NS_LDAP_SUCCESS) { 3428 __s_cvt_freeEntryRdn(entry, rdn); 3429 return (rc); 3430 } 3431 } 3432 3433 if (ptr->res2 != NULL) { 3434 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2); 3435 if (rc != NS_LDAP_SUCCESS) { 3436 __s_cvt_freeEntryRdn(entry, rdn); 3437 return (rc); 3438 } 3439 } 3440 3441 if (ptr->desc != NULL) { 3442 rc = __s_add_attr(e, "SolarisAttrLongDesc", ptr->desc); 3443 if (rc != NS_LDAP_SUCCESS) { 3444 __s_cvt_freeEntryRdn(entry, rdn); 3445 return (rc); 3446 } 3447 } 3448 3449 return (NS_LDAP_SUCCESS); 3450 } 3451 /* 3452 * Conversion: user_attr 3453 * Input format: userstr_t 3454 * Exported objectclass: SolarisUserAttr 3455 */ 3456 static int 3457 __s_cvt_userattr(const void *data, char **rdn, 3458 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3459 { 3460 ns_ldap_entry_t *e; 3461 int rc; 3462 char trdn[RDNSIZE]; 3463 /* routine specific */ 3464 userstr_t *ptr; 3465 int max_attr = 5; 3466 static char *oclist[] = { 3467 "SolarisUserAttr", 3468 NULL 3469 }; 3470 3471 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3472 return (NS_LDAP_OP_FAILED); 3473 3474 *entry = e = __s_mk_entry(oclist, max_attr); 3475 if (e == NULL) 3476 return (NS_LDAP_MEMORY); 3477 3478 /* Convert the structure */ 3479 ptr = (userstr_t *)data; 3480 3481 if (ptr->name == NULL || ptr->name[0] == '\0' || 3482 ptr->attr == NULL) { 3483 __ns_ldap_freeEntry(e); 3484 *entry = NULL; 3485 return (NS_LDAP_INVALID_PARAM); 3486 } 3487 3488 /* Create an appropriate rdn */ 3489 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->name); 3490 *rdn = strdup(trdn); 3491 if (*rdn == NULL) { 3492 __ns_ldap_freeEntry(e); 3493 *entry = NULL; 3494 return (NS_LDAP_MEMORY); 3495 } 3496 3497 /* 3498 * SolarisUserAttr has no uid attribute 3499 */ 3500 3501 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr); 3502 if (rc != NS_LDAP_SUCCESS) { 3503 __s_cvt_freeEntryRdn(entry, rdn); 3504 return (rc); 3505 } 3506 3507 if (ptr->qualifier != NULL) { 3508 rc = __s_add_attr(e, "SolarisUserQualifier", ptr->qualifier); 3509 if (rc != NS_LDAP_SUCCESS) { 3510 __s_cvt_freeEntryRdn(entry, rdn); 3511 return (rc); 3512 } 3513 } 3514 3515 if (ptr->res1 != NULL) { 3516 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1); 3517 if (rc != NS_LDAP_SUCCESS) { 3518 __s_cvt_freeEntryRdn(entry, rdn); 3519 return (rc); 3520 } 3521 } 3522 3523 if (ptr->res2 != NULL) { 3524 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2); 3525 if (rc != NS_LDAP_SUCCESS) { 3526 __s_cvt_freeEntryRdn(entry, rdn); 3527 return (rc); 3528 } 3529 } 3530 3531 return (NS_LDAP_SUCCESS); 3532 } 3533 /* 3534 * Conversion: audit_user 3535 * Input format: au_user_str_t 3536 * Exported objectclass: SolarisAuditUser 3537 */ 3538 static int 3539 __s_cvt_audituser(const void *data, char **rdn, 3540 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3541 { 3542 ns_ldap_entry_t *e; 3543 int rc; 3544 char trdn[RDNSIZE]; 3545 /* routine specific */ 3546 au_user_str_t *ptr; 3547 int max_attr = 3; 3548 static char *oclist[] = { 3549 "SolarisAuditUser", 3550 NULL 3551 }; 3552 3553 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3554 return (NS_LDAP_OP_FAILED); 3555 3556 *entry = e = __s_mk_entry(oclist, max_attr); 3557 if (e == NULL) 3558 return (NS_LDAP_MEMORY); 3559 3560 /* Convert the structure */ 3561 ptr = (au_user_str_t *)data; 3562 3563 if (ptr->au_name == NULL || ptr->au_name[0] == '\0') { 3564 __ns_ldap_freeEntry(e); 3565 *entry = NULL; 3566 return (NS_LDAP_INVALID_PARAM); 3567 } 3568 3569 /* Create an appropriate rdn */ 3570 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->au_name); 3571 *rdn = strdup(trdn); 3572 if (*rdn == NULL) { 3573 __ns_ldap_freeEntry(e); 3574 *entry = NULL; 3575 return (NS_LDAP_MEMORY); 3576 } 3577 3578 /* 3579 * Solaris AuditUser has no uid attribute 3580 */ 3581 3582 if (ptr->au_always != NULL) { 3583 rc = __s_add_attr(e, "SolarisAuditAlways", ptr->au_always); 3584 if (rc != NS_LDAP_SUCCESS) { 3585 __s_cvt_freeEntryRdn(entry, rdn); 3586 return (rc); 3587 } 3588 } 3589 3590 if (ptr->au_never != NULL) { 3591 rc = __s_add_attr(e, "SolarisAuditNever", ptr->au_never); 3592 if (rc != NS_LDAP_SUCCESS) { 3593 __s_cvt_freeEntryRdn(entry, rdn); 3594 return (rc); 3595 } 3596 } 3597 3598 return (NS_LDAP_SUCCESS); 3599 } 3600 /* 3601 * Conversion: tnrhtp 3602 * Input format: tsol_tpstr_t 3603 * Exported objectclass: ipTnetTemplate 3604 */ 3605 static int 3606 __s_cvt_tnrhtp(const void *data, char **rdn, 3607 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3608 { 3609 ns_ldap_entry_t *e; 3610 int rc; 3611 char trdn[RDNSIZE]; 3612 char esc_str[RDNSIZE]; 3613 /* routine specific */ 3614 int max_attr = 2; 3615 tsol_tpstr_t *ptr; 3616 static char *oclist[] = { 3617 "ipTnetTemplate", 3618 "top", 3619 NULL 3620 }; 3621 3622 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3623 return (NS_LDAP_OP_FAILED); 3624 3625 *entry = e = __s_mk_entry(oclist, max_attr); 3626 if (e == NULL) 3627 return (NS_LDAP_MEMORY); 3628 3629 /* Convert the structure */ 3630 ptr = (tsol_tpstr_t *)data; 3631 3632 if (ptr->template == NULL || *ptr->template == '\0') { 3633 __ns_ldap_freeEntry(e); 3634 *entry = NULL; 3635 return (NS_LDAP_INVALID_PARAM); 3636 } 3637 3638 /* 3639 * Escape special characters in Template name. 3640 */ 3641 if (escape_str(esc_str, ptr->template) != 0) { 3642 __ns_ldap_freeEntry(e); 3643 *entry = NULL; 3644 return (NS_LDAP_INVALID_PARAM); 3645 } 3646 3647 /* Create an appropriate rdn */ 3648 (void) snprintf(trdn, RDNSIZE, "ipTnetTemplateName=%s", esc_str); 3649 *rdn = strdup(trdn); 3650 if (*rdn == NULL) { 3651 __ns_ldap_freeEntry(e); 3652 *entry = NULL; 3653 return (NS_LDAP_MEMORY); 3654 } 3655 3656 rc = __s_add_attr(e, "ipTnetTemplateName", ptr->template); 3657 if (rc != NS_LDAP_SUCCESS) { 3658 __s_cvt_freeEntryRdn(entry, rdn); 3659 return (rc); 3660 } 3661 3662 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attrs); 3663 if (rc != NS_LDAP_SUCCESS) { 3664 __s_cvt_freeEntryRdn(entry, rdn); 3665 return (rc); 3666 } 3667 3668 return (NS_LDAP_SUCCESS); 3669 } 3670 /* 3671 * Conversion: tnrhdb 3672 * Input format: tsol_rhstr_t 3673 * Exported objectclass: ipTnetHost 3674 */ 3675 static int 3676 __s_cvt_tnrhdb(const void *data, char **rdn, 3677 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) 3678 { 3679 ns_ldap_entry_t *e; 3680 int rc; 3681 char trdn[RDNSIZE]; 3682 /* routine specific */ 3683 tsol_rhstr_t *ptr; 3684 int max_attr = 2; 3685 static char *oclist[] = { 3686 "ipTnetHost", 3687 "ipTnetTemplate", 3688 "top", 3689 NULL 3690 }; 3691 3692 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) 3693 return (NS_LDAP_OP_FAILED); 3694 3695 *entry = e = __s_mk_entry(oclist, max_attr); 3696 if (e == NULL) 3697 return (NS_LDAP_MEMORY); 3698 3699 /* Convert the structure */ 3700 ptr = (tsol_rhstr_t *)data; 3701 3702 if (ptr->address == NULL || *ptr->address == '\0' || 3703 ptr->template == NULL || *ptr->template == '\0') { 3704 __ns_ldap_freeEntry(e); 3705 *entry = NULL; 3706 return (NS_LDAP_INVALID_PARAM); 3707 } 3708 3709 /* Create an appropriate rdn */ 3710 (void) snprintf(trdn, RDNSIZE, "ipTnetNumber=%s", ptr->address); 3711 *rdn = strdup(trdn); 3712 if (*rdn == NULL) { 3713 __ns_ldap_freeEntry(e); 3714 *entry = NULL; 3715 return (NS_LDAP_MEMORY); 3716 } 3717 3718 rc = __s_add_attr(e, "ipTnetNumber", ptr->address); 3719 if (rc != NS_LDAP_SUCCESS) { 3720 __s_cvt_freeEntryRdn(entry, rdn); 3721 return (rc); 3722 } 3723 3724 rc = __s_add_attr(e, "ipTnetTemplateName", ptr->template); 3725 if (rc != NS_LDAP_SUCCESS) { 3726 __s_cvt_freeEntryRdn(entry, rdn); 3727 return (rc); 3728 } 3729 3730 return (NS_LDAP_SUCCESS); 3731 } 3732 /* 3733 * Add Typed Entry Conversion data structures 3734 */ 3735 3736 typedef struct __ns_cvt_type { 3737 const char *service; 3738 int flags; 3739 #define AE 1 /* alway add entries */ 3740 int (*cvt_rtn)(const void *data, 3741 char **rdn, 3742 ns_ldap_entry_t **entry, 3743 ns_ldap_error_t **errorp); 3744 } __ns_cvt_type_t; 3745 3746 static __ns_cvt_type_t __s_cvtlist[] = { 3747 { NS_LDAP_TYPE_PASSWD, 0, __s_cvt_passwd }, 3748 { NS_LDAP_TYPE_GROUP, 0, __s_cvt_group }, 3749 { NS_LDAP_TYPE_HOSTS, 0, __s_cvt_hosts }, 3750 { NS_LDAP_TYPE_IPNODES, 0, __s_cvt_hosts }, 3751 { NS_LDAP_TYPE_RPC, 0, __s_cvt_rpc }, 3752 { NS_LDAP_TYPE_PROTOCOLS, 0, __s_cvt_protocols }, 3753 { NS_LDAP_TYPE_NETWORKS, 0, __s_cvt_networks }, 3754 { NS_LDAP_TYPE_NETGROUP, 0, __s_cvt_netgroups }, 3755 { NS_LDAP_TYPE_ALIASES, 0, __s_cvt_aliases }, 3756 { NS_LDAP_TYPE_SERVICES, 0, __s_cvt_services }, 3757 { NS_LDAP_TYPE_ETHERS, 0, __s_cvt_ethers }, 3758 { NS_LDAP_TYPE_SHADOW, 0, __s_cvt_shadow }, 3759 { NS_LDAP_TYPE_NETMASKS, 0, __s_cvt_netmasks }, 3760 { NS_LDAP_TYPE_BOOTPARAMS, 0, __s_cvt_bootparams }, 3761 { NS_LDAP_TYPE_AUTHATTR, 0, __s_cvt_authattr }, 3762 { NS_LDAP_TYPE_EXECATTR, 0, __s_cvt_execattr }, 3763 { NS_LDAP_TYPE_PROFILE, 0, __s_cvt_profattr }, 3764 { NS_LDAP_TYPE_USERATTR, AE, __s_cvt_userattr }, 3765 { NS_LDAP_TYPE_AUTOMOUNT, 0, __s_cvt_auto_mount }, 3766 { NS_LDAP_TYPE_PUBLICKEY, AE, __s_cvt_publickey }, 3767 { NS_LDAP_TYPE_AUUSER, AE, __s_cvt_audituser }, 3768 { NS_LDAP_TYPE_TNRHTP, 0, __s_cvt_tnrhtp }, 3769 { NS_LDAP_TYPE_TNRHDB, 0, __s_cvt_tnrhdb }, 3770 { NS_LDAP_TYPE_PROJECT, 0, __s_cvt_project }, 3771 { NULL, 0, NULL }, 3772 }; 3773 3774 /* 3775 * Add Typed Entry Routine 3776 */ 3777 3778 /*ARGSUSED*/ 3779 int __ns_ldap_addTypedEntry( 3780 const char *servicetype, 3781 const char *basedn, 3782 const void *data, 3783 const int create, 3784 const ns_cred_t *cred, 3785 const int flags, 3786 ns_ldap_error_t **errorp) 3787 { 3788 char *rdn = NULL, *fulldn = NULL; 3789 void **paramVal = NULL; 3790 ns_ldap_entry_t *entry = NULL; 3791 const ns_ldap_attr_t *const *modattrlist; 3792 ns_ldap_search_desc_t **sdlist; 3793 char **dns = NULL; 3794 char trdn[RDNSIZE]; 3795 char service[BUFSIZE]; 3796 int rc = 0; 3797 int automount = 0; 3798 int i, s; 3799 3800 rc = NS_LDAP_OP_FAILED; 3801 for (s = 0; __s_cvtlist[s].service != NULL; s++) { 3802 if (__s_cvtlist[s].cvt_rtn == NULL) 3803 continue; 3804 if (strcasecmp(__s_cvtlist[s].service, servicetype) == 0) 3805 break; 3806 /* Or, check if the servicetype is auto_ */ 3807 if (strcmp(__s_cvtlist[s].service, 3808 NS_LDAP_TYPE_AUTOMOUNT) == 0 && 3809 strncasecmp(servicetype, NS_LDAP_TYPE_AUTOMOUNT, 3810 sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0) { 3811 automount++; 3812 break; 3813 } 3814 } 3815 if (__s_cvtlist[s].service == NULL) 3816 return (rc); 3817 3818 /* Convert the data */ 3819 rc = (*__s_cvtlist[s].cvt_rtn)(data, &rdn, &entry, errorp); 3820 if (rc != NS_LDAP_SUCCESS) { 3821 __s_cvt_freeEntryRdn(&entry, &rdn); 3822 return (rc); 3823 } 3824 if (rdn == NULL) { 3825 __ns_ldap_freeEntry(entry); 3826 return (NS_LDAP_OP_FAILED); 3827 } 3828 3829 if (strcmp(servicetype, "publickey") == 0) { 3830 struct _ns_pubkey *ptr; 3831 ptr = (struct _ns_pubkey *)data; 3832 if (ptr->hostcred == NS_HOSTCRED_TRUE) 3833 (void) strcpy(service, "hosts"); 3834 else 3835 (void) strcpy(service, "passwd"); 3836 } else 3837 (void) strcpy(service, servicetype); 3838 3839 /* Create the Full DN */ 3840 if (basedn == NULL) { 3841 rc = __s_api_get_SSD_from_SSDtoUse_service(service, 3842 &sdlist, errorp); 3843 if (rc != NS_LDAP_SUCCESS) { 3844 __s_cvt_freeEntryRdn(&entry, &rdn); 3845 return (rc); 3846 } 3847 3848 if (sdlist == NULL) { 3849 rc = __s_api_getDNs(&dns, service, errorp); 3850 if (rc != NS_LDAP_SUCCESS) { 3851 if (dns) { 3852 __s_api_free2dArray(dns); 3853 dns = NULL; 3854 } 3855 __s_cvt_freeEntryRdn(&entry, &rdn); 3856 return (rc); 3857 } 3858 (void) snprintf(trdn, RDNSIZE, "%s,%s", rdn, dns[0]); 3859 __s_api_free2dArray(dns); 3860 } else { 3861 if (sdlist[0]->basedn) { 3862 (void) snprintf(trdn, RDNSIZE, "%s,%s", 3863 rdn, sdlist[0]->basedn); 3864 } else { 3865 __s_cvt_freeEntryRdn(&entry, &rdn); 3866 return (NS_LDAP_OP_FAILED); 3867 } 3868 } 3869 i = strlen(trdn) - 1; 3870 if (trdn[i] == COMMATOK) { 3871 rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P, 3872 ¶mVal, errorp); 3873 if (rc != NS_LDAP_SUCCESS) { 3874 __s_cvt_freeEntryRdn(&entry, &rdn); 3875 return (rc); 3876 } 3877 i = strlen(trdn) + strlen((char *)(paramVal[0])) + 1; 3878 fulldn = (char *)calloc(i, 1); 3879 if (fulldn == NULL) { 3880 (void) __ns_ldap_freeParam(¶mVal); 3881 __s_cvt_freeEntryRdn(&entry, &rdn); 3882 return (NS_LDAP_MEMORY); 3883 } 3884 (void) snprintf(fulldn, i, "%s%s", trdn, 3885 (char *)(paramVal[0])); 3886 (void) __ns_ldap_freeParam(¶mVal); 3887 } else { 3888 fulldn = strdup(trdn); 3889 if (fulldn == NULL) { 3890 __s_cvt_freeEntryRdn(&entry, &rdn); 3891 return (NS_LDAP_MEMORY); 3892 } 3893 } 3894 } else { 3895 i = strlen(rdn) + strlen(basedn) + 2; 3896 fulldn = (char *)calloc(i, 1); 3897 if (fulldn == NULL) { 3898 __s_cvt_freeEntryRdn(&entry, &rdn); 3899 return (NS_LDAP_MEMORY); 3900 } 3901 (void) snprintf(fulldn, i, "%s,%s", rdn, basedn); 3902 } 3903 3904 modattrlist = (const ns_ldap_attr_t * const *)entry->attr_pair; 3905 /* Check to see if the entry exists already */ 3906 /* May need to delete or update first */ 3907 3908 if (create != 1) { 3909 /* Modify the entry */ 3910 /* 3911 * To add a shadow-like entry, the addTypedEntry function 3912 * would call __ns_ldap_repAttr first, and if server says 3913 * LDAP_NO_SUCH_OBJECT, then it tries __ns_ldap_addEntry. 3914 * This is to allow a netmask entry to be added even if the 3915 * base network entry is not in the directory. It would work 3916 * because the difference between the schema for the network 3917 * and netmask data contains only MAY attributes. 3918 * 3919 * But for shadow data, the attributes do not have MUST 3920 * attributes the base entry needs, so if the __ns_ldap_addEntry 3921 * is executed, it would fail. The real reason, however, is that 3922 * the base entry did not exist. So returning 3923 * LDAP_OBJECT_CLASS_VIOLATION would just confused. 3924 */ 3925 if ((__s_cvtlist[s].flags & AE) != 0) 3926 rc = __ns_ldap_addAttr(service, fulldn, modattrlist, 3927 cred, flags, errorp); 3928 else { 3929 rc = __ns_ldap_repAttr(service, fulldn, modattrlist, 3930 cred, flags, errorp); 3931 if (rc == NS_LDAP_INTERNAL && *errorp && 3932 (*errorp)->status == LDAP_NO_SUCH_OBJECT) { 3933 (void) __ns_ldap_freeError(errorp); 3934 rc = __ns_ldap_addEntry(service, fulldn, 3935 entry, cred, flags, errorp); 3936 if (rc == NS_LDAP_INTERNAL && *errorp && 3937 (*errorp)->status == 3938 LDAP_OBJECT_CLASS_VIOLATION) 3939 (*errorp)->status = LDAP_NO_SUCH_OBJECT; 3940 } 3941 } 3942 } else { 3943 /* Add the entry */ 3944 rc = __ns_ldap_addEntry(service, fulldn, entry, 3945 cred, flags, errorp); 3946 if (rc == NS_LDAP_INTERNAL && *errorp && 3947 (*errorp)->status == LDAP_ALREADY_EXISTS && 3948 ((strcmp(service, "ethers") == 0) || 3949 (strcmp(service, "bootparams") == 0))) { 3950 rc = modify_ethers_bootp(service, rdn, fulldn, 3951 modattrlist, cred, flags, errorp); 3952 } 3953 } 3954 3955 /* Free up entry created by conversion routine */ 3956 if (fulldn != NULL) 3957 free(fulldn); 3958 __s_cvt_freeEntryRdn(&entry, &rdn); 3959 return (rc); 3960 } 3961 3962 3963 /* 3964 * Append the default base dn to the dn 3965 * when it ends with ','. 3966 * e.g. 3967 * SSD = service:ou=foo, 3968 */ 3969 int 3970 __s_api_append_default_basedn(const char *dn, char **new_dn, int *allocated, 3971 ns_ldap_error_t **errp) 3972 { 3973 3974 int rc = NS_LDAP_SUCCESS, len = 0; 3975 void **param = NULL; 3976 char *str = NULL; 3977 3978 *allocated = FALSE; 3979 *new_dn = NULL; 3980 3981 if (dn == NULL) 3982 return (NS_LDAP_INVALID_PARAM); 3983 3984 rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P, 3985 (void ***)¶m, errp); 3986 3987 if (rc != NS_LDAP_SUCCESS) { 3988 if (param) 3989 (void) __ns_ldap_freeParam(¶m); 3990 return (rc); 3991 } 3992 3993 len = strlen(dn); 3994 str = ((char **)param)[0]; 3995 len = len + strlen(str) +1; 3996 *new_dn = (char *)malloc(len); 3997 if (*new_dn == NULL) { 3998 (void) __ns_ldap_freeParam(¶m); 3999 return (NS_LDAP_MEMORY); 4000 } 4001 *allocated = TRUE; 4002 4003 (void) strcpy(*new_dn, dn); 4004 (void) strcat(*new_dn, str); 4005 4006 (void) __ns_ldap_freeParam(¶m); 4007 return (NS_LDAP_SUCCESS); 4008 } 4009 4010 /* 4011 * Flatten the input ns_ldap_attr_t list, 'attr', and convert it into an 4012 * ldap_strlist_t structure in buffer 'buf', to be used by ldap_cachemgr. 4013 * The output contains a count, a list of offsets, which show where the 4014 * corresponding copied attribute type and attribute value are located. 4015 * For example, for dn=aaaa, userpassword=bbbb, shadowlastchange=cccc, 4016 * the output is the ldap_strlist_t structure with: ldap_count = 6, 4017 * (buf + ldap_offsets[0]) -> "dn" 4018 * (buf + ldap_offsets[1]) -> "aaaa" 4019 * (buf + ldap_offsets[2]) -> "userPassword" 4020 * (buf + ldap_offsets[3]) -> "bbbb" 4021 * (buf + ldap_offsets[4]) -> "shadowlastchange" 4022 * (buf + ldap_offsets[5]) -> "cccc" 4023 * and all the string data shown above copied into the buffer after 4024 * the offset array. The total length of the data will be the return 4025 * value, or -1 if error. 4026 */ 4027 static int 4028 attr2list(const char *dn, ns_ldap_attr_t **attr, 4029 char *buf, int bufsize) 4030 { 4031 int c = 0; 4032 char *ap; 4033 int ao; 4034 ldap_strlist_t *al = (ldap_strlist_t *)buf; 4035 ns_ldap_attr_t *a = (ns_ldap_attr_t *)*attr; 4036 ns_ldap_attr_t **aptr = (ns_ldap_attr_t **)attr; 4037 4038 /* bufsize > strlen(dn) + strlen("dn") + 1 ('\0') */ 4039 if ((strlen(dn) + 2 + 1) >= bufsize) 4040 return (-1); 4041 4042 /* count number of attributes */ 4043 while (*aptr++) 4044 c++; 4045 al->ldap_count = 2 + c * 2; 4046 ao = sizeof (al->ldap_count) + sizeof (al->ldap_offsets[0]) * 4047 al->ldap_count; 4048 if (ao > bufsize) 4049 return (-1); 4050 al->ldap_offsets[0] = ao; 4051 ap = buf + ao; 4052 ao += 3; 4053 4054 /* copy entry DN */ 4055 if (ao > bufsize) 4056 return (-1); 4057 (void) strlcpy(ap, "dn", bufsize); 4058 ap += 3; 4059 4060 al->ldap_offsets[1] = ao; 4061 ao += strlen(dn) + 1; 4062 if (ao > bufsize) 4063 return (-1); 4064 (void) strlcpy(ap, dn, bufsize); 4065 ap = buf + ao; 4066 4067 aptr = attr; 4068 for (c = 2; c < al->ldap_count; c++, aptr++) { 4069 a = *aptr; 4070 if (a->attrname == NULL || a->attrvalue == NULL || 4071 a->value_count != 1 || a->attrvalue[0] == NULL) 4072 return (-1); 4073 al->ldap_offsets[c] = ao; 4074 ao += strlen(a->attrname) + 1; 4075 if (ao > bufsize) 4076 return (-1); 4077 (void) strlcpy(ap, a->attrname, bufsize); 4078 ap = buf + ao; 4079 4080 c++; 4081 al->ldap_offsets[c] = ao; 4082 ao += strlen(a->attrvalue[0]) + 1; 4083 (void) strlcpy(ap, a->attrvalue[0], bufsize); 4084 ap = buf + ao; 4085 }; 4086 4087 return (ao); 4088 } 4089 4090 /* 4091 * Send a modify request to the ldap_cachemgr daemon 4092 * which will use the admin credential to perform the 4093 * operation. 4094 */ 4095 4096 static int 4097 send_to_cachemgr( 4098 const char *dn, 4099 ns_ldap_attr_t **attr, 4100 ns_ldap_error_t **errorp) 4101 { 4102 union { 4103 ldap_data_t s_d; 4104 char s_b[DOORBUFFERSIZE]; 4105 } space; 4106 4107 ldap_data_t *sptr; 4108 int ndata; 4109 int adata; 4110 int len; 4111 int rc; 4112 char errstr[MAXERROR]; 4113 ldap_admin_mod_result_t *admin_result; 4114 4115 *errorp = NULL; 4116 (void) memset(space.s_b, 0, DOORBUFFERSIZE); 4117 len = attr2list(dn, attr, (char *)&space.s_d.ldap_call.ldap_u.strlist, 4118 sizeof (space) - offsetof(ldap_return_t, ldap_u)); 4119 if (len <= 0) 4120 return (NS_LDAP_INVALID_PARAM); 4121 4122 adata = sizeof (ldap_call_t) + len; 4123 ndata = sizeof (space); 4124 space.s_d.ldap_call.ldap_callnumber = ADMINMODIFY; 4125 sptr = &space.s_d; 4126 4127 switch (__ns_ldap_trydoorcall(&sptr, &ndata, &adata)) { 4128 case NS_CACHE_SUCCESS: 4129 break; 4130 case NS_CACHE_NOTFOUND: 4131 (void) snprintf(errstr, sizeof (errstr), 4132 gettext("Door call ADMINMODIFY to " 4133 "ldap_cachemgr failed - error: %d"), 4134 space.s_d.ldap_ret.ldap_errno); 4135 MKERROR(LOG_WARNING, *errorp, NS_CONFIG_CACHEMGR, 4136 strdup(errstr), NULL); 4137 return (NS_LDAP_OP_FAILED); 4138 default: 4139 return (NS_LDAP_OP_FAILED); 4140 } 4141 4142 admin_result = &sptr->ldap_ret.ldap_u.admin_result; 4143 if (admin_result->ns_err == NS_LDAP_SUCCESS) 4144 rc = NS_LDAP_SUCCESS; 4145 else { 4146 rc = admin_result->ns_err; 4147 if (admin_result->msg_size == 0) 4148 *errorp = __s_api_make_error(admin_result->status, 4149 NULL); 4150 else 4151 *errorp = __s_api_make_error(admin_result->status, 4152 admin_result->msg); 4153 } 4154 4155 /* clean up the door call */ 4156 if (sptr != &space.s_d) { 4157 (void) munmap((char *)sptr, ndata); 4158 } 4159 4160 return (rc); 4161 } 4162