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 * Copyright 2012 Milan Jurik. All rights reserved.
26 * Copyright 2017 Gary Mills
27 */
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 *
rpcsec_gss_proc_to_string(unsigned int proc)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 *
rpcsec_gss_service_to_string(rpc_gss_service_t service)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
print_rpcsec_gss_cred(int xid,int authlen)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
rpcsec_gss_pre_proto(int type,int flags,int xid,int prog,int vers,int proc)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
rpcsec_gss_post_proto(int flags,int xid)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
rpcsec_gss_control_proc(int type,int flags,int xid)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
extract_rpcsec_gss_cred_info(int xid)295 extract_rpcsec_gss_cred_info(int xid)
296 {
297 unsigned int handle_len;
298 unsigned int rpcsec_gss_ver;
299 rpc_gss_service_t rpcsec_gss_service;
300 unsigned int rpcsec_gss_proc;
301 struct cache_struct *x;
302
303 (void) getxdr_u_long();
304 rpcsec_gss_ver = getxdr_u_long();
305 /* see if we know this version or not */
306 if (rpcsec_gss_ver != 1) {
307 longjmp(xdr_err, 1);
308 }
309 rpcsec_gss_proc = getxdr_u_long();
310 (void) getxdr_u_long();
311 rpcsec_gss_service = getxdr_enum();
312 /* skip the handle */
313 xdr_skip(RNDUP(getxdr_u_long()));
314
315 if (x = find_xid(xid)) {
316 x->xid_gss_service = rpcsec_gss_service;
317 x->xid_gss_proc = rpcsec_gss_proc;
318 }
319
320 }
321
322 /*
323 * Print the argument data for the RPCSEC_GSS_INIT control procedure.
324 */
325 static void
print_rpc_gss_init_arg(int flags,struct cache_struct * x)326 print_rpc_gss_init_arg(int flags, struct cache_struct *x)
327 {
328
329 char *line;
330 unsigned int token_len;
331 int pos = 0;
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 (void) 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 void
print_rpc_gss_init_res(int flags)362 print_rpc_gss_init_res(int flags)
363 {
364
365 char *handle, *line;
366 unsigned int token_len, handle_len;
367 unsigned int major, minor, seq_window;
368
369 int pos = 0;
370 struct cache_struct *x;
371
372 /* print it */
373
374 (void) sprintf(get_line(pos, getxdr_pos()), "RPCSEC_GSS_INIT result:");
375
376 pos = getxdr_pos();
377 handle_len = getxdr_u_long();
378 handle = getxdr_hex(handle_len);
379 line = get_line(pos, getxdr_pos());
380 sprintf(line, " handle: length = %d, data = [%s]",
381 handle_len, handle);
382 pos = getxdr_pos();
383 major = getxdr_u_long();
384 minor = getxdr_u_long();
385 seq_window = getxdr_u_long();
386
387 (void) sprintf(get_line(pos, getxdr_pos()),
388 " gss_major status = %u", major);
389
390 (void) sprintf(get_line(pos, getxdr_pos()),
391 " gss_minor status = %u", minor);
392
393 (void) sprintf(get_line(pos, getxdr_pos()),
394 " sequence window = %u", seq_window);
395 pos = getxdr_pos();
396 token_len = getxdr_u_long();
397 (void) getxdr_hex(token_len);
398 line = get_line(pos, getxdr_pos());
399 sprintf(line, " gss token: length = %d, data = [%d bytes]",
400 token_len, token_len);
401 show_trailer();
402 }
403