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