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