Home | History | Annotate | Download | only in src
      1 #include <errno.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include <stdio.h>
      5 
      6 #include "context_internal.h"
      7 #include "debug.h"
      8 #include "private.h"
      9 
     10 struct sepol_context {
     11 
     12 	/* Selinux user */
     13 	char *user;
     14 
     15 	/* Selinux role */
     16 	char *role;
     17 
     18 	/* Selinux type */
     19 	char *type;
     20 
     21 	/* MLS */
     22 	char *mls;
     23 };
     24 
     25 /* User */
     26 const char *sepol_context_get_user(const sepol_context_t * con)
     27 {
     28 
     29 	return con->user;
     30 }
     31 
     32 hidden_def(sepol_context_get_user)
     33 
     34 int sepol_context_set_user(sepol_handle_t * handle,
     35 			   sepol_context_t * con, const char *user)
     36 {
     37 
     38 	char *tmp_user = strdup(user);
     39 	if (!tmp_user) {
     40 		ERR(handle, "out of memory, could not set "
     41 		    "context user to %s", user);
     42 		return STATUS_ERR;
     43 	}
     44 
     45 	free(con->user);
     46 	con->user = tmp_user;
     47 	return STATUS_SUCCESS;
     48 }
     49 
     50 hidden_def(sepol_context_set_user)
     51 
     52 /* Role */
     53 const char *sepol_context_get_role(const sepol_context_t * con)
     54 {
     55 
     56 	return con->role;
     57 }
     58 
     59 hidden_def(sepol_context_get_role)
     60 
     61 int sepol_context_set_role(sepol_handle_t * handle,
     62 			   sepol_context_t * con, const char *role)
     63 {
     64 
     65 	char *tmp_role = strdup(role);
     66 	if (!tmp_role) {
     67 		ERR(handle, "out of memory, could not set "
     68 		    "context role to %s", role);
     69 		return STATUS_ERR;
     70 	}
     71 	free(con->role);
     72 	con->role = tmp_role;
     73 	return STATUS_SUCCESS;
     74 }
     75 
     76 hidden_def(sepol_context_set_role)
     77 
     78 /* Type */
     79 const char *sepol_context_get_type(const sepol_context_t * con)
     80 {
     81 
     82 	return con->type;
     83 }
     84 
     85 hidden_def(sepol_context_get_type)
     86 
     87 int sepol_context_set_type(sepol_handle_t * handle,
     88 			   sepol_context_t * con, const char *type)
     89 {
     90 
     91 	char *tmp_type = strdup(type);
     92 	if (!tmp_type) {
     93 		ERR(handle, "out of memory, could not set "
     94 		    "context type to %s", type);
     95 		return STATUS_ERR;
     96 	}
     97 	free(con->type);
     98 	con->type = tmp_type;
     99 	return STATUS_SUCCESS;
    100 }
    101 
    102 hidden_def(sepol_context_set_type)
    103 
    104 /* MLS */
    105 const char *sepol_context_get_mls(const sepol_context_t * con)
    106 {
    107 
    108 	return con->mls;
    109 }
    110 
    111 hidden_def(sepol_context_get_mls)
    112 
    113 int sepol_context_set_mls(sepol_handle_t * handle,
    114 			  sepol_context_t * con, const char *mls)
    115 {
    116 
    117 	char *tmp_mls = strdup(mls);
    118 	if (!tmp_mls) {
    119 		ERR(handle, "out of memory, could not set "
    120 		    "MLS fields to %s", mls);
    121 		return STATUS_ERR;
    122 	}
    123 	free(con->mls);
    124 	con->mls = tmp_mls;
    125 	return STATUS_SUCCESS;
    126 }
    127 
    128 hidden_def(sepol_context_set_mls)
    129 
    130 /* Create */
    131 int sepol_context_create(sepol_handle_t * handle, sepol_context_t ** con_ptr)
    132 {
    133 
    134 	sepol_context_t *con =
    135 	    (sepol_context_t *) malloc(sizeof(sepol_context_t));
    136 
    137 	if (!con) {
    138 		ERR(handle, "out of memory, could not " "create context\n");
    139 		return STATUS_ERR;
    140 	}
    141 
    142 	con->user = NULL;
    143 	con->role = NULL;
    144 	con->type = NULL;
    145 	con->mls = NULL;
    146 	*con_ptr = con;
    147 	return STATUS_SUCCESS;
    148 }
    149 
    150 hidden_def(sepol_context_create)
    151 
    152 /* Deep copy clone */
    153 int sepol_context_clone(sepol_handle_t * handle,
    154 			const sepol_context_t * con, sepol_context_t ** con_ptr)
    155 {
    156 
    157 	sepol_context_t *new_con = NULL;
    158 
    159 	if (!con) {
    160 		*con_ptr = NULL;
    161 		return 0;
    162 	}
    163 
    164 	if (sepol_context_create(handle, &new_con) < 0)
    165 		goto err;
    166 
    167 	if (!(new_con->user = strdup(con->user)))
    168 		goto omem;
    169 
    170 	if (!(new_con->role = strdup(con->role)))
    171 		goto omem;
    172 
    173 	if (!(new_con->type = strdup(con->type)))
    174 		goto omem;
    175 
    176 	if (con->mls && !(new_con->mls = strdup(con->mls)))
    177 		goto omem;
    178 
    179 	*con_ptr = new_con;
    180 	return STATUS_SUCCESS;
    181 
    182       omem:
    183 	ERR(handle, "out of memory");
    184 
    185       err:
    186 	ERR(handle, "could not clone context record");
    187 	sepol_context_free(new_con);
    188 	return STATUS_ERR;
    189 }
    190 
    191 hidden_def(sepol_context_clone)
    192 
    193 /* Destroy */
    194 void sepol_context_free(sepol_context_t * con)
    195 {
    196 
    197 	if (!con)
    198 		return;
    199 
    200 	free(con->user);
    201 	free(con->role);
    202 	free(con->type);
    203 	free(con->mls);
    204 	free(con);
    205 }
    206 
    207 hidden_def(sepol_context_free)
    208 
    209 int sepol_context_from_string(sepol_handle_t * handle,
    210 			      const char *str, sepol_context_t ** con)
    211 {
    212 
    213 	char *tmp = NULL, *low, *high;
    214 	sepol_context_t *tmp_con = NULL;
    215 
    216 	if (!strcmp(str, "<<none>>")) {
    217 		*con = NULL;
    218 		return STATUS_SUCCESS;
    219 	}
    220 
    221 	if (sepol_context_create(handle, &tmp_con) < 0)
    222 		goto err;
    223 
    224 	/* Working copy context */
    225 	tmp = strdup(str);
    226 	if (!tmp) {
    227 		ERR(handle, "out of memory");
    228 		goto err;
    229 	}
    230 	low = tmp;
    231 
    232 	/* Then, break it into its components */
    233 
    234 	/* User */
    235 	if (!(high = strchr(low, ':')))
    236 		goto mcontext;
    237 	else
    238 		*high++ = '\0';
    239 	if (sepol_context_set_user(handle, tmp_con, low) < 0)
    240 		goto err;
    241 	low = high;
    242 
    243 	/* Role */
    244 	if (!(high = strchr(low, ':')))
    245 		goto mcontext;
    246 	else
    247 		*high++ = '\0';
    248 	if (sepol_context_set_role(handle, tmp_con, low) < 0)
    249 		goto err;
    250 	low = high;
    251 
    252 	/* Type, and possibly MLS */
    253 	if (!(high = strchr(low, ':'))) {
    254 		if (sepol_context_set_type(handle, tmp_con, low) < 0)
    255 			goto err;
    256 	} else {
    257 		*high++ = '\0';
    258 		if (sepol_context_set_type(handle, tmp_con, low) < 0)
    259 			goto err;
    260 		low = high;
    261 		if (sepol_context_set_mls(handle, tmp_con, low) < 0)
    262 			goto err;
    263 	}
    264 
    265 	free(tmp);
    266 	*con = tmp_con;
    267 
    268 	return STATUS_SUCCESS;
    269 
    270       mcontext:
    271 	errno = EINVAL;
    272 	ERR(handle, "malformed context \"%s\"", str);
    273 
    274       err:
    275 	ERR(handle, "could not construct context from string");
    276 	free(tmp);
    277 	sepol_context_free(tmp_con);
    278 	return STATUS_ERR;
    279 }
    280 
    281 hidden_def(sepol_context_from_string)
    282 
    283 static inline int safe_sum(size_t *sum, const size_t augends[], const size_t cnt) {
    284 
    285 	size_t a, i;
    286 
    287 	*sum = 0;
    288 	for(i=0; i < cnt; i++) {
    289 		/* sum should not be smaller than the addend */
    290 		a = augends[i];
    291 		*sum += a;
    292 		if (*sum < a) {
    293 			return i;
    294 		}
    295 	}
    296 
    297 	return 0;
    298 }
    299 
    300 int sepol_context_to_string(sepol_handle_t * handle,
    301 			    const sepol_context_t * con, char **str_ptr)
    302 {
    303 
    304 	int rc;
    305 	char *str = NULL;
    306 	size_t total_sz, err;
    307 	const size_t sizes[] = {
    308 			strlen(con->user),                 /* user length */
    309 			strlen(con->role),                 /* role length */
    310 			strlen(con->type),                 /* type length */
    311 			(con->mls) ? strlen(con->mls) : 0, /* mls length */
    312 			((con->mls) ? 3 : 2) + 1           /* mls has extra ":" also null byte */
    313 	};
    314 
    315 	err = safe_sum(&total_sz, sizes, ARRAY_SIZE(sizes));
    316 	if (err) {
    317 		ERR(handle, "invalid size, overflow at position: %zu", err);
    318 		goto err;
    319 	}
    320 
    321 	str = (char *)malloc(total_sz);
    322 	if (!str) {
    323 		ERR(handle, "out of memory");
    324 		goto err;
    325 	}
    326 	if (con->mls) {
    327 		rc = snprintf(str, total_sz, "%s:%s:%s:%s",
    328 			      con->user, con->role, con->type, con->mls);
    329 	} else {
    330 		rc = snprintf(str, total_sz, "%s:%s:%s",
    331 			      con->user, con->role, con->type);
    332 	}
    333 
    334 	/*
    335 	 * rc is >= 0 on the size_t cast and is safe to promote
    336 	 * to an unsigned value.
    337 	 */
    338 	if (rc < 0 || (size_t)rc >= total_sz) {
    339 		ERR(handle, "print error");
    340 		goto err;
    341 	}
    342 
    343 	*str_ptr = str;
    344 	return STATUS_SUCCESS;
    345 
    346       err:
    347 	ERR(handle, "could not convert context to string");
    348 	free(str);
    349 	return STATUS_ERR;
    350 }
    351