Home | History | Annotate | Download | only in snoop
      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 2005 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     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 static void print_rpc_gss_init_arg(int, struct cache_struct *);
     48 static void print_rpc_gss_init_res(int);
     49 
     50 char *
     51 rpcsec_gss_proc_to_string(unsigned int proc)
     52 {
     53 	switch (proc) {
     54 	case RPCSEC_GSS_DATA:	return "RPCSEC_GSS_DATA"; break;
     55 	case RPCSEC_GSS_INIT:	return "RPCSEC_GSS_INIT"; break;
     56 	case RPCSEC_GSS_CONTINUE_INIT:
     57 				return ("RPCSEC_GSS_CONTINUE_INIT");
     58 	case RPCSEC_GSS_DESTROY:
     59 				return ("RPCSEC_GSS_DESTROY");
     60 	default:		return ("unknown");
     61 
     62 	}
     63 }
     64 
     65 
     66 char *
     67 rpcsec_gss_service_to_string(rpc_gss_service_t service)
     68 {
     69 	switch (service) {
     70 	case rpc_gss_svc_none:	return "none"; break;
     71 	case rpc_gss_svc_integrity: return "integrity"; break;
     72 	case rpc_gss_svc_privacy: return "privacy"; break;
     73 	default:		return "unknown";	  break;
     74 
     75 	}
     76 }
     77 
     78 /*
     79  *  Print detailed RPCSEC_GSS cred data.
     80  */
     81 void
     82 print_rpcsec_gss_cred(int xid, int authlen)
     83 {
     84 	unsigned int seq_num;
     85 	unsigned int handle_len;
     86 	unsigned int rpcsec_gss_ver;
     87 	rpc_gss_service_t rpcsec_gss_service;
     88 	unsigned int rpcsec_gss_proc;
     89 	char *handle, *line;
     90 	struct cache_struct *x;
     91 	int pos;
     92 
     93 	pos = getxdr_pos();
     94 	rpcsec_gss_ver = getxdr_u_long();
     95 
     96 	/* see if we know this version or not */
     97 
     98 	if (rpcsec_gss_ver != 1) {
     99 		(void) showxdr_hex(authlen, "[%s]");
    100 		return;
    101 	}
    102 
    103 	rpcsec_gss_proc   = getxdr_u_long();
    104 	seq_num    = getxdr_u_long();
    105 	rpcsec_gss_service    = getxdr_enum();
    106 
    107 	(void) sprintf(get_line(pos, getxdr_pos()),
    108 		"   version = %u",  rpcsec_gss_ver);
    109 
    110 	(void) sprintf(get_line(pos, getxdr_pos()),
    111 		"   gss control procedure = %u (%s)",
    112 		rpcsec_gss_proc,
    113 		rpcsec_gss_proc_to_string(rpcsec_gss_proc));
    114 
    115 	(void) sprintf(get_line(pos, getxdr_pos()),
    116 		"   sequence num = %u", seq_num);
    117 
    118 	(void) sprintf(get_line(pos, getxdr_pos()),
    119 	    "   service = %d (%s)", rpcsec_gss_service,
    120 	    rpcsec_gss_service_to_string(rpcsec_gss_service));
    121 	pos = getxdr_pos();
    122 	handle_len = getxdr_u_long();
    123 	handle = getxdr_hex(handle_len);
    124 	line = get_line(pos, getxdr_pos());
    125 	sprintf(line, "   handle: length = %d, data = [%s]",
    126 			handle_len, handle);
    127 	x = find_xid(xid);
    128 	if (x) {
    129 		x->xid_gss_proc    = rpcsec_gss_proc;
    130 		x->xid_gss_service = rpcsec_gss_service;
    131 	}
    132 }
    133 
    134 /*
    135  *  Based on different RPCSEC_GSS services supported, maybe a
    136  *  special handling is needed before printing the arguments.
    137  *
    138  *  For integrity service : print the sequence number.
    139  *  For privacy service : do not print the arguments.
    140  */
    141 int
    142 rpcsec_gss_pre_proto(int type, int flags, int xid,
    143 					int prog, int vers, int proc)
    144 {
    145 	int seq;
    146 	struct cache_struct *x;
    147 
    148 	if (! (x = find_xid(xid)))
    149 		return (0);
    150 
    151 	switch (x->xid_gss_service) {
    152 	case rpc_gss_svc_default:
    153 	case rpc_gss_svc_none:
    154 		break; /* standard call args */
    155 	case rpc_gss_svc_integrity:
    156 		/* length of rpc_gss_data_t encoded in the databody_integ */
    157 		getxdr_u_long();
    158 		/* read the seq number */
    159 		seq = getxdr_u_long();
    160 		if (flags & F_ALLSUM) {
    161 			(void) sprintf(get_sum_line(), "%s %c seq_num = %u",
    162 				"RPC RPCSEC_GSS", type == CALL ? 'C' : 'R',
    163 				seq);
    164 		} else if (flags & F_DTAIL) {
    165 			sprintf(get_line(0, 0),
    166 				"RPCSEC_GSS data seq_num = %u", seq);
    167 			show_space();
    168 		}
    169 		/* call args follow */
    170 		break;
    171 	case rpc_gss_svc_privacy: {
    172 		char *progname = nameof_prog(prog);
    173 		char prognum[32];
    174 
    175 		if (*progname == '?') {
    176 			sprintf(prognum, "%d", prog);
    177 			progname = prognum;
    178 		}
    179 
    180 		if (flags & F_SUM || flags & F_ALLSUM) {
    181 		    (void) sprintf(get_sum_line(),
    182 			"%s %c %s ver(%d) proc(%d) (data encrypted) ",
    183 			"RPC RPCSEC_GSS", type == CALL ? 'C' : 'R',
    184 			progname, vers, proc);
    185 		} else if (flags & F_DTAIL) {
    186 		    unsigned int args_len;
    187 
    188 		    args_len = getxdr_u_long();
    189 		    sprintf(get_line(0, 0),
    190 			"RPCSEC_GSS %s ver(%d) proc(%d)",
    191 			progname, vers, proc);
    192 		    sprintf(get_line(0, 0),
    193 			"(%s args encrypted, len = %d bytes)",
    194 			type == CALL ? "CALL" : "REPLY", args_len);
    195 		    show_space();
    196 		}
    197 		}
    198 		return (1);
    199 
    200 	default:
    201 		break;
    202 	}
    203 	return (0);
    204 }
    205 
    206 /*
    207  *  Based on different RPCSEC_GSS services supported, maybe a
    208  *  special handling is needed after printing the arguments.
    209  *
    210  *  For integrity service : print the checksum.
    211  */
    212 void
    213 rpcsec_gss_post_proto(int flags, int xid)
    214 {
    215 	char *line;
    216 
    217 	struct cache_struct *x;
    218 
    219 	if (! (x = find_xid(xid)))
    220 		return;
    221 
    222 	switch (x->xid_gss_service) {
    223 	case rpc_gss_svc_default:
    224 	case rpc_gss_svc_none:
    225 	case rpc_gss_svc_privacy:
    226 		/* nothing left */
    227 		break;
    228 	case rpc_gss_svc_integrity:
    229 		if (flags & F_ALLSUM) {
    230 			line = get_sum_line();
    231 			sprintf(line, "RPC RPCSEC_GSS C (checksum)");
    232 		} else if (flags & F_DTAIL) {
    233 			unsigned int checksum_len;
    234 			char *checksum;
    235 
    236 			show_header("RPC:  ", "RPCSEC_GSS", 0);
    237 			show_space();
    238 			checksum_len = getxdr_u_long();
    239 			checksum = getxdr_hex(checksum_len);
    240 			sprintf(get_line(0, 0),
    241 				"checksum: len = %d", checksum_len);
    242 			sprintf(get_line(0, 0), "[%s]", checksum);
    243 			show_trailer();
    244 		}
    245 		break;
    246 	default:
    247 		break;
    248 	}
    249 }
    250 
    251 /*
    252  *  Print RPCSEC_GSS control procedures protocol data,
    253  *  No-op for RPCSEC_GSS_DATA.
    254  */
    255 int
    256 rpcsec_gss_control_proc(int type, int flags, int xid)
    257 {
    258 	int seq;
    259 
    260 	struct cache_struct *x;
    261 
    262 	if (! (x = find_xid(xid)))
    263 		return (0);
    264 
    265 	if (x->xid_gss_proc != RPCSEC_GSS_DATA) {
    266 		if (flags & F_SUM) {
    267 			if (type == CALL) {
    268 				(void) sprintf(get_sum_line(), "%s %c %u (%s)",
    269 				"RPC RPCSEC_GSS",
    270 				type == CALL ? 'C' : 'R',
    271 				x->xid_gss_proc,
    272 				rpcsec_gss_proc_to_string(x->xid_gss_proc));
    273 			}
    274 		} else if (flags & F_DTAIL) {
    275 			if (x->xid_gss_proc == RPCSEC_GSS_INIT ||
    276 			    x->xid_gss_proc == RPCSEC_GSS_CONTINUE_INIT) {
    277 				if (type == CALL) {
    278 					print_rpc_gss_init_arg(flags, x);
    279 				} else {
    280 					print_rpc_gss_init_res(flags);
    281 				}
    282 			}
    283 		}
    284 		return (1);
    285 	}
    286 
    287 	return (0);
    288 }
    289 
    290 /*
    291  *  Skip the header RPCSEC_GSS cred data and
    292  *  put service and control type in the xid cache.
    293  */
    294 void
    295 extract_rpcsec_gss_cred_info(int xid)
    296 {
    297 	unsigned int seq_num;
    298 	unsigned int handle_len;
    299 	unsigned int flavor_len;
    300 	unsigned int rpcsec_gss_ver;
    301 	rpc_gss_service_t rpcsec_gss_service;
    302 	unsigned int rpcsec_gss_proc;
    303 	struct cache_struct *x;
    304 
    305 	flavor_len = getxdr_u_long();
    306 	rpcsec_gss_ver = getxdr_u_long();
    307 	/* see if we know this version or not */
    308 	if (rpcsec_gss_ver != 1) {
    309 		longjmp(xdr_err, 1);
    310 	}
    311 	rpcsec_gss_proc   = getxdr_u_long();
    312 	seq_num    = getxdr_u_long();
    313 	rpcsec_gss_service    = getxdr_enum();
    314 	/* skip the handle */
    315 	xdr_skip(RNDUP(getxdr_u_long()));
    316 
    317 	if (x = find_xid(xid)) {
    318 		x->xid_gss_service = rpcsec_gss_service;
    319 		x->xid_gss_proc = rpcsec_gss_proc;
    320 	}
    321 
    322 }
    323 
    324 /*
    325  *  Print the argument data for the RPCSEC_GSS_INIT control procedure.
    326  */
    327 static void
    328 print_rpc_gss_init_arg(int flags, struct cache_struct *x)
    329 {
    330 
    331 	char *token, *line;
    332 	unsigned int token_len;
    333 	int pos;
    334 
    335 	/*
    336 	 *  see if we need to print out the rpc_gss_init_arg structure
    337 	 *  or not.
    338 	 */
    339 
    340 	if (x->xid_gss_proc != RPCSEC_GSS_INIT &&
    341 		x->xid_gss_proc != RPCSEC_GSS_CONTINUE_INIT) {
    342 		return;
    343 	}
    344 
    345 	/* print it */
    346 
    347 	(void) sprintf(get_line(pos, getxdr_pos()),
    348 		"RPCSEC_GSS_INIT args:");
    349 
    350 	pos = getxdr_pos();
    351 	token_len = getxdr_u_long();
    352 	token = getxdr_hex(token_len);
    353 	line = get_line(pos, getxdr_pos());
    354 		sprintf(line, "   gss token: length = %d, data = [%d bytes]",
    355 			token_len, token_len);
    356 
    357 	show_trailer();
    358 }
    359 
    360 /*
    361  *  Print the results data for the RPCSEC_GSS_INIT control procedure.
    362  */
    363 void
    364 print_rpc_gss_init_res(int flags)
    365 {
    366 
    367 	char *handle, *token, *line;
    368 	unsigned int token_len, handle_len;
    369 	unsigned int major, minor, seq_window;
    370 
    371 	int pos;
    372 	struct cache_struct *x;
    373 
    374 	/* print it */
    375 
    376 	(void) sprintf(get_line(pos, getxdr_pos()), "RPCSEC_GSS_INIT result:");
    377 
    378 	pos = getxdr_pos();
    379 	handle_len = getxdr_u_long();
    380 	handle = getxdr_hex(handle_len);
    381 	line = get_line(pos, getxdr_pos());
    382 	sprintf(line, "   handle: length = %d, data = [%s]",
    383 		handle_len, handle);
    384 	pos = getxdr_pos();
    385 	major = getxdr_u_long();
    386 	minor = getxdr_u_long();
    387 	seq_window = getxdr_u_long();
    388 
    389 	(void) sprintf(get_line(pos, getxdr_pos()),
    390 				"   gss_major status = %u", major);
    391 
    392 	(void) sprintf(get_line(pos, getxdr_pos()),
    393 				"   gss_minor status = %u", minor);
    394 
    395 	(void) sprintf(get_line(pos, getxdr_pos()),
    396 				"   sequence window  = %u", seq_window);
    397 	pos = getxdr_pos();
    398 	token_len = getxdr_u_long();
    399 	token = getxdr_hex(token_len);
    400 	line = get_line(pos, getxdr_pos());
    401 	sprintf(line, "   gss token: length = %d, data = [%d bytes]",
    402 		token_len, token_len);
    403 	show_trailer();
    404 }
    405