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