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
xdr___nis_table_mapping_t(XDR * xdrs,void * t)49 xdr___nis_table_mapping_t(XDR *xdrs, void *t) {
50 return (TRUE);
51 }
52
53 bool_t
xdr___nisdb_ptr_t(XDR * xdrs,void * ptr)54 xdr___nisdb_ptr_t(XDR *xdrs, void *ptr) {
55 return (TRUE);
56 }
57
58 bool_t
xdr___nisdb_dictionary_defer_t(XDR * xdrs,void * defer)59 xdr___nisdb_dictionary_defer_t(XDR *xdrs, void *defer) {
60 return (TRUE);
61 }
62
63 bool_t
xdr___nisdb_rwlock_t(XDR * xdrs,void * rw)64 xdr___nisdb_rwlock_t(XDR *xdrs, void *rw) {
65 return (TRUE);
66 }
67
68 bool_t
xdr___nisdb_flag_t(XDR * xdrs,void * flag)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
xdr_nis_name_abbrev(XDR * xdrs,nis_name * namep,nis_name domainname)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
xdr_nis_fetus_object(XDR * xdrs,nis_object * objp,nis_object * tobj)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 *
makePseudoEntryObj(nis_object * obj,entry_obj * eo,nis_object * tobj)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 *
unmakePseudoEntryObj(entry_obj * e,nis_object * tobj)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 *
xdrNisObject(nis_object * obj,entry_obj ** ea,int numEa,int * xdrLenP)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 *
unXdrNisObject(void * buf,int bufLen,entry_obj *** eaP,int * numEaP)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
freeEntryObjArray(entry_obj ** ea,int numEa)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
sameNisPlusObj(nis_object * o1,nis_object * o2)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
sameNisPlusPseudoObj(nis_object * o1,entry_obj * e2)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