psss / rpms / libsemanage

Forked from rpms/libsemanage 5 years ago
Clone
Blob Blame History Raw
diff --git a/libsemanage/man/man3/semanage_bool_set_active.3 b/libsemanage/man/man3/semanage_bool_set_active.3
index 026e29d..d868fe8 100644
--- a/libsemanage/man/man3/semanage_bool_set_active.3
+++ b/libsemanage/man/man3/semanage_bool_set_active.3
@@ -40,7 +40,7 @@ This function requires an semanage connection to be established (see
 ).
 
 .SH "RETURN VALUE"
-In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error.
+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error.
 Otherwise 0 is returned.
 
 .SH "SEE ALSO"
diff --git a/libsemanage/man/man3/semanage_count.3 b/libsemanage/man/man3/semanage_count.3
index b131cbe..b865a21 100644
--- a/libsemanage/man/man3/semanage_count.3
+++ b/libsemanage/man/man3/semanage_count.3
@@ -33,7 +33,7 @@ This function requires an semanage connection to be established (see
 )
 
 .SH "RETURN VALUE"
-In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error.
+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error.
 Otherwise a non-negative integer is returned (a commit number). The same number will be returned by all other semanage object read calls until the next commit.
 
 .SH "SEE ALSO"
diff --git a/libsemanage/man/man3/semanage_del.3 b/libsemanage/man/man3/semanage_del.3
index 5b11ce3..4dd0a77 100644
--- a/libsemanage/man/man3/semanage_del.3
+++ b/libsemanage/man/man3/semanage_del.3
@@ -40,7 +40,7 @@ This function requires an semanage connection to be established (see
 ).
 
 .SH "RETURN VALUE"
-In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error.
+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error.
 Otherwise 0 is returned.
 
 .SH "SEE ALSO"
diff --git a/libsemanage/man/man3/semanage_exists.3 b/libsemanage/man/man3/semanage_exists.3
index da401c2..6d68c76 100644
--- a/libsemanage/man/man3/semanage_exists.3
+++ b/libsemanage/man/man3/semanage_exists.3
@@ -38,7 +38,7 @@ This function requires an semanage connection to be established (see
 )
 
 .SH "RETURN VALUE"
-In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error.
+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error.
 Otherwise a non-negative integer is returned (a commit number). The same number will be returned by all other read calls to the semanage database until the next commit.
 
 .SH "SEE ALSO"
diff --git a/libsemanage/man/man3/semanage_iterate.3 b/libsemanage/man/man3/semanage_iterate.3
index 8773800..1528164 100644
--- a/libsemanage/man/man3/semanage_iterate.3
+++ b/libsemanage/man/man3/semanage_iterate.3
@@ -31,7 +31,7 @@ if that is necessary.
 
 The handler code may not invoke any semanage write requests for the same object type (i.e. modifying the underlying store is not allowed). The iterate function is reentrant only while inside a transaction (see
 .B semanage_begin_transaction
-). It is not safe to execute other semanage read or write requests within iterate if not inside a transaction. The handler may return -1 to signal error exit, 0 to signal continue, and 1 to signal successful exit early (the iterate function will stop accordingly). 
+). It is not safe to execute other semanage read or write requests within iterate if not inside a transaction. The handler may return \-1 to signal error exit, 0 to signal continue, and 1 to signal successful exit early (the iterate function will stop accordingly).
 
 .TP
 .B Parameters:
@@ -50,7 +50,7 @@ This function requires an semanage connection to be established (see
 )
 
 .SH "RETURN VALUE"
-In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error.
+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error.
 Otherwise a non-negative integer is returned (a commit number). The same number will be returned by all other semanage object read calls until the next commit.
 
 .SH "SEE ALSO"
diff --git a/libsemanage/man/man3/semanage_list.3 b/libsemanage/man/man3/semanage_list.3
index 9376702..acc161f 100644
--- a/libsemanage/man/man3/semanage_list.3
+++ b/libsemanage/man/man3/semanage_list.3
@@ -39,7 +39,7 @@ This function requires an semanage connection to be established (see
 )
 
 .SH "RETURN VALUE"
