1 #include <stdio.h>
2 #include "mls_level.h"
3 #include <sepol/policydb/ebitmap.h>
4 
mls_level_from_string(char * mls_context)5 mls_level_t *mls_level_from_string(char *mls_context)
6 {
7 	char delim;
8 	char *scontextp, *p, *lptr;
9 	mls_level_t *l;
10 
11 	if (!mls_context) {
12 		return NULL;
13 	}
14 
15 	l = (mls_level_t *) calloc(1, sizeof(mls_level_t));
16 
17 	/* Extract low sensitivity. */
18 	scontextp = p = mls_context;
19 	while (*p && *p != ':' && *p != '-')
20 		p++;
21 
22 	delim = *p;
23 	if (delim != 0)
24 		*p++ = 0;
25 
26 	if (*scontextp != 's')
27 		goto err;
28 	l->sens = atoi(scontextp + 1);
29 
30 	if (delim == ':') {
31 		/* Extract category set. */
32 		while (1) {
33 			scontextp = p;
34 			while (*p && *p != ',' && *p != '-')
35 				p++;
36 			delim = *p;
37 			if (delim != 0)
38 				*p++ = 0;
39 
40 			/* Separate into level if exists */
41 			if ((lptr = strchr(scontextp, '.')) != NULL) {
42 				/* Remove '.' */
43 				*lptr++ = 0;
44 			}
45 
46 			if (*scontextp != 'c')
47 				goto err;
48 			int bit = atoi(scontextp + 1);
49 			if (ebitmap_set_bit(&l->cat, bit, 1))
50 				goto err;
51 
52 			/* If level, set all categories in level */
53 			if (lptr) {
54 				if (*lptr != 'c')
55 					goto err;
56 				int ubit = atoi(lptr + 1);
57 				int i;
58 				for (i = bit + 1; i <= ubit; i++) {
59 					if (ebitmap_set_bit
60 					    (&l->cat, i, 1))
61 						goto err;
62 				}
63 			}
64 
65 			if (delim != ',')
66 				break;
67 		}
68 	}
69 
70 	return l;
71 
72       err:
73 	free(l);
74 	return NULL;
75 }
76 
77 /*
78  * Return the length in bytes for the MLS fields of the
79  * security context string representation of `context'.
80  */
mls_compute_string_len(mls_level_t * l)81 unsigned int mls_compute_string_len(mls_level_t *l)
82 {
83 	unsigned int len = 0;
84 	char temp[16];
85 	unsigned int i, level = 0;
86 	ebitmap_node_t *cnode;
87 
88 	if (!l)
89 		return 0;
90 
91 	len += snprintf(temp, sizeof(temp), "s%d", l->sens);
92 
93 	ebitmap_for_each_bit(&l->cat, cnode, i) {
94 		if (ebitmap_node_get_bit(cnode, i)) {
95 			if (level) {
96 				level++;
97 				continue;
98 			}
99 
100 			len++; /* : or ,` */
101 
102 			len += snprintf(temp, sizeof(temp), "c%d", i);
103 			level++;
104 		} else {
105 			if (level > 1)
106 				len += snprintf(temp, sizeof(temp), ".c%d", i-1);
107 			level = 0;
108 		}
109 	}
110 
111 	/* Handle case where last category is the end of level */
112 	if (level > 1)
113 		len += snprintf(temp, sizeof(temp), ".c%d", i-1);
114 	return len;
115 }
116 
mls_level_to_string(mls_level_t * l)117 char *mls_level_to_string(mls_level_t *l)
118 {
119 	unsigned int wrote_sep, len = mls_compute_string_len(l);
120 	unsigned int i, level = 0;
121 	ebitmap_node_t *cnode;
122 	wrote_sep = 0;
123 
124 	if (len == 0)
125 		return NULL;
126 	char *result = (char *)malloc(len + 1);
127 	char *p = result;
128 
129 	p += sprintf(p, "s%d", l->sens);
130 
131 	/* categories */
132 	ebitmap_for_each_bit(&l->cat, cnode, i) {
133 		if (ebitmap_node_get_bit(cnode, i)) {
134 			if (level) {
135 				level++;
136 				continue;
137 			}
138 
139 			if (!wrote_sep) {
140 				*p++ = ':';
141 				wrote_sep = 1;
142 			} else
143 				*p++ = ',';
144 			p += sprintf(p, "c%d", i);
145 			level++;
146 		} else {
147 			if (level > 1) {
148 				if (level > 2)
149 					*p++ = '.';
150 				else
151 					*p++ = ',';
152 
153 				p += sprintf(p, "c%d", i-1);
154 			}
155 			level = 0;
156 		}
157 	}
158 	/* Handle case where last category is the end of level */
159 	if (level > 1) {
160 		if (level > 2)
161 			*p++ = '.';
162 		else
163 			*p++ = ',';
164 
165 		p += sprintf(p, "c%d", i-1);
166 	}
167 
168 	*(result + len) = 0;
169 	return result;
170 }
171