libsemanage: patch for MCS/MLS in user files

The attached patch makes the
/etc/selinux/default/contexts/files/file_contexts.homedirs generation process
include the MCS/MLS level.

This means that if you have a user with a MCS/MLS level that isn't SystemLow
then their home directory will be labeled such that they can have read/write
access to it by default.

Unless anyone has any better ideas for how to solve this problem I will upload
this to Debian shortly.

What do the MLS users do in this situation?  Just relabel home directories
manually?

Finally it seems that when you run "semanage user -m" the
file_contexts.homedirs doesn't get updated, it's only when you run
"semanage login -m" that it takes affect.

Signed-off-by: Eric Paris <eparis@redhat.com>
Acked-by: Russell Coker <russell@coker.com.au>
Acked-by: Dan Walsh <dwalsh@redhat.com>
This commit is contained in:
Russell Coker 2011-01-05 19:30:25 +11:00 committed by Eric Paris
parent 34d9c258da
commit d784fd71b5

View file

@ -76,9 +76,11 @@
#define TEMPLATE_USER "USER" #define TEMPLATE_USER "USER"
#define TEMPLATE_ROLE "ROLE" #define TEMPLATE_ROLE "ROLE"
#define TEMPLATE_SEUSER "system_u" #define TEMPLATE_SEUSER "system_u"
#define TEMPLATE_LEVEL "s0"
#define FALLBACK_USER "user_u" #define FALLBACK_USER "user_u"
#define FALLBACK_USER_PREFIX "user" #define FALLBACK_USER_PREFIX "user"
#define FALLBACK_USER_LEVEL "s0"
#define DEFAULT_LOGIN "__default__" #define DEFAULT_LOGIN "__default__"
typedef struct { typedef struct {
@ -87,6 +89,7 @@ typedef struct {
const char *homedir_template_path; const char *homedir_template_path;
char *fallback_user; char *fallback_user;
char *fallback_user_prefix; char *fallback_user_prefix;
char *fallback_user_level;
semanage_handle_t *h_semanage; semanage_handle_t *h_semanage;
sepol_policydb_t *policydb; sepol_policydb_t *policydb;
} genhomedircon_settings_t; } genhomedircon_settings_t;
@ -96,6 +99,7 @@ typedef struct user_entry {
char *sename; char *sename;
char *prefix; char *prefix;
char *home; char *home;
char *level;
struct user_entry *next; struct user_entry *next;
} genhomedircon_user_entry_t; } genhomedircon_user_entry_t;
@ -487,12 +491,13 @@ static int check_line(genhomedircon_settings_t * s, Ustr *line)
static int write_home_dir_context(genhomedircon_settings_t * s, FILE * out, static int write_home_dir_context(genhomedircon_settings_t * s, FILE * out,
semanage_list_t * tpl, const char *user, semanage_list_t * tpl, const char *user,
const char *seuser, const char *home, const char *seuser, const char *home,
const char *role_prefix) const char *role_prefix, const char *level)
{ {
replacement_pair_t repl[] = { replacement_pair_t repl[] = {
{.search_for = TEMPLATE_SEUSER,.replace_with = seuser}, {.search_for = TEMPLATE_SEUSER,.replace_with = seuser},
{.search_for = TEMPLATE_HOME_DIR,.replace_with = home}, {.search_for = TEMPLATE_HOME_DIR,.replace_with = home},
{.search_for = TEMPLATE_ROLE,.replace_with = role_prefix}, {.search_for = TEMPLATE_ROLE,.replace_with = role_prefix},
{.search_for = TEMPLATE_LEVEL,.replace_with = level},
{NULL, NULL} {NULL, NULL}
}; };
Ustr *line = USTR_NULL; Ustr *line = USTR_NULL;
@ -584,13 +589,15 @@ static int name_user_cmp(char *key, semanage_user_t ** val)
} }
static int push_user_entry(genhomedircon_user_entry_t ** list, const char *n, static int push_user_entry(genhomedircon_user_entry_t ** list, const char *n,
const char *sen, const char *pre, const char *h) const char *sen, const char *pre, const char *h,
const char *l)
{ {
genhomedircon_user_entry_t *temp = NULL; genhomedircon_user_entry_t *temp = NULL;
char *name = NULL; char *name = NULL;
char *sename = NULL; char *sename = NULL;
char *prefix = NULL; char *prefix = NULL;
char *home = NULL; char *home = NULL;
char *level = NULL;
temp = malloc(sizeof(genhomedircon_user_entry_t)); temp = malloc(sizeof(genhomedircon_user_entry_t));
if (!temp) if (!temp)
@ -607,11 +614,15 @@ static int push_user_entry(genhomedircon_user_entry_t ** list, const char *n,
home = strdup(h); home = strdup(h);
if (!home) if (!home)
goto cleanup; goto cleanup;
level = strdup(l);
if (!level)
goto cleanup;
temp->name = name; temp->name = name;
temp->sename = sename; temp->sename = sename;
temp->prefix = prefix; temp->prefix = prefix;
temp->home = home; temp->home = home;
temp->level = level;
temp->next = (*list); temp->next = (*list);
(*list) = temp; (*list) = temp;
@ -622,6 +633,7 @@ static int push_user_entry(genhomedircon_user_entry_t ** list, const char *n,
free(sename); free(sename);
free(prefix); free(prefix);
free(home); free(home);
free(level);
free(temp); free(temp);
return STATUS_ERR; return STATUS_ERR;
} }
@ -639,25 +651,30 @@ static void pop_user_entry(genhomedircon_user_entry_t ** list)
free(temp->sename); free(temp->sename);
free(temp->prefix); free(temp->prefix);
free(temp->home); free(temp->home);
free(temp->level);
free(temp); free(temp);
} }
static int set_fallback_user(genhomedircon_settings_t *s, static int set_fallback_user(genhomedircon_settings_t *s, const char *user,
const char *user, const char *prefix) const char *prefix, const char *level)
{ {
char *fallback_user = strdup(user); char *fallback_user = strdup(user);
char *fallback_user_prefix = strdup(prefix); char *fallback_user_prefix = strdup(prefix);
char *fallback_user_level = strdup(level);
if (fallback_user == NULL || fallback_user_prefix == NULL) { if (fallback_user == NULL || fallback_user_prefix == NULL || fallback_user_level == NULL) {
free(fallback_user); free(fallback_user);
free(fallback_user_prefix); free(fallback_user_prefix);
free(fallback_user_level);
return STATUS_ERR; return STATUS_ERR;
} }
free(s->fallback_user); free(s->fallback_user);
free(s->fallback_user_prefix); free(s->fallback_user_prefix);
free(s->fallback_user_level);
s->fallback_user = fallback_user; s->fallback_user = fallback_user;
s->fallback_user_prefix = fallback_user_prefix; s->fallback_user_prefix = fallback_user_prefix;
s->fallback_user_level = fallback_user_level;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -670,6 +687,7 @@ static int setup_fallback_user(genhomedircon_settings_t * s)
const char *name = NULL; const char *name = NULL;
const char *seuname = NULL; const char *seuname = NULL;
const char *prefix = NULL; const char *prefix = NULL;
const char *level = NULL;
unsigned int i; unsigned int i;
int retval; int retval;
int errors = 0; int errors = 0;
@ -692,11 +710,17 @@ static int setup_fallback_user(genhomedircon_settings_t * s)
break; break;
} }
if (semanage_user_query(s->h_semanage, key, &u) < 0) if (semanage_user_query(s->h_semanage, key, &u) < 0)
{
prefix = name; prefix = name;
level = "s0";
}
else else
{
prefix = semanage_user_get_prefix(u); prefix = semanage_user_get_prefix(u);
level = semanage_user_get_mlslevel(u);
}
if (set_fallback_user(s, seuname, prefix) != 0) if (set_fallback_user(s, seuname, prefix, level) != 0)
errors = STATUS_ERR; errors = STATUS_ERR;
semanage_user_key_free(key); semanage_user_key_free(key);
if (u) if (u)
@ -724,6 +748,7 @@ static genhomedircon_user_entry_t *get_users(genhomedircon_settings_t * s,
const char *name = NULL; const char *name = NULL;
const char *seuname = NULL; const char *seuname = NULL;
const char *prefix = NULL; const char *prefix = NULL;
const char *level = NULL;
struct passwd pwstorage, *pwent = NULL; struct passwd pwstorage, *pwent = NULL;
unsigned int i; unsigned int i;
long rbuflen; long rbuflen;
@ -775,8 +800,10 @@ static genhomedircon_user_entry_t *get_users(genhomedircon_settings_t * s,
&name_user_cmp); &name_user_cmp);
if (u) { if (u) {
prefix = semanage_user_get_prefix(*u); prefix = semanage_user_get_prefix(*u);
level = semanage_user_get_mlslevel(*u);
} else { } else {
prefix = name; prefix = name;
level = "s0";
} }
retval = getpwnam_r(name, &pwstorage, rbuf, rbuflen, &pwent); retval = getpwnam_r(name, &pwstorage, rbuf, rbuflen, &pwent);
@ -803,7 +830,7 @@ static genhomedircon_user_entry_t *get_users(genhomedircon_settings_t * s,
continue; continue;
} }
if (push_user_entry(&head, name, seuname, if (push_user_entry(&head, name, seuname,
prefix, pwent->pw_dir) != STATUS_SUCCESS) { prefix, pwent->pw_dir, level) != STATUS_SUCCESS) {
*errors = STATUS_ERR; *errors = STATUS_ERR;
break; break;
} }
@ -846,7 +873,7 @@ static int write_gen_home_dir_context(genhomedircon_settings_t * s, FILE * out,
if (write_home_dir_context(s, out, homedir_context_tpl, if (write_home_dir_context(s, out, homedir_context_tpl,
users->name, users->name,
users->sename, users->home, users->sename, users->home,
users->prefix)) { users->prefix, users->level)) {
return STATUS_ERR; return STATUS_ERR;
} }
if (write_user_context(s, out, user_context_tpl, users->name, if (write_user_context(s, out, user_context_tpl, users->name,
@ -910,7 +937,7 @@ static int write_context_file(genhomedircon_settings_t * s, FILE * out)
homedir_context_tpl, homedir_context_tpl,
s->fallback_user, s->fallback_user, s->fallback_user, s->fallback_user,
ustr_cstr(temp), ustr_cstr(temp),
s->fallback_user_prefix) != s->fallback_user_prefix, s->fallback_user_level) !=
STATUS_SUCCESS) { STATUS_SUCCESS) {
ustr_sc_free(&temp); ustr_sc_free(&temp);
retval = STATUS_ERR; retval = STATUS_ERR;
@ -967,7 +994,8 @@ int semanage_genhomedircon(semanage_handle_t * sh,
s.fallback_user = strdup(FALLBACK_USER); s.fallback_user = strdup(FALLBACK_USER);
s.fallback_user_prefix = strdup(FALLBACK_USER_PREFIX); s.fallback_user_prefix = strdup(FALLBACK_USER_PREFIX);
if (s.fallback_user == NULL || s.fallback_user_prefix == NULL) s.fallback_user_level = strdup(FALLBACK_USER_LEVEL);
if (s.fallback_user == NULL || s.fallback_user_prefix == NULL || s.fallback_user_level == NULL)
return STATUS_ERR; return STATUS_ERR;
s.usepasswd = usepasswd; s.usepasswd = usepasswd;