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