1 #include <stdlib.h> 2 #include <string.h> 3 #include <errno.h> 4 5 #include <sepol/policydb/policydb.h> 6 #include <sepol/policydb/services.h> 7 #include "context_internal.h" 8 9 #include "debug.h" 10 #include "context.h" 11 #include "handle.h" 12 #include "mls.h" 13 #include "private.h" 14 15 /* ----- Compatibility ---- */ 16 int policydb_context_isvalid(const policydb_t * p, const context_struct_t * c) 17 { 18 19 return context_is_valid(p, c); 20 } 21 22 int sepol_check_context(const char *context) 23 { 24 25 return sepol_context_to_sid((const sepol_security_context_t)context, 26 strlen(context) + 1, NULL); 27 } 28 29 /* ---- End compatibility --- */ 30 31 /* 32 * Return 1 if the fields in the security context 33 * structure `c' are valid. Return 0 otherwise. 34 */ 35 int context_is_valid(const policydb_t * p, const context_struct_t * c) 36 { 37 38 role_datum_t *role; 39 user_datum_t *usrdatum; 40 ebitmap_t types, roles; 41 int ret = 1; 42 43 ebitmap_init(&types); 44 ebitmap_init(&roles); 45 if (!c->role || c->role > p->p_roles.nprim) 46 return 0; 47 48 if (!c->user || c->user > p->p_users.nprim) 49 return 0; 50 51 if (!c->type || c->type > p->p_types.nprim) 52 return 0; 53 54 if (c->role != OBJECT_R_VAL) { 55 /* 56 * Role must be authorized for the type. 57 */ 58 role = p->role_val_to_struct[c->role - 1]; 59 if (!role || !ebitmap_get_bit(&role->cache, c->type - 1)) 60 /* role may not be associated with type */ 61 return 0; 62 63 /* 64 * User must be authorized for the role. 65 */ 66 usrdatum = p->user_val_to_struct[c->user - 1]; 67 if (!usrdatum) 68 return 0; 69 70 if (!ebitmap_get_bit(&usrdatum->cache, c->role - 1)) 71 /* user may not be associated with role */ 72 return 0; 73 } 74 75 if (!mls_context_isvalid(p, c)) 76 return 0; 77 78 return ret; 79 } 80 81 /* 82 * Write the security context string representation of 83 * the context structure `context' into a dynamically 84 * allocated string of the correct size. Set `*scontext' 85 * to point to this string and set `*scontext_len' to 86 * the length of the string. 87 */ 88 int context_to_string(sepol_handle_t * handle, 89 const policydb_t * policydb, 90 const context_struct_t * context, 91 char **result, size_t * result_len) 92 { 93 94 char *scontext = NULL; 95 size_t scontext_len = 0; 96 char *ptr; 97 98 /* Compute the size of the context. */ 99 scontext_len += 100 strlen(policydb->p_user_val_to_name[context->user - 1]) + 1; 101 scontext_len += 102 strlen(policydb->p_role_val_to_name[context->role - 1]) + 1; 103 scontext_len += strlen(policydb->p_type_val_to_name[context->type - 1]); 104 scontext_len += mls_compute_context_len(policydb, context); 105 106 /* We must null terminate the string */ 107 scontext_len += 1; 108 109 /* Allocate space for the context; caller must free this space. */ 110 scontext = malloc(scontext_len); 111 if (!scontext) 112 goto omem; 113 scontext[scontext_len - 1] = '\0'; 114 115 /* 116 * Copy the user name, role name and type name into the context. 117 */ 118 ptr = scontext; 119 sprintf(ptr, "%s:%s:%s", 120 policydb->p_user_val_to_name[context->user - 1], 121 policydb->p_role_val_to_name[context->role - 1], 122 policydb->p_type_val_to_name[context->type - 1]); 123 124 ptr += 125 strlen(policydb->p_user_val_to_name[context->user - 1]) + 1 + 126 strlen(policydb->p_role_val_to_name[context->role - 1]) + 1 + 127 strlen(policydb->p_type_val_to_name[context->type - 1]); 128 129 mls_sid_to_context(policydb, context, &ptr); 130 131 *result = scontext; 132 *result_len = scontext_len; 133 return STATUS_SUCCESS; 134 135 omem: 136 ERR(handle, "out of memory, could not convert " "context to string"); 137 free(scontext); 138 return STATUS_ERR; 139 } 140 141 /* 142 * Create a context structure from the given record 143 */ 144 int context_from_record(sepol_handle_t * handle, 145 const policydb_t * policydb, 146 context_struct_t ** cptr, 147 const sepol_context_t * record) 148 { 149 150 context_struct_t *scontext = NULL; 151 user_datum_t *usrdatum; 152 role_datum_t *roldatum; 153 type_datum_t *typdatum; 154 155 /* Hashtab keys are not constant - suppress warnings */ 156 char *user = strdup(sepol_context_get_user(record)); 157 char *role = strdup(sepol_context_get_role(record)); 158 char *type = strdup(sepol_context_get_type(record)); 159 const char *mls = sepol_context_get_mls(record); 160 161 scontext = (context_struct_t *) malloc(sizeof(context_struct_t)); 162 if (!user || !role || !type || !scontext) { 163 ERR(handle, "out of memory"); 164 goto err; 165 } 166 context_init(scontext); 167 168 /* User */ 169 usrdatum = (user_datum_t *) hashtab_search(policydb->p_users.table, 170 (hashtab_key_t) user); 171 if (!usrdatum) { 172 ERR(handle, "user %s is not defined", user); 173 goto err_destroy; 174 } 175 scontext->user = usrdatum->s.value; 176 177 /* Role */ 178 roldatum = (role_datum_t *) hashtab_search(policydb->p_roles.table, 179 (hashtab_key_t) role); 180 if (!roldatum) { 181 ERR(handle, "role %s is not defined", role); 182 goto err_destroy; 183 } 184 scontext->role = roldatum->s.value; 185 186 /* Type */ 187 typdatum = (type_datum_t *) hashtab_search(policydb->p_types.table, 188 (hashtab_key_t) type); 189 if (!typdatum || typdatum->flavor == TYPE_ATTRIB) { 190 ERR(handle, "type %s is not defined", type); 191 goto err_destroy; 192 } 193 scontext->type = typdatum->s.value; 194 195 /* MLS */ 196 if (mls && !policydb->mls) { 197 ERR(handle, "MLS is disabled, but MLS context \"%s\" found", 198 mls); 199 goto err_destroy; 200 } else if (!mls && policydb->mls) { 201 ERR(handle, "MLS is enabled, but no MLS context found"); 202 goto err_destroy; 203 } 204 if (mls && (mls_from_string(handle, policydb, mls, scontext) < 0)) 205 goto err_destroy; 206 207 /* Validity check */ 208 if (!context_is_valid(policydb, scontext)) { 209 if (mls) { 210 ERR(handle, 211 "invalid security context: \"%s:%s:%s:%s\"", 212 user, role, type, mls); 213 } else { 214 ERR(handle, 215 "invalid security context: \"%s:%s:%s\"", 216 user, role, type); 217 } 218 goto err_destroy; 219 } 220 221 *cptr = scontext; 222 free(user); 223 free(type); 224 free(role); 225 return STATUS_SUCCESS; 226 227 err_destroy: 228 errno = EINVAL; 229 context_destroy(scontext); 230 231 err: 232 free(scontext); 233 free(user); 234 free(type); 235 free(role); 236 ERR(handle, "could not create context structure"); 237 return STATUS_ERR; 238 } 239 240 /* 241 * Create a record from the given context structure 242 */ 243 int context_to_record(sepol_handle_t * handle, 244 const policydb_t * policydb, 245 const context_struct_t * context, 246 sepol_context_t ** record) 247 { 248 249 sepol_context_t *tmp_record = NULL; 250 char *mls = NULL; 251 252 if (sepol_context_create(handle, &tmp_record) < 0) 253 goto err; 254 255 if (sepol_context_set_user(handle, tmp_record, 256 policydb->p_user_val_to_name[context->user - 257 1]) < 0) 258 goto err; 259 260 if (sepol_context_set_role(handle, tmp_record, 261 policydb->p_role_val_to_name[context->role - 262 1]) < 0) 263 goto err; 264 265 if (sepol_context_set_type(handle, tmp_record, 266 policydb->p_type_val_to_name[context->type - 267 1]) < 0) 268 goto err; 269 270 if (policydb->mls) { 271 if (mls_to_string(handle, policydb, context, &mls) < 0) 272 goto err; 273 274 if (sepol_context_set_mls(handle, tmp_record, mls) < 0) 275 goto err; 276 } 277 278 free(mls); 279 *record = tmp_record; 280 return STATUS_SUCCESS; 281 282 err: 283 ERR(handle, "could not create context record"); 284 sepol_context_free(tmp_record); 285 free(mls); 286 return STATUS_ERR; 287 } 288 289 /* 290 * Create a context structure from the provided string. 291 */ 292 int context_from_string(sepol_handle_t * handle, 293 const policydb_t * policydb, 294 context_struct_t ** cptr, 295 const char *con_str, size_t con_str_len) 296 { 297 298 char *con_cpy = NULL; 299 sepol_context_t *ctx_record = NULL; 300 301 if (zero_or_saturated(con_str_len)) { 302 ERR(handle, "Invalid context length"); 303 goto err; 304 } 305 306 /* sepol_context_from_string expects a NULL-terminated string */ 307 con_cpy = malloc(con_str_len + 1); 308 if (!con_cpy) { 309 ERR(handle, "out of memory"); 310 goto err; 311 } 312 313 memcpy(con_cpy, con_str, con_str_len); 314 con_cpy[con_str_len] = '\0'; 315 316 if (sepol_context_from_string(handle, con_cpy, &ctx_record) < 0) 317 goto err; 318 319 /* Now create from the data structure */ 320 if (context_from_record(handle, policydb, cptr, ctx_record) < 0) 321 goto err; 322 323 free(con_cpy); 324 sepol_context_free(ctx_record); 325 return STATUS_SUCCESS; 326 327 err: 328 ERR(handle, "could not create context structure"); 329 free(con_cpy); 330 sepol_context_free(ctx_record); 331 return STATUS_ERR; 332 } 333 334 int sepol_context_check(sepol_handle_t * handle, 335 const sepol_policydb_t * policydb, 336 const sepol_context_t * context) 337 { 338 339 context_struct_t *con = NULL; 340 int ret = context_from_record(handle, &policydb->p, &con, context); 341 context_destroy(con); 342 free(con); 343 return ret; 344 } 345