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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 2001 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <string.h> 30 #include <sys/syslog.h> 31 #include <sys/types.h> 32 #include <rpc/types.h> 33 #include <rpc/xdr.h> 34 #include <rpcsvc/nis.h> 35 36 #include "db_mindex_c.h" 37 38 #include "ldap_xdr.h" 39 #include "ldap_util.h" 40 41 extern bool_t xdr_nis_object(); 42 43 /* 44 * In order not to change the on-disk NIS+ DB format, we need make sure 45 * that XDR does nothing for the new structures added to various C++ 46 * classes. 47 */ 48 49 bool_t 50 xdr___nis_table_mapping_t(XDR *xdrs, void *t) { 51 return (TRUE); 52 } 53 54 bool_t 55 xdr___nisdb_ptr_t(XDR *xdrs, void *ptr) { 56 return (TRUE); 57 } 58 59 bool_t 60 xdr___nisdb_dictionary_defer_t(XDR *xdrs, void *defer) { 61 return (TRUE); 62 } 63 64 bool_t 65 xdr___nisdb_rwlock_t(XDR *xdrs, void *rw) { 66 return (TRUE); 67 } 68 69 bool_t 70 xdr___nisdb_flag_t(XDR *xdrs, void *flag) { 71 return (TRUE); 72 } 73 74 /* 75 * Imported from rpc.nisd/nis_db.c 76 * 77 * Special abbreviated XDR string which knows that the namep parameter (mainly 78 * owner and group) has a trailing end which matches the last 'n' characters 79 * in the domainname part. It makes use of those common characters to 80 * encode/decode this information. We append an integer string to the 81 * name to be encoded which denotes the place in the domainname from where the 82 * common string starts. For example, if the name was "foo.my.domain." and the 83 * domainname was "my.domain.", the name would be encoded as "foo.10" because 84 * the length of the common part "my.domain." is 10. 85 */ 86 bool_t 87 xdr_nis_name_abbrev( 88 XDR *xdrs, 89 nis_name *namep, 90 nis_name domainname) /* domainname field from the table */ 91 { 92 size_t name_len, dom_len, min_len; 93 char buf[NIS_MAXNAMELEN]; 94 char *name; 95 char *lenstr, *tmp; 96 int i; 97 98 switch (xdrs->x_op) { 99 case XDR_ENCODE: 100 /* Get the start of the common part */ 101 name = *namep; 102 name_len = strlen(name); 103 if (name_len == 0) 104 return (xdr_nis_name(xdrs, namep)); 105 dom_len = strlen(domainname); 106 min_len = (name_len < dom_len) ? name_len : dom_len; 107 for (i = 1; i <= min_len; i++) { 108 if (name[name_len - i] != domainname[dom_len - i]) 109 break; 110 } 111 i--; 112 memcpy(buf, name, name_len - i); 113 sprintf(buf + name_len - i, ".%d", dom_len - i); 114 tmp = buf; 115 return (xdr_nis_name(xdrs, &tmp)); 116 117 case XDR_DECODE: 118 tmp = buf; 119 if (!xdr_nis_name(xdrs, &tmp)) 120 return (FALSE); 121 if ((buf[0] == NULL) || buf[strlen(buf) - 1] == '.') { 122 /* It is either a FQN or a NULL string */ 123 if (*namep) { 124 strcpy(*namep, buf); 125 return (TRUE); 126 } else { 127 if ((*namep = strdup(buf)) == NULL) 128 return (FALSE); 129 else 130 return (TRUE); 131 } 132 } 133 /* Now concoct the new name */ 134 if ((lenstr = strrchr(buf, '.')) == NULL) { 135 /* something went wrong here */ 136 syslog(LOG_ERR, 137 "xdr_nis_name_abbrev: no dot found in %s", buf); 138 return (FALSE); 139 } 140 i = atoi(lenstr + 1); 141 strcpy(lenstr, domainname + i); 142 if (*namep) { 143 strcpy(*namep, buf); 144 } else { 145 if ((*namep = strdup(buf)) == NULL) 146 return (FALSE); 147 } 148 return (TRUE); 149 150 default: 151 return (xdr_nis_name(xdrs, namep)); 152 } 153 } 154 155 /* 156 * Imported from rpc.nisd/nis_db.c 157 * 158 * special XDR for fetus object. We create the actual object from the 159 * "forming" object plus the table object. We create this special object to 160 * save the following components of the nis_object: 161 * zo_name and zo_domain: replaced by just the length field of 0. We had 162 * to keep the length field for backward compatibility. If we 163 * ever change the object format, we should fix this. 164 * zo_owner and zo_group: we condensed it by abbreviating the common part 165 * shared between the table object and the entry object 166 * en_type: Avoided altogether 167 * zo_type and other en_data: Avoided altogether. 168 * 169 * XXX: If the definition of nis_object ever changes, this should be changed. 170 */ 171 bool_t 172 xdr_nis_fetus_object( 173 XDR *xdrs, 174 nis_object *objp, /* Entry object */ 175 nis_object *tobj) /* Table object */ 176 { 177 uint_t size; 178 179 if (xdrs->x_op == XDR_FREE) 180 return (xdr_nis_object(xdrs, objp)); 181 if (!xdr_nis_oid(xdrs, &objp->zo_oid)) 182 return (FALSE); 183 184 /* 185 * While encoding of zo_name, we put 0 in the length field, while for 186 * decoding, we get the name from the table object. 187 */ 188 if (xdrs->x_op == XDR_ENCODE) { 189 size = 0; 190 if (!xdr_u_int(xdrs, &size)) 191 return (FALSE); 192 } else { 193 if (!xdr_u_int(xdrs, &size)) 194 return (FALSE); 195 if (size == 0) { /* shrinked format */ 196 /* get the name from the table object */ 197 if ((objp->zo_name = strdup(tobj->zo_name)) == NULL) 198 return (FALSE); 199 } else { 200 /* 201 * We are opening up the xdr_string implementation here 202 * because we called xdr_u_int() earlier. 203 */ 204 if ((objp->zo_name = (char *)malloc(size + 1)) == NULL) 205 return (FALSE); 206 if (!xdr_opaque(xdrs, objp->zo_name, size)) 207 return (FALSE); 208 } 209 } 210 211 /* 212 * We use the xdr_nis_name_abbrev() function for both owner 213 * and group which constructs the name from the domain name. 214 */ 215 if (!xdr_nis_name_abbrev(xdrs, &objp->zo_owner, tobj->zo_domain)) 216 return (FALSE); 217 if (!xdr_nis_name_abbrev(xdrs, &objp->zo_group, tobj->zo_domain)) 218 return (FALSE); 219 220 /* 221 * While encoding of zo_domain, we put 0 in the length field, while for 222 * decoding, we get the name from the table object. Same as above for 223 * the name. Could have used a function instead. 224 */ 225 if (xdrs->x_op == XDR_ENCODE) { 226 size = 0; 227 if (!xdr_u_int(xdrs, &size)) 228 return (FALSE); 229 } else { 230 if (!xdr_u_int(xdrs, &size)) 231 return (FALSE); 232 if (size == 0) { /* shrinked format */ 233 /* get the name from the table object */ 234 if ((objp->zo_domain = strdup(tobj->zo_domain)) == NULL) 235 return (FALSE); 236 } else { 237 /* 238 * We are opening up the xdr_string implementation here 239 * because we called xdr_u_int() earlier. 240 */ 241 if ((objp->zo_domain = (char *)malloc(size + 1)) 242 == NULL) 243 return (FALSE); 244 if (!xdr_opaque(xdrs, objp->zo_domain, size)) 245 return (FALSE); 246 } 247 } 248 249 if (!xdr_u_int(xdrs, &objp->zo_access)) 250 return (FALSE); 251 if (!xdr_u_int(xdrs, &objp->zo_ttl)) 252 return (FALSE); 253 254 /* 255 * We know that this is an entry object, so we'll save all the entry_obj 256 * space because we can recreate it later. 257 */ 258 if (xdrs->x_op == XDR_ENCODE) 259 return (TRUE); 260 /* Now for the DECODE case, just handcraft the entries and ignore XDR */ 261 objp->zo_data.zo_type = NIS_ENTRY_OBJ; 262 if ((objp->zo_data.objdata_u.en_data.en_type = 263 strdup(tobj->zo_data.objdata_u.ta_data.ta_type)) == NULL) 264 return (FALSE); 265 objp->zo_data.objdata_u.en_data.en_cols.en_cols_val = NULL; 266 objp->zo_data.objdata_u.en_data.en_cols.en_cols_len = 0; 267 return (TRUE); 268 } 269 270 static const char *in_directory = "IN_DIRECTORY"; 271 272 /* 273 * Given an input NIS+ object, create the kind 274 * of pseudo-entry_obj (with an XDR-encoded nis_object in the 275 * first column) that's stored in the DB. Note that: 276 * 277 * If the input object is an entry, it's assumed to have the 278 * columns moved up one step (col 0 in en_cols.en_cols_val[1], 279 * etc.). en_cols.en_cols_val[0] will be overwritten. The 280 * input object will be changed (some pointers set to zero, 281 * etc.) on exit. 282 * 283 * 'eo' is assumed to be a pointer to an empty entry_obj (or, 284 * at least, one that can be overwritten). It must not be a 285 * pointer to the entry_obj in 'obj'. If the input object is 286 * of a type other than entry, the 'eo' pointer must have 287 * en_cols.en_cols_val appropriately initialized to an array of 288 * (at least) length one. 289 * 290 * 'tobj' is a pointer to the table object for the table for 291 * which the entry_obj is destined. It's needed for entry objects, 292 * but unused for other object types. 293 */ 294 entry_obj * 295 makePseudoEntryObj(nis_object *obj, entry_obj *eo, nis_object *tobj) { 296 int bufsize; 297 char *buf; 298 XDR xdrs; 299 bool_t xret; 300 uint_t ecl; 301 entry_col *ecv; 302 char *myself = "makePseudoEntryObj"; 303 304 if (obj == 0 || eo == 0) 305 return (0); 306 307 if (obj->zo_data.zo_type == NIS_ENTRY_OBJ) { 308 *eo = obj->zo_data.objdata_u.en_data; 309 eo->en_type = 0; 310 311 /* 312 * To prevent the XDR function from making a copy of 313 * the entry columns, we set the columns structure to 314 * 0 (ie no column data) 315 */ 316 ecl = obj->EN_data.en_cols.en_cols_len; 317 ecv = obj->EN_data.en_cols.en_cols_val; 318 obj->EN_data.en_cols.en_cols_len = 0; 319 obj->EN_data.en_cols.en_cols_val = 0; 320 } else { 321 eo->en_type = (char *)in_directory; 322 } 323 324 bufsize = xdr_sizeof(xdr_nis_object, obj); 325 buf = am(myself, bufsize); 326 if (buf == 0) { 327 if (obj->zo_data.zo_type == NIS_ENTRY_OBJ) { 328 obj->EN_data.en_cols.en_cols_len = ecl; 329 obj->EN_data.en_cols.en_cols_val = ecv; 330 } 331 return (0); 332 } 333 334 xdrmem_create(&xdrs, (char *)buf, bufsize, XDR_ENCODE); 335 336 if (obj->zo_data.zo_type == NIS_ENTRY_OBJ) { 337 xret = xdr_nis_fetus_object(&xdrs, obj, tobj); 338 } else { 339 xret = xdr_nis_object(&xdrs, obj); 340 } 341 342 /* Restore the 'obj' */ 343 if (obj->zo_data.zo_type == NIS_ENTRY_OBJ) { 344 obj->EN_data.en_cols.en_cols_len = ecl; 345 obj->EN_data.en_cols.en_cols_val = ecv; 346 } 347 348 if (!xret) { 349 logmsg(MSG_NOTIMECHECK, LOG_ERR, 350 "%s: XDR encode failure", myself); 351 sfree(buf); 352 return (0); 353 } 354 355 eo->en_cols.en_cols_val[0].ec_value.ec_value_val = buf; 356 eo->en_cols.en_cols_val[0].ec_value.ec_value_len = xdr_getpos(&xdrs); 357 eo->en_cols.en_cols_val[0].ec_flags = EN_BINARY+EN_XDR; 358 359 return (eo); 360 } 361 362 nis_object * 363 unmakePseudoEntryObj(entry_obj *e, nis_object *tobj) { 364 nis_object *o; 365 XDR xdrs; 366 bool_t stat; 367 char *myself = "unmakePseudoEntryObj"; 368 369 if (e == 0 || e->en_cols.en_cols_val == 0 || 370 e->en_cols.en_cols_len == 0) 371 return (0); 372 373 o = am(myself, sizeof (*o)); 374 if (o == 0) 375 return (0); 376 377 xdrmem_create(&xdrs, e->en_cols.en_cols_val[0].ec_value.ec_value_val, 378 e->en_cols.en_cols_val[0].ec_value.ec_value_len, 379 XDR_DECODE); 380 381 if (tobj != 0 && (e->en_type == 0 || e->en_type[0] == '\0')) { 382 stat = xdr_nis_fetus_object(&xdrs, o, tobj); 383 } else { 384 stat = xdr_nis_object(&xdrs, o); 385 } 386 387 if (!stat) { 388 sfree(o); 389 o = 0; 390 } 391 392 /* 393 * If it's an entry object, construct the column information. 394 * We make this a copy, so that 'o' can be freed using 395 * nis_destroy_object(). 396 */ 397 if (o != 0 && o->zo_data.zo_type == NIS_ENTRY_OBJ && 398 o->zo_data.objdata_u.en_data.en_cols.en_cols_val == 0 && 399 e->en_cols.en_cols_len > 1) { 400 entry_col *ec, *oec; 401 uint_t i, *ocl; 402 403 ec = am(myself, (e->en_cols.en_cols_len - 1) * sizeof (ec[0])); 404 if (ec == 0) { 405 nis_destroy_object(o); 406 return (0); 407 } 408 409 o->zo_data.objdata_u.en_data.en_cols.en_cols_val = ec; 410 o->zo_data.objdata_u.en_data.en_cols.en_cols_len = 0; 411 ocl = &o->zo_data.objdata_u.en_data.en_cols.en_cols_len; 412 oec = e->en_cols.en_cols_val; 413 414 for (i = 1; i < e->en_cols.en_cols_len; i++) { 415 uint_t len; 416 417 if (oec[i].ec_value.ec_value_val != 0) { 418 len = oec[i].ec_value.ec_value_len; 419 if (len == 0) 420 len++; 421 ec[i-1].ec_value.ec_value_val = am(myself, len); 422 if (ec[i-1].ec_value.ec_value_val == 0) { 423 nis_destroy_object(o); 424 return (0); 425 } 426 (void) memcpy(ec[i-1].ec_value.ec_value_val, 427 oec[i].ec_value.ec_value_val, 428 oec[i].ec_value.ec_value_len); 429 ec[i-1].ec_value.ec_value_len = 430 oec[i].ec_value.ec_value_len; 431 } else { 432 ec[i-1].ec_value.ec_value_val = 0; 433 ec[i-1].ec_value.ec_value_len = 0; 434 } 435 *ocl += 1; 436 } 437 } 438 439 /* 440 * If it's an entry, and we have the table object, make sure 441 * zo_name and en_type either already are set, or get them 442 * from the table. 443 */ 444 if (o != 0 && o->zo_data.zo_type == NIS_ENTRY_OBJ && tobj != 0) { 445 if (o->zo_name == 0) 446 o->zo_name = sdup(myself, T, tobj->zo_name); 447 if (o->zo_data.objdata_u.en_data.en_type == 0) 448 o->zo_data.objdata_u.en_data.en_type = sdup(myself, T, 449 tobj->zo_data.objdata_u.ta_data.ta_type); 450 } 451 452 return (o); 453 } 454 455 /* 456 * Input: A (nis_object *), and (optionally) an (entry_obj *) array. 457 * Output: Pointer to an XDR:ed version of an (xdr_nis_object_t). 458 */ 459 void * 460 xdrNisObject(nis_object *obj, entry_obj **ea, int numEa, int *xdrLenP) { 461 xdr_nis_object_t xno; 462 void *buf; 463 int xdrLen; 464 XDR xdrs; 465 bool_t xret; 466 char *myself = "xdrNisObject"; 467 468 if (obj == 0) 469 return (0); 470 471 /* 472 * The version tells us what the XDR:ed buffer contains. 473 * Should be incremented whenever xdr_nis_object_t changes 474 * incompatibly. 475 */ 476 xno.xversion = 1; 477 478 xno.obj = obj; 479 480 if (obj->zo_data.zo_type == NIS_DIRECTORY_OBJ && 481 ea != 0 && numEa > 0) { 482 int i; 483 484 /* 485 * The ea[] array is expected to contain the kind of 486 * pseudo-entry object stored in the nisdb incarnation 487 * of a NIS+ directory. Column zero contains the XDR:ed 488 * directory entry object (which we ignore), while column 489 * one contains the name of said entry. It's the latter 490 * that we borrow for use in the dirEntry[] list of the 491 * xdr_nis_object_t. 492 */ 493 494 xno.dirEntry.dirEntry_len = 0; 495 xno.dirEntry.dirEntry_val = am(myself, numEa * 496 sizeof (xno.dirEntry.dirEntry_val[0])); 497 if (xno.dirEntry.dirEntry_val == 0) 498 return (0); 499 500 for (i = 0; i < numEa; i++) { 501 if (ea[i] == 0 || ea[i]->en_cols.en_cols_val == 0 || 502 ea[i]->en_cols.en_cols_len != 2 || 503 ea[i]->en_cols.en_cols_val[1]. 504 ec_value.ec_value_len == 0) 505 continue; 506 /* 507 * Yes, there's a NUL at the end of the dir entry 508 * name. 509 */ 510 xno.dirEntry.dirEntry_val[xno.dirEntry.dirEntry_len] = 511 ea[i]->en_cols.en_cols_val[1]. 512 ec_value.ec_value_val; 513 xno.dirEntry.dirEntry_len++; 514 } 515 } else { 516 /* No directory entries */ 517 xno.dirEntry.dirEntry_len = 0; 518 xno.dirEntry.dirEntry_val = 0; 519 } 520 521 xdrLen = xdr_sizeof(xdr_xdr_nis_object_t, &xno); 522 buf = am(myself, xdrLen); 523 if (buf == 0) 524 return (0); 525 526 xdrmem_create(&xdrs, (char *)buf, xdrLen, XDR_ENCODE); 527 528 xret = xdr_xdr_nis_object_t(&xdrs, &xno); 529 530 sfree(xno.dirEntry.dirEntry_val); 531 532 if (!xret) { 533 sfree(buf); 534 return (0); 535 } 536 537 if (xdrLenP != 0) 538 *xdrLenP = xdrLen; 539 540 return (buf); 541 } 542 543 /* 544 * Input: Pointer to an XDR:ed version of an (xdr_nis_object_t). 545 * Output: Pointer to a (nis_object *) and (if the object is a 546 * directory) a pointer to an array of (entry_obj *). 547 */ 548 nis_object * 549 unXdrNisObject(void *buf, int bufLen, entry_obj ***eaP, int *numEaP) { 550 xdr_nis_object_t *xno; 551 XDR xdrs; 552 bool_t xret; 553 entry_obj **ea; 554 int numEa; 555 nis_object *o; 556 char *myself = "unXdrNisObject"; 557 558 if (buf == 0 || bufLen <= 0) 559 return (0); 560 561 xno = am(myself, sizeof (*xno)); 562 if (xno == 0) 563 return (0); 564 565 xdrmem_create(&xdrs, buf, bufLen, XDR_DECODE); 566 xret = xdr_xdr_nis_object_t(&xdrs, xno); 567 568 if (!xret) { 569 sfree(xno); 570 return (0); 571 } 572 573 switch (xno->xversion) { 574 case 1: 575 break; 576 default: 577 xdr_free(xdr_xdr_nis_object_t, (char *)xno); 578 sfree(xno); 579 logmsg(MSG_NOTIMECHECK, LOG_WARNING, 580 "%s: Unknown xdr_nis_object_t version %d", 581 myself, xno->xversion); 582 return (0); 583 } 584 585 if (eaP != 0 && numEaP != 0 && xno->dirEntry.dirEntry_len > 0 && 586 xno->dirEntry.dirEntry_val != 0) { 587 ea = am(myself, xno->dirEntry.dirEntry_len * sizeof (ea[0])); 588 if (ea == 0) { 589 xdr_free(xdr_xdr_nis_object_t, (char *)xno); 590 sfree(xno); 591 return (0); 592 } 593 for (numEa = 0; numEa < xno->dirEntry.dirEntry_len; numEa++) { 594 ea[numEa] = am(myself, sizeof (*ea[numEa])); 595 if (ea[numEa] != 0) { 596 ea[numEa]->en_cols.en_cols_len = 2; 597 ea[numEa]->en_cols.en_cols_val = am(myself, 598 ea[numEa]->en_cols.en_cols_len * 599 sizeof (ea[numEa]->en_cols.en_cols_val[0])); 600 } 601 if (ea[numEa] == 0 || 602 ea[numEa]->en_cols.en_cols_val == 0) { 603 int i; 604 for (i = 0; i < numEa; i++) { 605 sfree(ea[i]->en_cols.en_cols_val); 606 sfree(ea[i]); 607 } 608 sfree(ea); 609 xdr_free(xdr_xdr_nis_object_t, (char *)xno); 610 sfree(xno); 611 return (0); 612 } 613 /* Leave column 0 (XDR:ed object) empty */ 614 ea[numEa]->en_cols.en_cols_val[0]. 615 ec_value.ec_value_len = 0; 616 ea[numEa]->en_cols.en_cols_val[0]. 617 ec_value.ec_value_val = 0; 618 /* 619 * Fill in name of dir entry. The DB counts the NUL 620 * as part of the dir entry name; hence, add one 621 * to the string length. 622 */ 623 ea[numEa]->en_cols.en_cols_val[1]. 624 ec_value.ec_value_len = slen(xno->dirEntry. 625 dirEntry_val[numEa]) + 1; 626 ea[numEa]->en_cols.en_cols_val[1]. 627 ec_value.ec_value_val = 628 xno->dirEntry.dirEntry_val[numEa]; 629 } 630 *eaP = ea; 631 *numEaP = numEa; 632 /* 633 * The xno->dirEntry.dirEntry_val[] pointers are duplicated 634 * in 'ea'. Set the xno pointers to zero, so that the xdr_free 635 * doesn't free the 'ea' data. 636 */ 637 if (numEa > 0) { 638 int i; 639 for (i = 0; i < numEa; i++) { 640 xno->dirEntry.dirEntry_val[i] = 0; 641 } 642 } 643 } else { 644 if (eaP != 0) 645 *eaP = 0; 646 if (numEaP != 0) 647 *numEaP = 0; 648 } 649 650 o = xno->obj; 651 xno->obj = 0; 652 xdr_free(xdr_xdr_nis_object_t, (char *)xno); 653 sfree(xno); 654 655 return (o); 656 } 657 658 void 659 freeEntryObjArray(entry_obj **ea, int numEa) { 660 int i; 661 662 if (ea == 0) 663 return; 664 665 for (i = 0; i < numEa; i++) { 666 int j; 667 668 for (j = 0; j < ea[i]->en_cols.en_cols_len; j++) { 669 sfree(ea[i]->en_cols.en_cols_val[j]. 670 ec_value.ec_value_val); 671 } 672 673 sfree(ea[i]->en_cols.en_cols_val); 674 } 675 676 sfree(ea); 677 } 678 679 /* 680 * Return TRUE if 'o1' and 'o2' are the same, FALSE otherwise. 681 * We perform the comparison by XDR encoding the objects, and then 682 * checking the XDR buffers for equality. However, we don't want to 683 * include the zo_oid (i.e., ctime and mtime) in the comparison. 684 */ 685 bool_t 686 sameNisPlusObj(nis_object *o1, nis_object *o2) { 687 XDR x1, x2; 688 void *b1, *b2; 689 int l1, l2; 690 bool_t ret; 691 nis_object obj1, obj2; 692 char *myself = "sameNisPlusObj"; 693 694 if (o1 == o2) 695 return (TRUE); 696 else if (o1 == 0 || o2 == 0) 697 return (FALSE); 698 699 /* 700 * We want to exclude the zo_oid from the comparison. In order 701 * not to modify the objects (even very briefly), we do this by 702 * making copies (nis_object itself only, not the underlying 703 * structures accessed through pointers), and setting the zo_oid 704 * to zero in the copies. 705 */ 706 obj1 = *o1; 707 obj2 = *o2; 708 obj1.zo_oid.ctime = obj1.zo_oid.mtime = 0; 709 obj2.zo_oid.ctime = obj2.zo_oid.mtime = 0; 710 711 l1 = xdr_sizeof(xdr_nis_object, &obj1); 712 l2 = xdr_sizeof(xdr_nis_object, &obj2); 713 if (l1 != l2) 714 return (FALSE); 715 716 b1 = am(myself, l1); 717 b2 = am(myself, l2); 718 if (b1 == 0 || b2 == 0) { 719 sfree(b1); 720 sfree(b2); 721 return (FALSE); 722 } 723 724 xdrmem_create(&x1, (char *)b1, l1, XDR_ENCODE); 725 xdrmem_create(&x2, (char *)b2, l2, XDR_ENCODE); 726 727 if (xdr_nis_object(&x1, &obj1) && xdr_nis_object(&x2, &obj2)) { 728 ret = (memcmp(b1, b2, l1) == 0); 729 } else { 730 logmsg(MSG_NOTIMECHECK, LOG_WARNING, 731 "%s: xdr_nis_object() error", 732 myself); 733 ret = FALSE; 734 } 735 736 sfree(b1); 737 sfree(b2); 738 739 return (ret); 740 } 741 742 /* 743 * A wrapper/convenience function for sameNisPlusObj() that extracts 744 * the object in column zero of 'e2'. 745 */ 746 bool_t 747 sameNisPlusPseudoObj(nis_object *o1, entry_obj *e2) { 748 nis_object *o2; 749 bool_t res; 750 751 if (o1 == 0 && e2 == 0) 752 return (TRUE); 753 else if (e2 == 0) 754 return (FALSE); 755 756 o2 = unmakePseudoEntryObj(e2, 0); 757 if (o2 == 0) 758 return ((o1 == 0) ? TRUE : FALSE); 759 760 res = sameNisPlusObj(o1, o2); 761 762 nis_destroy_object(o2); 763 764 return (res); 765 }