-In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error.
+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error.
 Otherwise a non-negative integer is returned (a commit number). The same number will be returned by all other semanage object read calls until the next commit.
 
 .SH "SEE ALSO"
diff --git a/libsemanage/man/man3/semanage_modify.3 b/libsemanage/man/man3/semanage_modify.3
index 04bd801..ee23900 100644
--- a/libsemanage/man/man3/semanage_modify.3
+++ b/libsemanage/man/man3/semanage_modify.3
@@ -42,7 +42,7 @@ This function requires an semanage connection to be established (see
 ).
 
 .SH "RETURN VALUE"
-In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error.
+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error.
 Otherwise 0 is returned.
 
 .SH "SEE ALSO"
diff --git a/libsemanage/man/man3/semanage_query.3 b/libsemanage/man/man3/semanage_query.3
index 1a6cdb2..e61c8b8 100644
--- a/libsemanage/man/man3/semanage_query.3
+++ b/libsemanage/man/man3/semanage_query.3
@@ -39,7 +39,7 @@ This function requires an semanage connection to be established (see
 )
 
 .SH "RETURN VALUE"
-In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error.
+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error.
 Otherwise a non-negative integer is returned (a commit number). The same number will be returned by all other semanage object read calls until the next commit.
 
 .SH "SEE ALSO"
diff --git a/libsemanage/man/man3/semanage_set_root.3 b/libsemanage/man/man3/semanage_set_root.3
index 2ae0f17..664822e 100644
--- a/libsemanage/man/man3/semanage_set_root.3
+++ b/libsemanage/man/man3/semanage_set_root.3
@@ -15,7 +15,7 @@ Set the alternate root directory for SELinux configuration directory.
 This function sets an alternate root directory to for SELinux configuration paths to be used by the semanage library.
 
 .SH "RETURN VALUE"
-In case of failure, -1 is returned.
+In case of failure, \-1 is returned.
 Otherwise 0 is returned.
 
 .SH "SEE ALSO"
diff --git a/libsemanage/src/Makefile b/libsemanage/src/Makefile
index c63bb22..edb84cc 100644
--- a/libsemanage/src/Makefile
+++ b/libsemanage/src/Makefile
@@ -92,7 +92,7 @@ $(LIBA): $(OBJS)
 	$(RANLIB) $@
 
 $(LIBSO): $(LOBJS)
