Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/lib/rpc/xdr.c
39536 views
1
/* @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC */
2
/*
3
* Copyright (c) 2010, Oracle America, Inc.
4
*
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions are met:
9
*
10
* * Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
*
13
* * Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in
15
* the documentation and/or other materials provided with the
16
* distribution.
17
*
18
* * Neither the name of the "Oracle America, Inc." nor the names of
19
* its contributors may be used to endorse or promote products
20
* derived from this software without specific prior written permission.
21
*
22
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
23
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
28
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
*/
34
#if !defined(lint) && defined(SCCSIDS)
35
static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
36
#endif
37
38
/*
39
* xdr.c, Generic XDR routines implementation.
40
*
41
* These are the "generic" xdr routines used to serialize and de-serialize
42
* most common data items. See xdr.h for more info on the interface to
43
* xdr.
44
*/
45
46
#include <stdio.h>
47
#include <string.h>
48
49
#include <gssrpc/types.h>
50
#include <gssrpc/xdr.h>
51
52
/*
53
* constants specific to the xdr "protocol"
54
*/
55
#define XDR_FALSE ((long) 0)
56
#define XDR_TRUE ((long) 1)
57
#define LASTUNSIGNED ((u_int) 0-1)
58
59
#ifdef USE_VALGRIND
60
#include <valgrind/memcheck.h>
61
#else
62
#define VALGRIND_CHECK_DEFINED(LVALUE) ((void)0)
63
#define VALGRIND_CHECK_READABLE(PTR,SIZE) ((void)0)
64
#endif
65
66
/*
67
* for unit alignment
68
*/
69
static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
70
71
/*
72
* Free a data structure using XDR
73
* Not a filter, but a convenient utility nonetheless
74
*/
75
void
76
xdr_free(xdrproc_t proc, void *objp)
77
{
78
XDR x;
79
80
x.x_op = XDR_FREE;
81
(*proc)(&x, objp);
82
}
83
84
/*
85
* XDR nothing
86
*/
87
bool_t
88
xdr_void(XDR *xdrs, void *addr)
89
{
90
91
return (TRUE);
92
}
93
94
/*
95
* XDR integers
96
*/
97
bool_t
98
xdr_int(XDR *xdrs, int *ip)
99
{
100
long l;
101
102
switch (xdrs->x_op) {
103
104
case XDR_ENCODE:
105
VALGRIND_CHECK_DEFINED(*ip);
106
if (*ip > 0x7fffffffL || *ip < -0x7fffffffL - 1L)
107
return (FALSE);
108
109
l = (long) *ip;
110
return (XDR_PUTLONG(xdrs, &l));
111
112
case XDR_DECODE:
113
if (!XDR_GETLONG(xdrs, &l))
114
return (FALSE);
115
116
if (l > INT_MAX || l < INT_MIN)
117
return (FALSE);
118
119
*ip = (int) l;
120
121
case XDR_FREE:
122
return (TRUE);
123
}
124
/*NOTREACHED*/
125
return(FALSE);
126
}
127
128
/*
129
* XDR unsigned integers
130
*/
131
bool_t
132
xdr_u_int(XDR *xdrs, u_int *up)
133
{
134
u_long l;
135
136
switch (xdrs->x_op) {
137
138
case XDR_ENCODE:
139
VALGRIND_CHECK_DEFINED(*up);
140
if (*up > 0xffffffffUL)
141
return (FALSE);
142
143
l = (u_long)*up;
144
return (XDR_PUTLONG(xdrs, (long *) &l));
145
146
case XDR_DECODE:
147
if (!XDR_GETLONG(xdrs, (long *) &l))
148
return (FALSE);
149
150
if ((uint32_t)l > UINT_MAX)
151
return (FALSE);
152
153
*up = (u_int) l;
154
return (TRUE);
155
156
case XDR_FREE:
157
return (TRUE);
158
}
159
/*NOTREACHED*/
160
return(FALSE);
161
}
162
163
/*
164
* XDR long integers
165
*/
166
bool_t
167
xdr_long(XDR *xdrs, long *lp)
168
{
169
170
switch (xdrs->x_op) {
171
case XDR_ENCODE:
172
VALGRIND_CHECK_DEFINED(*lp);
173
if (*lp > 0x7fffffffL || *lp < -0x7fffffffL - 1L)
174
return (FALSE);
175
176
return (XDR_PUTLONG(xdrs, lp));
177
178
case XDR_DECODE:
179
return (XDR_GETLONG(xdrs, lp));
180
181
case XDR_FREE:
182
return (TRUE);
183
}
184
return (FALSE);
185
}
186
187
/*
188
* XDR unsigned long integers
189
*/
190
bool_t
191
xdr_u_long(XDR *xdrs, u_long *ulp)
192
{
193
194
switch (xdrs->x_op) {
195
case XDR_ENCODE:
196
VALGRIND_CHECK_DEFINED(*ulp);
197
if (*ulp > 0xffffffffUL)
198
return (FALSE);
199
200
return (XDR_PUTLONG(xdrs, (long *) ulp));
201
202
case XDR_DECODE:
203
return (XDR_GETLONG(xdrs, (long *) ulp));
204
205
case XDR_FREE:
206
return (TRUE);
207
}
208
return (FALSE);
209
}
210
211
/*
212
* XDR short integers
213
*/
214
bool_t
215
xdr_short(XDR *xdrs, short *sp)
216
{
217
long l;
218
219
switch (xdrs->x_op) {
220
221
case XDR_ENCODE:
222
VALGRIND_CHECK_DEFINED(*sp);
223
l = (long) *sp;
224
return (XDR_PUTLONG(xdrs, &l));
225
226
case XDR_DECODE:
227
if (!XDR_GETLONG(xdrs, &l)) {
228
return (FALSE);
229
}
230
if (l > SHRT_MAX || l < SHRT_MIN)
231
return (FALSE);
232
233
*sp = (short) l;
234
return (TRUE);
235
236
case XDR_FREE:
237
return (TRUE);
238
}
239
return (FALSE);
240
}
241
242
/*
243
* XDR unsigned short integers
244
*/
245
bool_t
246
xdr_u_short(XDR *xdrs, u_short *usp)
247
{
248
u_long l;
249
250
switch (xdrs->x_op) {
251
252
case XDR_ENCODE:
253
VALGRIND_CHECK_DEFINED(*usp);
254
l = (u_long) *usp;
255
return (XDR_PUTLONG(xdrs, (long *) &l));
256
257
case XDR_DECODE:
258
if (!XDR_GETLONG(xdrs, (long *) &l)) {
259
return (FALSE);
260
}
261
*usp = (u_short) l;
262
return (TRUE);
263
264
case XDR_FREE:
265
return (TRUE);
266
}
267
return (FALSE);
268
}
269
270
271
/*
272
* XDR a char
273
*/
274
bool_t
275
xdr_char(XDR *xdrs, char *cp)
276
{
277
int i;
278
279
switch (xdrs->x_op) {
280
case XDR_ENCODE:
281
VALGRIND_CHECK_DEFINED(*cp);
282
break;
283
default:
284
break;
285
}
286
i = (*cp);
287
if (!xdr_int(xdrs, &i)) {
288
return (FALSE);
289
}
290
*cp = i;
291
return (TRUE);
292
}
293
294
/*
295
* XDR an unsigned char
296
*/
297
bool_t
298
xdr_u_char(XDR *xdrs, u_char *cp)
299
{
300
u_int u;
301
302
switch (xdrs->x_op) {
303
case XDR_ENCODE:
304
VALGRIND_CHECK_DEFINED(*cp);
305
break;
306
default:
307
break;
308
}
309
u = (*cp);
310
if (!xdr_u_int(xdrs, &u)) {
311
return (FALSE);
312
}
313
*cp = u;
314
return (TRUE);
315
}
316
317
/*
318
* XDR booleans
319
*/
320
bool_t
321
xdr_bool(XDR *xdrs, bool_t *bp)
322
{
323
long lb;
324
325
switch (xdrs->x_op) {
326
327
case XDR_ENCODE:
328
VALGRIND_CHECK_DEFINED(*bp);
329
lb = *bp ? XDR_TRUE : XDR_FALSE;
330
return (XDR_PUTLONG(xdrs, &lb));
331
332
case XDR_DECODE:
333
if (!XDR_GETLONG(xdrs, &lb)) {
334
return (FALSE);
335
}
336
*bp = (lb == XDR_FALSE) ? FALSE : TRUE;
337
return (TRUE);
338
339
case XDR_FREE:
340
return (TRUE);
341
}
342
return (FALSE);
343
}
344
345
/*
346
* XDR enumerations
347
*/
348
bool_t
349
xdr_enum(XDR *xdrs, enum_t *ep)
350
{
351
#ifndef lint
352
enum sizecheck { SIZEVAL }; /* used to find the size of an enum */
353
354
/*
355
* enums are treated as ints
356
*/
357
switch (xdrs->x_op) {
358
case XDR_ENCODE:
359
VALGRIND_CHECK_DEFINED(*ep);
360
break;
361
default:
362
break;
363
}
364
if (sizeof (enum sizecheck) == sizeof (long)) {
365
return (xdr_long(xdrs, (long *)(void *)ep));
366
} else if (sizeof (enum sizecheck) == sizeof (int)) {
367
return (xdr_int(xdrs, (int *)(void *)ep));
368
} else if (sizeof (enum sizecheck) == sizeof (short)) {
369
return (xdr_short(xdrs, (short *)(void *)ep));
370
} else {
371
return (FALSE);
372
}
373
#else
374
(void) (xdr_short(xdrs, (short *)(void *)ep));
375
return (xdr_long(xdrs, (long *)(void *)ep));
376
#endif
377
}
378
379
/*
380
* XDR opaque data
381
* Allows the specification of a fixed size sequence of opaque bytes.
382
* cp points to the opaque object and cnt gives the byte length.
383
*/
384
bool_t
385
xdr_opaque(XDR *xdrs, caddr_t cp, u_int cnt)
386
{
387
u_int rndup;
388
static int crud[BYTES_PER_XDR_UNIT];
389
390
/*
391
* if no data we are done
392
*/
393
if (cnt == 0)
394
return (TRUE);
395
396
/*
397
* round byte count to full xdr units
398
*/
399
rndup = cnt % BYTES_PER_XDR_UNIT;
400
if (rndup > 0)
401
rndup = BYTES_PER_XDR_UNIT - rndup;
402
403
if (xdrs->x_op == XDR_DECODE) {
404
if (!XDR_GETBYTES(xdrs, cp, cnt)) {
405
return (FALSE);
406
}
407
if (rndup == 0)
408
return (TRUE);
409
return (XDR_GETBYTES(xdrs, (caddr_t) (void *)crud, rndup));
410
}
411
412
if (xdrs->x_op == XDR_ENCODE) {
413
VALGRIND_CHECK_READABLE((volatile void *)cp, cnt);
414
if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
415
return (FALSE);
416
}
417
if (rndup == 0)
418
return (TRUE);
419
return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
420
}
421
422
if (xdrs->x_op == XDR_FREE) {
423
return (TRUE);
424
}
425
426
return (FALSE);
427
}
428
429
/*
430
* XDR counted bytes
431
* *cpp is a pointer to the bytes, *sizep is the count.
432
* If *cpp is NULL maxsize bytes are allocated
433
*/
434
bool_t
435
xdr_bytes(
436
XDR *xdrs,
437
char **cpp,
438
u_int *sizep,
439
u_int maxsize)
440
{
441
char *sp = *cpp; /* sp is the actual string pointer */
442
u_int nodesize;
443
444
/*
445
* first deal with the length since xdr bytes are counted
446
*/
447
if (! xdr_u_int(xdrs, sizep)) {
448
return (FALSE);
449
}
450
nodesize = *sizep;
451
if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
452
return (FALSE);
453
}
454
455
/*
456
* now deal with the actual bytes
457
*/
458
switch (xdrs->x_op) {
459
460
case XDR_DECODE:
461
if (nodesize == 0) {
462
return (TRUE);
463
}
464
if (sp == NULL) {
465
*cpp = sp = (char *)mem_alloc(nodesize);
466
}
467
if (sp == NULL) {
468
(void) fprintf(stderr, "xdr_bytes: out of memory\n");
469
return (FALSE);
470
}
471
/* fall into ... */
472
473
case XDR_ENCODE:
474
return (xdr_opaque(xdrs, sp, nodesize));
475
476
case XDR_FREE:
477
if (sp != NULL) {
478
mem_free(sp, nodesize);
479
*cpp = NULL;
480
}
481
return (TRUE);
482
}
483
return (FALSE);
484
}
485
486
/*
487
* Implemented here due to commonality of the object.
488
*/
489
bool_t
490
xdr_netobj(XDR *xdrs, struct netobj *np)
491
{
492
493
return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
494
}
495
496
bool_t
497
xdr_int32(XDR *xdrs, int32_t *ip)
498
{
499
long l;
500
501
switch (xdrs->x_op) {
502
503
case XDR_ENCODE:
504
VALGRIND_CHECK_DEFINED(*ip);
505
l = *ip;
506
return (xdr_long(xdrs, &l));
507
508
case XDR_DECODE:
509
if (!xdr_long(xdrs, &l)) {
510
return (FALSE);
511
}
512
*ip = l;
513
return (TRUE);
514
515
case XDR_FREE:
516
return (TRUE);
517
}
518
return (FALSE);
519
}
520
521
bool_t
522
xdr_u_int32(XDR *xdrs, uint32_t *up)
523
{
524
u_long ul;
525
526
switch (xdrs->x_op) {
527
528
case XDR_ENCODE:
529
VALGRIND_CHECK_DEFINED(*up);
530
ul = *up;
531
return (xdr_u_long(xdrs, &ul));
532
533
case XDR_DECODE:
534
if (!xdr_u_long(xdrs, &ul)) {
535
return (FALSE);
536
}
537
*up = ul;
538
return (TRUE);
539
540
case XDR_FREE:
541
return (TRUE);
542
}
543
return (FALSE);
544
}
545
546
/*
547
* XDR a discriminated union
548
* Support routine for discriminated unions.
549
* You create an array of xdrdiscrim structures, terminated with
550
* an entry with a null procedure pointer. The routine gets
551
* the discriminant value and then searches the array of xdrdiscrims
552
* looking for that value. It calls the procedure given in the xdrdiscrim
553
* to handle the discriminant. If there is no specific routine a default
554
* routine may be called.
555
* If there is no specific or default routine an error is returned.
556
*/
557
bool_t
558
xdr_union(
559
XDR *xdrs,
560
enum_t *dscmp, /* enum to decide which arm to work on */
561
char *unp, /* the union itself */
562
struct xdr_discrim *choices, /* [value, xdr proc] for each arm */
563
xdrproc_t dfault /* default xdr routine */
564
)
565
{
566
enum_t dscm;
567
568
/*
569
* we deal with the discriminator; it's an enum
570
*/
571
if (! xdr_enum(xdrs, dscmp)) {
572
return (FALSE);
573
}
574
dscm = *dscmp;
575
576
/*
577
* search choices for a value that matches the discriminator.
578
* if we find one, execute the xdr routine for that value.
579
*/
580
for (; choices->proc != NULL_xdrproc_t; choices++) {
581
if (choices->value == dscm)
582
return choices->proc(xdrs, unp);
583
}
584
585
/*
586
* no match - execute the default xdr routine if there is one
587
*/
588
return ((dfault == NULL_xdrproc_t) ? FALSE :
589
(*dfault)(xdrs, unp));
590
}
591
592
593
/*
594
* Non-portable xdr primitives.
595
* Care should be taken when moving these routines to new architectures.
596
*/
597
598
599
/*
600
* XDR null terminated ASCII strings
601
* xdr_string deals with "C strings" - arrays of bytes that are
602
* terminated by a NULL character. The parameter cpp references a
603
* pointer to storage; If the pointer is null, then the necessary
604
* storage is allocated. The last parameter is the max allowed length
605
* of the string as specified by a protocol.
606
*/
607
bool_t
608
xdr_string(XDR *xdrs, char **cpp, u_int maxsize)
609
{
610
char *sp = *cpp; /* sp is the actual string pointer */
611
u_int size;
612
u_int nodesize;
613
614
/*
615
* first deal with the length since xdr strings are counted-strings
616
*/
617
switch (xdrs->x_op) {
618
case XDR_FREE:
619
if (sp == NULL) {
620
return(TRUE); /* already free */
621
}
622
/* fall through... */
623
case XDR_ENCODE:
624
size = strlen(sp);
625
break;
626
case XDR_DECODE:
627
break;
628
}
629
if (! xdr_u_int(xdrs, &size)) {
630
return (FALSE);
631
}
632
if (size >= maxsize) {
633
return (FALSE);
634
}
635
nodesize = size + 1;
636
637
/*
638
* now deal with the actual bytes
639
*/
640
switch (xdrs->x_op) {
641
642
case XDR_DECODE:
643
if (nodesize == 0) {
644
return (TRUE);
645
}
646
if (sp == NULL)
647
*cpp = sp = (char *)mem_alloc(nodesize);
648
if (sp == NULL) {
649
(void) fprintf(stderr, "xdr_string: out of memory\n");
650
return (FALSE);
651
}
652
sp[size] = 0;
653
/* fall into ... */
654
655
case XDR_ENCODE:
656
return (xdr_opaque(xdrs, sp, size));
657
658
case XDR_FREE:
659
mem_free(sp, nodesize);
660
*cpp = NULL;
661
return (TRUE);
662
}
663
return (FALSE);
664
}
665
666
/*
667
* Wrapper for xdr_string that can be called directly from
668
* routines like clnt_call
669
*/
670
bool_t
671
xdr_wrapstring(XDR *xdrs, char **cpp)
672
{
673
if (xdr_string(xdrs, cpp, LASTUNSIGNED)) {
674
return (TRUE);
675
}
676
return (FALSE);
677
}
678
679