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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 
28 /*
29  *	lslabels - Display all labels dominating the specified label.
30  */
31 
32 #include <errno.h>
33 #include <libintl.h>
34 #include <locale.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <unistd.h>
39 #include <stropts.h>
40 
41 #include <sys/param.h>
42 
43 #include <tsol/label.h>
44 #include <sys/tsol/label_macro.h>
45 #include <iso/limits_iso.h>
46 
47 #if !defined(TEXT_DOMAIN)
48 #define	TEXT_DOMAIN	 "SYS_TEST"
49 #endif	/* !defined(TEXT_DOMAIN) */
50 
51 int hflg = 0;			/* true if hex output */
52 
53 /*
54  * Compartment mask macros.
55  */
56 
57 typedef uint32_t comp_chunk_t;
58 
59 #define	__NBWRD		(CHAR_BIT * sizeof (comp_chunk_t))
60 #define	COMP_BITS	(CHAR_BIT * sizeof (Compartments_t))
61 #define	compmask(n)	(1 << ((__NBWRD - 1) - ((n) % __NBWRD)))
62 #define	compword(n)	((n)/__NBWRD)
63 
64 #define	COMP_ADDSET(a, p)	((comp_chunk_t *)(a))[compword(p)] |= \
65 				    compmask(p)
66 #define	COMP_DELSET(a, p)	((comp_chunk_t *)(a))[compword(p)] &= \
67 				    ~compmask(p)
68 #define	COMP_ISMEMBER(a, p)	((((comp_chunk_t *)(a))[compword(p)] & \
69 				    compmask(p)) != 0)
70 
71 /* Need functions to test if bit is on */
72 
73 
74 void
bitfinder(m_label_t label,int next_bit)75 bitfinder(m_label_t label, int next_bit) {
76 	char *labelstr = NULL;
77 
78 	Compartments_t *comps = &label.compartments;
79 
80 	while (next_bit < COMP_BITS) {
81 		if (COMP_ISMEMBER(comps, next_bit)) {
82 			bitfinder(label, next_bit + 1);
83 			COMP_DELSET(comps, next_bit);
84 
85 			if (label_to_str(&label, &labelstr, M_LABEL,
86 			    LONG_NAMES) == 0) {
87 				m_label_t *label2 = NULL;
88 				int err;
89 
90 				if (str_to_label(labelstr, &label2, MAC_LABEL,
91 				    L_NO_CORRECTION, &err) == 0) {
92 					if (!hflg) {
93 						(void) printf("%s\n", labelstr);
94 					} else {
95 						free(labelstr);
96 						(void) label_to_str(&label,
97 						    &labelstr, M_INTERNAL, 0);
98 						(void) printf("%s\n", labelstr);
99 					}
100 					m_label_free(label2);
101 				}
102 				free(labelstr);
103 			}
104 			bitfinder(label, next_bit + 1);
105 			break;
106 		}
107 		next_bit++;
108 		}
109 }
110 
111 static void
label_error(const char * ascii,const int err)112 label_error(const char *ascii, const int err)
113 {
114 	if (errno == EINVAL) {
115 		switch (err) {
116 		case M_BAD_STRING:
117 			(void) fprintf(stderr,
118 			    gettext("lslabels: bad string %s\n"), ascii);
119 		break;
120 		case M_BAD_LABEL:
121 			(void) fprintf(stderr,
122 			    gettext("lslabels: bad previous label\n"));
123 		break;
124 		default:
125 			(void) fprintf(stderr,
126 			    gettext("lslabels: parsing error found in "
127 			    "\"%s\" at position %d\n"), ascii, err);
128 		break;
129 		}
130 	} else {
131 		perror("lslabels");
132 	}
133 	exit(1);
134 	/*NOTREACHED*/
135 }
136 
137 int
main(int argc,char ** argv)138 main(int argc, char **argv)
139 {
140 	int errflg = 0;			/* true if arg error */
141 	m_label_t *label = NULL;	/* binary labels */
142 	char ascii[PIPE_BUF];		/* human readable label */
143 	char *labelstr = NULL;		/* external label to start from */
144 	int err = 0;			/* label error */
145 	int c;
146 	int mode = M_LABEL;
147 	_Classification *level;
148 
149 	(void) setlocale(LC_ALL, "");
150 	(void) textdomain(TEXT_DOMAIN);
151 
152 	opterr = 0;
153 	while ((c = getopt(argc, argv, "h")) != EOF) {
154 
155 		switch (c) {
156 		case 'h':
157 			hflg++;
158 			mode = M_INTERNAL;
159 			break;
160 
161 		default:
162 			errflg++;
163 			break;
164 		}
165 	}
166 
167 	argc -= optind - 1;
168 	if (errflg || argc > 2) {
169 
170 		(void) fprintf(stderr,
171 		    gettext("usage: %s [-h] [label]\n"),
172 		    argv[0]);
173 		exit(1);
174 		/*NOTREACHED*/
175 	}
176 
177 	if (argc == 2) {
178 		/* use label on command line */
179 
180 		(void) strlcpy(ascii, argv[optind], sizeof (ascii));
181 	} else {
182 		/* read label from standard input */
183 		if ((c = read(STDIN_FILENO, ascii, sizeof (ascii))) <= 0) {
184 			perror(gettext("reading ASCII coded label"));
185 			exit(1);
186 			/*NOTREACHED*/
187 		}
188 
189 		/*
190 		 * replace '\n' or (end of buffer) with end of string.
191 		 */
192 		ascii[c-1] = '\0';
193 
194 		/*
195 		 * flush any remaining input past the size of the buffer.
196 		 */
197 		(void) ioctl(STDIN_FILENO, I_FLUSH, FLUSHR);
198 	}
199 
200 	if (str_to_label(ascii, &label, MAC_LABEL, L_NO_CORRECTION,
201 	    &err) == -1) {
202 		label_error(ascii, err);
203 	}
204 	if (label_to_str(label, &labelstr, mode,
205 	    DEF_NAMES) == 0) {
206 		(void) printf("%s\n", labelstr);
207 	}
208 
209 	level =  &label->classification.class_u.class_chunk;
210 	while (*level > 0) {
211 		bitfinder(*label, 0);
212 		*level -= 1;
213 	}
214 	m_label_free(label);
215 
216 	return (0);		/* really exit(0); */
217 }
218