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