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