xref: /illumos-gate/usr/src/cmd/rpcbind/rpcb_svc.c (revision 9b9d39d2a32ff806d2431dbcc50968ef1e6d46b2)
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 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 /*
27  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
28  */
29 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
30 /* All Rights Reserved */
31 /*
32  * University Copyright- Copyright (c) 1982, 1986, 1988
33  * The Regents of the University of California
34  * All Rights Reserved
35  *
36  * University Acknowledgment- Portions of this document are derived from
37  * software developed by the University of California, Berkeley, and its
38  * contributors.
39  */
40 
41 /*
42  * rpcb_svc.c
43  * The server procedure for the version 3 rpcbind (TLI).
44  *
45  * It maintains a separate list of all the registered services with the
46  * version 3 of rpcbind.
47  */
48 #include <stdio.h>
49 #include <strings.h>
50 #include <sys/types.h>
51 #include <rpc/rpc.h>
52 #include <rpc/rpcb_prot.h>
53 #include <netconfig.h>
54 #include <syslog.h>
55 #include <netdir.h>
56 #include <stdlib.h>
57 #include "rpcbind.h"
58 
59 /*
60  * Called by svc_getreqset. There is a separate server handle for
61  * every transport that it waits on.
62  */
63 void
64 rpcb_service_3(struct svc_req *rqstp, SVCXPRT *transp)
65 {
66 	union {
67 		rpcb rpcbproc_set_3_arg;
68 		rpcb rpcbproc_unset_3_arg;
69 		rpcb rpcbproc_getaddr_3_arg;
70 		rpcb_rmtcallargs rpcbproc_callit_3_arg;
71 		char *rpcbproc_uaddr2taddr_3_arg;
72 		struct netbuf rpcbproc_taddr2uaddr_3_arg;
73 	} argument;
74 	union {
75 		bool_t rpcbproc_set_3_res;
76 		bool_t rpcbproc_unset_3_res;
77 		char *rpcbproc_getaddr_3_res;
78 		rpcblist_ptr *rpcbproc_dump_3_res;
79 		ulong_t rpcbproc_gettime_3_res;
80 		struct netbuf rpcbproc_uaddr2taddr_3_res;
81 		char *rpcbproc_taddr2uaddr_3_res;
82 	} result;
83 	bool_t retval;
84 	xdrproc_t xdr_argument, xdr_result;
85 	bool_t (*local)();
86 
87 	rpcbs_procinfo(RPCBVERS_3_STAT, rqstp->rq_proc);
88 
89 	RPCB_CHECK(transp, rqstp->rq_proc);
90 
91 	switch (rqstp->rq_proc) {
92 	case NULLPROC:
93 		/*
94 		 * Null proc call
95 		 */
96 		(void) svc_sendreply(transp, (xdrproc_t)xdr_void, (char *)NULL);
97 		return;
98 
99 	case RPCBPROC_SET:
100 		/*
101 		 * Check to see whether the message came from
102 		 * loopback transports (for security reasons)
103 		 */
104 		if (strcasecmp(transp->xp_netid, loopback_dg) &&
105 		    strcasecmp(transp->xp_netid, loopback_vc) &&
106 		    strcasecmp(transp->xp_netid, loopback_vc_ord)) {
107 			char *uaddr;
108 
109 			uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid),
110 			    svc_getrpccaller(transp));
111 			syslog(LOG_ERR, "non-local attempt to set from %s",
112 			    uaddr == NULL ? "<unknown>" : uaddr);
113 			free(uaddr);
114 			svcerr_weakauth(transp);
115 			return;
116 		}
117 		xdr_argument = xdr_rpcb;
118 		xdr_result = xdr_bool;
119 		local = (bool_t (*)()) rpcbproc_set_com;
120 		break;
121 
122 	case RPCBPROC_UNSET:
123 		/*
124 		 * Check to see whether the message came from
125 		 * loopback transports (for security reasons)
126 		 */
127 		if (strcasecmp(transp->xp_netid, loopback_dg) &&
128 		    strcasecmp(transp->xp_netid, loopback_vc) &&
129 		    strcasecmp(transp->xp_netid, loopback_vc_ord)) {
130 			char *uaddr;
131 
132 			uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid),
133 			    svc_getrpccaller(transp));
134 			syslog(LOG_ERR, "non-local attempt to unset from %s",
135 			    uaddr == NULL ? "<unknown>" : uaddr);
136 			free(uaddr);
137 			svcerr_weakauth(transp);
138 			return;
139 		}
140 		xdr_argument = xdr_rpcb;
141 		xdr_result = xdr_bool;
142 		local = (bool_t (*)()) rpcbproc_unset_com;
143 		break;
144 
145 	case RPCBPROC_GETADDR:
146 		xdr_argument = xdr_rpcb;
147 		xdr_result = xdr_wrapstring;
148 		local = (bool_t (*)()) rpcbproc_getaddr_com;
149 		break;
150 
151 	case RPCBPROC_DUMP:
152 		xdr_argument = xdr_void;
153 		xdr_result = xdr_rpcblist_ptr_ptr;
154 		local = (bool_t (*)()) rpcbproc_dump_com;
155 		break;
156 
157 	case RPCBPROC_CALLIT:
158 		rpcbproc_callit_com(rqstp, transp, rqstp->rq_proc, RPCBVERS);
159 		return;
160 
161 	case RPCBPROC_GETTIME:
162 		xdr_argument = xdr_void;
163 		xdr_result = xdr_u_long;
164 		local = (bool_t (*)()) rpcbproc_gettime_com;
165 		break;
166 
167 	case RPCBPROC_UADDR2TADDR:
168 		xdr_argument = xdr_wrapstring;
169 		xdr_result = xdr_netbuf;
170 		local = (bool_t (*)()) rpcbproc_uaddr2taddr_com;
171 		break;
172 
173 	case RPCBPROC_TADDR2UADDR:
174 		xdr_argument = xdr_netbuf;
175 		xdr_result = xdr_wrapstring;
176 		local = (bool_t (*)()) rpcbproc_taddr2uaddr_com;
177 		break;
178 
179 	default:
180 		svcerr_noproc(transp);
181 		return;
182 	}
183 	(void) memset((char *)&argument, 0, sizeof (argument));
184 	if (!svc_getargs(transp, xdr_argument, (char *)&argument)) {
185 		svcerr_decode(transp);
186 		if (debugging)
187 			(void) fprintf(stderr, "rpcbind: could not decode\n");
188 		return;
189 	}
190 	retval = (*local)(&argument, &result, rqstp, RPCBVERS);
191 	if (retval > 0 && !svc_sendreply(transp, xdr_result, (char *)&result)) {
192 		svcerr_systemerr(transp);
193 		if (debugging) {
194 			(void) fprintf(stderr, "rpcbind: svc_sendreply\n");
195 			if (doabort) {
196 				rpcbind_abort();
197 			}
198 		}
199 	}
200 	if (!svc_freeargs(transp, xdr_argument, (char *)&argument)) {
201 		if (debugging) {
202 			(void) fprintf(stderr, "unable to free arguments\n");
203 			if (doabort) {
204 				rpcbind_abort();
205 			}
206 		}
207 	}
208 
209 	xdr_free(xdr_result, (char *)&result);
210 }
211