psss / rpms / libsemanage

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