Home | History | Annotate | Download | only in src
      1 #include <stdio.h>
      2 #include "mls_level.h"
      3 #include <sepol/policydb/ebitmap.h>
      4 
      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  */
     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 
    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