1/*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source.  A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12/*
13 * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
14 */
15
16#include <mdb/mdb_modapi.h>
17#include <sys/types.h>
18#include <sys/cred_impl.h>
19#include <sys/sid.h>
20
21#include "cred.h"
22
23#define	OPT_VERBOSE	1
24
25static void print_ksid(const ksid_t *);
26
27/*
28 * dcmd ::cred - display a credential (cred_t)
29 */
30int
31cmd_cred(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
32{
33	credgrp_t cr_grps;
34	cred_t	*cr;
35	mdb_arg_t cmdarg;
36	uint_t opts = FALSE;
37
38	if (mdb_getopts(argc, argv,
39	    'v', MDB_OPT_SETBITS, OPT_VERBOSE, &opts, NULL) != argc)
40		return (DCMD_USAGE);
41
42	if (!(flags & DCMD_ADDRSPEC)) {
43		return (DCMD_USAGE);
44	}
45
46	cr = mdb_alloc(sizeof (*cr), UM_SLEEP | UM_GC);
47	if (mdb_vread(cr, sizeof (*cr), addr) == -1) {
48		mdb_warn("error reading cred_t at %p", addr);
49		return (DCMD_ERR);
50	}
51
52	if (cr->cr_grps == NULL) {
53		bzero(&cr_grps, sizeof (cr_grps));
54	} else {
55		if (mdb_vread(&cr_grps, sizeof (cr_grps),
56		    (uintptr_t)cr->cr_grps) == -1) {
57			mdb_warn("error reading credgrp_t at %p",
58			    cr->cr_grps);
59			return (DCMD_ERR);
60		}
61	}
62
63	if (opts & OPT_VERBOSE) {
64		cmdarg.a_type = MDB_TYPE_STRING;
65		cmdarg.a_un.a_str = "cred_t";
66		(void) mdb_call_dcmd("print", addr, flags, 1, &cmdarg);
67		cmdarg.a_un.a_str = "-v";
68
69		mdb_printf("%<u>cr_grps:%</u>\n");
70		mdb_inc_indent(4);
71		if (cr->cr_grps == NULL) {
72			mdb_printf("(null)\n");
73		} else {
74			(void) mdb_call_dcmd("credgrp",
75			    (uintptr_t)cr->cr_grps, flags, 1, &cmdarg);
76		}
77		mdb_dec_indent(4);
78
79		mdb_printf("%<u>cr_ksid:%</u>\n");
80		mdb_inc_indent(4);
81		if (cr->cr_ksid == NULL) {
82			mdb_printf("(null)\n");
83		} else {
84			(void) mdb_call_dcmd("credsid",
85			    (uintptr_t)cr->cr_ksid, flags, 1, &cmdarg);
86		}
87		mdb_dec_indent(4);
88
89		return (DCMD_OK);
90	}
91
92	if (DCMD_HDRSPEC(flags))
93		mdb_printf("%<u>%?s %8s %8s %8s %8s% %8s%</u>\n",
94		    "ADDR", "UID", "GID", "RUID", "RGID", "#GRP(+SIDS)");
95
96	mdb_printf("%0?p %8u %8u %8u %8u %4u%s\n", addr,
97	    cr->cr_uid,  cr->cr_gid,
98	    cr->cr_ruid, cr->cr_rgid,
99	    cr_grps.crg_ngroups,
100	    (cr->cr_ksid == NULL) ? "" : "+");
101
102	return (DCMD_OK);
103}
104
105/*
106 * dcmd ::credgrp - display cred_t groups
107 */
108int
109cmd_credgrp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
110{
111	credgrp_t grps;
112	gid_t gid;
113	uint_t i, opts = FALSE;
114	int rv = DCMD_OK;
115
116	if (mdb_getopts(argc, argv,
117	    'v', MDB_OPT_SETBITS, OPT_VERBOSE, &opts, NULL) != argc)
118		return (DCMD_USAGE);
119
120	if (!(flags & DCMD_ADDRSPEC)) {
121		return (DCMD_USAGE);
122	}
123
124	if (mdb_vread(&grps, sizeof (grps), addr) == -1) {
125		mdb_warn("error reading credgrp_t at %p", addr);
126		return (DCMD_ERR);
127	}
128
129	if (opts & OPT_VERBOSE) {
130		mdb_printf("crg_ref = 0x%x\n", grps.crg_ref);
131		mdb_printf("crg_ngroups = 0x%x\n", grps.crg_ngroups);
132	}
133	mdb_printf("crg_groups = [\n");
134
135	addr += OFFSETOF(credgrp_t, crg_groups);
136	mdb_inc_indent(4);
137	for (i = 0; i < grps.crg_ngroups; i++, addr += sizeof (gid_t)) {
138		if (mdb_vread(&gid, sizeof (gid), addr) == -1) {
139			mdb_warn("error reading gid_t at %p", addr);
140			rv = DCMD_ERR;
141			break;
142		}
143		mdb_printf("\t%u,", gid);
144	}
145	mdb_dec_indent(4);
146	mdb_printf("\n]\n");
147
148	return (rv);
149}
150
151/*
152 * dcmd ::credsid - display a credsid_t
153 */
154int
155cmd_credsid(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
156{
157	credsid_t kr;
158	uint_t opts = FALSE;
159	int rv = DCMD_OK;
160
161	if (mdb_getopts(argc, argv,
162	    'v', MDB_OPT_SETBITS, OPT_VERBOSE, &opts, NULL) != argc)
163		return (DCMD_USAGE);
164
165	if (!(flags & DCMD_ADDRSPEC)) {
166		return (DCMD_USAGE);
167	}
168
169	if (mdb_vread(&kr, sizeof (kr), addr) == -1) {
170		mdb_warn("error reading credsid_t at %p", addr);
171		return (DCMD_ERR);
172	}
173
174	if (opts & OPT_VERBOSE)
175		mdb_printf("kr_ref = 0x%x\n", kr.kr_ref);
176
177	mdb_printf("kr_sidx[USER]  = ");
178	print_ksid(&kr.kr_sidx[KSID_USER]);
179
180	mdb_printf("kr_sidx[GROUP] = ");
181	print_ksid(&kr.kr_sidx[KSID_GROUP]);
182
183	mdb_printf("kr_sidx[OWNER] = ");
184	print_ksid(&kr.kr_sidx[KSID_OWNER]);
185
186	mdb_printf("kr_sidlist = %p\n", kr.kr_sidlist);
187	if (kr.kr_sidlist != NULL && (opts & OPT_VERBOSE) != 0) {
188		mdb_printf("*kr_sidlist = {\n");
189		mdb_inc_indent(4);
190		rv = mdb_call_dcmd("ksidlist",
191		    (uintptr_t)kr.kr_sidlist, flags, argc, argv);
192		mdb_dec_indent(4);
193		mdb_printf("}\n");
194	}
195
196	return (rv);
197}
198
199/*
200 * dcmd ::ksidlist - display a ksidlist_t
201 */
202int
203cmd_ksidlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
204{
205	ksidlist_t ksl;
206	ksid_t ks;
207	uint_t i, opts = FALSE;
208	int rv = DCMD_OK;
209
210	if (mdb_getopts(argc, argv,
211	    'v', MDB_OPT_SETBITS, OPT_VERBOSE, &opts, NULL) != argc)
212		return (DCMD_USAGE);
213
214	if (!(flags & DCMD_ADDRSPEC)) {
215		return (DCMD_USAGE);
216	}
217
218	if (mdb_vread(&ksl, sizeof (ksl), addr) == -1) {
219		mdb_warn("error reading ksidlist_t at %p", addr);
220		return (DCMD_ERR);
221	}
222
223	if (opts & OPT_VERBOSE) {
224		mdb_printf("ksl_ref = 0x%x\n", ksl.ksl_ref);
225		mdb_printf("ksl_nsid = 0x%x\n", ksl.ksl_nsid);
226		mdb_printf("ksl_neid = 0x%x\n", ksl.ksl_neid);
227	}
228
229	mdb_printf("ksl_sids = [\n");
230	addr += OFFSETOF(ksidlist_t, ksl_sids);
231	mdb_inc_indent(4);
232	for (i = 0; i < ksl.ksl_nsid; i++, addr += sizeof (ksid_t)) {
233		if (mdb_vread(&ks, sizeof (ks), addr) == -1) {
234			mdb_warn("error reading ksid_t at %p", addr);
235			rv = DCMD_ERR;
236			break;
237		}
238		print_ksid(&ks);
239	}
240	mdb_dec_indent(4);
241	mdb_printf("]\n");
242
243	return (rv);
244}
245
246static void
247print_ksid(const ksid_t *ks)
248{
249	char str[80];
250	ksiddomain_t kd;
251	uintptr_t da, sa;
252
253	/* in case of errors */
254	strcpy(str, "(domain?)");
255
256	da = (uintptr_t)ks->ks_domain;
257	if (da == 0 || mdb_vread(&kd, sizeof (kd), da) < 0)
258		bzero(&kd, sizeof (kd));
259	sa = (uintptr_t)kd.kd_name;
260	if (sa != 0)
261		(void) mdb_readstr(str, sizeof (str), sa);
262
263	mdb_printf("%s-%u,\n", str, ks->ks_rid);
264}
265