1/*
2 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3 * Use is subject to license terms.
4 */
5
6
7/*
8 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
9 *
10 *	Openvision retains the copyright to derivative works of
11 *	this source code.  Do *NOT* create a derivative of this
12 *	source code before consulting with your legal department.
13 *	Do *NOT* integrate *ANY* of this source code into another
14 *	product before consulting with your legal department.
15 *
16 *	For further information, read the top-level Openvision
17 *	copyright which is contained in the top-level MIT Kerberos
18 *	copyright.
19 *
20 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
21 *
22 */
23
24
25/*
26 * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
27 */
28
29#include <rpc/rpc.h>
30#include <errno.h>
31#include <kadm5/admin.h>
32#include <kadm5/kadm_rpc.h>
33#include <krb5.h>
34#include <stdlib.h>
35#include <string.h>
36
37static bool_t
38_xdr_kadm5_principal_ent_rec(XDR *xdrs, kadm5_principal_ent_rec *objp,
39			     int v);
40
41bool_t
42xdr_krb5_salttype(XDR *xdrs, krb5_int32 *objp); /* SUNWresync121 XXX */
43/*
44 * Function: xdr_ui_4
45 *
46 * Purpose: XDR function which serves as a wrapper for xdr_u_int,
47 * to prevent compiler warnings about type clashes between u_int32
48 * and krb5_ui_4.
49 */
50bool_t xdr_ui_4(XDR *xdrs, krb5_ui_4 *objp)
51{
52  /* Assumes that krb5_ui_4 and u_int32 are both four bytes long.
53     This should not be a harmful assumption. */
54  return xdr_u_int(xdrs, (uint32_t *) objp);
55}
56
57
58/*
59 * Function: xdr_nullstring
60 *
61 * Purpose: XDR function for "strings" that are either NULL-terminated
62 * or NULL.
63 */
64bool_t xdr_nullstring(XDR *xdrs, char **objp)
65{
66     u_int size;
67
68     if (xdrs->x_op == XDR_ENCODE) {
69	  if (*objp == NULL)
70	       size = 0;
71	  else
72	       size = strlen(*objp) + 1;
73     }
74     if (! xdr_u_int(xdrs, &size)) {
75	  return FALSE;
76	}
77     switch (xdrs->x_op) {
78     case XDR_DECODE:
79	  if (size == 0) {
80	       *objp = NULL;
81	       return TRUE;
82	  } else if (*objp == NULL) {
83	       *objp = (char *) mem_alloc(size);
84	       if (*objp == NULL) {
85		    errno = ENOMEM;
86		    return FALSE;
87	       }
88	  }
89	  return (xdr_opaque(xdrs, *objp, size));
90
91     case XDR_ENCODE:
92	  if (size != 0)
93	       return (xdr_opaque(xdrs, *objp, size));
94	  return TRUE;
95
96     case XDR_FREE:
97	  if (*objp != NULL)
98	       mem_free(*objp, size);
99	  *objp = NULL;
100	  return TRUE;
101     }
102
103     return FALSE;
104}
105
106/*
107 * Function: xdr_nulltype
108 *
109 * Purpose: XDR function for arbitrary pointer types that are either
110 * NULL or contain data.
111 */
112bool_t xdr_nulltype(XDR *xdrs, void **objp, xdrproc_t proc)
113{
114     bool_t null;
115
116     switch (xdrs->x_op) {
117     case XDR_DECODE:
118	  if (!xdr_bool(xdrs, &null))
119	      return FALSE;
120	  if (null) {
121	       *objp = NULL;
122	       return TRUE;
123	  }
124	  return (*proc)(xdrs, objp);
125
126     case XDR_ENCODE:
127	  if (*objp == NULL)
128	       null = TRUE;
129	  else
130	       null = FALSE;
131	  if (!xdr_bool(xdrs, &null))
132	       return FALSE;
133	  if (null == FALSE)
134	       return (*proc)(xdrs, objp);
135	  return TRUE;
136
137     case XDR_FREE:
138	  if (*objp)
139	       return (*proc)(xdrs, objp);
140	  return TRUE;
141     }
142
143     return FALSE;
144}
145
146bool_t
147xdr_krb5_timestamp(XDR *xdrs, krb5_timestamp *objp)
148{
149  /* This assumes that int32 and krb5_timestamp are the same size.
150     This shouldn't be a problem, since we've got a unit test which
151     checks for this. */
152	if (!xdr_int(xdrs, (int32_t *) objp)) {
153		return (FALSE);
154	}
155	return (TRUE);
156}
157
158bool_t
159xdr_krb5_kvno(XDR *xdrs, krb5_kvno *objp)
160{
161	unsigned char tmp;
162
163	tmp = '\0'; /* for purify, else xdr_u_char performs a umr */
164
165	if (xdrs->x_op == XDR_ENCODE)
166		tmp = (unsigned char) *objp;
167
168	if (!xdr_u_char(xdrs, &tmp))
169		return (FALSE);
170
171	if (xdrs->x_op == XDR_DECODE)
172		*objp = (krb5_kvno) tmp;
173
174	return (TRUE);
175}
176
177bool_t
178xdr_krb5_deltat(XDR *xdrs, krb5_deltat *objp)
179{
180  /* This assumes that int32 and krb5_deltat are the same size.
181     This shouldn't be a problem, since we've got a unit test which
182     checks for this. */
183	if (!xdr_int(xdrs, (int32_t *) objp)) {
184		return (FALSE);
185	}
186	return (TRUE);
187}
188
189bool_t
190xdr_krb5_flags(XDR *xdrs, krb5_flags *objp)
191{
192  /* This assumes that int32 and krb5_flags are the same size.
193     This shouldn't be a problem, since we've got a unit test which
194     checks for this. */
195	if (!xdr_int(xdrs, (int32_t *) objp)) {
196		return (FALSE);
197	}
198	return (TRUE);
199}
200
201bool_t
202xdr_krb5_ui_4(XDR *xdrs, krb5_ui_4 *objp)
203{
204	if (!xdr_u_int(xdrs, (uint32_t *) objp)) {
205		return (FALSE);
206	}
207	return (TRUE);
208}
209
210bool_t
211xdr_krb5_int16(XDR *xdrs, krb5_int16 *objp)
212{
213    int tmp;
214
215    tmp = (int) *objp;
216
217    if (!xdr_int(xdrs, &tmp))
218	return(FALSE);
219
220    *objp = (krb5_int16) tmp;
221
222    return(TRUE);
223}
224
225/*
226 * Function: xdr_krb5_ui_2
227 *
228 * Purpose: XDR function which serves as a wrapper for xdr_u_int,
229 * to prevent compiler warnings about type clashes between u_int
230 * and krb5_ui_2.
231 */
232bool_t
233xdr_krb5_ui_2(XDR *xdrs, krb5_ui_2 *objp)
234{
235    unsigned int tmp;
236
237    tmp = (unsigned int) *objp;
238
239    if (!xdr_u_int(xdrs, &tmp))
240	return(FALSE);
241
242    *objp = (krb5_ui_2) tmp;
243
244    return(TRUE);
245}
246
247
248
249bool_t xdr_krb5_key_data_nocontents(XDR *xdrs, krb5_key_data *objp)
250{
251     /*
252      * Note that this function intentionally DOES NOT tranfer key
253      * length or contents!  xdr_krb5_key_data in adb_xdr.c does, but
254      * that is only for use within the server-side library.
255      */
256     unsigned int tmp;
257
258     if (xdrs->x_op == XDR_DECODE)
259	  memset((char *) objp, 0, sizeof(krb5_key_data));
260
261     if (!xdr_krb5_int16(xdrs, &objp->key_data_ver)) {
262	  return (FALSE);
263     }
264     if (!xdr_krb5_int16(xdrs, &objp->key_data_kvno)) {
265	  return (FALSE);
266     }
267     if (!xdr_krb5_int16(xdrs, &objp->key_data_type[0])) {
268	  return (FALSE);
269     }
270     if (objp->key_data_ver > 1) {
271	  if (!xdr_krb5_int16(xdrs, &objp->key_data_type[1])) {
272	       return (FALSE);
273	  }
274     }
275     /*
276      * kadm5_get_principal on the server side allocates and returns
277      * key contents when asked.  Even though this function refuses to
278      * transmit that data, it still has to *free* the data at the
279      * appropriate time to avoid a memory leak.
280      */
281     if (xdrs->x_op == XDR_FREE) {
282	  tmp = (unsigned int) objp->key_data_length[0];
283	  if (!xdr_bytes(xdrs, (char **) &objp->key_data_contents[0],
284			 &tmp, ~0))
285	       return FALSE;
286
287	  tmp = (unsigned int) objp->key_data_length[1];
288	  if (!xdr_bytes(xdrs, (char **) &objp->key_data_contents[1],
289			 &tmp, ~0))
290	       return FALSE;
291     }
292
293     return (TRUE);
294}
295
296
297bool_t
298xdr_krb5_key_salt_tuple(XDR *xdrs, krb5_key_salt_tuple *objp)
299{
300    if (!xdr_krb5_enctype(xdrs, &objp->ks_enctype))
301	return FALSE;
302    if (!xdr_krb5_salttype(xdrs, &objp->ks_salttype))
303	return FALSE;
304    return TRUE;
305}
306
307bool_t xdr_krb5_tl_data(XDR *xdrs, krb5_tl_data **tl_data_head)
308{
309     krb5_tl_data *tl, *tl2;
310     bool_t more;
311     unsigned int len;
312
313     switch (xdrs->x_op) {
314     case XDR_FREE:
315	  tl = tl2 = *tl_data_head;
316	  while (tl) {
317	       tl2 = tl->tl_data_next;
318	       free(tl->tl_data_contents);
319	       free(tl);
320	       tl = tl2;
321	  }
322	  break;
323
324     case XDR_ENCODE:
325	  tl = *tl_data_head;
326	  while (1) {
327	       more = (tl != NULL);
328	       if (!xdr_bool(xdrs, &more))
329		    return FALSE;
330	       if (tl == NULL)
331		    break;
332	       if (!xdr_krb5_int16(xdrs, &tl->tl_data_type))
333		    return FALSE;
334	       len = tl->tl_data_length;
335	       if (!xdr_bytes(xdrs, (char **) &tl->tl_data_contents, &len, ~0))
336		    return FALSE;
337	       tl = tl->tl_data_next;
338	  }
339	  break;
340
341     case XDR_DECODE:
342	  tl = NULL;
343	  while (1) {
344	       if (!xdr_bool(xdrs, &more))
345		    return FALSE;
346	       if (more == FALSE)
347		    break;
348	       tl2 = (krb5_tl_data *) malloc(sizeof(krb5_tl_data));
349	       if (tl2 == NULL)
350		    return FALSE;
351	       memset((char *) tl2, 0, sizeof(krb5_tl_data));
352	       if (!xdr_krb5_int16(xdrs, &tl2->tl_data_type))
353		    return FALSE;
354	       if (!xdr_bytes(xdrs, (char **)&tl2->tl_data_contents, &len, ~0))
355		    return FALSE;
356	       tl2->tl_data_length = len;
357
358	       tl2->tl_data_next = tl;
359	       tl = tl2;
360	  }
361
362	  *tl_data_head = tl;
363	  break;
364     }
365
366     return TRUE;
367}
368
369bool_t
370xdr_kadm5_ret_t(XDR *xdrs, kadm5_ret_t *objp)
371{
372	uint32_t tmp;
373
374	if (xdrs->x_op == XDR_ENCODE)
375		tmp = (uint32_t) *objp;
376
377	if (!xdr_u_int(xdrs, &tmp))
378		return (FALSE);
379
380	if (xdrs->x_op == XDR_DECODE)
381		*objp = (kadm5_ret_t) tmp;
382
383	return (TRUE);
384}
385
386bool_t xdr_kadm5_principal_ent_rec_v1(XDR *xdrs,
387				      kadm5_principal_ent_rec *objp)
388{
389     return _xdr_kadm5_principal_ent_rec(xdrs, objp, KADM5_API_VERSION_1);
390}
391
392bool_t xdr_kadm5_principal_ent_rec(XDR *xdrs,
393				   kadm5_principal_ent_rec *objp)
394{
395     return _xdr_kadm5_principal_ent_rec(xdrs, objp, KADM5_API_VERSION_2);
396}
397
398static bool_t
399_xdr_kadm5_principal_ent_rec(XDR *xdrs, kadm5_principal_ent_rec *objp,
400			     int v)
401{
402     unsigned int n;
403
404	if (!xdr_krb5_principal(xdrs, &objp->principal)) {
405		return (FALSE);
406	}
407	if (!xdr_krb5_timestamp(xdrs, &objp->princ_expire_time)) {
408		return (FALSE);
409	}
410	if (!xdr_krb5_timestamp(xdrs, &objp->last_pwd_change)) {
411		return (FALSE);
412	}
413	if (!xdr_krb5_timestamp(xdrs, &objp->pw_expiration)) {
414		return (FALSE);
415	}
416	if (!xdr_krb5_deltat(xdrs, &objp->max_life)) {
417		return (FALSE);
418	}
419        if (v == KADM5_API_VERSION_1) {
420	     if (!xdr_krb5_principal(xdrs, &objp->mod_name)) {
421		  return (FALSE);
422	     }
423	} else {
424	     if (!xdr_nulltype(xdrs, (void **) &objp->mod_name,
425			       xdr_krb5_principal)) {
426		  return (FALSE);
427	     }
428	}
429	if (!xdr_krb5_timestamp(xdrs, &objp->mod_date)) {
430		return (FALSE);
431	}
432	if (!xdr_krb5_flags(xdrs, &objp->attributes)) {
433		return (FALSE);
434	}
435	if (!xdr_krb5_kvno(xdrs, &objp->kvno)) {
436		return (FALSE);
437	}
438	if (!xdr_krb5_kvno(xdrs, &objp->mkvno)) {
439		return (FALSE);
440	}
441	if (!xdr_nullstring(xdrs, &objp->policy)) {
442		return (FALSE);
443	}
444	if (!xdr_long(xdrs, &objp->aux_attributes)) {
445		return (FALSE);
446	}
447	if (v != KADM5_API_VERSION_1) {
448	     if (!xdr_krb5_deltat(xdrs, &objp->max_renewable_life)) {
449		  return (FALSE);
450	     }
451	     if (!xdr_krb5_timestamp(xdrs, &objp->last_success)) {
452		  return (FALSE);
453	     }
454	     if (!xdr_krb5_timestamp(xdrs, &objp->last_failed)) {
455		  return (FALSE);
456	     }
457	     if (!xdr_krb5_kvno(xdrs, &objp->fail_auth_count)) {
458		  return (FALSE);
459	     }
460	     if (!xdr_krb5_int16(xdrs, &objp->n_key_data)) {
461		  return (FALSE);
462	     }
463	     if (!xdr_krb5_int16(xdrs, &objp->n_tl_data)) {
464		  return (FALSE);
465	     }
466	     if (!xdr_nulltype(xdrs, (void **) &objp->tl_data,
467			       xdr_krb5_tl_data)) {
468		  return FALSE;
469	     }
470	     n = objp->n_key_data;
471	     if (!xdr_array(xdrs, (caddr_t *) &objp->key_data,
472			    &n, ~0, sizeof(krb5_key_data),
473			    xdr_krb5_key_data_nocontents)) {
474		  return (FALSE);
475	     }
476	}
477	return (TRUE);
478}
479
480bool_t
481xdr_kadm5_policy_ent_rec(XDR *xdrs, kadm5_policy_ent_rec *objp)
482{
483	if (!xdr_nullstring(xdrs, &objp->policy)) {
484		return (FALSE);
485	}
486	/* these all used to be u_int32, but it's stupid for sized types
487	   to be exposed at the api, and they're the same as longs on the
488	   wire. */
489	if (!xdr_long(xdrs, &objp->pw_min_life)) {
490		return (FALSE);
491	}
492	if (!xdr_long(xdrs, &objp->pw_max_life)) {
493		return (FALSE);
494	}
495	if (!xdr_long(xdrs, &objp->pw_min_length)) {
496		return (FALSE);
497	}
498	if (!xdr_long(xdrs, &objp->pw_min_classes)) {
499		return (FALSE);
500	}
501	if (!xdr_long(xdrs, &objp->pw_history_num)) {
502		return (FALSE);
503	}
504	if (!xdr_long(xdrs, &objp->policy_refcnt)) {
505		return (FALSE);
506	}
507	return (TRUE);
508}
509
510bool_t
511xdr_cprinc_arg(XDR *xdrs, cprinc_arg *objp)
512{
513	if (!xdr_ui_4(xdrs, &objp->api_version)) {
514		return (FALSE);
515	}
516	if (objp->api_version == KADM5_API_VERSION_1) {
517	     if (!xdr_kadm5_principal_ent_rec_v1(xdrs, &objp->rec)) {
518		  return (FALSE);
519	     }
520	} else {
521	     if (!xdr_kadm5_principal_ent_rec(xdrs, &objp->rec)) {
522		  return (FALSE);
523	     }
524	}
525	if (!xdr_long(xdrs, &objp->mask)) {
526		return (FALSE);
527	}
528	if (!xdr_nullstring(xdrs, &objp->passwd)) {
529		return (FALSE);
530	}
531	return (TRUE);
532}
533
534bool_t
535xdr_cprinc3_arg(XDR *xdrs, cprinc3_arg *objp)
536{
537	if (!xdr_ui_4(xdrs, &objp->api_version)) {
538		return (FALSE);
539	}
540	if (objp->api_version == KADM5_API_VERSION_1) {
541		if (!xdr_kadm5_principal_ent_rec_v1(xdrs, &objp->rec)) {
542			return (FALSE);
543		}
544	} else {
545		if (!xdr_kadm5_principal_ent_rec(xdrs, &objp->rec)) {
546			return (FALSE);
547		}
548	}
549	if (!xdr_long(xdrs, &objp->mask)) {
550		return (FALSE);
551	}
552	if (!xdr_array(xdrs, (caddr_t *)&objp->ks_tuple,
553		       (unsigned int *)&objp->n_ks_tuple, ~0,
554		       sizeof(krb5_key_salt_tuple),
555		       xdr_krb5_key_salt_tuple)) {
556		return (FALSE);
557	}
558	if (!xdr_nullstring(xdrs, &objp->passwd)) {
559		return (FALSE);
560	}
561	return (TRUE);
562}
563
564bool_t
565xdr_generic_ret(XDR *xdrs, generic_ret *objp)
566{
567	if (!xdr_ui_4(xdrs, &objp->api_version)) {
568		return (FALSE);
569	}
570	if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
571		return (FALSE);
572	}
573
574	return(TRUE);
575}
576
577bool_t
578xdr_dprinc_arg(XDR *xdrs, dprinc_arg *objp)
579{
580	if (!xdr_ui_4(xdrs, &objp->api_version)) {
581		return (FALSE);
582	}
583	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
584		return (FALSE);
585	}
586	return (TRUE);
587}
588
589bool_t
590xdr_mprinc_arg(XDR *xdrs, mprinc_arg *objp)
591{
592	if (!xdr_ui_4(xdrs, &objp->api_version)) {
593		return (FALSE);
594	}
595	if (objp->api_version == KADM5_API_VERSION_1) {
596	     if (!xdr_kadm5_principal_ent_rec_v1(xdrs, &objp->rec)) {
597		  return (FALSE);
598	     }
599	} else {
600	     if (!xdr_kadm5_principal_ent_rec(xdrs, &objp->rec)) {
601		  return (FALSE);
602	     }
603	}
604	if (!xdr_long(xdrs, &objp->mask)) {
605		return (FALSE);
606	}
607	return (TRUE);
608}
609
610bool_t
611xdr_rprinc_arg(XDR *xdrs, rprinc_arg *objp)
612{
613	if (!xdr_ui_4(xdrs, &objp->api_version)) {
614		return (FALSE);
615	}
616	if (!xdr_krb5_principal(xdrs, &objp->src)) {
617		return (FALSE);
618	}
619	if (!xdr_krb5_principal(xdrs, &objp->dest)) {
620		return (FALSE);
621	}
622	return (TRUE);
623}
624
625bool_t
626xdr_gprincs_arg(XDR *xdrs, gprincs_arg *objp)
627{
628     if (!xdr_ui_4(xdrs, &objp->api_version)) {
629	  return (FALSE);
630     }
631     if (!xdr_nullstring(xdrs, &objp->exp)) {
632	  return (FALSE);
633     }
634     return (TRUE);
635}
636
637bool_t
638xdr_gprincs_ret(XDR *xdrs, gprincs_ret *objp)
639{
640     if (!xdr_ui_4(xdrs, &objp->api_version)) {
641	  return (FALSE);
642     }
643     if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
644	  return (FALSE);
645     }
646     if (objp->code == KADM5_OK) {
647	  if (!xdr_int(xdrs, &objp->count)) {
648	       return (FALSE);
649	  }
650	  if (!xdr_array(xdrs, (caddr_t *) &objp->princs,
651			 (unsigned int *) &objp->count, ~0,
652			 sizeof(char *), xdr_nullstring)) {
653	       return (FALSE);
654	  }
655     }
656
657     return (TRUE);
658}
659
660bool_t
661xdr_chpass_arg(XDR *xdrs, chpass_arg *objp)
662{
663	if (!xdr_ui_4(xdrs, &objp->api_version)) {
664		return (FALSE);
665	}
666	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
667		return (FALSE);
668	}
669	if (!xdr_nullstring(xdrs, &objp->pass)) {
670		return (FALSE);
671	}
672	return (TRUE);
673}
674
675bool_t
676xdr_chpass3_arg(XDR *xdrs, chpass3_arg *objp)
677{
678	if (!xdr_ui_4(xdrs, &objp->api_version)) {
679		return (FALSE);
680	}
681	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
682		return (FALSE);
683	}
684	if (!xdr_bool(xdrs, (bool_t *) &objp->keepold)) { /* SUNWresync121 XXX */
685		return (FALSE);
686	}
687	if (!xdr_array(xdrs, (caddr_t *)&objp->ks_tuple,
688		       (unsigned int*)&objp->n_ks_tuple, ~0,
689		       sizeof(krb5_key_salt_tuple),
690		       xdr_krb5_key_salt_tuple)) {
691		return (FALSE);
692	}
693	if (!xdr_nullstring(xdrs, &objp->pass)) {
694		return (FALSE);
695	}
696	return (TRUE);
697}
698
699bool_t
700xdr_setv4key_arg(XDR *xdrs, setv4key_arg *objp)
701{
702	unsigned int n_keys = 1;
703
704	if (!xdr_ui_4(xdrs, &objp->api_version)) {
705		return (FALSE);
706	}
707	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
708		return (FALSE);
709	}
710	if (!xdr_array(xdrs, (caddr_t *) &objp->keyblock,
711		       &n_keys, ~0,
712		       sizeof(krb5_keyblock), xdr_krb5_keyblock)) {
713	        return (FALSE);
714	}
715	return (TRUE);
716}
717
718bool_t
719xdr_setkey_arg(XDR *xdrs, setkey_arg *objp)
720{
721	if (!xdr_ui_4(xdrs, &objp->api_version)) {
722		return (FALSE);
723	}
724	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
725		return (FALSE);
726	}
727	if (!xdr_array(xdrs, (caddr_t *) &objp->keyblocks,
728		       (unsigned int *) &objp->n_keys, ~0,
729		       sizeof(krb5_keyblock), xdr_krb5_keyblock)) {
730	        return (FALSE);
731	}
732	return (TRUE);
733}
734
735bool_t
736xdr_setkey3_arg(XDR *xdrs, setkey3_arg *objp)
737{
738	if (!xdr_ui_4(xdrs, &objp->api_version)) {
739		return (FALSE);
740	}
741	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
742		return (FALSE);
743	}
744	if (!xdr_bool(xdrs, (bool_t *) &objp->keepold)) { /* SUNWresync121 XXX */
745		return (FALSE);
746	}
747	if (!xdr_array(xdrs, (caddr_t *) &objp->ks_tuple,
748		       (unsigned int *) &objp->n_ks_tuple, ~0,
749		       sizeof(krb5_key_salt_tuple), xdr_krb5_key_salt_tuple)) {
750		return (FALSE);
751	}
752	if (!xdr_array(xdrs, (caddr_t *) &objp->keyblocks,
753		       (unsigned int *) &objp->n_keys, ~0,
754		       sizeof(krb5_keyblock), xdr_krb5_keyblock)) {
755		return (FALSE);
756	}
757	return (TRUE);
758}
759
760bool_t
761xdr_chrand_arg(XDR *xdrs, chrand_arg *objp)
762{
763	if (!xdr_ui_4(xdrs, &objp->api_version)) {
764		return (FALSE);
765	}
766	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
767		return (FALSE);
768	}
769	return (TRUE);
770}
771
772bool_t
773xdr_chrand3_arg(XDR *xdrs, chrand3_arg *objp)
774{
775	if (!xdr_ui_4(xdrs, &objp->api_version)) {
776		return (FALSE);
777	}
778	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
779		return (FALSE);
780	}
781	if (!xdr_bool(xdrs, (bool_t *) &objp->keepold)) { /* SUNWresync121 XXX */
782		return (FALSE);
783	}
784	if (!xdr_array(xdrs, (caddr_t *)&objp->ks_tuple,
785		       (unsigned int*)&objp->n_ks_tuple, ~0,
786		       sizeof(krb5_key_salt_tuple),
787		       xdr_krb5_key_salt_tuple)) {
788		return (FALSE);
789	}
790	return (TRUE);
791}
792
793bool_t
794xdr_chrand_ret(XDR *xdrs, chrand_ret *objp)
795{
796	if (!xdr_ui_4(xdrs, &objp->api_version)) {
797		return (FALSE);
798	}
799	if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
800		return (FALSE);
801	}
802	if (objp->api_version == KADM5_API_VERSION_1) {
803	     if(objp->code == KADM5_OK) {
804		  if (!xdr_krb5_keyblock(xdrs, &objp->key)) {
805		       return (FALSE);
806		  }
807	     }
808	} else {
809	     if (objp->code == KADM5_OK) {
810		  if (!xdr_array(xdrs, (char **)&objp->keys, (unsigned int *)&objp->n_keys, ~0,
811				 sizeof(krb5_keyblock),
812				 xdr_krb5_keyblock))
813		       return FALSE;
814	     }
815	}
816
817	return (TRUE);
818}
819
820bool_t
821xdr_gprinc_arg(XDR *xdrs, gprinc_arg *objp)
822{
823	if (!xdr_ui_4(xdrs, &objp->api_version)) {
824		return (FALSE);
825	}
826	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
827		return (FALSE);
828	}
829	if ((objp->api_version > KADM5_API_VERSION_1) &&
830	    !xdr_long(xdrs, &objp->mask)) {
831	     return FALSE;
832	}
833
834	return (TRUE);
835}
836
837bool_t
838xdr_gprinc_ret(XDR *xdrs, gprinc_ret *objp)
839{
840	if (!xdr_ui_4(xdrs, &objp->api_version)) {
841		return (FALSE);
842	}
843	if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
844		return (FALSE);
845	}
846	if(objp->code == KADM5_OK)  {
847	     if (objp->api_version == KADM5_API_VERSION_1) {
848		  if (!xdr_kadm5_principal_ent_rec_v1(xdrs, &objp->rec)) {
849		       return (FALSE);
850		  }
851	     } else {
852		  if (!xdr_kadm5_principal_ent_rec(xdrs, &objp->rec)) {
853		       return (FALSE);
854		  }
855	     }
856	}
857
858	return (TRUE);
859}
860
861bool_t
862xdr_cpol_arg(XDR *xdrs, cpol_arg *objp)
863{
864	if (!xdr_ui_4(xdrs, &objp->api_version)) {
865		return (FALSE);
866	}
867	if (!xdr_kadm5_policy_ent_rec(xdrs, &objp->rec)) {
868		return (FALSE);
869	}
870	if (!xdr_long(xdrs, &objp->mask)) {
871		return (FALSE);
872	}
873	return (TRUE);
874}
875
876bool_t
877xdr_dpol_arg(XDR *xdrs, dpol_arg *objp)
878{
879	if (!xdr_ui_4(xdrs, &objp->api_version)) {
880		return (FALSE);
881	}
882	if (!xdr_nullstring(xdrs, &objp->name)) {
883		return (FALSE);
884	}
885	return (TRUE);
886}
887
888bool_t
889xdr_mpol_arg(XDR *xdrs, mpol_arg *objp)
890{
891	if (!xdr_ui_4(xdrs, &objp->api_version)) {
892		return (FALSE);
893	}
894	if (!xdr_kadm5_policy_ent_rec(xdrs, &objp->rec)) {
895		return (FALSE);
896	}
897	if (!xdr_long(xdrs, &objp->mask)) {
898		return (FALSE);
899	}
900	return (TRUE);
901}
902
903bool_t
904xdr_gpol_arg(XDR *xdrs, gpol_arg *objp)
905{
906	if (!xdr_ui_4(xdrs, &objp->api_version)) {
907		return (FALSE);
908	}
909	if (!xdr_nullstring(xdrs, &objp->name)) {
910		return (FALSE);
911	}
912	return (TRUE);
913}
914
915bool_t
916xdr_gpol_ret(XDR *xdrs, gpol_ret *objp)
917{
918	if (!xdr_ui_4(xdrs, &objp->api_version)) {
919		return (FALSE);
920	}
921	if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
922		return (FALSE);
923	}
924	if(objp->code == KADM5_OK) {
925	    if (!xdr_kadm5_policy_ent_rec(xdrs, &objp->rec))
926		return (FALSE);
927	}
928
929	return (TRUE);
930}
931
932bool_t
933xdr_gpols_arg(XDR *xdrs, gpols_arg *objp)
934{
935     if (!xdr_ui_4(xdrs, &objp->api_version)) {
936	  return (FALSE);
937     }
938     if (!xdr_nullstring(xdrs, &objp->exp)) {
939	  return (FALSE);
940     }
941     return (TRUE);
942}
943
944bool_t
945xdr_gpols_ret(XDR *xdrs, gpols_ret *objp)
946{
947     if (!xdr_ui_4(xdrs, &objp->api_version)) {
948	  return (FALSE);
949     }
950     if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
951	  return (FALSE);
952     }
953     if (objp->code == KADM5_OK) {
954	  if (!xdr_int(xdrs, &objp->count)) {
955	       return (FALSE);
956	  }
957	  if (!xdr_array(xdrs, (caddr_t *) &objp->pols,
958			 (unsigned int *) &objp->count, ~0,
959			 sizeof(char *), xdr_nullstring)) {
960	       return (FALSE);
961	  }
962     }
963
964     return (TRUE);
965}
966
967bool_t xdr_getprivs_ret(XDR *xdrs, getprivs_ret *objp)
968{
969	if (!xdr_ui_4(xdrs, &objp->api_version)) {
970		return (FALSE);
971	}
972     if (! xdr_kadm5_ret_t(xdrs, &objp->code) ||
973	 ! xdr_long(xdrs, &objp->privs))
974	  return FALSE;
975
976     return TRUE;
977}
978
979bool_t
980xdr_krb5_principal(XDR *xdrs, krb5_principal *objp)
981{
982    int	    ret;
983    char	    *p = NULL;
984    krb5_principal  pr = NULL;
985    static krb5_context context = NULL;
986
987    /* using a static context here is ugly, but should work
988       ok, and the other solutions are even uglier */
989
990    if (!context &&
991	kadm5_init_krb5_context(&context))
992       return(FALSE);
993
994    switch(xdrs->x_op) {
995    case XDR_ENCODE:
996	if (*objp) {
997	     if((ret = krb5_unparse_name(context, *objp, &p)) != 0)
998		  return FALSE;
999	}
1000	if(!xdr_nullstring(xdrs, &p))
1001	    return FALSE;
1002	if (p) free(p);
1003	break;
1004    case XDR_DECODE:
1005	if(!xdr_nullstring(xdrs, &p))
1006	    return FALSE;
1007	if (p) {
1008	     ret = krb5_parse_name(context, p, &pr);
1009	     if(ret != 0)
1010		  return FALSE;
1011	     *objp = pr;
1012	     free(p);
1013	} else
1014	     *objp = NULL;
1015	break;
1016    case XDR_FREE:
1017	if(*objp != NULL)
1018	    krb5_free_principal(context, *objp);
1019	break;
1020    }
1021    return TRUE;
1022}
1023
1024bool_t
1025xdr_krb5_octet(XDR *xdrs, krb5_octet *objp)
1026{
1027   if (!xdr_u_char(xdrs, objp))
1028	return (FALSE);
1029   return (TRUE);
1030}
1031
1032bool_t
1033xdr_krb5_enctype(XDR *xdrs, krb5_enctype *objp)
1034{
1035   /*
1036    * This used to be xdr_krb5_keytype, but keytypes and enctypes have
1037    * been merged into only enctypes.  However, randkey_principal
1038    * already ensures that only a key of ENCTYPE_DES_CBC_CRC will be
1039    * returned to v1 clients, and ENCTYPE_DES_CBC_CRC has the same
1040    * value as KEYTYPE_DES used too, which is what all v1 clients
1041    * expect.  Therefore, IMHO, just encoding whatever enctype we get
1042    * is safe.
1043    */
1044
1045   if (!xdr_u_int(xdrs, (unsigned int *) objp))
1046	return (FALSE);
1047   return (TRUE);
1048}
1049
1050bool_t
1051xdr_krb5_salttype(XDR *xdrs, krb5_int32 *objp)
1052{
1053    if (!xdr_int(xdrs, (int32_t *) objp))
1054	return FALSE;
1055    return TRUE;
1056}
1057
1058bool_t
1059xdr_krb5_keyblock(XDR *xdrs, krb5_keyblock *objp)
1060{
1061   /* XXX This only works because free_keyblock assumes ->contents
1062      is allocated by malloc() */
1063
1064   if(!xdr_krb5_enctype(xdrs, &objp->enctype))
1065      return FALSE;
1066   if(!xdr_bytes(xdrs, (char **) &objp->contents, (unsigned int *)
1067		 &objp->length, ~0))
1068      return FALSE;
1069   return TRUE;
1070}
1071