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