1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21: #include <assert.h>
22: #include <string.h>
23: #include <rpcsvc/nis.h>
24:
25: #include "nis_xdr.h"
26: #include "nis_intern.h"
27: #include "libnsl.h"
28:
29:
30: struct ib_request *
31: __create_ib_request (const_nis_name name, unsigned int flags)
32: {
33: struct ib_request *ibreq = calloc (1, sizeof (struct ib_request));
34: nis_attr *search_val = NULL;
35: size_t search_len = 0;
36: size_t size = 0;
37:
38: if (ibreq == NULL)
39: return NULL;
40:
41: ibreq->ibr_flags = flags;
42:
43: char *cptr = strdupa (name);
44:
45:
46: if (cptr[0] != '[')
47: {
48: ibreq->ibr_name = strdup (cptr);
49: if (ibreq->ibr_name == NULL)
50: {
51: free (ibreq);
52: return NULL;
53: }
54: return ibreq;
55: }
56:
57:
58: ibreq->ibr_name = strchr (cptr, ']');
59: if (ibreq->ibr_name == NULL || ibreq->ibr_name[1] != ',')
60: {
61:
62: free (ibreq);
63: return NULL;
64: }
65:
66:
67: if (ibreq->ibr_name[-1] == ',')
68: ibreq->ibr_name[-1] = '\0';
69: else
70: ibreq->ibr_name[0] = '\0';
71: ibreq->ibr_name += 2;
72: ibreq->ibr_name = strdup (ibreq->ibr_name);
73: if (ibreq->ibr_name == NULL)
74: {
75: free_null:
76: while (search_len-- > 0)
77: {
78: free (search_val[search_len].zattr_ndx);
79: free (search_val[search_len].zattr_val.zattr_val_val);
80: }
81: free (search_val);
82: nis_free_request (ibreq);
83: return NULL;
84: }
85:
86: ++cptr;
87:
88: while (cptr != NULL && cptr[0] != '\0')
89: {
90: char *key = cptr;
91: char *val = strchr (cptr, '=');
92:
93: cptr = strchr (key, ',');
94: if (cptr != NULL)
95: *cptr++ = '\0';
96:
97: if (__builtin_expect (val == NULL, 0))
98: {
99: nis_free_request (ibreq);
100: return NULL;
101: }
102: *val++ = '\0';
103: if (search_len + 1 >= size)
104: {
105: size += 1;
106: nis_attr *newp = realloc (search_val, size * sizeof (nis_attr));
107: if (newp == NULL)
108: goto free_null;
109: search_val = newp;
110: }
111: search_val[search_len].zattr_ndx = strdup (key);
112: if (search_val[search_len].zattr_ndx == NULL)
113: goto free_null;
114:
115: search_val[search_len].zattr_val.zattr_val_len = strlen (val) + 1;
116: search_val[search_len].zattr_val.zattr_val_val = strdup (val);
117: if (search_val[search_len].zattr_val.zattr_val_val == NULL)
118: {
119: free (search_val[search_len].zattr_ndx);
120: goto free_null;
121: }
122:
123: ++search_len;
124: }
125:
126: ibreq->ibr_srch.ibr_srch_val = search_val;
127: ibreq->ibr_srch.ibr_srch_len = search_len;
128:
129: return ibreq;
130: }
131: libnsl_hidden_def (__create_ib_request)
132:
133: static const struct timeval RPCTIMEOUT = {10, 0};
134:
135: static char *
136: get_tablepath (char *name, dir_binding *bptr)
137: {
138: enum clnt_stat result;
139: nis_result res;
140: struct ns_request req;
141:
142: memset (&res, '\0', sizeof (res));
143:
144: req.ns_name = name;
145: req.ns_object.ns_object_len = 0;
146: req.ns_object.ns_object_val = NULL;
147:
148: result = clnt_call (bptr->clnt, NIS_LOOKUP, (xdrproc_t) _xdr_ns_request,
149: (caddr_t) &req, (xdrproc_t) _xdr_nis_result,
150: (caddr_t) &res, RPCTIMEOUT);
151:
152: const char *cptr;
153: if (result == RPC_SUCCESS && NIS_RES_STATUS (&res) == NIS_SUCCESS
154: && __type_of (NIS_RES_OBJECT (&res)) == NIS_TABLE_OBJ)
155: cptr = NIS_RES_OBJECT (&res)->TA_data.ta_path;
156: else
157: cptr = "";
158:
159: char *str = strdup (cptr);
160:
161: if (result == RPC_SUCCESS)
162: xdr_free ((xdrproc_t) _xdr_nis_result, (char *) &res);
163:
164: return str;
165: }
166:
167:
168: nis_error
169: __follow_path (char **tablepath, char **tableptr, struct ib_request *ibreq,
170: dir_binding *bptr)
171: {
172: if (*tablepath == NULL)
173: {
174: *tablepath = get_tablepath (ibreq->ibr_name, bptr);
175: if (*tablepath == NULL)
176: return NIS_NOMEMORY;
177:
178: *tableptr = *tablepath;
179: }
180: if (*tableptr == NULL)
181: return NIS_NOTFOUND;
182:
183: char *newname = strsep (tableptr, ":");
184: if (newname[0] == '\0')
185: return NIS_NOTFOUND;
186:
187: newname = strdup (newname);
188: if (newname == NULL)
189: return NIS_NOMEMORY;
190:
191: free (ibreq->ibr_name);
192: ibreq->ibr_name = newname;
193:
194: return NIS_SUCCESS;
195: }
196: libnsl_hidden_def (__follow_path)
197:
198:
199: nis_result *
200: nis_list (const_nis_name name, unsigned int flags,
201: int (*callback) (const_nis_name name,
202: const nis_object *object,
203: const void *userdata),
204: const void *userdata)
205: {
206: nis_result *res = malloc (sizeof (nis_result));
207: ib_request *ibreq;
208: int status;
209: enum clnt_stat clnt_status;
210: int count_links = 0;
211: int done = 0;
212: nis_name *names;
213: nis_name namebuf[2] = {NULL, NULL};
214: int name_nr = 0;
215: nis_cb *cb = NULL;
216: char *tableptr;
217: char *tablepath = NULL;
218: int first_try = 0;
219: nis_result *allres = NULL;
220:
221: if (res == NULL)
222: return NULL;
223:
224: if (name == NULL)
225: {
226: status = NIS_BADNAME;
227: err_out:
228: nis_freeresult (allres);
229: memset (res, '\0', sizeof (nis_result));
230: NIS_RES_STATUS (res) = status;
231: return res;
232: }
233:
234: ibreq = __create_ib_request (name, flags);
235: if (ibreq == NULL)
236: {
237: status = NIS_BADNAME;
238: goto err_out;
239: }
240:
241: if ((flags & EXPAND_NAME)
242: && ibreq->ibr_name[strlen (ibreq->ibr_name) - 1] != '.')
243: {
244: names = nis_getnames (ibreq->ibr_name);
245: free (ibreq->ibr_name);
246: ibreq->ibr_name = NULL;
247: if (names == NULL)
248: {
249: nis_free_request (ibreq);
250: status = NIS_BADNAME;
251: goto err_out;
252: }
253: ibreq->ibr_name = strdup (names[name_nr]);
254: if (ibreq->ibr_name == NULL)
255: {
256: nis_freenames (names);
257: nis_free_request (ibreq);
258: status = NIS_NOMEMORY;
259: goto err_out;
260: }
261: }
262: else
263: {
264: names = namebuf;
265: names[name_nr] = ibreq->ibr_name;
266: }
267:
268: cb = NULL;
269:
270: while (!done)
271: {
272: dir_binding bptr;
273: directory_obj *dir = NULL;
274:
275: memset (res, '\0', sizeof (nis_result));
276:
277: status = __nisfind_server (ibreq->ibr_name,
278: ibreq->ibr_srch.ibr_srch_val != NULL,
279: &dir, &bptr, flags & ~MASTER_ONLY);
280: if (status != NIS_SUCCESS)
281: {
282: NIS_RES_STATUS (res) = status;
283: goto fail3;
284: }
285:
286: while (__nisbind_connect (&bptr) != NIS_SUCCESS)
287: if (__builtin_expect (__nisbind_next (&bptr) != NIS_SUCCESS, 0))
288: {
289: NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE;
290: goto fail;
291: }
292:
293: if (callback != NULL)
294: {
295: assert (cb == NULL);
296: cb = __nis_create_callback (callback, userdata, flags);
297: ibreq->ibr_cbhost.ibr_cbhost_len = 1;
298: ibreq->ibr_cbhost.ibr_cbhost_val = cb->serv;
299: }
300:
301: again:
302: clnt_status = clnt_call (bptr.clnt, NIS_IBLIST,
303: (xdrproc_t) _xdr_ib_request, (caddr_t) ibreq,
304: (xdrproc_t) _xdr_nis_result,
305: (caddr_t) res, RPCTIMEOUT);
306:
307: if (__builtin_expect (clnt_status != RPC_SUCCESS, 0))
308: NIS_RES_STATUS (res) = NIS_RPCERROR;
309: else
310: switch (NIS_RES_STATUS (res))
311: {
312: case NIS_PARTIAL:
313: case NIS_SUCCESS:
314: case NIS_S_SUCCESS:
315: if (__type_of (NIS_RES_OBJECT (res)) == NIS_LINK_OBJ
316: && (flags & FOLLOW_LINKS))
317: {
318: free (ibreq->ibr_name);
319: ibreq->ibr_name = NULL;
320:
321: if (__builtin_expect (count_links > NIS_MAXLINKS, 0))
322: {
323: NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
324: ++done;
325: break;
326: }
327: ++count_links;
328: ibreq->ibr_name =
329: strdup (NIS_RES_OBJECT (res)->LI_data.li_name);
330: if (ibreq->ibr_name == NULL)
331: {
332: NIS_RES_STATUS (res) = NIS_NOMEMORY;
333: fail:
334: __nisbind_destroy (&bptr);
335: nis_free_directory (dir);
336: fail3:
337: free (tablepath);
338: if (cb)
339: {
340: __nis_destroy_callback (cb);
341: ibreq->ibr_cbhost.ibr_cbhost_len = 0;
342: ibreq->ibr_cbhost.ibr_cbhost_val = NULL;
343: }
344: if (names != namebuf)
345: nis_freenames (names);
346: nis_free_request (ibreq);
347: nis_freeresult (allres);
348: return res;
349: }
350: if (NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len)
351: if (ibreq->ibr_srch.ibr_srch_len == 0)
352: {
353: ibreq->ibr_srch.ibr_srch_len =
354: NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len;
355: ibreq->ibr_srch.ibr_srch_val =
356: NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_val;
357: }
358:
359:
360:
361:
362:
363: xdr_free ((xdrproc_t) _xdr_nis_result, (char *)res);
364: memset (res, '\0', sizeof (*res));
365: first_try = 1;
366: goto again;
367: }
368: else if ((flags & FOLLOW_PATH)
369: && NIS_RES_STATUS (res) == NIS_PARTIAL)
370: {
371: clnt_status = __follow_path (&tablepath, &tableptr, ibreq,
372: &bptr);
373: if (clnt_status != NIS_SUCCESS)
374: {
375: if (clnt_status == NIS_NOMEMORY)
376: NIS_RES_STATUS (res) = clnt_status;
377: ++done;
378: }
379: else
380: {
381:
382:
383:
384:
385:
386: xdr_free ((xdrproc_t) _xdr_nis_result, (char *) res);
387: memset (res, '\0', sizeof (*res));
388: first_try = 1;
389: goto again;
390: }
391: }
392: else if ((flags & (FOLLOW_PATH | ALL_RESULTS))
393: == (FOLLOW_PATH | ALL_RESULTS))
394: {
395: if (allres == NULL)
396: {
397: allres = res;
398: res = malloc (sizeof (nis_result));
399: if (res == NULL)
400: {
401: res = allres;
402: allres = NULL;
403: NIS_RES_STATUS (res) = NIS_NOMEMORY;
404: goto fail;
405: }
406: NIS_RES_STATUS (res) = NIS_RES_STATUS (allres);
407: }
408: else
409: {
410: nis_object *objects_val
411: = realloc (NIS_RES_OBJECT (allres),
412: (NIS_RES_NUMOBJ (allres)
413: + NIS_RES_NUMOBJ (res))
414: * sizeof (nis_object));
415: if (objects_val == NULL)
416: {
417: NIS_RES_STATUS (res) = NIS_NOMEMORY;
418: goto fail;
419: }
420: NIS_RES_OBJECT (allres) = objects_val;
421: memcpy (NIS_RES_OBJECT (allres) + NIS_RES_NUMOBJ (allres),
422: NIS_RES_OBJECT (res),
423: NIS_RES_NUMOBJ (res) * sizeof (nis_object));
424: NIS_RES_NUMOBJ (allres) += NIS_RES_NUMOBJ (res);
425: NIS_RES_NUMOBJ (res) = 0;
426: free (NIS_RES_OBJECT (res));
427: NIS_RES_OBJECT (res) = NULL;
428: NIS_RES_STATUS (allres) = NIS_RES_STATUS (res);
429: xdr_free ((xdrproc_t) _xdr_nis_result, (char *) res);
430: }
431: clnt_status = __follow_path (&tablepath, &tableptr, ibreq,
432: &bptr);
433: if (clnt_status != NIS_SUCCESS)
434: {
435:
436: memset (res, '\0', sizeof (*res));
437:
438: if (clnt_status == NIS_NOMEMORY)
439: NIS_RES_STATUS (allres) = clnt_status;
440: ++done;
441: }
442: }
443: else
444: ++done;
445: break;
446: case NIS_CBRESULTS:
447: if (cb != NULL)
448: {
449: __nis_do_callback (&bptr, &res->cookie, cb);
450: NIS_RES_STATUS (res) = cb->result;
451:
452: if (!(flags & ALL_RESULTS))
453: ++done;
454: else
455: {
456: clnt_status
457: = __follow_path (&tablepath, &tableptr, ibreq, &bptr);
458: if (clnt_status != NIS_SUCCESS)
459: {
460: if (clnt_status == NIS_NOMEMORY)
461: NIS_RES_STATUS (res) = clnt_status;
462: ++done;
463: }
464: }
465: }
466: break;
467: case NIS_SYSTEMERROR:
468: case NIS_NOSUCHNAME:
469: case NIS_NOT_ME:
470:
471:
472: if (!first_try)
473: {
474: if (__nisbind_next (&bptr) != NIS_SUCCESS)
475: {
476: ++done;
477: break;
478: }
479: while (__nisbind_connect (&bptr) != NIS_SUCCESS)
480: {
481: if (__nisbind_next (&bptr) != NIS_SUCCESS)
482: {
483: ++done;
484: break;
485: }
486: }
487: goto again;
488: }
489: break;
490: default:
491: if (!first_try)
492: {
493:
494: free (ibreq->ibr_name);
495: ibreq->ibr_name = NULL;
496: if (__builtin_expect (count_links, 0))
497: {
498: NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
499: ++done;
500: break;
501: }
502: ++name_nr;
503: if (names[name_nr] == NULL)
504: {
505: ++done;
506: break;
507: }
508: ibreq->ibr_name = strdup (names[name_nr]);
509: if (ibreq->ibr_name == NULL)
510: {
511: NIS_RES_STATUS (res) = NIS_NOMEMORY;
512: goto fail;
513: }
514: first_try = 1;
515: goto again;
516: }
517: break;
518: }
519: first_try = 0;
520:
521: if (cb)
522: {
523: __nis_destroy_callback (cb);
524: ibreq->ibr_cbhost.ibr_cbhost_len = 0;
525: ibreq->ibr_cbhost.ibr_cbhost_val = NULL;
526: cb = NULL;
527: }
528:
529: __nisbind_destroy (&bptr);
530: nis_free_directory (dir);
531: }
532:
533: free (tablepath);
534:
535: if (names != namebuf)
536: nis_freenames (names);
537:
538: nis_free_request (ibreq);
539:
540: if (allres)
541: {
542: nis_freeresult (res);
543: return allres;
544: }
545:
546: return res;
547: }
548: libnsl_hidden_def (nis_list)
549:
550: nis_result *
551: nis_add_entry (const_nis_name name, const nis_object *obj2, unsigned int flags)
552: {
553: nis_result *res = calloc (1, sizeof (nis_result));
554: if (res == NULL)
555: return NULL;
556:
557: if (name == NULL)
558: {
559: NIS_RES_STATUS (res) = NIS_BADNAME;
560: return res;
561: }
562:
563: ib_request *ibreq = __create_ib_request (name, flags);
564: if (ibreq == NULL)
565: {
566: NIS_RES_STATUS (res) = NIS_BADNAME;
567: return res;
568: }
569:
570: nis_object obj;
571: memcpy (&obj, obj2, sizeof (nis_object));
572:
573: size_t namelen = strlen (name);
574: char buf1[namelen + 20];
575: char buf4[namelen + 20];
576:
577: if (obj.zo_name == NULL || strlen (obj.zo_name) == 0)
578: obj.zo_name = nis_leaf_of_r (name, buf1, sizeof (buf1));
579:
580: if (obj.zo_owner == NULL || strlen (obj.zo_owner) == 0)
581: obj.zo_owner = nis_local_principal ();
582:
583: if (obj.zo_group == NULL || strlen (obj.zo_group) == 0)
584: obj.zo_group = nis_local_group ();
585:
586: obj.zo_domain = nis_domain_of_r (name, buf4, sizeof (buf4));
587:
588: ibreq->ibr_obj.ibr_obj_val = nis_clone_object (&obj, NULL);
589: if (ibreq->ibr_obj.ibr_obj_val == NULL)
590: {
591: nis_free_request (