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