|
From: <ssm...@us...> - 2007-08-23 14:41:52
|
Revision: 2527
http://selinux.svn.sourceforge.net/selinux/?rev=2527&view=rev
Author: ssmalley
Date: 2007-08-23 07:41:50 -0700 (Thu, 23 Aug 2007)
Log Message:
-----------
Author: tm...@tr...
Email: tm...@tr...
Subject: libsemanage: genhomedircon replacement
Date: Tue, 21 Aug 2007 15:10:44 -0400
Remove python script genhomedircon from libsemanage and replace
with C functionality.
Note: This code fixes a bug in the orignal genhomedircon python script; the
following two lines are added to the file contexts whereas the old
genhomedircon would not add them:
/tmp/\.exchange-.*(/.*)? user_u:object_r:user_evolution_exchange_tmp_t:s0
/tmp/\.exchange-root(/.*)? root:object_r:user_evolution_exchange_tmp_t:s0
Modified Paths:
--------------
trunk/libselinux/src/file_path_suffixes.h
trunk/libsemanage/src/Makefile
trunk/libsemanage/src/semanage_store.c
trunk/libsemanage/src/semanage_store.h
Added Paths:
-----------
trunk/libsemanage/src/genhomedircon.c
trunk/libsemanage/src/genhomedircon.h
trunk/libsemanage/src/utilities.c
trunk/libsemanage/src/utilities.h
Modified: trunk/libselinux/src/file_path_suffixes.h
===================================================================
--- trunk/libselinux/src/file_path_suffixes.h 2007-08-23 14:39:48 UTC (rev 2526)
+++ trunk/libselinux/src/file_path_suffixes.h 2007-08-23 14:41:50 UTC (rev 2527)
@@ -16,6 +16,6 @@
S_(SEUSERS, "/seusers")
S_(TRANSLATIONS, "/setrans.conf")
S_(NETFILTER_CONTEXTS, "/contexts/netfilter_contexts")
- S_(FILE_CONTEXTS_HOMEDIR, "/contexts/files/file_contexts.homedir")
+ S_(FILE_CONTEXTS_HOMEDIR, "/contexts/files/file_contexts.homedirs")
S_(FILE_CONTEXTS_LOCAL, "/contexts/files/file_contexts.local")
S_(X_CONTEXTS, "/contexts/x_contexts")
Modified: trunk/libsemanage/src/Makefile
===================================================================
--- trunk/libsemanage/src/Makefile 2007-08-23 14:39:48 UTC (rev 2526)
+++ trunk/libsemanage/src/Makefile 2007-08-23 14:41:50 UTC (rev 2527)
@@ -54,7 +54,7 @@
ranlib $@
$(LIBSO): $(LOBJS)
- $(CC) $(LDFLAGS) -shared -o $@ $^ -lsepol -lselinux -L$(LIBDIR) -Wl,-soname,$(LIBSO),--version-script=libsemanage.map,-z,defs
+ $(CC) $(LDFLAGS) -shared -o $@ $^ -lsepol -lselinux -lustr -L$(LIBDIR) -Wl,-soname,$(LIBSO),--version-script=libsemanage.map,-z,defs
ln -sf $@ $(TARGET)
conf-scan.c: conf-scan.l conf-parse.h
Added: trunk/libsemanage/src/genhomedircon.c
===================================================================
--- trunk/libsemanage/src/genhomedircon.c (rev 0)
+++ trunk/libsemanage/src/genhomedircon.c 2007-08-23 14:41:50 UTC (rev 2527)
@@ -0,0 +1,717 @@
+/* Author: Mark Goldman <mgo...@tr...>
+ * Paul Rosenfeld <pro...@tr...>
+ *
+ * Copyright (C) 2007 Tresys Technology, LLC
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <semanage/handle.h>
+#include <semanage/seusers_policy.h>
+#include <semanage/users_policy.h>
+#include <semanage/user_record.h>
+#include "semanage_store.h"
+#include "seuser_internal.h"
+#include "debug.h"
+
+#include "utilities.h"
+#include "genhomedircon.h"
+#include <ustr.h>
+
+#include <assert.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <errno.h>
+
+/* paths used in get_home_dirs() */
+#define PATH_ETC_USERADD "/etc/default/useradd"
+#define PATH_ETC_LIBUSER "/etc/libuser.conf"
+#define PATH_DEFAULT_HOME "/home"
+#define PATH_EXPORT_HOME "/export/home"
+#define PATH_ETC_LOGIN_DEFS "/etc/login.defs"
+
+/* other paths */
+#define PATH_SHELLS_FILE "/etc/shells"
+#define PATH_NOLOGIN_SHELL "/sbin/nologin"
+
+/* comments written to context file */
+#define COMMENT_FILE_CONTEXT_HEADER "#\n#\n# " \
+ "User-specific file contexts, generated via libsemanage\n" \
+ "# use semanage command to manage system users to change" \
+ " the file_context\n#\n#\n"
+
+#define COMMENT_USER_HOME_CONTEXT "\n\n#\n# Home Context for user %s" \
+ "\n#\n\n"
+
+/* placeholders used in the template file
+ which are searched for and replaced */
+#define TEMPLATE_HOME_ROOT "HOME_ROOT"
+#define TEMPLATE_HOME_DIR "HOME_DIR"
+#define TEMPLATE_USER "USER"
+#define TEMPLATE_ROLE "ROLE"
+#define TEMPLATE_SEUSER "system_u"
+
+#define FALLBACK_USER "user_u"
+#define FALLBACK_USER_PREFIX "user"
+#define DEFAULT_LOGIN "__default__"
+
+typedef struct {
+ const char *fcfilepath;
+ int usepasswd;
+ const char *homedir_template_path;
+ semanage_handle_t *h_semanage;
+} genhomedircon_settings_t;
+
+typedef struct user_entry {
+ char *name;
+ char *sename;
+ char *prefix;
+ char *home;
+ struct user_entry *next;
+} genhomedircon_user_entry_t;
+
+typedef struct {
+ const char *search_for;
+ const char *replace_with;
+} replacement_pair_t;
+
+static semanage_list_t *default_shell_list(void)
+{
+ semanage_list_t *list = NULL;
+
+ if (semanage_list_push(&list, "/bin/csh")
+ || semanage_list_push(&list, "/bin/tcsh")
+ || semanage_list_push(&list, "/bin/ksh")
+ || semanage_list_push(&list, "/bin/bsh")
+ || semanage_list_push(&list, "/bin/ash")
+ || semanage_list_push(&list, "/usr/bin/ksh")
+ || semanage_list_push(&list, "/usr/bin/pdksh")
+ || semanage_list_push(&list, "/bin/zsh")
+ || semanage_list_push(&list, "/bin/sh")
+ || semanage_list_push(&list, "/bin/bash"))
+ goto fail;
+
+ return list;
+
+ fail:
+ semanage_list_destroy(&list);
+ return NULL;
+}
+
+static semanage_list_t *get_shell_list(void)
+{
+ FILE *shells;
+ char *temp = NULL;
+ semanage_list_t *list = NULL;
+ size_t buff_len = 0;
+
+ shells = fopen(PATH_SHELLS_FILE, "r");
+ if (!shells)
+ return default_shell_list();
+ while (getline(&temp, &buff_len, shells) >= 0) {
+ if (strcmp(temp, PATH_NOLOGIN_SHELL)) {
+ if (semanage_list_push(&list, temp)) {
+ free(temp);
+ semanage_list_destroy(&list);
+ return default_shell_list();
+ }
+ }
+ }
+ free(temp);
+
+ return list;
+}
+
+static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
+{
+ semanage_list_t *homedir_list = NULL;
+ semanage_list_t *shells = NULL;
+ char *path = NULL;
+ size_t minuid = 0;
+ size_t minuid_set = 0;
+ size_t temp;
+ struct passwd *pwbuf;
+ struct stat buf;
+
+ shells = get_shell_list();
+ assert(shells);
+
+ path = semanage_findval(PATH_ETC_USERADD, "HOME", "=");
+ if (path && *path) {
+ if (semanage_list_push(&homedir_list, path)) {
+ free(path);
+ goto fail;
+ }
+ }
+ free(path);
+
+ path = semanage_findval(PATH_ETC_LIBUSER, "LU_HOMEDIRECTORY", "=");
+ if (path && *path) {
+ if (semanage_list_push(&homedir_list, path)) {
+ free(path);
+ goto fail;
+ }
+ }
+ free(path);
+
+ if (!homedir_list) {
+ if (semanage_list_push(&homedir_list, PATH_DEFAULT_HOME)) {
+ goto fail;
+ }
+ }
+
+ if (!stat(PATH_EXPORT_HOME, &buf)) {
+ if (S_ISDIR(buf.st_mode)) {
+ if (semanage_list_push(&homedir_list, PATH_EXPORT_HOME)) {
+ goto fail;
+ }
+ }
+ }
+
+ if (!(s->usepasswd))
+ return homedir_list;
+
+ path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL);
+ if (path && *path) {
+ temp = atoi(path);
+ if (!minuid_set || temp < minuid) {
+ minuid = temp;
+ minuid_set = 1;
+ }
+ }
+ free(path);
+
+ path = semanage_findval(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=");
+ if (path && *path) {
+ temp = atoi(path);
+ if (!minuid_set || temp < minuid) {
+ minuid = temp;
+ minuid_set = 1;
+ }
+ }
+ free(path);
+
+ if (!minuid_set) {
+ minuid = 500;
+ minuid_set = 1;
+ }
+
+ setpwent();
+ for (errno = 0; (pwbuf = getpwent()); errno = 0) {
+ if (pwbuf->pw_uid < minuid)
+ continue;
+ if (!semanage_list_find(shells, pwbuf->pw_shell))
+ continue;
+ if (strcmp(pwbuf->pw_dir, "/") == 0)
+ continue;
+ if (semanage_str_count(pwbuf->pw_dir, '/') <= 1)
+ continue;
+ if (!(path = strdup(pwbuf->pw_dir))) {
+ break;
+ }
+
+ semanage_rtrim(path, '/');
+ if (!semanage_list_find(homedir_list, path)) {
+ if (semanage_list_push(&homedir_list, path)) {
+ free(path);
+ goto fail;
+ }
+ }
+ free(path);
+ }
+
+ if (errno) {
+ WARN(s->h_semanage, "Error while fetching users. "
+ "Returning list so far.");
+ }
+ endpwent();
+ semanage_list_destroy(&shells);
+ if (semanage_list_sort(&homedir_list))
+ goto fail;
+
+ return homedir_list;
+
+ fail:
+ semanage_list_destroy(&homedir_list);
+ semanage_list_destroy(&shells);
+ return NULL;
+}
+
+/**
+ * @param s settings structure, stores various paths etc. Must never be NULL
+ * @param out the FILE to put all the output in.
+ * @return 0 on success
+ */
+static int write_file_context_header(genhomedircon_settings_t * s, FILE * out)
+{
+ if (fprintf(out, COMMENT_FILE_CONTEXT_HEADER) < 0) {
+ return STATUS_ERR;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+/* Predicates for use with semanage_slurp_file_filter() the homedir_template
+ * file currently contains lines that serve as the template for a user's
+ * homedir.
+ *
+ * It also contains lines that are the template for the parent of a
+ * user's home directory.
+ *
+ * Currently, the only lines that apply to the the root of a user's home
+ * directory are all prefixed with the string "HOME_ROOT". All other
+ * lines apply to a user's home directory. If this changes the
+ * following predicates need to change to reflect that.
+ */
+static int HOME_ROOT_PRED(const char *string)
+{
+ return semanage_is_prefix(string, TEMPLATE_HOME_ROOT);
+}
+
+static int HOME_DIR_PRED(const char *string)
+{
+ return semanage_is_prefix(string, TEMPLATE_HOME_DIR);
+}
+
+static int USER_CONTEXT_PRED(const char *string)
+{
+ return (int)(strstr(string, TEMPLATE_USER) != NULL);
+}
+
+/* make_tempate
+ * @param s the settings holding the paths to various files
+ * @param pred function pointer to function to use as filter for slurp
+ * file filter
+ * @return a list of lines from the template file with inappropriate
+ * lines filtered out.
+ */
+static semanage_list_t *make_template(genhomedircon_settings_t * s,
+ int (*pred) (const char *))
+{
+ FILE *template_file = NULL;
+ semanage_list_t *template_data = NULL;
+
+ template_file = fopen(s->homedir_template_path, "r");
+ if (!template_file)
+ return NULL;
+ template_data = semanage_slurp_file_filter(template_file, pred);
+ fclose(template_file);
+
+ return template_data;
+}
+
+static Ustr *replace_all(const char *str, const replacement_pair_t * repl)
+{
+ Ustr *retval = USTR_NULL;
+ int i, num_replaced = 0;
+
+ if (!str || !repl)
+ goto done;
+ if (!(retval = ustr_dup_cstr(str)))
+ goto done;
+
+ for (i = 0; repl[i].search_for; i++) {
+ num_replaced += ustr_replace_cstr(&retval, repl[i].search_for,
+ repl[i].replace_with, 0);
+ }
+ if (!num_replaced)
+ ustr_sc_free(&retval);
+
+ done:
+ return retval;
+}
+
+static int write_home_dir_context(FILE * out, semanage_list_t * tpl,
+ const char *user, const char *seuser,
+ const char *home, const char *role_prefix)
+{
+ replacement_pair_t repl[] = {
+ {.search_for = TEMPLATE_SEUSER,.replace_with = seuser},
+ {.search_for = TEMPLATE_HOME_DIR,.replace_with = home},
+ {.search_for = TEMPLATE_ROLE,.replace_with = role_prefix},
+ {NULL, NULL}
+ };
+ Ustr *line = USTR_NULL;
+
+ if (fprintf(out, COMMENT_USER_HOME_CONTEXT, user) < 0)
+ return STATUS_ERR;
+
+ for (; tpl; tpl = tpl->next) {
+ line = replace_all(tpl->data, repl);
+ if (!line || !ustr_io_putfileline(&line, out))
+ goto fail;
+ ustr_sc_free(&line);
+ }
+ return STATUS_SUCCESS;
+
+ fail:
+ ustr_sc_free(&line);
+ return STATUS_ERR;
+}
+
+static int write_home_root_context(FILE * out, semanage_list_t * tpl,
+ char *homedir)
+{
+ replacement_pair_t repl[] = {
+ {.search_for = TEMPLATE_HOME_ROOT,.replace_with = homedir},
+ {NULL, NULL}
+ };
+ Ustr *line = USTR_NULL;
+
+ for (; tpl; tpl = tpl->next) {
+ line = replace_all(tpl->data, repl);
+ if (!line || !ustr_io_putfileline(&line, out))
+ goto fail;
+ ustr_sc_free(&line);
+ }
+ return STATUS_SUCCESS;
+
+ fail:
+ ustr_sc_free(&line);
+ return STATUS_ERR;
+}
+
+static int write_user_context(FILE * out, semanage_list_t * tpl, char *user,
+ char *seuser, char *role_prefix)
+{
+ replacement_pair_t repl[] = {
+ {.search_for = TEMPLATE_USER,.replace_with = user},
+ {.search_for = TEMPLATE_ROLE,.replace_with = role_prefix},
+ {.search_for = TEMPLATE_SEUSER,.replace_with = seuser},
+ {NULL, NULL}
+ };
+ Ustr *line = USTR_NULL;
+
+ for (; tpl; tpl = tpl->next) {
+ line = replace_all(tpl->data, repl);
+ if (!line || !ustr_io_putfileline(&line, out))
+ goto fail;
+ ustr_sc_free(&line);
+ }
+ return STATUS_SUCCESS;
+
+ fail:
+ ustr_sc_free(&line);
+ return STATUS_ERR;
+}
+
+static int user_sort_func(semanage_user_t ** arg1, semanage_user_t ** arg2)
+{
+ return strcmp(semanage_user_get_name(*arg1),
+ semanage_user_get_name(*arg2));
+}
+
+static int name_user_cmp(char *key, semanage_user_t ** val)
+{
+ return strcmp(key, semanage_user_get_name(*val));
+}
+
+static int push_user_entry(genhomedircon_user_entry_t ** list, const char *n,
+ const char *sen, const char *pre, const char *h)
+{
+ genhomedircon_user_entry_t *temp = NULL;
+ char *name = NULL;
+ char *sename = NULL;
+ char *prefix = NULL;
+ char *home = NULL;
+
+ temp = malloc(sizeof(genhomedircon_user_entry_t));
+ if (!temp)
+ goto cleanup;
+ name = strdup(n);
+ if (!name)
+ goto cleanup;
+ sename = strdup(sen);
+ if (!sename)
+ goto cleanup;
+ prefix = strdup(pre);
+ if (!prefix)
+ goto cleanup;
+ home = strdup(h);
+ if (!home)
+ goto cleanup;
+
+ temp->name = name;
+ temp->sename = sename;
+ temp->prefix = prefix;
+ temp->home = home;
+ temp->next = (*list);
+ (*list) = temp;
+
+ return STATUS_SUCCESS;
+
+ cleanup:
+ free(name);
+ free(sename);
+ free(prefix);
+ free(home);
+ free(temp);
+ return STATUS_ERR;
+}
+
+static void pop_user_entry(genhomedircon_user_entry_t ** list)
+{
+ genhomedircon_user_entry_t *temp;
+
+ if (!list || !(*list))
+ return;
+
+ temp = *list;
+ *list = temp->next;
+ free(temp->name);
+ free(temp->sename);
+ free(temp->prefix);
+ free(temp->home);
+ free(temp);
+}
+
+static genhomedircon_user_entry_t *get_users(genhomedircon_settings_t * s,
+ int *errors)
+{
+ genhomedircon_user_entry_t *head = NULL;
+ semanage_seuser_t **seuser_list = NULL;
+ unsigned int nseusers = 0;
+ semanage_user_t **user_list = NULL;
+ unsigned int nusers = 0;
+ semanage_user_t **u = NULL;
+ const char *name = NULL;
+ const char *seuname = NULL;
+ const char *prefix = NULL;
+ struct passwd *pwent = NULL;
+ unsigned int i;
+ int retval;
+
+ *errors = 0;
+ retval = semanage_seuser_list(s->h_semanage, &seuser_list, &nseusers);
+ if (retval < 0 || (nseusers < 1)) {
+ /* if there are no users, this function can't do any other work */
+ return NULL;
+ }
+
+ if (semanage_user_list(s->h_semanage, &user_list, &nusers) < 0) {
+ nusers = 0;
+ }
+
+ qsort(user_list, nusers, sizeof(semanage_user_t *),
+ (int (*)(const void *, const void *))&user_sort_func);
+
+ for (i = 0; i < nseusers; i++) {
+ name = semanage_seuser_get_name(seuser_list[i]);
+ seuname = semanage_seuser_get_sename(seuser_list[i]);
+
+ if (strcmp(seuname, FALLBACK_USER) == 0)
+ continue;
+ if (strcmp(seuname, DEFAULT_LOGIN) == 0)
+ continue;
+ if (strcmp(seuname, TEMPLATE_SEUSER) == 0)
+ continue;
+
+ /* find the user structure given the name */
+ u = bsearch(seuname, user_list, nusers, sizeof(semanage_user_t *),
+ (int (*)(const void *, const void *))
+ &name_user_cmp);
+ if (u) {
+ prefix = semanage_user_get_prefix(*u);
+ } else {
+ prefix = name;
+ }
+
+ errno = 0;
+ pwent = getpwnam(name);
+ if (!pwent) {
+ if (errno != 0) {
+ *errors = STATUS_ERR;
+ goto cleanup;
+ }
+ WARN(s->h_semanage,
+ "user %s not in password file", name);
+ continue;
+ }
+
+ if (strcmp(pwent->pw_dir, "/") == 0) {
+ /* don't relabel / genhomdircon checked to see if root
+ * was the user and if so, set his home directory to
+ * /root */
+ continue;
+ }
+ if (push_user_entry(&head, name, seuname,
+ prefix, pwent->pw_dir) != STATUS_SUCCESS) {
+ *errors = STATUS_ERR;
+ break;
+ }
+ }
+
+ cleanup:
+ if (*errors) {
+ for (; head; pop_user_entry(&head)) {
+ /* the pop function takes care of all the cleanup
+ so the loop body is just empty */
+ }
+ }
+ for (i = 0; i < nseusers; i++) {
+ semanage_seuser_free(seuser_list[i]);
+ }
+ free(seuser_list);
+
+ for (i = 0; i < nusers; i++) {
+ semanage_user_free(user_list[i]);
+ }
+ free(user_list);
+
+ return head;
+}
+
+static int write_gen_home_dir_context(FILE * out, genhomedircon_settings_t * s,
+ semanage_list_t * user_context_tpl,
+ semanage_list_t * homedir_context_tpl)
+{
+ genhomedircon_user_entry_t *users;
+ int errors = 0;
+
+ users = get_users(s, &errors);
+ if (!users && errors) {
+ return STATUS_ERR;
+ }
+
+ for (; users; pop_user_entry(&users)) {
+ if (write_home_dir_context(out, homedir_context_tpl,
+ users->name,
+ users->sename, users->home,
+ users->prefix)) {
+ return STATUS_ERR;
+ }
+ if (write_user_context(out, user_context_tpl, users->name,
+ users->sename, users->prefix)) {
+ return STATUS_ERR;
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+/**
+ * @param s settings structure, stores various paths etc. Must never be NULL
+ * @param out the FILE to put all the output in.
+ * @return 0 on success
+ */
+static int write_context_file(genhomedircon_settings_t * s, FILE * out)
+{
+ semanage_list_t *homedirs = NULL;
+ semanage_list_t *h = NULL;
+ semanage_list_t *user_context_tpl = NULL;
+ semanage_list_t *homedir_context_tpl = NULL;
+ semanage_list_t *homeroot_context_tpl = NULL;
+ int retval = STATUS_SUCCESS;
+
+ homedirs = get_home_dirs(s);
+ if (!homedirs) {
+ WARN(s->h_semanage,
+ "no home directories were available, exiting without writing");
+ return STATUS_ERR; /* No homedirs so no output */
+ }
+
+ if (write_file_context_header(s, out) != STATUS_SUCCESS)
+ return STATUS_ERR;
+
+ homedir_context_tpl = make_template(s, &HOME_DIR_PRED);
+ homeroot_context_tpl = make_template(s, &HOME_ROOT_PRED);
+ user_context_tpl = make_template(s, &USER_CONTEXT_PRED);
+ if (!homedir_context_tpl || !homeroot_context_tpl || !user_context_tpl) {
+ retval = STATUS_ERR;
+ goto done;
+ }
+
+ for (h = homedirs; h; h = h->next) {
+ Ustr *temp = ustr_dup_cstr(h->data);
+
+ if (!temp || !ustr_add_cstr(&temp, "/[^/]*")) {
+ ustr_sc_free(&temp);
+ retval = STATUS_ERR;
+ goto done;
+ }
+
+ if (write_home_dir_context(out,
+ homedir_context_tpl, FALLBACK_USER,
+ FALLBACK_USER, ustr_cstr(temp),
+ FALLBACK_USER_PREFIX) !=
+ STATUS_SUCCESS) {
+ ustr_sc_free(&temp);
+ retval = STATUS_ERR;
+ goto done;
+ }
+ if (write_home_root_context(out,
+ homeroot_context_tpl,
+ h->data) != STATUS_SUCCESS) {
+ ustr_sc_free(&temp);
+ retval = STATUS_ERR;
+ goto done;
+ }
+
+ ustr_sc_free(&temp);
+ }
+ if (write_user_context(out, user_context_tpl,
+ ".*", FALLBACK_USER,
+ FALLBACK_USER_PREFIX) != STATUS_SUCCESS) {
+ retval = STATUS_ERR;
+ goto done;
+ }
+ if (write_gen_home_dir_context(out, s, user_context_tpl,
+ homedir_context_tpl) != STATUS_SUCCESS) {
+ retval = STATUS_ERR;
+ }
+
+ done:
+ /* Cleanup */
+ semanage_list_destroy(&homedirs);
+ semanage_list_destroy(&user_context_tpl);
+ semanage_list_destroy(&homedir_context_tpl);
+ semanage_list_destroy(&homeroot_context_tpl);
+
+ return retval;
+}
+
+int semanage_genhomedircon(semanage_handle_t * sh, int usepasswd)
+{
+ genhomedircon_settings_t s;
+ FILE *out = NULL;
+ int retval = 0;
+
+ assert(sh);
+
+ s.homedir_template_path =
+ semanage_path(SEMANAGE_TMP, SEMANAGE_HOMEDIR_TMPL);
+ s.fcfilepath = semanage_path(SEMANAGE_TMP, SEMANAGE_FC_HOMEDIRS);
+
+ s.usepasswd = usepasswd;
+ s.h_semanage = sh;
+
+ if (!(out = fopen(s.fcfilepath, "w"))) {
+ /* couldn't open output file */
+ ERR(sh, "Could not open the file_context file for writing");
+ return STATUS_ERR;
+ }
+
+ retval = write_context_file(&s, out);
+
+ fclose(out);
+ return retval;
+}
Added: trunk/libsemanage/src/genhomedircon.h
===================================================================
--- trunk/libsemanage/src/genhomedircon.h (rev 0)
+++ trunk/libsemanage/src/genhomedircon.h 2007-08-23 14:41:50 UTC (rev 2527)
@@ -0,0 +1,27 @@
+/* Author: Mark Goldman <mgo...@tr...>
+ *
+ * Copyright (C) 2007 Tresys Technology, LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _SEMANAGE_GENHOMEDIRCON_H_
+#define _SEMANAGE_GENHOMEDIRCON_H_
+
+#include "utilities.h"
+
+int semanage_genhomedircon(semanage_handle_t * sh, int usepasswd);
+
+#endif
Modified: trunk/libsemanage/src/semanage_store.c
===================================================================
--- trunk/libsemanage/src/semanage_store.c 2007-08-23 14:39:48 UTC (rev 2526)
+++ trunk/libsemanage/src/semanage_store.c 2007-08-23 14:41:50 UTC (rev 2527)
@@ -34,6 +34,7 @@
#include "semanage_store.h"
#include "database_policydb.h"
#include "handle.h"
+#include "genhomedircon.h"
#include <selinux/selinux.h>
#include <sepol/policydb.h>
@@ -60,6 +61,9 @@
#define SEMANAGE_CONF_FILE "semanage.conf"
/* relative path names to enum semanage_paths to special files and
* directories for the module store */
+
+#define TRUE 1
+
enum semanage_file_defs {
SEMANAGE_ROOT,
SEMANAGE_TRANS_LOCK,
@@ -110,6 +114,7 @@
"/seusers.final",
"/users_extra",
"/netfilter_contexts",
+ "/file_contexts.homedirs",
};
/* A node used in a linked list of file contexts; used for sorting.
@@ -1264,15 +1269,15 @@
goto cleanup;
}
- if ((commit_num = semanage_commit_sandbox(sh)) < 0) {
- retval = commit_num;
+ if ((retval =
+ semanage_genhomedircon(sh, TRUE)) != 0) {
+ ERR(sh, "semanage_genhomedircon returned error code %d.",
+ retval);
goto cleanup;
}
- if ((retval =
- semanage_exec_prog(sh, sh->conf->genhomedircon,
- sh->conf->store_path, "")) != 0) {
- ERR(sh, "genhomedircon returned error code %d.", retval);
+ if ((commit_num = semanage_commit_sandbox(sh)) < 0) {
+ retval = commit_num;
goto cleanup;
}
Modified: trunk/libsemanage/src/semanage_store.h
===================================================================
--- trunk/libsemanage/src/semanage_store.h 2007-08-23 14:39:48 UTC (rev 2526)
+++ trunk/libsemanage/src/semanage_store.h 2007-08-23 14:41:50 UTC (rev 2527)
@@ -57,6 +57,7 @@
SEMANAGE_SEUSERS,
SEMANAGE_USERS_EXTRA,
SEMANAGE_NC,
+ SEMANAGE_FC_HOMEDIRS,
SEMANAGE_STORE_NUM_PATHS
};
Added: trunk/libsemanage/src/utilities.c
===================================================================
--- trunk/libsemanage/src/utilities.c (rev 0)
+++ trunk/libsemanage/src/utilities.c 2007-08-23 14:41:50 UTC (rev 2527)
@@ -0,0 +1,312 @@
+/* Author: Mark Goldman <mgo...@tr...>
+ * Paul Rosenfeld <pro...@tr...>
+ *
+ * Copyright (C) 2007 Tresys Technology, LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "utilities.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <ustr.h>
+
+#define TRUE 1
+#define FALSE 0
+
+char *semanage_findval(char *file, char *var, char *delim)
+{
+ FILE *fd;
+ char *buff = NULL;
+ char *retval = NULL;
+ size_t buff_len = 0;
+
+ assert(file);
+ assert(var);
+
+ if ((fd = fopen(file, "r")) == NULL)
+ return NULL;
+
+ while (getline(&buff, &buff_len, fd) > 0) {
+ if (semanage_is_prefix(buff, var)) {
+ retval = semanage_split(buff, delim);
+ if (retval)
+ semanage_rtrim(retval, '\n');
+ break;
+ }
+ }
+ free(buff);
+ fclose(fd);
+
+ return retval;
+}
+
+int semanage_is_prefix(const char *str, const char *prefix)
+{
+ int retval;
+ Ustr *ustr = USTR_NULL;
+
+ if (!str) {
+ return FALSE;
+ }
+ if (!prefix) {
+ return TRUE;
+ }
+ if (!(ustr = ustr_dup_cstr(str))) {
+ return FALSE;
+ }
+ retval = (ustr_srch_cstr_fwd(ustr, 0, prefix) == 1);
+ ustr_sc_free(&ustr);
+
+ return retval;
+}
+
+char *semanage_split_on_space(const char *str)
+{
+ /* as per the man page, these are the isspace() chars */
+ const char *seps = "\f\n\r\t\v ";
+ size_t slen = strlen(seps);
+ size_t off = 0, rside_len = 0;
+ char *retval = NULL;
+ Ustr *ustr = USTR_NULL, *temp = USTR_NULL;
+
+ if (!str)
+ goto done;
+ if (!(ustr = ustr_dup_cstr(str)))
+ goto done;
+ temp =
+ ustr_split_spn_chrs(ustr, &off, seps, slen, USTR_NULL,
+ USTR_FLAG_SPLIT_DEF);
+ if (!temp)
+ goto done;
+ /* throw away the left hand side */
+ ustr_sc_free(&temp);
+
+ rside_len = ustr_len(ustr) - off;
+ temp = ustr_dup_subustr(ustr, off + 1, rside_len);
+ if (!temp)
+ goto done;
+ retval = strdup(ustr_cstr(temp));
+ ustr_sc_free(&temp);
+
+ done:
+ ustr_sc_free(&ustr);
+ return retval;
+}
+
+char *semanage_split(const char *str, const char *delim)
+{
+ Ustr *ustr = USTR_NULL, *temp = USTR_NULL;
+ size_t off = 0, rside_len = 0;
+ char *retval = NULL;
+
+ if (!str)
+ goto done;
+ if (!delim || !(*delim))
+ return semanage_split_on_space(str);
+ ustr = ustr_dup_cstr(str);
+ temp =
+ ustr_split_cstr(ustr, &off, delim, USTR_NULL, USTR_FLAG_SPLIT_DEF);
+ if (!temp)
+ goto done;
+ /* throw away the left hand side */
+ ustr_sc_free(&temp);
+
+ rside_len = ustr_len(ustr) - off;
+
+ temp = ustr_dup_subustr(ustr, off + 1, rside_len);
+ if (!temp)
+ goto done;
+ retval = strdup(ustr_cstr(temp));
+ ustr_sc_free(&temp);
+
+ done:
+ ustr_sc_free(&ustr);
+ return retval;
+}
+
+int semanage_list_push(semanage_list_t ** list, char *data)
+{
+ semanage_list_t *temp = NULL;
+
+ if (!data)
+ return EINVAL;
+ if (!(temp = malloc(sizeof(semanage_list_t))))
+ return ENOMEM;
+
+ if (!(temp->data = strdup(data))) {
+ free(temp);
+ return ENOMEM;
+ }
+ temp->next = *list;
+ *list = temp;
+
+ return 0;
+}
+
+char *semanage_list_pop(semanage_list_t ** list)
+{
+ semanage_list_t *node = NULL;
+ char *data = NULL;
+
+ if (!list || !(*list))
+ return NULL;
+
+ node = (*list);
+ data = node->data;
+
+ (*list) = node->next;
+ free(node);
+
+ return data;
+}
+
+void semanage_list_destroy(semanage_list_t ** list)
+{
+ semanage_list_t *temp;
+
+ while ((temp = (*list))) {
+ free(temp->data);
+ (*list) = temp->next;
+ free(temp);
+ }
+}
+
+semanage_list_t *semanage_list_find(semanage_list_t * l, char *data)
+{
+ if (!data)
+ return NULL;
+ while (l && strcmp(l->data, data))
+ l = l->next;
+
+ return l;
+}
+
+int semanage_list_sort(semanage_list_t ** l)
+{
+ semanage_list_t **array = NULL;
+ semanage_list_t *temp = NULL;
+ size_t count = 0;
+ size_t i = 0;
+
+ if (!l)
+ return 0;
+
+ for (temp = *l; temp; temp = temp->next)
+ ++count;
+
+ array = malloc(sizeof(semanage_list_t *) * count);
+ if (!array)
+ return ENOMEM; /* couldn't allocate memory for sort */
+ for (temp = *l; temp; temp = temp->next) {
+ array[i++] = temp;
+ }
+
+ qsort(array, count, sizeof(semanage_list_t *),
+ (int (*)(const void *, const void *))&semanage_cmp_plist_t);
+ for (i = 0; i < (count - 1); ++i) {
+ array[i]->next = array[i + 1];
+ }
+ array[i]->next = NULL;
+ (*l) = array[0];
+ free(array);
+
+ return 0;
+}
+
+int semanage_cmp_plist_t(const semanage_list_t ** x, const semanage_list_t ** y)
+{
+ return strcmp((*x)->data, (*y)->data);
+}
+
+int semanage_str_count(char *data, char what)
+{
+ int count = 0;
+
+ if (!data)
+ return 0;
+ while (*data) {
+ if (*data == what)
+ ++count;
+ ++data;
+ }
+
+ return count;
+}
+
+void semanage_rtrim(char *str, char trim_to)
+{
+ int len = 0;
+
+ if (!str)
+ return;
+ len = strlen(str);
+
+ while (len > 0) {
+ if (str[--len] == trim_to) {
+ str[len] = '\0';
+ return;
+ }
+ }
+}
+
+/* list_addafter_controlmem does *NOT* duplicate the data argument
+ * use at your own risk, I am building a list out of malloc'd memory and
+ * it is only going to get stored into this list, thus when I destroy it
+ * later I won't free a ptr twice.
+ *
+ * returns the newly created node or NULL on error
+ */
+semanage_list_t *list_addafter_controlmem(semanage_list_t * item, char *data)
+{
+ semanage_list_t *temp = malloc(sizeof(semanage_list_t));
+
+ if (!temp)
+ return NULL;
+ temp->data = data;
+ temp->next = item->next;
+ item->next = temp;
+
+ return temp;
+}
+
+semanage_list_t *semanage_slurp_file_filter(FILE * file,
+ int (*pred) (const char *))
+{
+ semanage_list_t head;
+ semanage_list_t *current = &head;
+ char *line = NULL;
+ size_t buff_len = 0;
+
+ head.next = NULL; /* initialize head, we aren't going to use the data */
+ while (getline(&line, &buff_len, file) >= 0) {
+ if (pred(line)) {
+ semanage_rtrim(line, '\n');
+ current = list_addafter_controlmem(current, line);
+ if (!current)
+ break;
+ line = NULL;
+ buff_len = 0;
+ }
+ }
+ free(line);
+
+ return head.next;
+}
Added: trunk/libsemanage/src/utilities.h
===================================================================
--- trunk/libsemanage/src/utilities.h (rev 0)
+++ trunk/libsemanage/src/utilities.h 2007-08-23 14:41:50 UTC (rev 2527)
@@ -0,0 +1,137 @@
+/* Author: Mark Goldman <mgo...@tr...>
+ *
+ * Copyright (C) 2007 Tresys Technology, LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* This file contains helper functions that are loosely based off of what is
+ * available from the python script genhomedircon. Also this file contains
+ * c implementations of a couple of python functions so that genhomedircon will
+ * look/act like the python script.
+ */
+#ifndef _SEMANAGE_UTILITIES_H_
+#define _SEMANAGE_UTILITIES_H_
+
+#include <stdio.h>
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+#define WARN_UNUSED \
+ __attribute__ ((__warn_unused_result__))
+#else
+# define WARN_UNUSED /* nothing */
+#endif
+
+typedef struct list {
+ char *data;
+ struct list *next;
+} semanage_list_t;
+
+/**
+ * @param file the path to the file to look for a variable in
+ * @param var the variable that you want the value of
+ * @param delim the value that separates the part you care about from the part
+ * that you don't.
+ * @return for the first instance of var in the file, returns everything after
+ * delim.
+ * returns "" if not found IE if(*(semanage_findval(f,v,d)) == '\0'){
+ * printf("%s not found in file", v);
+ * }
+ *
+ * NULL for error (out of memory, etc)
+ */
+char *semanage_findval(char *file, char *var, char *delim) WARN_UNUSED;
+
+/**
+ * @param str string to test
+ * @param val prefix
+ * @return 1 if val is the prefix of str
+ * 0 if val is not the prefix of str
+ *
+ * note: if str == NULL, returns false
+ * if val == NULL, returns true --nothing can always be the prefix of
+ * something
+ * if (*val) == "" returns true same as above.
+ */
+int semanage_is_prefix(const char *str, const char *val) WARN_UNUSED;
+
+/**
+ * @param str the string to semanage_split
+ * @return malloc'd string after the first run of charachters that aren't whitespace
+ */
+char *semanage_split_on_space(const char *str) WARN_UNUSED;
+
+/**
+ * @param str the string to semanage_split
+ * @param delim the string delimiter. NOT a set of charachters that can be
+ * a delimiter.
+ * if *delim == '\0' behaves as semanage_splitOnSpace()
+ * @return a ptr to the first charachter past the delimiter.
+ * if delim doesn't appear in the string, returns a ptr to the
+ * trailing null in the string
+ */
+char *semanage_split(const char *str, const char *delim) WARN_UNUSED;
+
+/* linked list string functions
+ * Functions allocate memory. Must be free'd with
+ * either semanage_list_pop until list == NULL or semanage_list_destroy()
+ */
+int semanage_list_push(semanage_list_t ** list, char *data) WARN_UNUSED;
+char *semanage_list_pop(semanage_list_t ** list);
+void semanage_list_destroy(semanage_list_t ** list);
+semanage_list_t *semanage_list_find(semanage_list_t * l,
+ char *data) WARN_UNUSED;
+int semanage_list_sort(semanage_list_t ** l) WARN_UNUSED;
+/* function to compare 2 semanage_list_t nodes,
+ * returns strcmp(x->data, y->data)
+ * used internally by semanage_list_sort()
+ */
+int semanage_cmp_plist_t(const semanage_list_t ** x,
+ const semanage_list_t ** y);
+/**
+ * @param data a target string
+ * @param what a charachter
+ * @returns the number of times the char appears in the string
+ */
+int semanage_str_count(char *data, char what);
+/**
+ * @param - a string
+ * @param the charachter to trim to
+ * @return - mangles the string, converting the first
+ * occurrance of the charachter to a '\0' from
+ * the end of the string.
+ */
+void semanage_rtrim(char *str, char trim_to);
+
+/**
+ * @param data some string
+ * @return modifies the string such that the first whitespace char becomes
+ * '\0', ending the string.
+ */
+void semanage_keep_until_space(char *data);
+
+/**
+ * @param file - an open FILE to read from
+ * @param pred - a function taking a string that
+ * returns 1 if the string should be
+ * kept and 0 otherwise
+ * @return a list of lines from the file (empty lines become
+ * empty strings) in the file order where pred(line)
+ * returns > 0
+ */
+semanage_list_t *semanage_slurp_file_filter(FILE * file,
+ int (*pred) (const char *))
+ WARN_UNUSED;
+#endif
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|