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