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