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