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