xref: /reactos/dll/3rdparty/libtirpc/src/rpc_prot.c (revision d6eebaa4)
1 /*
2  * Copyright (c) 2009, Sun Microsystems, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * - Redistributions of source code must retain the above copyright notice,
8  *   this list of conditions and the following disclaimer.
9  * - Redistributions in binary form must reproduce the above copyright notice,
10  *   this list of conditions and the following disclaimer in the documentation
11  *   and/or other materials provided with the distribution.
12  * - Neither the name of Sun Microsystems, Inc. nor the names of its
13  *   contributors may be used to endorse or promote products derived
14  *   from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /*
30  * rpc_prot.c
31  *
32  * Copyright (C) 1984, Sun Microsystems, Inc.
33  *
34  * This set of routines implements the rpc message definition,
35  * its serializer and some common rpc utility routines.
36  * The routines are meant for various implementations of rpc -
37  * they are NOT for the rpc client or rpc service implementations!
38  * Because authentication stuff is easy and is part of rpc, the opaque
39  * routines are also in this program.
40  */
41 
42 /* NFSv4.1 client for Windows
43  * Copyright � 2012 The Regents of the University of Michigan
44  *
45  * Olga Kornievskaia <aglo@umich.edu>
46  * Casey Bodley <cbodley@umich.edu>
47  *
48  * This library is free software; you can redistribute it and/or modify it
49  * under the terms of the GNU Lesser General Public License as published by
50  * the Free Software Foundation; either version 2.1 of the License, or (at
51  * your option) any later version.
52  *
53  * This library is distributed in the hope that it will be useful, but
54  * without any warranty; without even the implied warranty of merchantability
55  * or fitness for a particular purpose.  See the GNU Lesser General Public
56  * License for more details.
57  *
58  * You should have received a copy of the GNU Lesser General Public License
59  * along with this library; if not, write to the Free Software Foundation,
60  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
61  */
62 
63 #include <wintirpc.h>
64 //#include <sys/param.h>
65 
66 #include <assert.h>
67 
68 #include <rpc/rpc.h>
69 
70 static void accepted(enum accept_stat, struct rpc_err *);
71 static void rejected(enum reject_stat, struct rpc_err *);
72 
73 /* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
74 
75 extern struct opaque_auth _null_auth;
76 
77 /*
78  * XDR an opaque authentication struct
79  * (see auth.h)
80  */
81 bool_t
82 xdr_opaque_auth(xdrs, ap)
83 	XDR *xdrs;
84 	struct opaque_auth *ap;
85 {
86 
87 	assert(xdrs != NULL);
88 	assert(ap != NULL);
89 
90 	if (xdr_enum(xdrs, &(ap->oa_flavor)))
91 		return (xdr_bytes(xdrs, &ap->oa_base,
92 			&ap->oa_length, MAX_AUTH_BYTES));
93 	return (FALSE);
94 }
95 
96 /*
97  * XDR a DES block
98  */
99 bool_t
100 xdr_des_block(xdrs, blkp)
101 	XDR *xdrs;
102 	des_block *blkp;
103 {
104 
105 	assert(xdrs != NULL);
106 	assert(blkp != NULL);
107 
108 	return (xdr_opaque(xdrs, (caddr_t)(void *)blkp, sizeof(des_block)));
109 }
110 
111 /* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
112 
113 /*
114  * XDR the MSG_ACCEPTED part of a reply message union
115  */
116 bool_t
117 xdr_accepted_reply(xdrs, ar)
118 	XDR *xdrs;
119 	struct accepted_reply *ar;
120 {
121 
122 	assert(xdrs != NULL);
123 	assert(ar != NULL);
124 
125 	/* personalized union, rather than calling xdr_union */
126 	if (! xdr_opaque_auth(xdrs, &(ar->ar_verf)))
127 		return (FALSE);
128 	if (! xdr_enum(xdrs, (enum_t *)&(ar->ar_stat)))
129 		return (FALSE);
130 	switch (ar->ar_stat) {
131 
132 	case SUCCESS:
133 		return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where));
134 
135 	case PROG_MISMATCH:
136 		if (! xdr_u_int32_t(xdrs, &(ar->ar_vers.low)))
137 			return (FALSE);
138 		return (xdr_u_int32_t(xdrs, &(ar->ar_vers.high)));
139 
140 	case GARBAGE_ARGS:
141 	case SYSTEM_ERR:
142 	case PROC_UNAVAIL:
143 	case PROG_UNAVAIL:
144 		break;
145 	}
146 	return (TRUE);  /* TRUE => open ended set of problems */
147 }
148 
149 /*
150  * XDR the MSG_DENIED part of a reply message union
151  */
152 bool_t
153 xdr_rejected_reply(xdrs, rr)
154 	XDR *xdrs;
155 	struct rejected_reply *rr;
156 {
157 
158 	assert(xdrs != NULL);
159 	assert(rr != NULL);
160 
161 	/* personalized union, rather than calling xdr_union */
162 	if (! xdr_enum(xdrs, (enum_t *)&(rr->rj_stat)))
163 		return (FALSE);
164 	switch (rr->rj_stat) {
165 
166 	case RPC_MISMATCH:
167 		if (! xdr_u_int32_t(xdrs, &(rr->rj_vers.low)))
168 			return (FALSE);
169 		return (xdr_u_int32_t(xdrs, &(rr->rj_vers.high)));
170 
171 	case AUTH_ERROR:
172 		return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why)));
173 	}
174 	/* NOTREACHED */
175 	assert(0);
176 	return (FALSE);
177 }
178 
179 static const struct xdr_discrim reply_dscrm[3] = {
180 	{ (int)MSG_ACCEPTED, (xdrproc_t)xdr_accepted_reply },
181 	{ (int)MSG_DENIED, (xdrproc_t)xdr_rejected_reply },
182 	{ __dontcare__, NULL_xdrproc_t } };
183 
184 /*
185  * XDR a reply message
186  */
187 bool_t
188 xdr_replymsg(xdrs, rmsg)
189 	XDR *xdrs;
190 	struct rpc_msg *rmsg;
191 {
192 	assert(xdrs != NULL);
193 	assert(rmsg != NULL);
194 
195 	if (
196 	    xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) &&
197 	    xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)) &&
198 	    (rmsg->rm_direction == REPLY) )
199 		return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat),
200 		   (caddr_t)(void *)&(rmsg->rm_reply.ru), reply_dscrm,
201 		   NULL_xdrproc_t));
202 	return (FALSE);
203 }
204 
205 /*
206  * XDR a reply message in pieces, first xid and direction, then union
207  */
208 bool_t
209 xdr_getxiddir(xdrs, rmsg)
210 	XDR *xdrs;
211 	struct rpc_msg *rmsg;
212 {
213 	assert(xdrs != NULL);
214 	assert(rmsg != NULL);
215 
216     return (xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) &&
217 	    xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)));
218 }
219 
220 bool_t
221 xdr_getreplyunion(xdrs, rmsg)
222 	XDR *xdrs;
223 	struct rpc_msg *rmsg;
224 {
225 	assert(xdrs != NULL);
226 	assert(rmsg != NULL);
227 
228 	return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat),
229 		(caddr_t)(void *)&(rmsg->rm_reply.ru), reply_dscrm,
230 		NULL_xdrproc_t));
231 }
232 
233 bool_t
234 xdr_getcallbody(xdrs, rmsg)
235 	XDR *xdrs;
236 	struct rpc_msg *rmsg;
237 {
238 	assert(xdrs != NULL);
239 	assert(rmsg != NULL);
240 
241 	if (
242 	    xdr_u_int32_t(xdrs, &(rmsg->rm_call.cb_rpcvers)) &&
243 	    xdr_u_int32_t(xdrs, &(rmsg->rm_call.cb_prog)) &&
244 	    xdr_u_int32_t(xdrs, &(rmsg->rm_call.cb_vers)) &&
245 	    xdr_u_int32_t(xdrs, &(rmsg->rm_call.cb_proc)) &&
246 	    xdr_opaque_auth(xdrs, &(rmsg->rm_call.cb_cred)) )
247 		return (xdr_opaque_auth(xdrs, &(rmsg->rm_call.cb_verf)));
248     return FALSE;
249 }
250 
251 /*
252  * Serializes the "static part" of a call message header.
253  * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
254  * The rm_xid is not really static, but the user can easily munge on the fly.
255  */
256 bool_t
257 xdr_callhdr(xdrs, cmsg)
258 	XDR *xdrs;
259 	struct rpc_msg *cmsg;
260 {
261 
262 	assert(xdrs != NULL);
263 	assert(cmsg != NULL);
264 
265 	cmsg->rm_direction = CALL;
266 	cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
267 	if (
268 	    (xdrs->x_op == XDR_ENCODE) &&
269 	    xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) &&
270 	    xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) &&
271 	    xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
272 	    xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)) )
273 		return (xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers)));
274 	return (FALSE);
275 }
276 
277 /* ************************** Client utility routine ************* */
278 
279 static void
280 accepted(acpt_stat, error)
281 	enum accept_stat acpt_stat;
282 	struct rpc_err *error;
283 {
284 
285 	assert(error != NULL);
286 
287 	switch (acpt_stat) {
288 
289 	case PROG_UNAVAIL:
290 		error->re_status = RPC_PROGUNAVAIL;
291 		return;
292 
293 	case PROG_MISMATCH:
294 		error->re_status = RPC_PROGVERSMISMATCH;
295 		return;
296 
297 	case PROC_UNAVAIL:
298 		error->re_status = RPC_PROCUNAVAIL;
299 		return;
300 
301 	case GARBAGE_ARGS:
302 		error->re_status = RPC_CANTDECODEARGS;
303 		return;
304 
305 	case SYSTEM_ERR:
306 		error->re_status = RPC_SYSTEMERROR;
307 		return;
308 
309 	case SUCCESS:
310 		error->re_status = RPC_SUCCESS;
311 		return;
312 	}
313 	/* NOTREACHED */
314 	/* something's wrong, but we don't know what ... */
315 	error->re_status = RPC_FAILED;
316 	error->re_lb.s1 = (int32_t)MSG_ACCEPTED;
317 	error->re_lb.s2 = (int32_t)acpt_stat;
318 }
319 
320 static void
321 rejected(rjct_stat, error)
322 	enum reject_stat rjct_stat;
323 	struct rpc_err *error;
324 {
325 
326 	assert(error != NULL);
327 
328 	switch (rjct_stat) {
329 	case RPC_MISMATCH:
330 		error->re_status = RPC_VERSMISMATCH;
331 		return;
332 
333 	case AUTH_ERROR:
334 		error->re_status = RPC_AUTHERROR;
335 		return;
336 	}
337 	/* something's wrong, but we don't know what ... */
338 	/* NOTREACHED */
339 	error->re_status = RPC_FAILED;
340 	error->re_lb.s1 = (int32_t)MSG_DENIED;
341 	error->re_lb.s2 = (int32_t)rjct_stat;
342 }
343 
344 /*
345  * given a reply message, fills in the error
346  */
347 void
348 _seterr_reply(msg, error)
349 	struct rpc_msg *msg;
350 	struct rpc_err *error;
351 {
352 
353 	assert(msg != NULL);
354 	assert(error != NULL);
355 
356 	/* optimized for normal, SUCCESSful case */
357 	switch (msg->rm_reply.rp_stat) {
358 
359 	case MSG_ACCEPTED:
360 		if (msg->acpted_rply.ar_stat == SUCCESS) {
361 			error->re_status = RPC_SUCCESS;
362 			return;
363 		}
364 		accepted(msg->acpted_rply.ar_stat, error);
365 		break;
366 
367 	case MSG_DENIED:
368 		rejected(msg->rjcted_rply.rj_stat, error);
369 		break;
370 
371 	default:
372 		error->re_status = RPC_FAILED;
373 		error->re_lb.s1 = (int32_t)(msg->rm_reply.rp_stat);
374 		break;
375 	}
376 	switch (error->re_status) {
377 
378 	case RPC_VERSMISMATCH:
379 		error->re_vers.low = msg->rjcted_rply.rj_vers.low;
380 		error->re_vers.high = msg->rjcted_rply.rj_vers.high;
381 		break;
382 
383 	case RPC_AUTHERROR:
384 		error->re_why = msg->rjcted_rply.rj_why;
385 		break;
386 
387 	case RPC_PROGVERSMISMATCH:
388 		error->re_vers.low = msg->acpted_rply.ar_vers.low;
389 		error->re_vers.high = msg->acpted_rply.ar_vers.high;
390 		break;
391 
392 	case RPC_FAILED:
393 	case RPC_SUCCESS:
394 	case RPC_PROGNOTREGISTERED:
395 	case RPC_PMAPFAILURE:
396 	case RPC_UNKNOWNPROTO:
397 	case RPC_UNKNOWNHOST:
398 	case RPC_SYSTEMERROR:
399 	case RPC_CANTDECODEARGS:
400 	case RPC_PROCUNAVAIL:
401 	case RPC_PROGUNAVAIL:
402 	case RPC_TIMEDOUT:
403 	case RPC_CANTRECV:
404 	case RPC_CANTSEND:
405 	case RPC_CANTDECODERES:
406 	case RPC_CANTENCODEARGS:
407 	default:
408 		break;
409 	}
410 }
411