Home | History | Annotate | Download | only in src
      1 /* Copyright (C) 2005 Red Hat, Inc. */
      2 
      3 struct semanage_seuser;
      4 struct semanage_seuser_key;
      5 typedef struct semanage_seuser_key record_key_t;
      6 typedef struct semanage_seuser record_t;
      7 #define DBASE_RECORD_DEFINED
      8 
      9 #include <sepol/policydb.h>
     10 #include <sepol/context.h>
     11 #include <libaudit.h>
     12 #include <errno.h>
     13 #include "user_internal.h"
     14 #include "seuser_internal.h"
     15 #include "handle.h"
     16 #include "database.h"
     17 #include "debug.h"
     18 #include "string.h"
     19 #include <stdlib.h>
     20 
     21 static char *semanage_user_roles(semanage_handle_t * handle, const char *sename) {
     22 	char *roles = NULL;
     23 	unsigned int num_roles;
     24 	size_t i;
     25 	size_t size = 0;
     26 	const char **roles_arr;
     27 	semanage_user_key_t *key = NULL;
     28 	semanage_user_t * user;
     29 	if (semanage_user_key_create(handle, sename, &key) >= 0) {
     30 		if (semanage_user_query(handle, key, &user) >= 0) {
     31 			if (semanage_user_get_roles(handle,
     32 						    user,
     33 						    &roles_arr,
     34 						    &num_roles) >= 0) {
     35 				for (i = 0; i<num_roles; i++) {
     36 					size += (strlen(roles_arr[i]) + 1);
     37 				}
     38 				roles = malloc(size);
     39 				if (roles) {
     40 					strcpy(roles,roles_arr[0]);
     41 					for (i = 1; i<num_roles; i++) {
     42 						strcat(roles,",");
     43 						strcat(roles,roles_arr[i]);
     44 					}
     45 				}
     46 			}
     47 			semanage_user_free(user);
     48 		}
     49 		semanage_user_key_free(key);
     50 	}
     51 	return roles;
     52 }
     53 
     54 static int semanage_seuser_audit(semanage_handle_t * handle,
     55 			  const semanage_seuser_t * seuser,
     56 			  const semanage_seuser_t * previous,
     57 			  int audit_type,
     58 			  int success) {
     59 	const char *name = NULL;
     60 	const char *sename = NULL;
     61 	char *roles = NULL;
     62 	const char *mls = NULL;
     63 	const char *psename = NULL;
     64 	const char *pmls = NULL;
     65 	char *proles = NULL;
     66 	char msg[1024];
     67 	const char *sep = "-";
     68 	int rc = -1;
     69 	strcpy(msg, "login");
     70 	if (seuser) {
     71 		name = semanage_seuser_get_name(seuser);
     72 		sename = semanage_seuser_get_sename(seuser);
     73 		mls = semanage_seuser_get_mlsrange(seuser);
     74 		roles = semanage_user_roles(handle, sename);
     75 	}
     76 	if (previous) {
     77 		psename = semanage_seuser_get_sename(previous);
     78 		pmls = semanage_seuser_get_mlsrange(previous);
     79 		proles = semanage_user_roles(handle, psename);
     80 	}
     81 	if (audit_type != AUDIT_ROLE_REMOVE) {
     82 		if (sename && (!psename || strcmp(psename, sename) != 0)) {
     83 			strcat(msg,sep);
     84 			strcat(msg,"sename");
     85 			sep = ",";
     86 		}
     87 		if (roles && (!proles || strcmp(proles, roles) != 0)) {
     88 			strcat(msg,sep);
     89 			strcat(msg,"role");
     90 			sep = ",";
     91 		}
     92 		if (mls && (!pmls || strcmp(pmls, mls) != 0)) {
     93 			strcat(msg,sep);
     94 			strcat(msg,"range");
     95 		}
     96 	}
     97 
     98 	int fd = audit_open();
     99 	if (fd < 0)
    100 	{
    101 		/* If kernel doesn't support audit, bail out */
    102 		if (errno == EINVAL || errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT) {
    103 			rc = 0;
    104 			goto err;
    105 		}
    106 		rc = fd;
    107 		goto err;
    108 	}
    109 	audit_log_semanage_message(fd, audit_type, NULL, msg, name, 0, sename, roles, mls, psename, proles, pmls, NULL, NULL,NULL, success);
    110 	rc = 0;
    111 err:
    112 	audit_close(fd);
    113 	free(roles);
    114 	free(proles);
    115 	return rc;
    116 }
    117 
    118 int semanage_seuser_modify_local(semanage_handle_t * handle,
    119 				 const semanage_seuser_key_t * key,
    120 				 const semanage_seuser_t * data)
    121 {
    122 	int rc;
    123 	void *callback = (void *) handle->msg_callback;
    124 	dbase_config_t *dconfig = semanage_seuser_dbase_local(handle);
    125 	const char *sename = semanage_seuser_get_sename(data);
    126 	const char *mls_range = semanage_seuser_get_mlsrange(data);
    127 	semanage_seuser_t *previous = NULL;
    128 	semanage_seuser_t *new = NULL;
    129 
    130 	if (!sename) {
    131 		errno=EINVAL;
    132 		return -1;
    133 	}
    134 	rc = semanage_seuser_clone(handle, data, &new);
    135 	if (rc < 0) {
    136 		goto err;
    137 	}
    138 
    139 	if (!mls_range && semanage_mls_enabled(handle)) {
    140 		semanage_user_key_t *ukey = NULL;
    141 		semanage_user_t *u = NULL;
    142 		rc = semanage_user_key_create(handle, sename, &ukey);
    143 		if (rc < 0)
    144 			goto err;
    145 
    146 		rc = semanage_user_query(handle, ukey, &u);
    147 		semanage_user_key_free(ukey);
    148 		if (rc >= 0 ) {
    149 			mls_range = semanage_user_get_mlsrange(u);
    150 			rc = semanage_seuser_set_mlsrange(handle, new, mls_range);
    151 			semanage_user_free(u);
    152 		}
    153 		if (rc < 0)
    154 			goto err;
    155 	}
    156 
    157 	handle->msg_callback = NULL;
    158 	(void) semanage_seuser_query(handle, key, &previous);
    159 	handle->msg_callback = callback;
    160 	rc = dbase_modify(handle, dconfig, key, new);
    161 	if (semanage_seuser_audit(handle, new, previous, AUDIT_ROLE_ASSIGN, rc == 0) < 0)
    162 		rc = -1;
    163 err:
    164 	if (previous)
    165 		semanage_seuser_free(previous);
    166 	semanage_seuser_free(new);
    167 	return rc;
    168 }
    169 
    170 int semanage_seuser_del_local(semanage_handle_t * handle,
    171 			      const semanage_seuser_key_t * key)
    172 {
    173 	int rc;
    174 	semanage_seuser_t *seuser = NULL;
    175 	dbase_config_t *dconfig = semanage_seuser_dbase_local(handle);
    176 	rc = dbase_del(handle, dconfig, key);
    177 	semanage_seuser_query(handle, key, &seuser);
    178 	if (semanage_seuser_audit(handle, NULL, seuser, AUDIT_ROLE_REMOVE, rc == 0) < 0)
    179 		rc = -1;
    180 	if (seuser)
    181 		semanage_seuser_free(seuser);
    182 	return rc;
    183 }
    184 
    185 int semanage_seuser_query_local(semanage_handle_t * handle,
    186 				const semanage_seuser_key_t * key,
    187 				semanage_seuser_t ** response)
    188 {
    189 
    190 	dbase_config_t *dconfig = semanage_seuser_dbase_local(handle);
    191 	return dbase_query(handle, dconfig, key, response);
    192 }
    193 
    194 int semanage_seuser_exists_local(semanage_handle_t * handle,
    195 				 const semanage_seuser_key_t * key,
    196 				 int *response)
    197 {
    198 
    199 	dbase_config_t *dconfig = semanage_seuser_dbase_local(handle);
    200 	return dbase_exists(handle, dconfig, key, response);
    201 }
    202 
    203 int semanage_seuser_count_local(semanage_handle_t * handle,
    204 				unsigned int *response)
    205 {
    206 
    207 	dbase_config_t *dconfig = semanage_seuser_dbase_local(handle);
    208 	return dbase_count(handle, dconfig, response);
    209 }
    210 
    211 int semanage_seuser_iterate_local(semanage_handle_t * handle,
    212 				  int (*handler) (const semanage_seuser_t *
    213 						  record, void *varg),
    214 				  void *handler_arg)
    215 {
    216 
    217 	dbase_config_t *dconfig = semanage_seuser_dbase_local(handle);
    218 	return dbase_iterate(handle, dconfig, handler, handler_arg);
    219 }
    220 
    221 hidden_def(semanage_seuser_iterate_local)
    222 
    223 int semanage_seuser_list_local(semanage_handle_t * handle,
    224 			       semanage_seuser_t *** records,
    225 			       unsigned int *count)
    226 {
    227 
    228 	dbase_config_t *dconfig = semanage_seuser_dbase_local(handle);
    229 	return dbase_list(handle, dconfig, records, count);
    230 }
    231 
    232 struct validate_handler_arg {
    233 	semanage_handle_t *handle;
    234 	const sepol_policydb_t *policydb;
    235 };
    236 
    237 static int validate_handler(const semanage_seuser_t * seuser, void *varg)
    238 {
    239 
    240 	semanage_user_t *user = NULL;
    241 	semanage_user_key_t *key = NULL;
    242 	int exists, mls_ok;
    243 
    244 	/* Unpack varg */
    245 	struct validate_handler_arg *arg = (struct validate_handler_arg *)varg;
    246 	semanage_handle_t *handle = arg->handle;
    247 	const sepol_policydb_t *policydb = arg->policydb;
    248 
    249 	/* Unpack seuser */
    250 	const char *name = semanage_seuser_get_name(seuser);
    251 	const char *sename = semanage_seuser_get_sename(seuser);
    252 	const char *mls_range = semanage_seuser_get_mlsrange(seuser);
    253 	const char *user_mls_range;
    254 
    255 	/* Make sure the (SElinux) user exists */
    256 	if (semanage_user_key_create(handle, sename, &key) < 0)
    257 		goto err;
    258 	if (semanage_user_exists(handle, key, &exists) < 0)
    259 		goto err;
    260 	if (!exists) {
    261 		ERR(handle, "selinux user %s does not exist", sename);
    262 		goto invalid;
    263 	}
    264 
    265 	/* Verify that the mls range is valid, and that it's contained
    266 	 * within the (SELinux) user mls range. This range is optional */
    267 	if (mls_range && sepol_policydb_mls_enabled(policydb)) {
    268 
    269 		if (semanage_user_query(handle, key, &user) < 0)
    270 			goto err;
    271 		user_mls_range = semanage_user_get_mlsrange(user);
    272 
    273 		if (sepol_mls_check(handle->sepolh, policydb, mls_range) < 0)
    274 			goto invalid;
    275 		if (sepol_mls_contains(handle->sepolh, policydb,
    276 				       user_mls_range, mls_range, &mls_ok) < 0)
    277 			goto err;
    278 
    279 		if (!mls_ok) {
    280 			ERR(handle, "MLS range %s for Unix user %s "
    281 			    "exceeds allowed range %s for SELinux user %s",
    282 			    mls_range, name, user_mls_range, sename);
    283 			goto invalid;
    284 		}
    285 
    286 	} else if (mls_range) {
    287 		ERR(handle, "MLS is disabled, but MLS range %s "
    288 		    "was found for Unix user %s", mls_range, name);
    289 		goto invalid;
    290 	}
    291 
    292 	semanage_user_key_free(key);
    293 	semanage_user_free(user);
    294 	return 0;
    295 
    296       err:
    297 	ERR(handle, "could not check if seuser mapping for %s is valid", name);
    298 	semanage_user_key_free(key);
    299 	semanage_user_free(user);
    300 	return -1;
    301 
    302       invalid:
    303 	if (mls_range)
    304 		ERR(handle, "seuser mapping [%s -> (%s, %s)] is invalid",
    305 		    name, sename, mls_range);
    306 	else
    307 		ERR(handle, "seuser mapping [%s -> %s] is invalid",
    308 		    name, sename);
    309 	semanage_user_key_free(key);
    310 	semanage_user_free(user);
    311 	return -1;
    312 }
    313 
    314 /* This function may not be called outside a transaction, or
    315  * it will (1) deadlock, because iterate is not reentrant outside
    316  * a transaction, and (2) be racy, because it makes multiple dbase calls */
    317 
    318 int hidden semanage_seuser_validate_local(semanage_handle_t * handle,
    319 					  const sepol_policydb_t * policydb)
    320 {
    321 
    322 	struct validate_handler_arg arg;
    323 	arg.handle = handle;
    324 	arg.policydb = policydb;
    325 	return semanage_seuser_iterate_local(handle, validate_handler, &arg);
    326 }
    327