xref: /onnv-gate/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_rpcsec.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright (c) 1996 by Sun Microsystems, Inc.
24*0Sstevel@tonic-gate  * All rights reserved.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <sys/types.h>
30*0Sstevel@tonic-gate #include <sys/errno.h>
31*0Sstevel@tonic-gate #include <sys/tiuser.h>
32*0Sstevel@tonic-gate #include <setjmp.h>
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate #include <rpc/types.h>
35*0Sstevel@tonic-gate #include <rpc/xdr.h>
36*0Sstevel@tonic-gate #include <rpc/auth.h>
37*0Sstevel@tonic-gate #include <rpc/clnt.h>
38*0Sstevel@tonic-gate #include <rpc/rpc_msg.h>
39*0Sstevel@tonic-gate #include <rpc/rpcsec_gss.h>
40*0Sstevel@tonic-gate #include <string.h>
41*0Sstevel@tonic-gate #include "snoop.h"
42*0Sstevel@tonic-gate 
43*0Sstevel@tonic-gate extern jmp_buf xdr_err;
44*0Sstevel@tonic-gate 
45*0Sstevel@tonic-gate struct cache_struct *find_xid();
46*0Sstevel@tonic-gate char *nameof_prog(int prog);
47*0Sstevel@tonic-gate 
48*0Sstevel@tonic-gate char *
49*0Sstevel@tonic-gate rpcsec_gss_proc_to_string(unsigned int proc)
50*0Sstevel@tonic-gate {
51*0Sstevel@tonic-gate 	switch (proc) {
52*0Sstevel@tonic-gate 	case RPCSEC_GSS_DATA:	return "RPCSEC_GSS_DATA"; break;
53*0Sstevel@tonic-gate 	case RPCSEC_GSS_INIT:	return "RPCSEC_GSS_INIT"; break;
54*0Sstevel@tonic-gate 	case RPCSEC_GSS_CONTINUE_INIT:
55*0Sstevel@tonic-gate 				return ("RPCSEC_GSS_CONTINUE_INIT");
56*0Sstevel@tonic-gate 	case RPCSEC_GSS_DESTROY:
57*0Sstevel@tonic-gate 				return ("RPCSEC_GSS_DESTROY");
58*0Sstevel@tonic-gate 	default:		return ("unknown");
59*0Sstevel@tonic-gate 
60*0Sstevel@tonic-gate 	}
61*0Sstevel@tonic-gate }
62*0Sstevel@tonic-gate 
63*0Sstevel@tonic-gate 
64*0Sstevel@tonic-gate char *
65*0Sstevel@tonic-gate rpcsec_gss_service_to_string(rpc_gss_service_t service)
66*0Sstevel@tonic-gate {
67*0Sstevel@tonic-gate 	switch (service) {
68*0Sstevel@tonic-gate 	case rpc_gss_svc_none:	return "none"; break;
69*0Sstevel@tonic-gate 	case rpc_gss_svc_integrity: return "integrity"; break;
70*0Sstevel@tonic-gate 	case rpc_gss_svc_privacy: return "privacy"; break;
71*0Sstevel@tonic-gate 	default:		return "unknown";	  break;
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate 	}
74*0Sstevel@tonic-gate }
75*0Sstevel@tonic-gate 
76*0Sstevel@tonic-gate /*
77*0Sstevel@tonic-gate  *  Print detailed RPCSEC_GSS cred data.
78*0Sstevel@tonic-gate  */
79*0Sstevel@tonic-gate void
80*0Sstevel@tonic-gate print_rpcsec_gss_cred(int xid, int authlen)
81*0Sstevel@tonic-gate {
82*0Sstevel@tonic-gate 	unsigned int seq_num;
83*0Sstevel@tonic-gate 	unsigned int handle_len;
84*0Sstevel@tonic-gate 	unsigned int rpcsec_gss_ver;
85*0Sstevel@tonic-gate 	rpc_gss_service_t rpcsec_gss_service;
86*0Sstevel@tonic-gate 	unsigned int rpcsec_gss_proc;
87*0Sstevel@tonic-gate 	char *handle, *line;
88*0Sstevel@tonic-gate 	struct cache_struct *x;
89*0Sstevel@tonic-gate 	int pos;
90*0Sstevel@tonic-gate 
91*0Sstevel@tonic-gate 	pos = getxdr_pos();
92*0Sstevel@tonic-gate 	rpcsec_gss_ver = getxdr_u_long();
93*0Sstevel@tonic-gate 
94*0Sstevel@tonic-gate 	/* see if we know this version or not */
95*0Sstevel@tonic-gate 
96*0Sstevel@tonic-gate 	if (rpcsec_gss_ver != 1) {
97*0Sstevel@tonic-gate 		(void) showxdr_hex(authlen, "[%s]");
98*0Sstevel@tonic-gate 		return;
99*0Sstevel@tonic-gate 	}
100*0Sstevel@tonic-gate 
101*0Sstevel@tonic-gate 	rpcsec_gss_proc   = getxdr_u_long();
102*0Sstevel@tonic-gate 	seq_num    = getxdr_u_long();
103*0Sstevel@tonic-gate 	rpcsec_gss_service    = getxdr_enum();
104*0Sstevel@tonic-gate 
105*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()),
106*0Sstevel@tonic-gate 		"   version = %u",  rpcsec_gss_ver);
107*0Sstevel@tonic-gate 
108*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()),
109*0Sstevel@tonic-gate 		"   gss control procedure = %u (%s)",
110*0Sstevel@tonic-gate 		rpcsec_gss_proc,
111*0Sstevel@tonic-gate 		rpcsec_gss_proc_to_string(rpcsec_gss_proc));
112*0Sstevel@tonic-gate 
113*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()),
114*0Sstevel@tonic-gate 		"   sequence num = %u", seq_num);
115*0Sstevel@tonic-gate 
116*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()),
117*0Sstevel@tonic-gate 	    "   service = %d (%s)", rpcsec_gss_service,
118*0Sstevel@tonic-gate 	    rpcsec_gss_service_to_string(rpcsec_gss_service));
119*0Sstevel@tonic-gate 	pos = getxdr_pos();
120*0Sstevel@tonic-gate 	handle_len = getxdr_u_long();
121*0Sstevel@tonic-gate 	handle = getxdr_hex(handle_len);
122*0Sstevel@tonic-gate 	line = get_line(pos, getxdr_pos());
123*0Sstevel@tonic-gate 	sprintf(line, "   handle: length = %d, data = [%s]",
124*0Sstevel@tonic-gate 			handle_len, handle);
125*0Sstevel@tonic-gate 	x = find_xid(xid);
126*0Sstevel@tonic-gate 	if (x) {
127*0Sstevel@tonic-gate 		x->xid_gss_proc    = rpcsec_gss_proc;
128*0Sstevel@tonic-gate 		x->xid_gss_service = rpcsec_gss_service;
129*0Sstevel@tonic-gate 	}
130*0Sstevel@tonic-gate }
131*0Sstevel@tonic-gate 
132*0Sstevel@tonic-gate /*
133*0Sstevel@tonic-gate  *  Based on different RPCSEC_GSS services supported, maybe a
134*0Sstevel@tonic-gate  *  special handling is needed before printing the arguments.
135*0Sstevel@tonic-gate  *
136*0Sstevel@tonic-gate  *  For integrity service : print the sequence number.
137*0Sstevel@tonic-gate  *  For privacy service : do not print the arguments.
138*0Sstevel@tonic-gate  */
139*0Sstevel@tonic-gate int
140*0Sstevel@tonic-gate rpcsec_gss_pre_proto(int type, int flags, int xid,
141*0Sstevel@tonic-gate 					int prog, int vers, int proc)
142*0Sstevel@tonic-gate {
143*0Sstevel@tonic-gate 	int seq;
144*0Sstevel@tonic-gate 	struct cache_struct *x;
145*0Sstevel@tonic-gate 
146*0Sstevel@tonic-gate 	if (! (x = find_xid(xid)))
147*0Sstevel@tonic-gate 		return (0);
148*0Sstevel@tonic-gate 
149*0Sstevel@tonic-gate 	switch (x->xid_gss_service) {
150*0Sstevel@tonic-gate 	case rpc_gss_svc_default:
151*0Sstevel@tonic-gate 	case rpc_gss_svc_none:
152*0Sstevel@tonic-gate 		break; /* standard call args */
153*0Sstevel@tonic-gate 	case rpc_gss_svc_integrity:
154*0Sstevel@tonic-gate 		/* length of rpc_gss_data_t encoded in the databody_integ */
155*0Sstevel@tonic-gate 		getxdr_u_long();
156*0Sstevel@tonic-gate 		/* read the seq number */
157*0Sstevel@tonic-gate 		seq = getxdr_u_long();
158*0Sstevel@tonic-gate 		if (flags & F_ALLSUM) {
159*0Sstevel@tonic-gate 			(void) sprintf(get_sum_line(), "%s %c seq_num = %u",
160*0Sstevel@tonic-gate 				"RPC RPCSEC_GSS", type == CALL ? 'C' : 'R',
161*0Sstevel@tonic-gate 				seq);
162*0Sstevel@tonic-gate 		} else if (flags & F_DTAIL) {
163*0Sstevel@tonic-gate 			sprintf(get_line(0, 0),
164*0Sstevel@tonic-gate 				"RPCSEC_GSS data seq_num = %u", seq);
165*0Sstevel@tonic-gate 			show_space();
166*0Sstevel@tonic-gate 		}
167*0Sstevel@tonic-gate 		/* call args follow */
168*0Sstevel@tonic-gate 		break;
169*0Sstevel@tonic-gate 	case rpc_gss_svc_privacy: {
170*0Sstevel@tonic-gate 		char *progname = nameof_prog(prog);
171*0Sstevel@tonic-gate 		char prognum[32];
172*0Sstevel@tonic-gate 
173*0Sstevel@tonic-gate 		if (*progname == '?') {
174*0Sstevel@tonic-gate 			sprintf(prognum, "%d", prog);
175*0Sstevel@tonic-gate 			progname = prognum;
176*0Sstevel@tonic-gate 		}
177*0Sstevel@tonic-gate 
178*0Sstevel@tonic-gate 		if (flags & F_SUM || flags & F_ALLSUM) {
179*0Sstevel@tonic-gate 		    (void) sprintf(get_sum_line(),
180*0Sstevel@tonic-gate 			"%s %c %s ver(%d) proc(%d) (data encrypted) ",
181*0Sstevel@tonic-gate 			"RPC RPCSEC_GSS", type == CALL ? 'C' : 'R',
182*0Sstevel@tonic-gate 			progname, vers, proc);
183*0Sstevel@tonic-gate 		} else if (flags & F_DTAIL) {
184*0Sstevel@tonic-gate 		    unsigned int args_len;
185*0Sstevel@tonic-gate 
186*0Sstevel@tonic-gate 		    args_len = getxdr_u_long();
187*0Sstevel@tonic-gate 		    sprintf(get_line(0, 0),
188*0Sstevel@tonic-gate 			"RPCSEC_GSS %s ver(%d) proc(%d)",
189*0Sstevel@tonic-gate 			progname, vers, proc);
190*0Sstevel@tonic-gate 		    sprintf(get_line(0, 0),
191*0Sstevel@tonic-gate 			"(%s args encrypted, len = %d bytes)",
192*0Sstevel@tonic-gate 			type == CALL ? "CALL" : "REPLY", args_len);
193*0Sstevel@tonic-gate 		    show_space();
194*0Sstevel@tonic-gate 		}
195*0Sstevel@tonic-gate 		}
196*0Sstevel@tonic-gate 		return (1);
197*0Sstevel@tonic-gate 
198*0Sstevel@tonic-gate 	default:
199*0Sstevel@tonic-gate 		break;
200*0Sstevel@tonic-gate 	}
201*0Sstevel@tonic-gate 	return (0);
202*0Sstevel@tonic-gate }
203*0Sstevel@tonic-gate 
204*0Sstevel@tonic-gate /*
205*0Sstevel@tonic-gate  *  Based on different RPCSEC_GSS services supported, maybe a
206*0Sstevel@tonic-gate  *  special handling is needed after printing the arguments.
207*0Sstevel@tonic-gate  *
208*0Sstevel@tonic-gate  *  For integrity service : print the checksum.
209*0Sstevel@tonic-gate  */
210*0Sstevel@tonic-gate void
211*0Sstevel@tonic-gate rpcsec_gss_post_proto(int flags, int xid)
212*0Sstevel@tonic-gate {
213*0Sstevel@tonic-gate 	char *line;
214*0Sstevel@tonic-gate 
215*0Sstevel@tonic-gate 	struct cache_struct *x;
216*0Sstevel@tonic-gate 
217*0Sstevel@tonic-gate 	if (! (x = find_xid(xid)))
218*0Sstevel@tonic-gate 		return;
219*0Sstevel@tonic-gate 
220*0Sstevel@tonic-gate 	switch (x->xid_gss_service) {
221*0Sstevel@tonic-gate 	case rpc_gss_svc_default:
222*0Sstevel@tonic-gate 	case rpc_gss_svc_none:
223*0Sstevel@tonic-gate 	case rpc_gss_svc_privacy:
224*0Sstevel@tonic-gate 		/* nothing left */
225*0Sstevel@tonic-gate 		break;
226*0Sstevel@tonic-gate 	case rpc_gss_svc_integrity:
227*0Sstevel@tonic-gate 		if (flags & F_ALLSUM) {
228*0Sstevel@tonic-gate 			line = get_sum_line();
229*0Sstevel@tonic-gate 			sprintf(line, "RPC RPCSEC_GSS C (checksum)");
230*0Sstevel@tonic-gate 		} else if (flags & F_DTAIL) {
231*0Sstevel@tonic-gate 			unsigned int checksum_len;
232*0Sstevel@tonic-gate 			char *checksum;
233*0Sstevel@tonic-gate 
234*0Sstevel@tonic-gate 			show_header("RPC:  ", "RPCSEC_GSS", 0);
235*0Sstevel@tonic-gate 			show_space();
236*0Sstevel@tonic-gate 			checksum_len = getxdr_u_long();
237*0Sstevel@tonic-gate 			checksum = getxdr_hex(checksum_len);
238*0Sstevel@tonic-gate 			sprintf(get_line(0, 0),
239*0Sstevel@tonic-gate 				"checksum: len = %d", checksum_len);
240*0Sstevel@tonic-gate 			sprintf(get_line(0, 0), "[%s]", checksum);
241*0Sstevel@tonic-gate 			show_trailer();
242*0Sstevel@tonic-gate 		}
243*0Sstevel@tonic-gate 		break;
244*0Sstevel@tonic-gate 	default:
245*0Sstevel@tonic-gate 		break;
246*0Sstevel@tonic-gate 	}
247*0Sstevel@tonic-gate }
248*0Sstevel@tonic-gate 
249*0Sstevel@tonic-gate /*
250*0Sstevel@tonic-gate  *  Print RPCSEC_GSS control procedures protocol data,
251*0Sstevel@tonic-gate  *  No-op for RPCSEC_GSS_DATA.
252*0Sstevel@tonic-gate  */
253*0Sstevel@tonic-gate int
254*0Sstevel@tonic-gate rpcsec_gss_control_proc(int type, int flags, int xid)
255*0Sstevel@tonic-gate {
256*0Sstevel@tonic-gate 	int seq;
257*0Sstevel@tonic-gate 
258*0Sstevel@tonic-gate 	struct cache_struct *x;
259*0Sstevel@tonic-gate 
260*0Sstevel@tonic-gate 	if (! (x = find_xid(xid)))
261*0Sstevel@tonic-gate 		return (0);
262*0Sstevel@tonic-gate 
263*0Sstevel@tonic-gate 	if (x->xid_gss_proc != RPCSEC_GSS_DATA) {
264*0Sstevel@tonic-gate 		if (flags & F_SUM) {
265*0Sstevel@tonic-gate 			if (type == CALL) {
266*0Sstevel@tonic-gate 				(void) sprintf(get_sum_line(), "%s %c %u (%s)",
267*0Sstevel@tonic-gate 				"RPC RPCSEC_GSS",
268*0Sstevel@tonic-gate 				type == CALL ? 'C' : 'R',
269*0Sstevel@tonic-gate 				x->xid_gss_proc,
270*0Sstevel@tonic-gate 				rpcsec_gss_proc_to_string(x->xid_gss_proc));
271*0Sstevel@tonic-gate 			}
272*0Sstevel@tonic-gate 		} else if (flags & F_DTAIL) {
273*0Sstevel@tonic-gate 			if (x->xid_gss_proc == RPCSEC_GSS_INIT ||
274*0Sstevel@tonic-gate 			    x->xid_gss_proc == RPCSEC_GSS_CONTINUE_INIT) {
275*0Sstevel@tonic-gate 				if (type == CALL) {
276*0Sstevel@tonic-gate 					print_rpc_gss_init_arg(flags, x);
277*0Sstevel@tonic-gate 				} else {
278*0Sstevel@tonic-gate 					print_rpc_gss_init_res(flags);
279*0Sstevel@tonic-gate 				}
280*0Sstevel@tonic-gate 			}
281*0Sstevel@tonic-gate 		}
282*0Sstevel@tonic-gate 		return (1);
283*0Sstevel@tonic-gate 	}
284*0Sstevel@tonic-gate 
285*0Sstevel@tonic-gate 	return (0);
286*0Sstevel@tonic-gate }
287*0Sstevel@tonic-gate 
288*0Sstevel@tonic-gate /*
289*0Sstevel@tonic-gate  *  Skip the header RPCSEC_GSS cred data and
290*0Sstevel@tonic-gate  *  put service and control type in the xid cache.
291*0Sstevel@tonic-gate  */
292*0Sstevel@tonic-gate extract_rpcsec_gss_cred_info(int xid)
293*0Sstevel@tonic-gate {
294*0Sstevel@tonic-gate 	unsigned int seq_num;
295*0Sstevel@tonic-gate 	unsigned int handle_len;
296*0Sstevel@tonic-gate 	unsigned int flavor_len;
297*0Sstevel@tonic-gate 	unsigned int rpcsec_gss_ver;
298*0Sstevel@tonic-gate 	rpc_gss_service_t rpcsec_gss_service;
299*0Sstevel@tonic-gate 	unsigned int rpcsec_gss_proc;
300*0Sstevel@tonic-gate 	struct cache_struct *x;
301*0Sstevel@tonic-gate 
302*0Sstevel@tonic-gate 	flavor_len = getxdr_u_long();
303*0Sstevel@tonic-gate 	rpcsec_gss_ver = getxdr_u_long();
304*0Sstevel@tonic-gate 	/* see if we know this version or not */
305*0Sstevel@tonic-gate 	if (rpcsec_gss_ver != 1) {
306*0Sstevel@tonic-gate 		longjmp(xdr_err, 1);
307*0Sstevel@tonic-gate 	}
308*0Sstevel@tonic-gate 	rpcsec_gss_proc   = getxdr_u_long();
309*0Sstevel@tonic-gate 	seq_num    = getxdr_u_long();
310*0Sstevel@tonic-gate 	rpcsec_gss_service    = getxdr_enum();
311*0Sstevel@tonic-gate 	/* skip the handle */
312*0Sstevel@tonic-gate 	xdr_skip(RNDUP(getxdr_u_long()));
313*0Sstevel@tonic-gate 
314*0Sstevel@tonic-gate 	if (x = find_xid(xid)) {
315*0Sstevel@tonic-gate 		x->xid_gss_service = rpcsec_gss_service;
316*0Sstevel@tonic-gate 		x->xid_gss_proc = rpcsec_gss_proc;
317*0Sstevel@tonic-gate 	}
318*0Sstevel@tonic-gate 
319*0Sstevel@tonic-gate }
320*0Sstevel@tonic-gate 
321*0Sstevel@tonic-gate /*
322*0Sstevel@tonic-gate  *  Print the argument data for the RPCSEC_GSS_INIT control procedure.
323*0Sstevel@tonic-gate  */
324*0Sstevel@tonic-gate print_rpc_gss_init_arg(flags, x)
325*0Sstevel@tonic-gate 	int flags;
326*0Sstevel@tonic-gate 	struct cache_struct *x;
327*0Sstevel@tonic-gate {
328*0Sstevel@tonic-gate 
329*0Sstevel@tonic-gate 	char *token, *line;
330*0Sstevel@tonic-gate 	unsigned int token_len;
331*0Sstevel@tonic-gate 	int pos;
332*0Sstevel@tonic-gate 
333*0Sstevel@tonic-gate 	/*
334*0Sstevel@tonic-gate 	 *  see if we need to print out the rpc_gss_init_arg structure
335*0Sstevel@tonic-gate 	 *  or not.
336*0Sstevel@tonic-gate 	 */
337*0Sstevel@tonic-gate 
338*0Sstevel@tonic-gate 	if (x->xid_gss_proc != RPCSEC_GSS_INIT &&
339*0Sstevel@tonic-gate 		x->xid_gss_proc != RPCSEC_GSS_CONTINUE_INIT) {
340*0Sstevel@tonic-gate 		return;
341*0Sstevel@tonic-gate 	}
342*0Sstevel@tonic-gate 
343*0Sstevel@tonic-gate 	/* print it */
344*0Sstevel@tonic-gate 
345*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()),
346*0Sstevel@tonic-gate 		"RPCSEC_GSS_INIT args:");
347*0Sstevel@tonic-gate 
348*0Sstevel@tonic-gate 	pos = getxdr_pos();
349*0Sstevel@tonic-gate 	token_len = getxdr_u_long();
350*0Sstevel@tonic-gate 	token = getxdr_hex(token_len);
351*0Sstevel@tonic-gate 	line = get_line(pos, getxdr_pos());
352*0Sstevel@tonic-gate 		sprintf(line, "   gss token: length = %d, data = [%d bytes]",
353*0Sstevel@tonic-gate 			token_len, token_len);
354*0Sstevel@tonic-gate 
355*0Sstevel@tonic-gate 	show_trailer();
356*0Sstevel@tonic-gate }
357*0Sstevel@tonic-gate 
358*0Sstevel@tonic-gate /*
359*0Sstevel@tonic-gate  *  Print the results data for the RPCSEC_GSS_INIT control procedure.
360*0Sstevel@tonic-gate  */
361*0Sstevel@tonic-gate print_rpc_gss_init_res(int flags)
362*0Sstevel@tonic-gate {
363*0Sstevel@tonic-gate 
364*0Sstevel@tonic-gate 	char *handle, *token, *line;
365*0Sstevel@tonic-gate 	unsigned int token_len, handle_len;
366*0Sstevel@tonic-gate 	unsigned int major, minor, seq_window;
367*0Sstevel@tonic-gate 
368*0Sstevel@tonic-gate 	int pos;
369*0Sstevel@tonic-gate 	struct cache_struct *x;
370*0Sstevel@tonic-gate 
371*0Sstevel@tonic-gate 	/* print it */
372*0Sstevel@tonic-gate 
373*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()), "RPCSEC_GSS_INIT result:");
374*0Sstevel@tonic-gate 
375*0Sstevel@tonic-gate 	pos = getxdr_pos();
376*0Sstevel@tonic-gate 	handle_len = getxdr_u_long();
377*0Sstevel@tonic-gate 	handle = getxdr_hex(handle_len);
378*0Sstevel@tonic-gate 	line = get_line(pos, getxdr_pos());
379*0Sstevel@tonic-gate 	sprintf(line, "   handle: length = %d, data = [%s]",
380*0Sstevel@tonic-gate 		handle_len, handle);
381*0Sstevel@tonic-gate 	pos = getxdr_pos();
382*0Sstevel@tonic-gate 	major = getxdr_u_long();
383*0Sstevel@tonic-gate 	minor = getxdr_u_long();
384*0Sstevel@tonic-gate 	seq_window = getxdr_u_long();
385*0Sstevel@tonic-gate 
386*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()),
387*0Sstevel@tonic-gate 				"   gss_major status = %u", major);
388*0Sstevel@tonic-gate 
389*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()),
390*0Sstevel@tonic-gate 				"   gss_minor status = %u", minor);
391*0Sstevel@tonic-gate 
392*0Sstevel@tonic-gate 	(void) sprintf(get_line(pos, getxdr_pos()),
393*0Sstevel@tonic-gate 				"   sequence window  = %u", seq_window);
394*0Sstevel@tonic-gate 	pos = getxdr_pos();
395*0Sstevel@tonic-gate 	token_len = getxdr_u_long();
396*0Sstevel@tonic-gate 	token = getxdr_hex(token_len);
397*0Sstevel@tonic-gate 	line = get_line(pos, getxdr_pos());
398*0Sstevel@tonic-gate 	sprintf(line, "   gss token: length = %d, data = [%d bytes]",
399*0Sstevel@tonic-gate 		token_len, token_len);
400*0Sstevel@tonic-gate 	show_trailer();
401*0Sstevel@tonic-gate }
402