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