-	$(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ -lsepol -lselinux -lbz2 -lustr -L$(LIBDIR) -Wl,-soname,$(LIBSO),--version-script=libsemanage.map,-z,defs
+	$(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ -lsepol -laudit -lselinux -lbz2 -lustr -L$(LIBDIR) -Wl,-soname,$(LIBSO),--version-script=libsemanage.map,-z,defs
 	ln -sf $@ $(TARGET)
 
 $(LIBPC): $(LIBPC).in ../VERSION
diff --git a/libsemanage/src/genhomedircon.c b/libsemanage/src/genhomedircon.c
index 3c81d7a..f3b9b5c 100644
--- a/libsemanage/src/genhomedircon.c
+++ b/libsemanage/src/genhomedircon.c
@@ -283,7 +283,7 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
 	char *rbuf = NULL;
 	char *path = NULL;
 	long rbuflen;
-	uid_t temp, minuid = 500;
+	uid_t temp, minuid = 500, maxuid = 60000;
 	int minuid_set = 0;
 	struct passwd pwstorage, *pwbuf;
 	struct stat buf;
@@ -333,6 +333,14 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
 	free(path);
 	path = NULL;
 
+	path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL);
+	if (path && *path) {
+		temp = atoi(path);
+		maxuid = temp;
+	}
+	free(path);
+	path = NULL;
+
 	path = semanage_findval(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=");
 	if (path && *path) {
 		temp = atoi(path);
@@ -352,7 +360,7 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
 		goto fail;
 	setpwent();
 	while ((retval = getpwent_r(&pwstorage, rbuf, rbuflen, &pwbuf)) == 0) {
-		if (pwbuf->pw_uid < minuid)
+		if (pwbuf->pw_uid < minuid || pwbuf->pw_uid > maxuid)
 			continue;
 		if (!semanage_list_find(shells, pwbuf->pw_shell))
 			continue;
@@ -385,7 +393,7 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
 
 			/* NOTE: old genhomedircon printed a warning on match */
 			if (hand.matched) {
-				WARN(s->h_semanage, "%s homedir %s or its parent directory conflicts with a file context already specified in the policy.  This usually indicates an incorrectly defined system account.  If it is a system account please make sure its uid is less than %u or its login shell is /sbin/nologin.", pwbuf->pw_name, pwbuf->pw_dir, minuid);
+				WARN(s->h_semanage, "%s homedir %s or its parent directory conflicts with a file context already specified in the policy.  This usually indicates an incorrectly defined system account.  If it is a system account please make sure its uid is less than %u or greater than %u or its login shell is /sbin/nologin.", pwbuf->pw_name, pwbuf->pw_dir, minuid, maxuid);
 			} else {
 				if (semanage_list_push(&homedir_list, path))
 					goto fail;
diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c
index 57ef49f..4b040c3 100644
--- a/libsemanage/src/semanage_store.c
+++ b/libsemanage/src/semanage_store.c
@@ -1234,6 +1234,10 @@ static int semanage_install_active(semanage_handle_t * sh)
 
 	retval = 0;
       cleanup:
+	(void) unlink(active_kernel);
+	if (symlink(store_pol, active_kernel) < 0) {
+		ERR(sh, "Unable to create sybolic link from %s to %s error code %d.", active_kernel, store_pol, r);
+	}
 	free(storepath);
 	return retval;
 }
diff --git a/libsemanage/src/seusers_local.c b/libsemanage/src/seusers_local.c
index e7cf12c..f379211 100644
--- a/libsemanage/src/seusers_local.c
+++ b/libsemanage/src/seusers_local.c
@@ -8,27 +8,177 @@ typedef struct semanage_seuser record_t;
 
 #include <sepol/policydb.h>
 #include <sepol/context.h>
+#include <libaudit.h>
+#include <errno.h>
 #include "user_internal.h"
 #include "seuser_internal.h"
 #include "handle.h"
 #include "database.h"
 #include "debug.h"
+#include "string.h"
+#include <stdlib.h>
+
+static char *semanage_user_roles(semanage_handle_t * handle, const char *sename) {
+	char *roles = NULL;
+	unsigned int num_roles;
+	size_t i;
+	size_t size = 0;
+	const char **roles_arr;
+	semanage_user_key_t *key = NULL;
+	semanage_user_t * user;
+	if (semanage_user_key_create(handle, sename, &key) >= 0) {
+		if (semanage_user_query(handle, key, &user) >= 0) {
+			if (semanage_user_get_roles(handle, 
+						    user, 
+						    &roles_arr, 
+						    &num_roles) >= 0) {
+				for (i = 0; i<num_roles; i++) {
+					size += (strlen(roles_arr[i]) + 1);
+				}
+				roles = malloc(size);
+				if (roles) {
+					strcpy(roles,roles_arr[0]);
+					for (i = 1; i<num_roles; i++) {
+						strcat(roles,",");
+						strcat(roles,roles_arr[i]);
+					}
+				}
+			}
+			semanage_user_free(user);
+		}
+		semanage_user_key_free(key);
+	}
+	return roles;
+}
+
+static int semanage_seuser_audit(semanage_handle_t * handle,
+			  const semanage_seuser_t * seuser, 
+			  const semanage_seuser_t * previous,
+			  int audit_type, 
+			  int success) {
+	const char *name = NULL;
+	const char *sename = NULL;
+	char *roles = NULL;
+	const char *mls = NULL;
+	const char *psename = NULL;
+	const char *pmls = NULL;
+	char *proles = NULL;
+	char msg[1024];
+	const char *sep = "-";
+	int rc = -1;
+	strcpy(msg, "login");
+	if (seuser) {
+		name = semanage_seuser_get_name(seuser);
+		sename = semanage_seuser_get_sename(seuser);
+		mls = semanage_seuser_get_mlsrange(seuser);
+		roles = semanage_user_roles(handle, sename);
+	}
+	if (previous) {
+		psename = semanage_seuser_get_sename(previous);
+		pmls = semanage_seuser_get_mlsrange(previous);
+		proles = semanage_user_roles(handle, psename);
+	}
+	if (audit_type != AUDIT_ROLE_REMOVE) {
+		if (sename && (!psename || strcmp(psename, sename) != 0)) {
+			strcat(msg,sep);
+			strcat(msg,"sename");
+			sep = ",";
+		}
+		if (roles && (!proles || strcmp(proles, roles) != 0)) {
+			strcat(msg,sep);
+			strcat(msg,"role");
+			sep = ",";
+		}
+		if (mls && (!pmls || strcmp(pmls, mls) != 0)) {
+			strcat(msg,sep);
+			strcat(msg,"range");
+		}
+	}
+
+	int fd = audit_open();
+	if (fd < 0)
+	{
+		/* If kernel doesn't support audit, bail out */
+		if (errno == EINVAL || errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT) {
+			rc = 0;
+			goto err;
+		}
+		rc = fd;
+		goto err;
+	}
+	audit_log_semanage_message(fd, audit_type, NULL, msg, name, 0, sename, roles, mls, psename, proles, pmls, NULL, NULL,NULL, success);
+	rc = 0;
+err:
+	audit_close(fd);
+	free(roles);
+	free(proles);
+	return rc;
+}
 
 int semanage_seuser_modify_local(semanage_handle_t * handle,
 				 const semanage_seuser_key_t * key,
 				 const semanage_seuser_t * data)
 {
-
+	int rc;
+	void *callback = (void *) handle->msg_callback;
 	dbase_config_t *dconfig = semanage_seuser_dbase_local(handle);
-	return dbase_modify(handle, dconfig, key, data);
+	const char *sename = semanage_seuser_get_sename(data);
+	const char *mls_range = semanage_seuser_get_mlsrange(data);
+	semanage_seuser_t *previous = NULL;
+	semanage_seuser_t *new = NULL;
+
+	if (!sename) {
+		errno=EINVAL;
+		return -1;
+	}
+	if (semanage_seuser_clone(handle, data, &new) < 0) {
+		goto err;
+	}
+		
+	if (!mls_range && semanage_mls_enabled(handle)) {
+		semanage_user_key_t *ukey = NULL;
+		semanage_user_t *u = NULL;
+		rc = semanage_user_key_create(handle, sename, &ukey);
+		if (rc < 0)
+			goto err;
+
+		rc = semanage_user_query(handle, ukey, &u);
+		semanage_user_key_free(ukey);
+		if (rc >= 0 ) {
+			mls_range = semanage_user_get_mlsrange(u);
+			rc = semanage_seuser_set_mlsrange(handle, new, mls_range);
+			semanage_user_free(u);
+		}
+		if (rc < 0)
+			goto err;
+	}
+
+	handle->msg_callback = NULL;
+	(void) semanage_seuser_query(handle, key, &previous);
+	handle->msg_callback = callback;
+	rc = dbase_modify(handle, dconfig, key, new);
+	if (semanage_seuser_audit(handle, new, previous, AUDIT_ROLE_ASSIGN, rc == 0) < 0) 
+		rc = -1;
+err:
+	if (previous)
+		semanage_seuser_free(previous);
+	semanage_seuser_free(new);
+	return rc;
 }
 
 int semanage_seuser_del_local(semanage_handle_t * handle,
 			      const semanage_seuser_key_t * key)
 {
-
+	int rc;
+	semanage_seuser_t *seuser = NULL;
 	dbase_config_t *dconfig = semanage_seuser_dbase_local(handle);
-	return dbase_del(handle, dconfig, key);
+	rc = dbase_del(handle, dconfig, key);
+	semanage_seuser_query(handle, key, &seuser);
+	if (semanage_seuser_audit(handle, NULL, seuser, AUDIT_ROLE_REMOVE, rc == 0) < 0) 
+		rc = -1;
+	if (seuser)
+		semanage_seuser_free(seuser);
+	return rc;
 }
 
 int semanage_seuser_query_local(semanage_handle_t * handle,
diff --git a/libsemanage/src/users_local.c b/libsemanage/src/users_local.c
index 8742ca1..b78ad0e 100644
--- a/libsemanage/src/users_local.c
+++ b/libsemanage/src/users_local.c
@@ -6,9 +6,14 @@ typedef struct semanage_user_key record_key_t;
 typedef struct semanage_user record_t;
 #define DBASE_RECORD_DEFINED
 
+#include <string.h>
+#include <stdlib.h>
 #include "user_internal.h"
+#include "seuser_internal.h"
 #include "handle.h"
 #include "database.h"
+#include "errno.h"
+#include "debug.h"
 
 int semanage_user_modify_local(semanage_handle_t * handle,
 			       const semanage_user_key_t * key,
@@ -19,9 +24,43 @@ int semanage_user_modify_local(semanage_handle_t * handle,
 	return dbase_modify(handle, dconfig, key, data);
 }
 
+static int lookup_seuser(semanage_handle_t * handle, const semanage_user_key_t *k) {
+	semanage_user_t *user;
+	semanage_seuser_t **records;
+	const char *name;
+	const char *sename;
+	unsigned int count;
+	size_t i;
+	int rc = 0;
+	if (semanage_user_query(handle, k, &user) < 0)
+		return 0;
+	name = semanage_user_get_name(user);
+	semanage_seuser_list_local(handle,
+				   &records,
+				   &count);
+	for(i=0; i<count; i++) {
+		sename = semanage_seuser_get_sename(records[i]);
+		if (strcmp(name, sename) == 0) {
+			errno = EINVAL;
+			ERR(handle, "%s is being used by %s login record", 
+			    sename, semanage_seuser_get_name(records[i]));
+			rc = -1;
+		}
+	}
+	for(i=0; i<count; i++)
+		semanage_seuser_free(records[i]);
+	free(records);
+	semanage_user_free(user);
+	if (rc)
+		errno = EINVAL;
+	return rc;
+}
+
 int semanage_user_del_local(semanage_handle_t * handle,
 			    const semanage_user_key_t * key)
 {
+	if (lookup_seuser(handle, key))
+		return -1;
 
 	dbase_config_t *dconfig = semanage_user_dbase_local(handle);
 	return dbase_del(handle, dconfig, key);
diff --git a/libsemanage/src/utilities.c b/libsemanage/src/utilities.c
index 349a4be..a340fc8 100644
--- a/libsemanage/src/utilities.c
+++ b/libsemanage/src/utilities.c
@@ -140,6 +140,10 @@ int semanage_list_push(semanage_list_t ** list, char *data)
 
 	if (!data)
 		return EINVAL;
+
+	if (semanage_list_find(*list, data) != NULL)
+		return 0;
+
 	if (!(temp = malloc(sizeof(semanage_list_t))))
 		return ENOMEM;
 
diff --git a/libsemanage/tests/Makefile b/libsemanage/tests/Makefile
index f92455c..ad1869b 100644
--- a/libsemanage/tests/Makefile
+++ b/libsemanage/tests/Makefile
@@ -13,7 +13,7 @@ EXECUTABLE = libsemanage-tests
 CC = gcc
 CFLAGS = -c -g -o0 -Wall -W -Wundef -Wmissing-noreturn -Wmissing-format-attribute -Wno-unused-parameter
 INCLUDE = -I$(TESTSRC) -I$(TESTSRC)/../include
-LDFLAGS = -lcunit -lustr -lbz2
+LDFLAGS = -lcunit -lustr -lbz2 -lpthread
 OBJECTS = $(SOURCES:.c=.o) 
 
 all: $(EXECUTABLE)