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