1 /*
2  * clnt_unix.c, Implements a TCP/IP based, client side RPC.
3  *
4  * Copyright (c) 2010, Oracle America, Inc.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above
13  *       copyright notice, this list of conditions and the following
14  *       disclaimer in the documentation and/or other materials
15  *       provided with the distribution.
16  *     * Neither the name of the "Oracle America, Inc." nor the names of its
17  *       contributors may be used to endorse or promote products derived
18  *       from this software without specific prior written permission.
19  *
20  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * TCP based RPC supports 'batched calls'.
34  * A sequence of calls may be batched-up in a send buffer.  The rpc call
35  * return immediately to the client even though the call was not necessarily
36  * sent.  The batching occurs if the results' xdr routine is NULL (0) AND
37  * the rpc timeout value is zero (see clnt.h, rpc).
38  *
39  * Clients should NOT casually batch calls that in fact return results; that is,
40  * the server side should be aware that a call is batched and not produce any
41  * return message.  Batched calls that produce many result messages can
42  * deadlock (netlock) the client and the server....
43  *
44  * Now go hang yourself.
45  */
46 
47 #include <netdb.h>
48 #include <errno.h>
49 #include <stdio.h>
50 #include <unistd.h>
51 #include <libintl.h>
52 #include <rpc/rpc.h>
53 #include <sys/uio.h>
54 #include <sys/poll.h>
55 #include <sys/socket.h>
56 #include <rpc/pmap_clnt.h>
57 #include <wchar.h>
58 #include <shlib-compat.h>
59 
60 extern u_long _create_xid (void);
61 
62 #define MCALL_MSG_SIZE 24
63 
64 struct ct_data
65   {
66     int ct_sock;
67     bool_t ct_closeit;
68     struct timeval ct_wait;
69     bool_t ct_waitset;		/* wait set by clnt_control? */
70     struct sockaddr_un ct_addr;
71     struct rpc_err ct_error;
72     char ct_mcall[MCALL_MSG_SIZE];	/* marshalled callmsg */
73     u_int ct_mpos;		/* pos after marshal */
74     XDR ct_xdrs;
75   };
76 
77 static int readunix (char *, char *, int);
78 static int writeunix (char *, char *, int);
79 
80 static enum clnt_stat clntunix_call (CLIENT *, u_long, xdrproc_t, caddr_t,
81 				    xdrproc_t, caddr_t, struct timeval);
82 static void clntunix_abort (void);
83 static void clntunix_geterr (CLIENT *, struct rpc_err *);
84 static bool_t clntunix_freeres (CLIENT *, xdrproc_t, caddr_t);
85 static bool_t clntunix_control (CLIENT *, int, char *);
86 static void clntunix_destroy (CLIENT *);
87 
88 static const struct clnt_ops unix_ops =
89 {
90   clntunix_call,
91   clntunix_abort,
92   clntunix_geterr,
93   clntunix_freeres,
94   clntunix_destroy,
95   clntunix_control
96 };
97 
98 /*
99  * Create a client handle for a tcp/ip connection.
100  * If *sockp<0, *sockp is set to a newly created TCP socket and it is
101  * connected to raddr.  If *sockp non-negative then
102  * raddr is ignored.  The rpc/tcp package does buffering
103  * similar to stdio, so the client must pick send and receive buffer sizes,];
104  * 0 => use the default.
105  * If raddr->sin_port is 0, then a binder on the remote machine is
106  * consulted for the right port number.
107  * NB: *sockp is copied into a private area.
108  * NB: It is the clients responsibility to close *sockp.
109  * NB: The rpch->cl_auth is set null authentication.  Caller may wish to set this
110  * something more useful.
111  */
112 CLIENT *
clntunix_create(struct sockaddr_un * raddr,u_long prog,u_long vers,int * sockp,u_int sendsz,u_int recvsz)113 clntunix_create (struct sockaddr_un *raddr, u_long prog, u_long vers,
114 		 int *sockp, u_int sendsz, u_int recvsz)
115 {
116   CLIENT *h;
117   struct ct_data *ct = (struct ct_data *) mem_alloc (sizeof (*ct));
118   struct rpc_msg call_msg;
119   int len;
120 
121   h = (CLIENT *) mem_alloc (sizeof (*h));
122   if (h == NULL || ct == NULL)
123     {
124       struct rpc_createerr *ce = &get_rpc_createerr ();
125       (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
126       ce->cf_stat = RPC_SYSTEMERROR;
127       ce->cf_error.re_errno = ENOMEM;
128       goto fooy;
129     }
130 
131   /*
132    * If no socket given, open one
133    */
134   if (*sockp < 0)
135     {
136       *sockp = __socket (AF_UNIX, SOCK_STREAM, 0);
137       len = strlen (raddr->sun_path) + sizeof (raddr->sun_family) + 1;
138       if (*sockp < 0
139 	  || __connect (*sockp, (struct sockaddr *) raddr, len) < 0)
140 	{
141 	  struct rpc_createerr *ce = &get_rpc_createerr ();
142 	  ce->cf_stat = RPC_SYSTEMERROR;
143 	  ce->cf_error.re_errno = errno;
144 	  if (*sockp != -1)
145 	    __close (*sockp);
146 	  goto fooy;
147 	}
148       ct->ct_closeit = TRUE;
149     }
150   else
151     {
152       ct->ct_closeit = FALSE;
153     }
154 
155   /*
156    * Set up private data struct
157    */
158   ct->ct_sock = *sockp;
159   ct->ct_wait.tv_usec = 0;
160   ct->ct_waitset = FALSE;
161   ct->ct_addr = *raddr;
162 
163   /*
164    * Initialize call message
165    */
166   call_msg.rm_xid = _create_xid ();
167   call_msg.rm_direction = CALL;
168   call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
169   call_msg.rm_call.cb_prog = prog;
170   call_msg.rm_call.cb_vers = vers;
171 
172   /*
173    * pre-serialize the static part of the call msg and stash it away
174    */
175   xdrmem_create (&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, XDR_ENCODE);
176   if (!xdr_callhdr (&(ct->ct_xdrs), &call_msg))
177     {
178       if (ct->ct_closeit)
179 	__close (*sockp);
180       goto fooy;
181     }
182   ct->ct_mpos = XDR_GETPOS (&(ct->ct_xdrs));
183   XDR_DESTROY (&(ct->ct_xdrs));
184 
185   /*
186    * Create a client handle which uses xdrrec for serialization
187    * and authnone for authentication.
188    */
189   xdrrec_create (&(ct->ct_xdrs), sendsz, recvsz,
190 		 (caddr_t) ct, readunix, writeunix);
191   h->cl_ops = (struct clnt_ops *) &unix_ops;
192   h->cl_private = (caddr_t) ct;
193   h->cl_auth = authnone_create ();
194   return h;
195 
196 fooy:
197   /*
198    * Something goofed, free stuff and barf
199    */
200   mem_free ((caddr_t) ct, sizeof (struct ct_data));
201   mem_free ((caddr_t) h, sizeof (CLIENT));
202   return (CLIENT *) NULL;
203 }
libc_hidden_nolink_sunrpc(clntunix_create,GLIBC_2_1)204 libc_hidden_nolink_sunrpc (clntunix_create, GLIBC_2_1)
205 
206 static enum clnt_stat
207 clntunix_call (CLIENT *h, u_long proc, xdrproc_t xdr_args, caddr_t args_ptr,
208 	       xdrproc_t xdr_results, caddr_t results_ptr,
209 	       struct timeval timeout)
210 {
211   struct ct_data *ct = (struct ct_data *) h->cl_private;
212   XDR *xdrs = &(ct->ct_xdrs);
213   struct rpc_msg reply_msg;
214   u_long x_id;
215   uint32_t *msg_x_id = (uint32_t *) (ct->ct_mcall);	/* yuk */
216   bool_t shipnow;
217   int refreshes = 2;
218 
219   if (!ct->ct_waitset)
220     {
221       ct->ct_wait = timeout;
222     }
223 
224   shipnow =
225     (xdr_results == (xdrproc_t) 0 && ct->ct_wait.tv_sec == 0
226      && ct->ct_wait.tv_usec == 0) ? FALSE : TRUE;
227 
228 call_again:
229   xdrs->x_op = XDR_ENCODE;
230   ct->ct_error.re_status = RPC_SUCCESS;
231   x_id = ntohl (--(*msg_x_id));
232   if ((!XDR_PUTBYTES (xdrs, ct->ct_mcall, ct->ct_mpos)) ||
233       (!XDR_PUTLONG (xdrs, (long *) &proc)) ||
234       (!AUTH_MARSHALL (h->cl_auth, xdrs)) ||
235       (!(*xdr_args) (xdrs, args_ptr)))
236     {
237       if (ct->ct_error.re_status == RPC_SUCCESS)
238 	ct->ct_error.re_status = RPC_CANTENCODEARGS;
239       (void) xdrrec_endofrecord (xdrs, TRUE);
240       return ct->ct_error.re_status;
241     }
242   if (!xdrrec_endofrecord (xdrs, shipnow))
243     return ct->ct_error.re_status = RPC_CANTSEND;
244   if (!shipnow)
245     return RPC_SUCCESS;
246   /*
247    * Hack to provide rpc-based message passing
248    */
249   if (ct->ct_wait.tv_sec == 0 && ct->ct_wait.tv_usec == 0)
250     return ct->ct_error.re_status = RPC_TIMEDOUT;
251 
252 
253   /*
254    * Keep receiving until we get a valid transaction id
255    */
256   xdrs->x_op = XDR_DECODE;
257   while (TRUE)
258     {
259       reply_msg.acpted_rply.ar_verf = _null_auth;
260       reply_msg.acpted_rply.ar_results.where = NULL;
261       reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
262       if (!xdrrec_skiprecord (xdrs))
263 	return ct->ct_error.re_status;
264       /* now decode and validate the response header */
265       if (!xdr_replymsg (xdrs, &reply_msg))
266 	{
267 	  if (ct->ct_error.re_status == RPC_SUCCESS)
268 	    continue;
269 	  return ct->ct_error.re_status;
270 	}
271       if (reply_msg.rm_xid == x_id)
272 	break;
273     }
274 
275   /*
276    * process header
277    */
278   _seterr_reply (&reply_msg, &(ct->ct_error));
279   if (ct->ct_error.re_status == RPC_SUCCESS)
280     {
281       if (!AUTH_VALIDATE (h->cl_auth, &reply_msg.acpted_rply.ar_verf))
282 	{
283 	  ct->ct_error.re_status = RPC_AUTHERROR;
284 	  ct->ct_error.re_why = AUTH_INVALIDRESP;
285 	}
286       else if (!(*xdr_results) (xdrs, results_ptr))
287 	{
288 	  if (ct->ct_error.re_status == RPC_SUCCESS)
289 	    ct->ct_error.re_status = RPC_CANTDECODERES;
290 	}
291       /* free verifier ... */
292       if (reply_msg.acpted_rply.ar_verf.oa_base != NULL)
293 	{
294 	  xdrs->x_op = XDR_FREE;
295 	  (void) xdr_opaque_auth (xdrs, &(reply_msg.acpted_rply.ar_verf));
296 	}
297     }				/* end successful completion */
298   else
299     {
300       /* maybe our credentials need to be refreshed ... */
301       if (refreshes-- && AUTH_REFRESH (h->cl_auth))
302 	goto call_again;
303     }				/* end of unsuccessful completion */
304   return ct->ct_error.re_status;
305 }
306 
307 static void
clntunix_geterr(CLIENT * h,struct rpc_err * errp)308 clntunix_geterr (CLIENT *h, struct rpc_err *errp)
309 {
310   struct ct_data *ct = (struct ct_data *) h->cl_private;
311 
312   *errp = ct->ct_error;
313 }
314 
315 static bool_t
clntunix_freeres(CLIENT * cl,xdrproc_t xdr_res,caddr_t res_ptr)316 clntunix_freeres (CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr)
317 {
318   struct ct_data *ct = (struct ct_data *) cl->cl_private;
319   XDR *xdrs = &(ct->ct_xdrs);
320 
321   xdrs->x_op = XDR_FREE;
322   return (*xdr_res) (xdrs, res_ptr);
323 }
324 
325 static void
clntunix_abort(void)326 clntunix_abort (void)
327 {
328 }
329 
330 static bool_t
clntunix_control(CLIENT * cl,int request,char * info)331 clntunix_control (CLIENT *cl, int request, char *info)
332 {
333   struct ct_data *ct = (struct ct_data *) cl->cl_private;
334   u_long ul;
335   uint32_t ui32;
336 
337   switch (request)
338     {
339     case CLSET_FD_CLOSE:
340       ct->ct_closeit = TRUE;
341       break;
342     case CLSET_FD_NCLOSE:
343       ct->ct_closeit = FALSE;
344       break;
345     case CLSET_TIMEOUT:
346       ct->ct_wait = *(struct timeval *) info;
347       break;
348     case CLGET_TIMEOUT:
349       *(struct timeval *) info = ct->ct_wait;
350       break;
351     case CLGET_SERVER_ADDR:
352       *(struct sockaddr_un *) info = ct->ct_addr;
353       break;
354     case CLGET_FD:
355       *(int *)info = ct->ct_sock;
356       break;
357     case CLGET_XID:
358       /*
359        * use the knowledge that xid is the
360        * first element in the call structure *.
361        * This will get the xid of the PREVIOUS call
362        */
363       memcpy (&ui32, ct->ct_mcall, sizeof (ui32));
364       ul = ntohl (ui32);
365       memcpy (info, &ul, sizeof (ul));
366       break;
367     case CLSET_XID:
368       /* This will set the xid of the NEXT call */
369       memcpy (&ul, info, sizeof (ul));
370       ui32 = htonl (ul - 1);
371       memcpy (ct->ct_mcall, &ui32, sizeof (ui32));
372       /* decrement by 1 as clntunix_call() increments once */
373       break;
374     case CLGET_VERS:
375       /*
376        * This RELIES on the information that, in the call body,
377        * the version number field is the fifth field from the
378        * beginning of the RPC header. MUST be changed if the
379        * call_struct is changed
380        */
381       memcpy (&ui32, ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT, sizeof (ui32));
382       ul = ntohl (ui32);
383       memcpy (info, &ul, sizeof (ul));
384       break;
385     case CLSET_VERS:
386       memcpy (&ul, info, sizeof (ul));
387       ui32 = htonl (ul);
388       memcpy (ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT, &ui32, sizeof (ui32));
389       break;
390     case CLGET_PROG:
391       /*
392        * This RELIES on the information that, in the call body,
393        * the program number field is the  field from the
394        * beginning of the RPC header. MUST be changed if the
395        * call_struct is changed
396        */
397       memcpy (&ui32, ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT, sizeof (ui32));
398       ul = ntohl (ui32);
399       memcpy (info, &ul, sizeof (ul));
400       break;
401     case CLSET_PROG:
402       memcpy (&ul, info, sizeof (ul));
403       ui32 = htonl (ul);
404       memcpy (ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT, &ui32, sizeof (ui32));
405       break;
406     /* The following are only possible with TI-RPC */
407     case CLGET_RETRY_TIMEOUT:
408     case CLSET_RETRY_TIMEOUT:
409     case CLGET_SVC_ADDR:
410     case CLSET_SVC_ADDR:
411     case CLSET_PUSH_TIMOD:
412     case CLSET_POP_TIMOD:
413     default:
414       return FALSE;
415     }
416   return TRUE;
417 }
418 
419 
420 static void
clntunix_destroy(CLIENT * h)421 clntunix_destroy (CLIENT *h)
422 {
423   struct ct_data *ct =
424   (struct ct_data *) h->cl_private;
425 
426   if (ct->ct_closeit)
427     {
428       (void) __close (ct->ct_sock);
429     }
430   XDR_DESTROY (&(ct->ct_xdrs));
431   mem_free ((caddr_t) ct, sizeof (struct ct_data));
432   mem_free ((caddr_t) h, sizeof (CLIENT));
433 }
434 
435 static int
__msgread(int sock,void * data,size_t cnt)436 __msgread (int sock, void *data, size_t cnt)
437 {
438   struct iovec iov;
439   struct msghdr msg;
440 #ifdef SCM_CREDENTIALS
441   static char cm[CMSG_SPACE(sizeof (struct ucred))];
442 #endif
443   int len;
444 
445   iov.iov_base = data;
446   iov.iov_len = cnt;
447 
448   msg.msg_iov = &iov;
449   msg.msg_iovlen = 1;
450   msg.msg_name = NULL;
451   msg.msg_namelen = 0;
452 #ifdef SCM_CREDENTIALS
453   msg.msg_control = (caddr_t) &cm;
454   msg.msg_controllen = CMSG_SPACE(sizeof (struct ucred));
455 #endif
456   msg.msg_flags = 0;
457 
458 #ifdef SO_PASSCRED
459   {
460     int on = 1;
461     if (__setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)))
462       return -1;
463   }
464 #endif
465 
466  restart:
467   len = __recvmsg (sock, &msg, 0);
468   if (len >= 0)
469     {
470       if (msg.msg_flags & MSG_CTRUNC || len == 0)
471 	return 0;
472       else
473 	return len;
474     }
475   if (errno == EINTR)
476     goto restart;
477   return -1;
478 }
479 
480 static int
__msgwrite(int sock,void * data,size_t cnt)481 __msgwrite (int sock, void *data, size_t cnt)
482 {
483 #ifndef SCM_CREDENTIALS
484   /* We cannot implement this reliably.  */
485   __set_errno (ENOSYS);
486   return -1;
487 #else
488   struct iovec iov;
489   struct msghdr msg;
490   struct cmsghdr *cmsg = alloca (CMSG_SPACE(sizeof (struct ucred)));
491   struct ucred cred;
492   int len;
493 
494   /* XXX I'm not sure, if gete?id() is always correct, or if we should use
495      get?id(). But since keyserv needs geteuid(), we have no other chance.
496      It would be much better, if the kernel could pass both to the server. */
497   cred.pid = __getpid ();
498   cred.uid = __geteuid ();
499   cred.gid = __getegid ();
500 
501   memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred));
502   cmsg->cmsg_level = SOL_SOCKET;
503   cmsg->cmsg_type = SCM_CREDENTIALS;
504   cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred);
505 
506   iov.iov_base = data;
507   iov.iov_len = cnt;
508 
509   msg.msg_iov = &iov;
510   msg.msg_iovlen = 1;
511   msg.msg_name = NULL;
512   msg.msg_namelen = 0;
513   msg.msg_control = cmsg;
514   msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len);
515   msg.msg_flags = 0;
516 
517  restart:
518   len = __sendmsg (sock, &msg, 0);
519   if (len >= 0)
520     return len;
521   if (errno == EINTR)
522     goto restart;
523   return -1;
524 
525 #endif
526 }
527 
528 
529 /*
530  * Interface between xdr serializer and unix connection.
531  * Behaves like the system calls, read & write, but keeps some error state
532  * around for the rpc level.
533  */
534 static int
readunix(char * ctptr,char * buf,int len)535 readunix (char *ctptr, char *buf, int len)
536 {
537   struct ct_data *ct = (struct ct_data *) ctptr;
538   struct pollfd fd;
539   int milliseconds = ((ct->ct_wait.tv_sec * 1000)
540 		      + (ct->ct_wait.tv_usec / 1000));
541 
542   if (len == 0)
543     return 0;
544 
545   fd.fd = ct->ct_sock;
546   fd.events = POLLIN;
547   while (TRUE)
548     {
549       switch (__poll (&fd, 1, milliseconds))
550 	{
551 	case 0:
552 	  ct->ct_error.re_status = RPC_TIMEDOUT;
553 	  return -1;
554 
555 	case -1:
556 	  if (errno == EINTR)
557 	    continue;
558 	  ct->ct_error.re_status = RPC_CANTRECV;
559 	  ct->ct_error.re_errno = errno;
560 	  return -1;
561 	}
562       break;
563     }
564   switch (len = __msgread (ct->ct_sock, buf, len))
565     {
566 
567     case 0:
568       /* premature eof */
569       ct->ct_error.re_errno = ECONNRESET;
570       ct->ct_error.re_status = RPC_CANTRECV;
571       len = -1;			/* it's really an error */
572       break;
573 
574     case -1:
575       ct->ct_error.re_errno = errno;
576       ct->ct_error.re_status = RPC_CANTRECV;
577       break;
578     }
579   return len;
580 }
581 
582 static int
writeunix(char * ctptr,char * buf,int len)583 writeunix (char *ctptr, char *buf, int len)
584 {
585   int i, cnt;
586   struct ct_data *ct = (struct ct_data *) ctptr;
587 
588   for (cnt = len; cnt > 0; cnt -= i, buf += i)
589     {
590       if ((i = __msgwrite (ct->ct_sock, buf, cnt)) == -1)
591 	{
592 	  ct->ct_error.re_errno = errno;
593 	  ct->ct_error.re_status = RPC_CANTSEND;
594 	  return -1;
595 	}
596     }
597   return len;
598 }
599