1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #include <errno.h>
21: #include <stdio.h>
22: #include <stdlib.h>
23: #include <unistd.h>
24: #include <libintl.h>
25: #include <rpc/rpc.h>
26: #include <rpc/pmap_clnt.h>
27: #include <string.h>
28: #include <memory.h>
29: #include <syslog.h>
30: #include <sys/poll.h>
31: #include <sys/socket.h>
32: #include <netinet/in.h>
33: #include <arpa/inet.h>
34: #include <rpc/key_prot.h>
35: #include <rpcsvc/nis.h>
36: #include <rpcsvc/nis_callback.h>
37: #include <bits/libc-lock.h>
38:
39: #include "nis_xdr.h"
40: #include "nis_intern.h"
41:
42:
43:
44:
45:
46:
47: static nis_cb *data;
48:
49: __libc_lock_define_initialized (static, callback)
50:
51:
52: #if 0
53: static char *
54: __nis_getpkey(const char *sname)
55: {
56: char buf[(strlen (sname) + 1) * 2 + 40];
57: char pkey[HEXKEYBYTES + 1];
58: char *cp, *domain;
59: nis_result *res;
60: unsigned int len = 0;
61:
62: domain = strchr (sname, '.');
63: if (domain == NULL)
64: return NULL;
65:
66:
67: ++domain;
68:
69: cp = stpcpy (buf, "[cname=");
70: cp = stpcpy (cp, sname);
71: cp = stpcpy (cp, ",auth_type=DES],cred.org_dir.");
72: cp = stpcpy (cp, domain);
73:
74: res = nis_list (buf, USE_DGRAM|NO_AUTHINFO|FOLLOW_LINKS|FOLLOW_PATH,
75: NULL, NULL);
76:
77: if (res == NULL)
78: return NULL;
79:
80: if (NIS_RES_STATUS (res) != NIS_SUCCESS)
81: {
82: nis_freeresult (res);
83: return NULL;
84: }
85:
86: len = ENTRY_LEN(NIS_RES_OBJECT(res), 3);
87: strncpy (pkey, ENTRY_VAL(NIS_RES_OBJECT(res), 3), len);
88: pkey[len] = '\0';
89: cp = strchr (pkey, ':');
90: if (cp != NULL)
91: *cp = '\0';
92:
93: nis_freeresult (res);
94:
95: return strdup (pkey);
96: }
97: #endif
98:
99: static void
100: cb_prog_1 (struct svc_req *rqstp, SVCXPRT *transp)
101: {
102: union
103: {
104: cback_data cbproc_receive_1_arg;
105: nis_error cbproc_error_1_arg;
106: }
107: argument;
108: char *result;
109: xdrproc_t xdr_argument, xdr_result;
110: bool_t bool_result;
111:
112: switch (rqstp->rq_proc)
113: {
114: case NULLPROC:
115: svc_sendreply (transp, (xdrproc_t) xdr_void, (char *) NULL);
116: return;
117:
118: case CBPROC_RECEIVE:
119: {
120: unsigned int i;
121:
122: xdr_argument = (xdrproc_t) xdr_cback_data;
123: xdr_result = (xdrproc_t) xdr_bool;
124: memset (&argument, 0, sizeof (argument));
125: if (!svc_getargs (transp, xdr_argument, (caddr_t) & argument))
126: {
127: svcerr_decode (transp);
128: return;
129: }
130: bool_result = FALSE;
131: for (i = 0; i < argument.cbproc_receive_1_arg.entries.entries_len; ++i)
132: {
133: #define cbproc_entry(a) argument.cbproc_receive_1_arg.entries.entries_val[a]
134: char name[strlen (cbproc_entry(i)->zo_name) +
135: strlen (cbproc_entry(i)->zo_domain) + 3];
136: char *cp;
137:
138: cp = stpcpy (name, cbproc_entry(i)->zo_name);
139: *cp++ = '.';
140: cp = stpcpy (cp, cbproc_entry(i)->zo_domain);
141:
142: if ((data->callback) (name, cbproc_entry(i), data->userdata))
143: {
144: bool_result = TRUE;
145: data->nomore = 1;
146: data->result = NIS_SUCCESS;
147: break;
148: }
149: }
150: result = (char *) &bool_result;
151: }
152: break;
153: case CBPROC_FINISH:
154: xdr_argument = (xdrproc_t) xdr_void;
155: xdr_result = (xdrproc_t) xdr_void;
156: memset (&argument, 0, sizeof (argument));
157: if (!svc_getargs (transp, xdr_argument, (caddr_t) & argument))
158: {
159: svcerr_decode (transp);
160: return;
161: }
162: data->nomore = 1;
163: data->result = NIS_SUCCESS;
164: bool_result = TRUE;
165: result = (char *) &bool_result;
166: break;
167: case CBPROC_ERROR:
168: xdr_argument = (xdrproc_t) _xdr_nis_error;
169: xdr_result = (xdrproc_t) xdr_void;
170: memset (&argument, 0, sizeof (argument));
171: if (!svc_getargs (transp, xdr_argument, (caddr_t) & argument))
172: {
173: svcerr_decode (transp);
174: return;
175: }
176: data->nomore = 1;
177: data->result = argument.cbproc_error_1_arg;
178: bool_result = TRUE;
179: result = (char *) &bool_result;
180: break;
181: default:
182: svcerr_noproc (transp);
183: return;
184: }
185: if (result != NULL && !svc_sendreply (transp, xdr_result, result))
186: svcerr_systemerr (transp);
187: if (!svc_freeargs (transp, xdr_argument, (caddr_t) & argument))
188: {
189: fputs (_ ("unable to free arguments"), stderr);
190: exit (1);
191: }
192: return;
193: }
194:
195: static nis_error
196: internal_nis_do_callback (struct dir_binding *bptr, netobj *cookie,
197: struct nis_cb *cb)
198: {
199: struct timeval TIMEOUT = {25, 0};
200: bool_t cb_is_running;
201:
202: data = cb;
203:
204: for (;;)
205: {
206: struct pollfd my_pollfd[svc_max_pollfd];
207: int i;
208:
209: if (svc_max_pollfd == 0 && svc_pollfd == NULL)
210: return NIS_CBERROR;
211:
212: for (i = 0; i < svc_max_pollfd; ++i)
213: {
214: my_pollfd[i].fd = svc_pollfd[i].fd;
215: my_pollfd[i].events = svc_pollfd[i].events;
216: my_pollfd[i].revents = 0;
217: }
218:
219: switch (i = TEMP_FAILURE_RETRY (__poll (my_pollfd, svc_max_pollfd,
220: 25*1000)))
221: {
222: case -1:
223: return NIS_CBERROR;
224: case 0:
225:
226: cb_is_running = FALSE;
227: if (clnt_call (bptr->clnt, NIS_CALLBACK, (xdrproc_t) xdr_netobj,
228: (caddr_t) cookie, (xdrproc_t) xdr_bool,
229: (caddr_t) &cb_is_running, TIMEOUT) != RPC_SUCCESS)
230: cb_is_running = FALSE;
231:
232: if (cb_is_running == FALSE)
233: {
234: syslog (LOG_ERR, "NIS+: callback timed out");
235: return NIS_CBERROR;
236: }
237: break;
238: default:
239: svc_getreq_poll (my_pollfd, i);
240: if (data->nomore)
241: return data->result;
242: }
243: }
244: }
245:
246: nis_error
247: __nis_do_callback (struct dir_binding *bptr, netobj *cookie,
248: struct nis_cb *cb)
249: {
250: nis_error result;
251:
252: __libc_lock_lock (callback);
253:
254: result = internal_nis_do_callback (bptr, cookie, cb);
255:
256: __libc_lock_unlock (callback);
257:
258: return result;
259: }
260:
261: struct nis_cb *
262: __nis_create_callback (int (*callback) (const_nis_name, const nis_object *,
263: const void *),
264: const void *userdata, unsigned int flags)
265: {
266: struct nis_cb *cb;
267: int sock = RPC_ANYSOCK;
268: struct sockaddr_in sin;
269: socklen_t len = sizeof (struct sockaddr_in);
270: unsigned short port;
271: int nomsg = 0;
272:
273: cb = (struct nis_cb *) calloc (1,
274: sizeof (struct nis_cb) + sizeof (nis_server));
275: if (__builtin_expect (cb == NULL, 0))
276: goto failed;
277: cb->serv = (nis_server *) (cb + 1);
278: cb->serv->name = strdup (nis_local_principal ());
279: if (__builtin_expect (cb->serv->name == NULL, 0))
280: goto failed;
281: cb->serv->ep.ep_val = (endpoint *) calloc (2, sizeof (endpoint));
282: if (__builtin_expect (cb->serv->ep.ep_val == NULL, 0))
283: goto failed;
284: cb->serv->ep.ep_len = 1;
285: cb->serv->ep.ep_val[0].family = strdup ("inet");
286: if (__builtin_expect (cb->serv->ep.ep_val[0].family == NULL, 0))
287: goto failed;
288: cb->callback = callback;
289: cb->userdata = userdata;
290:
291: if ((flags & NO_AUTHINFO) || !key_secretkey_is_set ())
292: {
293: cb->serv->key_type = NIS_PK_NONE;
294: cb->serv->pkey.n_bytes = NULL;
295: cb->serv->pkey.n_len = 0;
296: }
297: else
298: {
299: #if 0
300: if ((cb->serv->pkey.n_bytes = __nis_getpkey (cb->serv->name)) == NULL)
301: {
302: cb->serv->pkey.n_len = 0;
303: cb->serv->key_type = NIS_PK_NONE;
304: }
305: else
306: {
307: cb->serv->key_type = NIS_PK_DH;
308: cb->serv->pkey.n_len = strlen(cb->serv->pkey.n_bytes);
309: }
310: #else
311: cb->serv->pkey.n_len =0;
312: cb->serv->pkey.n_bytes = NULL;
313: cb->serv->key_type = NIS_PK_NONE;
314: #endif
315: }
316:
317: cb->serv->ep.ep_val[0].proto = strdup ((flags & USE_DGRAM) ? "udp" : "tcp");
318: if (__builtin_expect (cb->serv->ep.ep_val[0].proto == NULL, 0))
319: goto failed;
320: cb->xprt = ((flags & USE_DGRAM)
321: ? svcudp_bufcreate (sock, 100, 8192)
322: : svctcp_create (sock, 100, 8192));
323: if (cb->xprt == NULL)
324: {
325: nomsg = 1;
326: goto failed;
327: }
328: cb->sock = cb->xprt->xp_sock;
329: if (!svc_register (cb->xprt, CB_PROG, CB_VERS, cb_prog_1, 0))
330: {
331: xprt_unregister (cb->xprt);
332: svc_destroy (cb->xprt);
333: xdr_free ((xdrproc_t) _xdr_nis_server, (char *) cb->serv);
334: free (cb);
335: syslog (LOG_ERR, "NIS+: failed to register callback dispatcher");
336: return NULL;
337: }
338:
339: if (getsockname (cb->sock, (struct sockaddr *) &sin, &len) == -1)
340: {
341: xprt_unregister (cb->xprt);
342: svc_destroy (cb->xprt);
343: xdr_free ((xdrproc_t) _xdr_nis_server, (char *) cb->serv);
344: free (cb);
345: syslog (LOG_ERR, "NIS+: failed to read local socket info");
346: return NULL;
347: }
348: port = ntohs (sin.sin_port);
349: get_myaddress (&sin);
350:
351: if (asprintf (&cb->serv->ep.ep_val[0].uaddr, "%s.%d.%d",
352: inet_ntoa (sin.sin_addr), (port & 0xFF00) >> 8, port & 0x00FF)
353: < 0)
354: goto failed;
355:
356: return cb;
357:
358: failed:
359: if (cb)
360: {
361: if (cb->xprt)
362: svc_destroy (cb->xprt);
363: xdr_free ((xdrproc_t) _xdr_nis_server, (char *) cb->serv);
364: free (cb);
365: }
366: if (!nomsg)
367: syslog (LOG_ERR, "NIS+: out of memory allocating callback");
368: return NULL;
369: }
370:
371: nis_error
372: __nis_destroy_callback (struct nis_cb *cb)
373: {
374: xprt_unregister (cb->xprt);
375: svc_destroy (cb->xprt);
376: close (cb->sock);
377: xdr_free ((xdrproc_t) _xdr_nis_server, (char *) cb->serv);
378: free (cb);
379:
380: return NIS_SUCCESS;
381: }