Home | History | Annotate | Download | only in src
      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