1 /* -*-  mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil;  -*- */
2 /*
3    Copyright (C) 2012 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU Lesser General Public License as published by
7    the Free Software Foundation; either version 2.1 of the License, or
8    (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public License
16    along with this program; if not, see <http://www.gnu.org/licenses/>.
17 */
18 /*
19  * This file contains definitions for the built in ZDR implementation.
20  * This is a very limited ZDR subset that can only marshal to/from a momory buffer,
21  * i.e. zdrmem_create() buffers.
22  * It aims to be compatible with normal rpcgen generated functions.
23  */
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #ifdef WIN32
29 #include <win32/win32_compat.h>
30 #endif
31 
32 #ifdef AROS
33 #include "aros_compat.h"
34 #endif
35 
36 #ifdef HAVE_ARPA_INET_H
37 #include <arpa/inet.h>
38 #endif
39 
40 #ifdef HAVE_UNISTD_H
41 #include <unistd.h>
42 #endif
43 
44 #include <stddef.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <time.h>
48 #include "libnfs-zdr.h"
49 #include "libnfs.h"
50 #include "libnfs-raw.h"
51 #include "libnfs-private.h"
52 
53 struct zdr_mem {
54        struct zdr_mem *next;
55        uint32_t size;
56        char buf[1];
57 };
58 
59 struct opaque_auth _null_auth;
60 
libnfs_zdr_setpos(ZDR * zdrs,uint32_t pos)61 bool_t libnfs_zdr_setpos(ZDR *zdrs, uint32_t pos)
62 {
63 	zdrs->pos = pos;
64 
65 	return TRUE;
66 }
67 
libnfs_zdr_getpos(ZDR * zdrs)68 uint32_t libnfs_zdr_getpos(ZDR *zdrs)
69 {
70 	return zdrs->pos;
71 }
72 
libnfs_zdrmem_create(ZDR * zdrs,const caddr_t addr,uint32_t size,enum zdr_op xop)73 void libnfs_zdrmem_create(ZDR *zdrs, const caddr_t addr, uint32_t size, enum zdr_op xop)
74 {
75 	zdrs->x_op = xop;
76 	zdrs->buf  = addr;
77 	zdrs->size = size;
78 	zdrs->pos  = 0;
79 	zdrs->mem = NULL;
80 }
81 
zdr_malloc(ZDR * zdrs,uint32_t size)82 void *zdr_malloc(ZDR *zdrs, uint32_t size)
83 {
84 	struct zdr_mem *mem;
85 	int mem_size;
86 
87 	mem_size = offsetof(struct zdr_mem, buf) + size;
88 	mem = malloc(mem_size);
89 
90 	mem->next = zdrs->mem;
91 	mem->size = size;
92 
93 	zdrs->mem = mem;
94 
95 	return &mem->buf[0];
96 }
97 
libnfs_zdr_destroy(ZDR * zdrs)98 void libnfs_zdr_destroy(ZDR *zdrs)
99 {
100 	while (zdrs->mem != NULL) {
101 		struct zdr_mem *mem = zdrs->mem->next;
102 		free(zdrs->mem);
103 		zdrs->mem = mem;
104 	}
105 }
106 
libnfs_zdr_u_int(ZDR * zdrs,uint32_t * u)107 bool_t libnfs_zdr_u_int(ZDR *zdrs, uint32_t *u)
108 {
109 	if (zdrs->pos + 4 > zdrs->size) {
110 		return FALSE;
111 	}
112 
113 	switch (zdrs->x_op) {
114 	case ZDR_ENCODE:
115 		*(uint32_t *)(void *)&zdrs->buf[zdrs->pos] = htonl(*u);
116 		zdrs->pos += 4;
117 		return TRUE;
118 	case ZDR_DECODE:
119 		*u = ntohl(*(uint32_t *)(void *)&zdrs->buf[zdrs->pos]);
120 		zdrs->pos += 4;
121 		return TRUE;
122 	}
123 
124 	return FALSE;
125 }
126 
libnfs_zdr_int(ZDR * zdrs,int32_t * i)127 bool_t libnfs_zdr_int(ZDR *zdrs, int32_t *i)
128 {
129 	return libnfs_zdr_u_int(zdrs, (uint32_t *)i);
130 }
131 
libnfs_zdr_uint64_t(ZDR * zdrs,uint64_t * u)132 bool_t libnfs_zdr_uint64_t(ZDR *zdrs, uint64_t *u)
133 {
134 	if (zdrs->pos + 8 > zdrs->size) {
135 		return FALSE;
136 	}
137 
138 	switch (zdrs->x_op) {
139 	case ZDR_ENCODE:
140 		*(uint32_t *)(void *)&zdrs->buf[zdrs->pos] = htonl((*u >> 32));
141 		zdrs->pos += 4;
142 		*(uint32_t *)(void *)&zdrs->buf[zdrs->pos] = htonl((*u & 0xffffffff));
143 		zdrs->pos += 4;
144 		return TRUE;
145 	case ZDR_DECODE:
146 		*u = ntohl(*(uint32_t *)(void *)&zdrs->buf[zdrs->pos]);
147 		zdrs->pos += 4;
148 		*u <<= 32;
149 		*u |= (uint32_t)ntohl(*(uint32_t *)(void *)&zdrs->buf[zdrs->pos]);
150 		zdrs->pos += 4;
151 		return TRUE;
152 	}
153 
154 	return FALSE;
155 }
156 
libnfs_zdr_int64_t(ZDR * zdrs,int64_t * i)157 bool_t libnfs_zdr_int64_t(ZDR *zdrs, int64_t *i)
158 {
159 	return libnfs_zdr_uint64_t(zdrs, (uint64_t *)i);
160 }
161 
libnfs_zdr_bytes(ZDR * zdrs,char ** bufp,uint32_t * size,uint32_t maxsize)162 bool_t libnfs_zdr_bytes(ZDR *zdrs, char **bufp, uint32_t *size, uint32_t maxsize)
163 {
164         uint32_t zero = 0;
165         int pad;
166 
167 	if (!libnfs_zdr_u_int(zdrs, size)) {
168 		return FALSE;
169 	}
170 
171 	if (zdrs->pos + (int)*size > zdrs->size) {
172 		return FALSE;
173 	}
174 
175 	switch (zdrs->x_op) {
176 	case ZDR_ENCODE:
177 		memcpy(&zdrs->buf[zdrs->pos], *bufp, *size);
178 		zdrs->pos += *size;
179 
180                 pad = (4 - (zdrs->pos & 0x03)) & 0x03;
181                 if (pad) {
182                         /* Make valgrind happy again */
183                         memcpy(&zdrs->buf[zdrs->pos], &zero, pad);
184                         zdrs->pos += pad;
185                 }
186 		return TRUE;
187 	case ZDR_DECODE:
188 		if (*bufp != NULL) {
189 			memcpy(*bufp, &zdrs->buf[zdrs->pos], *size);
190 		} else {
191 			*bufp = &zdrs->buf[zdrs->pos];
192 		}
193 		zdrs->pos += *size;
194 		zdrs->pos = (zdrs->pos + 3) & ~3;
195 		return TRUE;
196 	}
197 
198 	return FALSE;
199 }
200 
201 
libnfs_zdr_enum(ZDR * zdrs,enum_t * e)202 bool_t libnfs_zdr_enum(ZDR *zdrs, enum_t *e)
203 {
204 	bool_t ret;
205 	int32_t i = *e;
206 
207 	ret = libnfs_zdr_u_int(zdrs, (uint32_t *)&i);
208 	*e = i;
209 
210 	return ret;
211 }
212 
libnfs_zdr_bool(ZDR * zdrs,bool_t * b)213 bool_t libnfs_zdr_bool(ZDR *zdrs, bool_t *b)
214 {
215 	return libnfs_zdr_u_int(zdrs, (uint32_t *)b);
216 }
217 
libnfs_zdr_void(ZDR * zdrs,void * v)218 bool_t libnfs_zdr_void(ZDR *zdrs, void *v)
219 {
220 	return TRUE;
221 }
222 
libnfs_zdr_pointer(ZDR * zdrs,char ** objp,uint32_t size,zdrproc_t proc)223 bool_t libnfs_zdr_pointer(ZDR *zdrs, char **objp, uint32_t size, zdrproc_t proc)
224 {
225 	bool_t more_data;
226 
227 	more_data = (*objp != NULL);
228 
229 	if (!libnfs_zdr_bool(zdrs, &more_data)) {
230 		return FALSE;
231 	}
232 	if (more_data == 0) {
233 		*objp = NULL;
234 		return TRUE;
235 	}
236 
237 	if (zdrs->x_op == ZDR_DECODE) {
238 		*objp = zdr_malloc(zdrs, size);
239 		if (*objp == NULL) {
240 			return FALSE;
241 		}
242 		memset(*objp, 0, size);
243 	}
244 	return proc(zdrs, *objp);
245 }
246 
libnfs_zdr_opaque(ZDR * zdrs,char * objp,uint32_t size)247 bool_t libnfs_zdr_opaque(ZDR *zdrs, char *objp, uint32_t size)
248 {
249 	switch (zdrs->x_op) {
250 	case ZDR_ENCODE:
251 		memcpy(&zdrs->buf[zdrs->pos], objp, size);
252 		zdrs->pos += size;
253 		if (zdrs->pos & 3) {
254 			memset(&zdrs->buf[zdrs->pos], 0x00, 4 - (zdrs->pos & 3));
255 		}
256 		zdrs->pos = (zdrs->pos + 3) & ~3;
257 		return TRUE;
258 	case ZDR_DECODE:
259 		memcpy(objp, &zdrs->buf[zdrs->pos], size);
260 		zdrs->pos += size;
261 		zdrs->pos = (zdrs->pos + 3) & ~3;
262 		return TRUE;
263 	}
264 
265 	return FALSE;
266 }
267 
libnfs_zdr_string(ZDR * zdrs,char ** strp,uint32_t maxsize)268 bool_t libnfs_zdr_string(ZDR *zdrs, char **strp, uint32_t maxsize)
269 {
270 	uint32_t size;
271 
272 	if (zdrs->x_op == ZDR_ENCODE) {
273 		size = strlen(*strp);
274 	}
275 
276 	if (!libnfs_zdr_u_int(zdrs, &size)) {
277 		return FALSE;
278 	}
279 
280 	if (zdrs->pos + (int)size > zdrs->size) {
281 		return FALSE;
282 	}
283 
284 	switch (zdrs->x_op) {
285 	case ZDR_ENCODE:
286 		return libnfs_zdr_opaque(zdrs, *strp, size);
287 	case ZDR_DECODE:
288 		/* If the we string is null terminated we can just return it
289 		 * in place.
290 		 */
291 	  if (zdrs->size > zdrs->pos + (int)size && zdrs->buf[zdrs->pos + size] == 0) {
292 			if (*strp == NULL) {
293 				*strp = &zdrs->buf[zdrs->pos];
294                                 (*strp)[size] = 0;
295                                 zdrs->pos += size;
296                                 zdrs->pos = (zdrs->pos + 3) & ~3;
297                                 return TRUE;
298 			}
299 			(*strp)[size] = 0;
300 			return libnfs_zdr_opaque(zdrs, *strp, size);
301 		}
302 
303 		/* Crap. The string is not null terminated in the rx buffer.
304 		 * we have to allocate a buffer so we can add the null byte.
305 		 */
306 		*strp = zdr_malloc(zdrs, size + 1);
307 		if (*strp == NULL) {
308 			return FALSE;
309 		}
310 		(*strp)[size] = 0;
311 		return libnfs_zdr_opaque(zdrs, *strp, size);
312 	}
313 
314 	return FALSE;
315 }
316 
libnfs_zdr_array(ZDR * zdrs,char ** arrp,uint32_t * size,uint32_t maxsize,uint32_t elsize,zdrproc_t proc)317 bool_t libnfs_zdr_array(ZDR *zdrs, char **arrp, uint32_t *size, uint32_t maxsize, uint32_t elsize, zdrproc_t proc)
318 {
319 	int  i;
320 
321 	if (!libnfs_zdr_u_int(zdrs, size)) {
322 		return FALSE;
323 	}
324 
325 	if (zdrs->x_op == ZDR_DECODE) {
326 		*arrp = zdr_malloc(zdrs, *size * elsize);
327 		if (*arrp == NULL) {
328 			return FALSE;
329 		}
330 		memset(*arrp, 0, *size * elsize);
331 	}
332 
333 	for (i = 0; i < (int)*size; i++) {
334 		if (!proc(zdrs, *arrp + i * elsize)) {
335 			return FALSE;
336 		}
337 	}
338 	return TRUE;
339 }
340 
libnfs_zdr_free(zdrproc_t proc,char * objp)341 void libnfs_zdr_free(zdrproc_t proc, char *objp)
342 {
343 }
344 
libnfs_opaque_auth(ZDR * zdrs,struct opaque_auth * auth)345 static bool_t libnfs_opaque_auth(ZDR *zdrs, struct opaque_auth *auth)
346 {
347 	if (!libnfs_zdr_u_int(zdrs, &auth->oa_flavor)) {
348 		return FALSE;
349 	}
350 
351 	if (!libnfs_zdr_bytes(zdrs, &auth->oa_base, &auth->oa_length, auth->oa_length)) {
352 		return FALSE;
353 	}
354 
355 	return TRUE;
356 }
357 
libnfs_rpc_call_body(struct rpc_context * rpc,ZDR * zdrs,struct call_body * cmb)358 static bool_t libnfs_rpc_call_body(struct rpc_context *rpc, ZDR *zdrs, struct call_body *cmb)
359 {
360 	if (!libnfs_zdr_u_int(zdrs, &cmb->rpcvers)) {
361 		rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
362 			"RPCVERS");
363 		return FALSE;
364 	}
365 
366 	if (!libnfs_zdr_u_int(zdrs, &cmb->prog)) {
367 		rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
368 			"PROG");
369 		return FALSE;
370 	}
371 
372 	if (!libnfs_zdr_u_int(zdrs, &cmb->vers)) {
373 		rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
374 			"VERS");
375 		return FALSE;
376 	}
377 
378 	if (!libnfs_zdr_u_int(zdrs, &cmb->proc)) {
379 		rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
380 			"PROC");
381 		return FALSE;
382 	}
383 
384 	if (!libnfs_opaque_auth(zdrs, &cmb->cred)) {
385 		rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
386 			"CRED");
387 		return FALSE;
388 	}
389 
390 	if (!libnfs_opaque_auth(zdrs, &cmb->verf)) {
391 		rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
392 			"VERF");
393 		return FALSE;
394 	}
395 
396 	return TRUE;
397 }
398 
libnfs_accepted_reply(ZDR * zdrs,struct accepted_reply * ar)399 static bool_t libnfs_accepted_reply(ZDR *zdrs, struct accepted_reply *ar)
400 {
401 	if (!libnfs_opaque_auth(zdrs, &ar->verf)) {
402 		return FALSE;
403 	}
404 
405 	if (!libnfs_zdr_u_int(zdrs, &ar->stat)) {
406 		return FALSE;
407 	}
408 
409 	switch (ar->stat) {
410 	case SUCCESS:
411 		if (!ar->reply_data.results.proc(zdrs, ar->reply_data.results.where)) {
412 			return FALSE;
413 		}
414 		return TRUE;
415 	case PROG_MISMATCH:
416 		if (!libnfs_zdr_u_int(zdrs, &ar->reply_data.mismatch_info.low)) {
417 			return FALSE;
418 		}
419 		if (!libnfs_zdr_u_int(zdrs, &ar->reply_data.mismatch_info.high)) {
420 			return FALSE;
421 		}
422 		return TRUE;
423 	default:
424 		return TRUE;
425 	}
426 
427 	return FALSE;
428 }
429 
libnfs_rejected_reply(ZDR * zdrs,struct rejected_reply * rr)430 static bool_t libnfs_rejected_reply(ZDR *zdrs, struct rejected_reply *rr)
431 {
432 	if (!libnfs_zdr_u_int(zdrs, (uint32_t *)&rr->stat)) {
433 		return FALSE;
434 	}
435 
436 	switch (rr->stat) {
437 	case RPC_MISMATCH:
438 		if (!libnfs_zdr_u_int(zdrs, &rr->reject_data.mismatch_info.low)) {
439 			return FALSE;
440 		}
441 		if (!libnfs_zdr_u_int(zdrs, &rr->reject_data.mismatch_info.high)) {
442 			return FALSE;
443 		}
444 		return TRUE;
445 	case AUTH_ERROR:
446 	  if (!libnfs_zdr_u_int(zdrs, (uint32_t *)&rr->reject_data.stat)) {
447 			return FALSE;
448 		}
449 		return TRUE;
450 	default:
451 		return TRUE;
452 	}
453 
454 	return FALSE;
455 }
456 
libnfs_rpc_reply_body(struct rpc_context * rpc,ZDR * zdrs,struct reply_body * rmb)457 static bool_t libnfs_rpc_reply_body(struct rpc_context *rpc, ZDR *zdrs, struct reply_body *rmb)
458 {
459 	if (!libnfs_zdr_u_int(zdrs, &rmb->stat)) {
460 		rpc_set_error(rpc, "libnfs_rpc_reply_body failed to decode "
461 			"STAT");
462 		return FALSE;
463 	}
464 
465 	switch (rmb->stat) {
466 	case MSG_ACCEPTED:
467 		if (!libnfs_accepted_reply(zdrs, &rmb->reply.areply)) {
468 			rpc_set_error(rpc, "libnfs_rpc_reply_body failed to "
469 				"decode ACCEPTED");
470 			return FALSE;
471 		}
472 		return TRUE;
473 	case MSG_DENIED:
474 		if (!libnfs_rejected_reply(zdrs, &rmb->reply.rreply)) {
475 			rpc_set_error(rpc, "libnfs_rpc_reply_body failed to "
476 				"decode DENIED");
477 			return FALSE;
478 		}
479 		return TRUE;
480 	}
481 
482 	rpc_set_error(rpc, "libnfs_rpc_reply_body failed to "
483 		"decode. Neither ACCEPTED nor DENIED");
484 	return FALSE;
485 }
486 
libnfs_rpc_msg(struct rpc_context * rpc,ZDR * zdrs,struct rpc_msg * msg)487 static bool_t libnfs_rpc_msg(struct rpc_context *rpc, ZDR *zdrs, struct rpc_msg *msg)
488 {
489 	int ret;
490 
491 	if (!libnfs_zdr_u_int(zdrs, &msg->xid)) {
492 		rpc_set_error(rpc, "libnfs_rpc_msg failed to decode XID");
493 		return FALSE;
494 	}
495 
496 	if (!libnfs_zdr_u_int(zdrs, &msg->direction)) {
497 		rpc_set_error(rpc, "libnfs_rpc_msg failed to decode DIRECTION");
498 		return FALSE;
499 	}
500 
501 	switch (msg->direction) {
502 	case CALL:
503 		ret = libnfs_rpc_call_body(rpc, zdrs, &msg->body.cbody);
504 		if (!ret) {
505 			rpc_set_error(rpc, "libnfs_rpc_msg failed to encode "
506 				"CALL, ret=%d: %s", ret, rpc_get_error(rpc));
507 		}
508 		return ret;
509 	case REPLY:
510 		ret = libnfs_rpc_reply_body(rpc, zdrs, &msg->body.rbody);
511 		if (!ret) {
512 			rpc_set_error(rpc, "libnfs_rpc_msg failed to decode "
513 				"REPLY, ret=%d: %s", ret, rpc_get_error(rpc));
514 		}
515 		return ret;
516 	default:
517 		rpc_set_error(rpc, "libnfs_rpc_msg failed to decode. "
518 			"Neither CALL not REPLY");
519 		return FALSE;
520 	}
521 }
522 
libnfs_zdr_callmsg(struct rpc_context * rpc,ZDR * zdrs,struct rpc_msg * msg)523 bool_t libnfs_zdr_callmsg(struct rpc_context *rpc, ZDR *zdrs, struct rpc_msg *msg)
524 {
525 	return libnfs_rpc_msg(rpc, zdrs, msg);
526 }
527 
libnfs_zdr_replymsg(struct rpc_context * rpc,ZDR * zdrs,struct rpc_msg * msg)528 bool_t libnfs_zdr_replymsg(struct rpc_context *rpc, ZDR *zdrs, struct rpc_msg *msg)
529 {
530 	return libnfs_rpc_msg(rpc, zdrs, msg);
531 }
532 
authnone_create(void)533 struct AUTH *authnone_create(void)
534 {
535 	struct AUTH *auth;
536 
537 	auth = malloc(sizeof(struct AUTH));
538 
539 	auth->ah_cred.oa_flavor = AUTH_NONE;
540 	auth->ah_cred.oa_length = 0;
541 	auth->ah_cred.oa_base = NULL;
542 
543 	auth->ah_verf.oa_flavor = AUTH_NONE;
544 	auth->ah_verf.oa_length = 0;
545 	auth->ah_verf.oa_base = NULL;
546 
547 	auth->ah_private = NULL;
548 
549 	return auth;
550 }
551 
libnfs_authunix_create(const char * host,uint32_t uid,uint32_t gid,uint32_t len,uint32_t * groups)552 struct AUTH *libnfs_authunix_create(const char *host, uint32_t uid, uint32_t gid, uint32_t len, uint32_t *groups)
553 {
554 	struct AUTH *auth;
555 	int size;
556 	uint32_t *buf;
557 	int idx;
558 
559 	size = 4 + 4 + ((strlen(host) + 3) & ~3) + 4 + 4 + 4 + len * 4;
560 	auth = malloc(sizeof(struct AUTH));
561 	memset(auth, 0x00, sizeof(struct AUTH));
562 	auth->ah_cred.oa_flavor = AUTH_UNIX;
563 	auth->ah_cred.oa_length = size;
564 	auth->ah_cred.oa_base = malloc(size);
565 
566 	memset(auth->ah_cred.oa_base, 0x00, size);
567 	buf = (uint32_t *)(void *)auth->ah_cred.oa_base;
568 	idx = 0;
569 	buf[idx++] = htonl((uint32_t)rpc_current_time());
570 	buf[idx++] = htonl(strlen(host));
571 	memcpy(&buf[2], host, strlen(host));
572 
573 	idx += (strlen(host) + 3) >> 2;
574 	buf[idx++] = htonl(uid);
575 	buf[idx++] = htonl(gid);
576 	buf[idx++] = htonl(len);
577 	while (len-- > 0) {
578 		buf[idx++] = htonl(*groups++);
579 	}
580 
581 	auth->ah_verf.oa_flavor = AUTH_NONE;
582 	auth->ah_verf.oa_length = 0;
583 	auth->ah_verf.oa_base = NULL;
584 
585 	auth->ah_private = NULL;
586 
587 	return auth;
588 }
589 
libnfs_authunix_create_default(void)590 struct AUTH *libnfs_authunix_create_default(void)
591 {
592 #ifdef WIN32
593 	return libnfs_authunix_create("libnfs", 65534, 65534, 0, NULL);
594 #else
595 	return libnfs_authunix_create("libnfs", getuid(), getgid(), 0, NULL);
596 #endif
597 }
598 
libnfs_auth_destroy(struct AUTH * auth)599 void libnfs_auth_destroy(struct AUTH *auth)
600 {
601 	if (auth->ah_cred.oa_base) {
602 		free(auth->ah_cred.oa_base);
603 	}
604 	if (auth->ah_verf.oa_base) {
605 		free(auth->ah_verf.oa_base);
606 	}
607 	free(auth);
608 }
609 
610