113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Author: Mark Goldman	  <mgoldman@tresys.com>
213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * 	   Paul Rosenfeld <prosenfeld@tresys.com>
313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * 	   Todd C. Miller <tmiller@tresys.com>
413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Copyright (C) 2007 Tresys Technology, LLC
613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  This library is free software; you can redistribute it and/or modify
813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  it under the terms of the GNU Lesser General Public License as
913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  published by the Free Software Foundation; either version 2.1 of the
1013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  License, or (at your option) any later version.
1113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
1213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  This library is distributed in the hope that it will be useful, but
1313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  WITHOUT ANY WARRANTY; without even the implied warranty of
1413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  Lesser General Public License for more details.
1613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
1713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  You should have received a copy of the GNU Lesser General Public
1813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  License along with this library; if not, write to the Free Software
1913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
2013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  02110-1301  USA
2113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
2213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <semanage/handle.h>
2413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <semanage/seusers_policy.h>
2513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <semanage/users_policy.h>
2613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <semanage/user_record.h>
2713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <semanage/fcontext_record.h>
2813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <semanage/fcontexts_policy.h>
2913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/context.h>
3013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/context_record.h>
3113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "semanage_store.h"
3213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "seuser_internal.h"
3313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "debug.h"
3413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "utilities.h"
3613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "genhomedircon.h"
3713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <assert.h>
39300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss#include <ctype.h>
4013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <limits.h>
4113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdio.h>
4213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdlib.h>
4313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <string.h>
4413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sys/types.h>
4513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sys/stat.h>
4613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <fcntl.h>
4713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <pwd.h>
4813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <errno.h>
4913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <unistd.h>
5013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <regex.h>
5167b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney#include <grp.h>
5267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney#include <search.h>
5313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
5413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* paths used in get_home_dirs() */
5513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define PATH_ETC_USERADD "/etc/default/useradd"
5613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define PATH_ETC_LIBUSER "/etc/libuser.conf"
5713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define PATH_DEFAULT_HOME "/home"
5813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define PATH_EXPORT_HOME "/export/home"
5913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define PATH_ETC_LOGIN_DEFS "/etc/login.defs"
6013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
6113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* other paths */
6213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define PATH_SHELLS_FILE "/etc/shells"
6313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define PATH_NOLOGIN_SHELL "/sbin/nologin"
6413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
6513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* comments written to context file */
6613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define COMMENT_FILE_CONTEXT_HEADER "#\n#\n# " \
6713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			"User-specific file contexts, generated via libsemanage\n" \
6813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			"# use semanage command to manage system users to change" \
6913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			" the file_context\n#\n#\n"
7013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define COMMENT_USER_HOME_CONTEXT "\n\n#\n# Home Context for user %s" \
7213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			"\n#\n\n"
7313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* placeholders used in the template file
7513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle   which are searched for and replaced */
7613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define TEMPLATE_HOME_ROOT "HOME_ROOT"
7713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define TEMPLATE_HOME_DIR "HOME_DIR"
7808cde98b606cd04e26061d16ec537a2549f5199cJason Zaman/* these are legacy */
7913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define TEMPLATE_USER "USER"
8013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define TEMPLATE_ROLE "ROLE"
8108cde98b606cd04e26061d16ec537a2549f5199cJason Zaman/* new names */
8208cde98b606cd04e26061d16ec537a2549f5199cJason Zaman#define TEMPLATE_USERNAME "%{USERNAME}"
8308cde98b606cd04e26061d16ec537a2549f5199cJason Zaman#define TEMPLATE_USERID "%{USERID}"
8408cde98b606cd04e26061d16ec537a2549f5199cJason Zaman
85925914acea3e2a95f4ccc9d39498cede345061d5Jason Zaman#define FALLBACK_SENAME "user_u"
86925914acea3e2a95f4ccc9d39498cede345061d5Jason Zaman#define FALLBACK_PREFIX "user"
87925914acea3e2a95f4ccc9d39498cede345061d5Jason Zaman#define FALLBACK_LEVEL "s0"
885ebc83b1d395d1ad9e122935834f7ef7f9fb17aaJason Zaman#define FALLBACK_NAME "[^/]+"
893b23f12eb9aa2ee828561ffb414efa8c2031e75fJason Zaman#define FALLBACK_UIDGID "[0-9]+"
9013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define DEFAULT_LOGIN "__default__"
9113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
92d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney#define CONTEXT_NONE "<<none>>"
93d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney
9413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindletypedef struct user_entry {
9513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *name;
963b23f12eb9aa2ee828561ffb414efa8c2031e75fJason Zaman	char *uid;
973b23f12eb9aa2ee828561ffb414efa8c2031e75fJason Zaman	char *gid;
9813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *sename;
9913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *prefix;
10013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *home;
101d784fd71b56cb8f57d5b9fcd784094e004bf7c6aRussell Coker	char *level;
10267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	char *login;
10388e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney	char *homedir_role;
10413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct user_entry *next;
10513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle} genhomedircon_user_entry_t;
10613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
10713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindletypedef struct {
108c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman	const char *fcfilepath;
109c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman	int usepasswd;
110c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman	const char *homedir_template_path;
111c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman	genhomedircon_user_entry_t *fallback;
112c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman	semanage_handle_t *h_semanage;
113c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman	sepol_policydb_t *policydb;
114c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman} genhomedircon_settings_t;
115c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman
116c90780aaf767485fbdc063eab905422d756f22b5Jason Zamantypedef struct {
11713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	const char *search_for;
11813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	const char *replace_with;
11913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle} replacement_pair_t;
12013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
12113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindletypedef struct {
12213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	const char *dir;
12313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int matched;
12413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle} fc_match_handle_t;
12513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
126915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paristypedef struct IgnoreDir {
127915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris	struct IgnoreDir *next;
128915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris	char *dir;
129915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris} ignoredir_t;
130915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris
131915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Parisignoredir_t *ignore_head = NULL;
132915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris
133915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Parisstatic void ignore_free(void) {
134915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris	ignoredir_t *next;
135915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris
136915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris	while (ignore_head) {
137915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris		next = ignore_head->next;
138915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris		free(ignore_head->dir);
139915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris		free(ignore_head);
140915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris		ignore_head = next;
141915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris	}
142915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris}
143915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris
144915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Parisstatic int ignore_setup(char *ignoredirs) {
145915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris	char *tok;
146915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris	ignoredir_t *ptr = NULL;
147915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris
148915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris	tok = strtok(ignoredirs, ";");
149915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris	while(tok) {
150915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris		ptr = calloc(sizeof(ignoredir_t),1);
151915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris		if (!ptr)
152915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris			goto err;
153915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris		ptr->dir = strdup(tok);
154915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris		if (!ptr->dir)
155915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris			goto err;
156915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris
157915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris		ptr->next = ignore_head;
158915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris		ignore_head = ptr;
159915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris
160915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris		tok = strtok(NULL, ";");
161915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris	}
162915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris
163915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris	return 0;
164915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Pariserr:
165915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris	free(ptr);
166915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris	ignore_free();
167915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris	return -1;
168915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris}
169915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris
170915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Parisstatic int ignore(const char *homedir) {
171915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris	ignoredir_t *ptr = ignore_head;
172915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris	while (ptr) {
173915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris		if (strcmp(ptr->dir, homedir) == 0) {
174915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris			return 1;
175915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris		}
176915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris		ptr = ptr->next;
177915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris	}
178915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris	return 0;
179915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris}
180915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris
18188e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierneystatic int prefix_is_homedir_role(const semanage_user_t *user,
18288e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney				  const char *prefix)
18388e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney{
18488e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney	return strcmp(OBJECT_R, prefix) == 0 ||
18588e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney		semanage_user_has_role(user, prefix);
18688e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney}
18788e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney
18813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic semanage_list_t *default_shell_list(void)
18913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
19013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_list_t *list = NULL;
19113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
19213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (semanage_list_push(&list, "/bin/csh")
19313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    || semanage_list_push(&list, "/bin/tcsh")
19413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    || semanage_list_push(&list, "/bin/ksh")
19513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    || semanage_list_push(&list, "/bin/bsh")
19613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    || semanage_list_push(&list, "/bin/ash")
19713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    || semanage_list_push(&list, "/usr/bin/ksh")
19813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    || semanage_list_push(&list, "/usr/bin/pdksh")
19913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    || semanage_list_push(&list, "/bin/zsh")
20013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    || semanage_list_push(&list, "/bin/sh")
20113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    || semanage_list_push(&list, "/bin/bash"))
20213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto fail;
20313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
20413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return list;
20513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
20613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      fail:
20713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_list_destroy(&list);
20813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return NULL;
20913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
21013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
21113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic semanage_list_t *get_shell_list(void)
21213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
21313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	FILE *shells;
21413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *temp = NULL;
21513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_list_t *list = NULL;
21613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	size_t buff_len = 0;
21713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ssize_t len;
21813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
21913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	shells = fopen(PATH_SHELLS_FILE, "r");
22013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!shells)
22113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return default_shell_list();
22213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while ((len = getline(&temp, &buff_len, shells)) > 0) {
22313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (temp[len-1] == '\n') temp[len-1] = 0;
22413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (strcmp(temp, PATH_NOLOGIN_SHELL)) {
22513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (semanage_list_push(&list, temp)) {
22613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				free(temp);
22713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				semanage_list_destroy(&list);
22813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				return default_shell_list();
22913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
23013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
23113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
23213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(temp);
23313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
23413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return list;
23513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
23613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
23713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Helper function called via semanage_fcontext_iterate() */
23813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int fcontext_matches(const semanage_fcontext_t *fcontext, void *varg)
23913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
24013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	const char *oexpr = semanage_fcontext_get_expr(fcontext);
24113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	fc_match_handle_t *handp = varg;
242300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	char *expr = NULL;
24313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	regex_t re;
24413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int type, retval = -1;
245300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	size_t len;
24613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
24713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Only match ALL or DIR */
24813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	type = semanage_fcontext_get_type(fcontext);
2495b0ad2f00ec730b86eb871d30cb98661dc7a6554Nicolas Iooss	if (type != SEMANAGE_FCONTEXT_ALL && type != SEMANAGE_FCONTEXT_DIR)
25013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
25113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
252300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	len = strlen(oexpr);
253300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	/* Define a macro to strip a literal string from the end of oexpr */
254300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss#define rstrip_oexpr_len(cstr, cstrlen) \
255300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	do { \
256300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss		if (len >= (cstrlen) && !strncmp(oexpr + len - (cstrlen), (cstr), (cstrlen))) \
257300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss			len -= (cstrlen); \
258300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	} while (0)
259300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss#define rstrip_oexpr(cstr) rstrip_oexpr_len(cstr, sizeof(cstr) - 1)
260300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss
261300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	rstrip_oexpr(".+");
262300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	rstrip_oexpr(".*");
263300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	rstrip_oexpr("(/.*)?");
264300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	rstrip_oexpr("/");
265300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss
266300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss#undef rstrip_oexpr_len
267300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss#undef rstrip_oexpr
268300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss
269300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	/* Anchor oexpr at the beginning and append pattern to eat up trailing slashes */
270300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	if (asprintf(&expr, "^%.*s/*$", (int)len, oexpr) < 0)
271300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss		return -1;
27213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
27313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Check dir against expr */
274300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	if (regcomp(&re, expr, REG_EXTENDED) != 0)
27513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto done;
27613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (regexec(&re, handp->dir, 0, NULL, 0) == 0)
27713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		handp->matched = 1;
27813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	regfree(&re);
27913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
28013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval = 0;
28113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
28213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindledone:
283300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	free(expr);
28413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
28513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return retval;
28613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
28713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
28813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
28913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
29013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_list_t *homedir_list = NULL;
29113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_list_t *shells = NULL;
29213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	fc_match_handle_t hand;
29313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *path = NULL;
294f18320d56330af157c19dfa63886119bac6cf082Manoj Srivastava	uid_t temp, minuid = 500, maxuid = 60000;
29588f0c1aa6659f99a89770622f4bc2914435db1bbStephen Smalley	int minuid_set = 0;
2962c651e0a2822368c74587efe6ec920e64e72f37bPatrick Steinhardt	struct passwd *pwbuf;
29713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct stat buf;
29813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
29913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	path = semanage_findval(PATH_ETC_USERADD, "HOME", "=");
30013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (path && *path) {
30113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (semanage_list_push(&homedir_list, path))
30213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto fail;
30313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
30413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(path);
30513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
30613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	path = semanage_findval(PATH_ETC_LIBUSER, "LU_HOMEDIRECTORY", "=");
30713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (path && *path) {
30813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (semanage_list_push(&homedir_list, path))
30913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto fail;
31013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
31113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(path);
31213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	path = NULL;
31313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
31413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!homedir_list) {
31513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (semanage_list_push(&homedir_list, PATH_DEFAULT_HOME)) {
31613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto fail;
31713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
31813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
31913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
32013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!stat(PATH_EXPORT_HOME, &buf)) {
32113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (S_ISDIR(buf.st_mode)) {
32213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (semanage_list_push(&homedir_list, PATH_EXPORT_HOME)) {
32313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto fail;
32413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
32513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
32613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
32713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
32813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!(s->usepasswd))
32913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return homedir_list;
33013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3315812ec2fbbb9e9244e31525737ea967c7a795252Eric Paris	shells = get_shell_list();
3325812ec2fbbb9e9244e31525737ea967c7a795252Eric Paris	assert(shells);
3335812ec2fbbb9e9244e31525737ea967c7a795252Eric Paris
33413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL);
33513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (path && *path) {
33613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		temp = atoi(path);
337d1c606ba46f661b950d6a6b2b29dfc07a536fb0aEric Paris		minuid = temp;
338d1c606ba46f661b950d6a6b2b29dfc07a536fb0aEric Paris		minuid_set = 1;
33913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
34013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(path);
34113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	path = NULL;
34213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
343f18320d56330af157c19dfa63886119bac6cf082Manoj Srivastava	path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL);
344f18320d56330af157c19dfa63886119bac6cf082Manoj Srivastava	if (path && *path) {
345f18320d56330af157c19dfa63886119bac6cf082Manoj Srivastava		temp = atoi(path);
346f18320d56330af157c19dfa63886119bac6cf082Manoj Srivastava		maxuid = temp;
347f18320d56330af157c19dfa63886119bac6cf082Manoj Srivastava	}
348f18320d56330af157c19dfa63886119bac6cf082Manoj Srivastava	free(path);
349f18320d56330af157c19dfa63886119bac6cf082Manoj Srivastava	path = NULL;
350f18320d56330af157c19dfa63886119bac6cf082Manoj Srivastava
35113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	path = semanage_findval(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=");
35213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (path && *path) {
35313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		temp = atoi(path);
35413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!minuid_set || temp < minuid) {
35513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			minuid = temp;
35613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			minuid_set = 1;
35713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
35813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
35913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(path);
36013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	path = NULL;
36113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3622c651e0a2822368c74587efe6ec920e64e72f37bPatrick Steinhardt	errno = 0;
36313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	setpwent();
3642c651e0a2822368c74587efe6ec920e64e72f37bPatrick Steinhardt	while ((pwbuf = getpwent()) != NULL) {
365f18320d56330af157c19dfa63886119bac6cf082Manoj Srivastava		if (pwbuf->pw_uid < minuid || pwbuf->pw_uid > maxuid)
36613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
36713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!semanage_list_find(shells, pwbuf->pw_shell))
36813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
369faff0a77c679e8290bac6595c9764dc8929f32d6Daniel J Walsh		int len = strlen(pwbuf->pw_dir) -1;
370faff0a77c679e8290bac6595c9764dc8929f32d6Daniel J Walsh		for(; len > 0 && pwbuf->pw_dir[len] == '/'; len--) {
371faff0a77c679e8290bac6595c9764dc8929f32d6Daniel J Walsh			pwbuf->pw_dir[len] = '\0';
372faff0a77c679e8290bac6595c9764dc8929f32d6Daniel J Walsh		}
37313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (strcmp(pwbuf->pw_dir, "/") == 0)
37413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
375915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris		if (ignore(pwbuf->pw_dir))
376915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris			continue;
37713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (semanage_str_count(pwbuf->pw_dir, '/') <= 1)
37813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
37913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!(path = strdup(pwbuf->pw_dir))) {
38013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
38113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
38213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
38313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		semanage_rtrim(path, '/');
38413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
38513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!semanage_list_find(homedir_list, path)) {
38613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/*
38713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * Now check for an existing file context that matches
38813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 * so we don't label a non-homedir as a homedir.
38913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			 */
39013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			hand.dir = path;
39113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			hand.matched = 0;
39213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (semanage_fcontext_iterate(s->h_semanage,
39313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    fcontext_matches, &hand) == STATUS_ERR)
39413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto fail;
39513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
39613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* NOTE: old genhomedircon printed a warning on match */
39713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (hand.matched) {
398f18320d56330af157c19dfa63886119bac6cf082Manoj Srivastava				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);
39913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else {
40013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (semanage_list_push(&homedir_list, path))
40113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					goto fail;
40213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
40313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
40413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(path);
40513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		path = NULL;
4062c651e0a2822368c74587efe6ec920e64e72f37bPatrick Steinhardt		errno = 0;
40713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
40813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
4092c651e0a2822368c74587efe6ec920e64e72f37bPatrick Steinhardt	if (errno) {
41013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		WARN(s->h_semanage, "Error while fetching users.  "
41113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     "Returning list so far.");
41213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
413e1400f04044e8405419ee4534f8ff4f45c5d532aEric Paris
414e1400f04044e8405419ee4534f8ff4f45c5d532aEric Paris	if (semanage_list_sort(&homedir_list))
415e1400f04044e8405419ee4534f8ff4f45c5d532aEric Paris		goto fail;
416e1400f04044e8405419ee4534f8ff4f45c5d532aEric Paris
41713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	endpwent();
41813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_list_destroy(&shells);
41913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
42013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return homedir_list;
42113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
42213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      fail:
42313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	endpwent();
42413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(path);
42513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_list_destroy(&homedir_list);
42613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_list_destroy(&shells);
42713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return NULL;
42813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
42913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
43013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/**
43113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * @param	out	the FILE to put all the output in.
43213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * @return	0 on success
43313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
434d67b1ea1cbe30afb4894634f06ca25916b03cbd7Eric Parisstatic int write_file_context_header(FILE * out)
43513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
43613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (fprintf(out, COMMENT_FILE_CONTEXT_HEADER) < 0) {
43713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return STATUS_ERR;
43813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
43913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
44013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return STATUS_SUCCESS;
44113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
44213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
44313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Predicates for use with semanage_slurp_file_filter() the homedir_template
44413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * file currently contains lines that serve as the template for a user's
44513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * homedir.
44613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
44713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * It also contains lines that are the template for the parent of a
44813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * user's home directory.
44913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
45013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Currently, the only lines that apply to the the root of a user's home
45113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * directory are all prefixed with the string "HOME_ROOT".  All other
45213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * lines apply to a user's home directory.  If this changes the
45313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * following predicates need to change to reflect that.
45413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
45513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int HOME_ROOT_PRED(const char *string)
45613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
45713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return semanage_is_prefix(string, TEMPLATE_HOME_ROOT);
45813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
45913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
46013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int HOME_DIR_PRED(const char *string)
46113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
46213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return semanage_is_prefix(string, TEMPLATE_HOME_DIR);
46313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
46413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
46508cde98b606cd04e26061d16ec537a2549f5199cJason Zaman/* new names */
46608cde98b606cd04e26061d16ec537a2549f5199cJason Zamanstatic int USERNAME_CONTEXT_PRED(const char *string)
46708cde98b606cd04e26061d16ec537a2549f5199cJason Zaman{
46808cde98b606cd04e26061d16ec537a2549f5199cJason Zaman	return (int)(
46908cde98b606cd04e26061d16ec537a2549f5199cJason Zaman		(strstr(string, TEMPLATE_USERNAME) != NULL) ||
47008cde98b606cd04e26061d16ec537a2549f5199cJason Zaman		(strstr(string, TEMPLATE_USERID) != NULL)
47108cde98b606cd04e26061d16ec537a2549f5199cJason Zaman	);
47208cde98b606cd04e26061d16ec537a2549f5199cJason Zaman}
47308cde98b606cd04e26061d16ec537a2549f5199cJason Zaman
47408cde98b606cd04e26061d16ec537a2549f5199cJason Zaman/* This will never match USER if USERNAME or USERID are found. */
47513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int USER_CONTEXT_PRED(const char *string)
47613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
47708cde98b606cd04e26061d16ec537a2549f5199cJason Zaman	if (USERNAME_CONTEXT_PRED(string))
47808cde98b606cd04e26061d16ec537a2549f5199cJason Zaman		return 0;
47908cde98b606cd04e26061d16ec537a2549f5199cJason Zaman
48013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return (int)(strstr(string, TEMPLATE_USER) != NULL);
48113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
48213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
48367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierneystatic int STR_COMPARATOR(const void *a, const void *b)
48467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney{
48567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	return strcmp((const char *) a, (const char *) b);
48667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney}
48767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
48813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* make_tempate
48913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * @param	s	  the settings holding the paths to various files
49013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * @param	pred	function pointer to function to use as filter for slurp
49113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * 					file filter
49213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * @return   a list of lines from the template file with inappropriate
49313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *	    lines filtered out.
49413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
49513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic semanage_list_t *make_template(genhomedircon_settings_t * s,
49613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				      int (*pred) (const char *))
49713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
49813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	FILE *template_file = NULL;
49913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_list_t *template_data = NULL;
50013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
50113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	template_file = fopen(s->homedir_template_path, "r");
50213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!template_file)
50313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return NULL;
50413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	template_data = semanage_slurp_file_filter(template_file, pred);
50513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	fclose(template_file);
50613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
50713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return template_data;
50813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
50913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
510300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Ioossstatic char *replace_all(const char *str, const replacement_pair_t * repl)
51113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
512300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	char *retval, *retval2;
51313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int i;
51413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
51513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!str || !repl)
516300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss		return NULL;
51713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
518300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	retval = strdup(str);
519300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	for (i = 0; retval != NULL && repl[i].search_for; i++) {
520300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss		retval2 = semanage_str_replace(repl[i].search_for,
521300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss					       repl[i].replace_with, retval, 0);
522300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss		free(retval);
523300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss		retval = retval2;
52413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
52513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return retval;
52613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
52713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
528300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Ioossstatic const char *extract_context(const char *line)
52913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
530300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	const char *p = line;
531300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	size_t off;
532300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss
533300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	off = strlen(p);
534300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	p += off;
535300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	/* consider trailing whitespaces */
536300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	while (off > 0) {
537300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss		p--;
538300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss		off--;
539300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss		if (!isspace(*p))
540300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss			break;
541300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	}
542300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	if (off == 0)
54313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return NULL;
544300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss
545300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	/* find the last field in line */
546300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	while (off > 0 && !isspace(*(p - 1))) {
547300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss		p--;
548300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss		off--;
549300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	}
550300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	return p;
55113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
55213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
553300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Ioossstatic int check_line(genhomedircon_settings_t * s, const char *line)
55413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
55513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_context_t *ctx_record = NULL;
55613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	const char *ctx_str;
55713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int result;
55813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
55913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ctx_str = extract_context(line);
56013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!ctx_str)
56113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return STATUS_ERR;
56213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
56313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	result = sepol_context_from_string(s->h_semanage->sepolh,
56413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					   ctx_str, &ctx_record);
56513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (result == STATUS_SUCCESS && ctx_record != NULL) {
56613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		result = sepol_context_check(s->h_semanage->sepolh,
56713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					     s->policydb, ctx_record);
56813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		sepol_context_free(ctx_record);
56913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
57013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return result;
57113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
57213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
573a63b96b7e2d3edb4b3b1283558da7ca6735d66daJason Zamanstatic int write_replacements(genhomedircon_settings_t * s, FILE * out,
574a63b96b7e2d3edb4b3b1283558da7ca6735d66daJason Zaman			      const semanage_list_t * tpl,
575a63b96b7e2d3edb4b3b1283558da7ca6735d66daJason Zaman			      const replacement_pair_t *repl)
57613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
577300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	char *line;
57813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
57913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (; tpl; tpl = tpl->next) {
58013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		line = replace_all(tpl->data, repl);
58113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!line)
58213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto fail;
58313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (check_line(s, line) == STATUS_SUCCESS) {
584300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss			if (fprintf(out, "%s\n", line) < 0)
58513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto fail;
58613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
587300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss		free(line);
58813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
58913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return STATUS_SUCCESS;
59013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
59113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      fail:
592300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	free(line);
59313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return STATUS_ERR;
59413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
59513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
596d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierneystatic int write_contexts(genhomedircon_settings_t *s, FILE *out,
597d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney			  semanage_list_t *tpl, const replacement_pair_t *repl,
598d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney			  const genhomedircon_user_entry_t *user)
599d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney{
600300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	char *line, *temp;
60103298a22f7dc6f45885307976d09c9a2f070f9fdNicolas Iooss	sepol_context_t *context;
60203298a22f7dc6f45885307976d09c9a2f070f9fdNicolas Iooss	char *new_context_str;
603d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney
604d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney	for (; tpl; tpl = tpl->next) {
60503298a22f7dc6f45885307976d09c9a2f070f9fdNicolas Iooss		context = NULL;
60603298a22f7dc6f45885307976d09c9a2f070f9fdNicolas Iooss		new_context_str = NULL;
607d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney		line = replace_all(tpl->data, repl);
608d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney		if (!line) {
609d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney			goto fail;
610d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney		}
611d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney
612d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney		const char *old_context_str = extract_context(line);
613d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney		if (!old_context_str) {
614d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney			goto fail;
615d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney		}
616d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney
617d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney		if (strcmp(old_context_str, CONTEXT_NONE) == 0) {
618d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney			if (check_line(s, line) == STATUS_SUCCESS &&
619300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss			    fprintf(out, "%s\n", line) < 0) {
620d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney				goto fail;
621d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney			}
622300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss			free(line);
623d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney			continue;
624d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney		}
625d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney
626d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney		sepol_handle_t *sepolh = s->h_semanage->sepolh;
627d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney
628d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney		if (sepol_context_from_string(sepolh, old_context_str,
629d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney					      &context) < 0) {
630d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney			goto fail;
631d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney		}
632d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney
6334cf9b9ce2df06fd5a29e5264a6552c9b02ec0b5bStephen Smalley		if (sepol_context_set_user(sepolh, context, user->sename) < 0) {
6344cf9b9ce2df06fd5a29e5264a6552c9b02ec0b5bStephen Smalley			goto fail;
6354cf9b9ce2df06fd5a29e5264a6552c9b02ec0b5bStephen Smalley		}
6364cf9b9ce2df06fd5a29e5264a6552c9b02ec0b5bStephen Smalley
6374cf9b9ce2df06fd5a29e5264a6552c9b02ec0b5bStephen Smalley		if (sepol_policydb_mls_enabled(s->policydb) &&
638d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney		    sepol_context_set_mls(sepolh, context, user->level) < 0) {
639d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney			goto fail;
640d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney		}
641d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney
64288e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney		if (user->homedir_role &&
64388e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney		    sepol_context_set_role(sepolh, context, user->homedir_role) < 0) {
64488e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney			goto fail;
64588e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney		}
64688e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney
647d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney		if (sepol_context_to_string(sepolh, context,
648d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney					    &new_context_str) < 0) {
649d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney			goto fail;
650d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney		}
651d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney
652300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss		temp = semanage_str_replace(old_context_str, new_context_str,
653300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss					    line, 1);
654300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss		if (!temp) {
655d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney			goto fail;
656d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney		}
657300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss		free(line);
658300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss		line = temp;
659d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney
660d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney		if (check_line(s, line) == STATUS_SUCCESS) {
661300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss			if (fprintf(out, "%s\n", line) < 0)
662d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney				goto fail;
663d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney		}
664d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney
665300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss		free(line);
666d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney		sepol_context_free(context);
667d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney		free(new_context_str);
668d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney	}
669d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney
670d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney	return STATUS_SUCCESS;
671d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierneyfail:
672300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss	free(line);
673d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney	sepol_context_free(context);
674d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney	free(new_context_str);
675d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney	return STATUS_ERR;
676d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney}
677d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney
678a63b96b7e2d3edb4b3b1283558da7ca6735d66daJason Zamanstatic int write_home_dir_context(genhomedircon_settings_t * s, FILE * out,
679c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman				  semanage_list_t * tpl, const genhomedircon_user_entry_t *user)
680a63b96b7e2d3edb4b3b1283558da7ca6735d66daJason Zaman{
681a63b96b7e2d3edb4b3b1283558da7ca6735d66daJason Zaman	replacement_pair_t repl[] = {
682c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman		{.search_for = TEMPLATE_HOME_DIR,.replace_with = user->home},
683c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman		{.search_for = TEMPLATE_ROLE,.replace_with = user->prefix},
684a63b96b7e2d3edb4b3b1283558da7ca6735d66daJason Zaman		{NULL, NULL}
685a63b96b7e2d3edb4b3b1283558da7ca6735d66daJason Zaman	};
686a63b96b7e2d3edb4b3b1283558da7ca6735d66daJason Zaman
687c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman	if (strcmp(user->name, FALLBACK_NAME) == 0) {
688c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman		if (fprintf(out, COMMENT_USER_HOME_CONTEXT, FALLBACK_SENAME) < 0)
689c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman			return STATUS_ERR;
690c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman	} else {
691c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman		if (fprintf(out, COMMENT_USER_HOME_CONTEXT, user->name) < 0)
692c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman			return STATUS_ERR;
693c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman	}
694a63b96b7e2d3edb4b3b1283558da7ca6735d66daJason Zaman
695d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney	return write_contexts(s, out, tpl, repl, user);
696a63b96b7e2d3edb4b3b1283558da7ca6735d66daJason Zaman}
697a63b96b7e2d3edb4b3b1283558da7ca6735d66daJason Zaman
69813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int write_home_root_context(genhomedircon_settings_t * s, FILE * out,
69913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				   semanage_list_t * tpl, char *homedir)
70013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
70113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	replacement_pair_t repl[] = {
70213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		{.search_for = TEMPLATE_HOME_ROOT,.replace_with = homedir},
70313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		{NULL, NULL}
70413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	};
70513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
706a63b96b7e2d3edb4b3b1283558da7ca6735d66daJason Zaman	return write_replacements(s, out, tpl, repl);
70713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
70813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7094bbec88baa66d1376629fb6f860eb51657429b91Jason Zamanstatic int write_username_context(genhomedircon_settings_t * s, FILE * out,
7104bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman				  semanage_list_t * tpl,
7114bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman				  const genhomedircon_user_entry_t *user)
7124bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman{
7134bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman	replacement_pair_t repl[] = {
7144bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman		{.search_for = TEMPLATE_USERNAME,.replace_with = user->name},
7154bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman		{.search_for = TEMPLATE_USERID,.replace_with = user->uid},
7164bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman		{.search_for = TEMPLATE_ROLE,.replace_with = user->prefix},
7174bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman		{NULL, NULL}
7184bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman	};
7194bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman
720d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney	return write_contexts(s, out, tpl, repl, user);
7214bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman}
7224bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman
72313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int write_user_context(genhomedircon_settings_t * s, FILE * out,
724c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman			      semanage_list_t * tpl, const genhomedircon_user_entry_t *user)
72513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
72613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	replacement_pair_t repl[] = {
727c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman		{.search_for = TEMPLATE_USER,.replace_with = user->name},
728c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman		{.search_for = TEMPLATE_ROLE,.replace_with = user->prefix},
72913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		{NULL, NULL}
73013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	};
73113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
732d97292639cf816a946919aa0f2ed086f14c7db44Gary Tierney	return write_contexts(s, out, tpl, repl, user);
73313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
73413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
73567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierneystatic int seuser_sort_func(const void *arg1, const void *arg2)
73667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney{
73767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	const semanage_seuser_t **u1 = (const semanage_seuser_t **) arg1;
73867b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	const semanage_seuser_t **u2 = (const semanage_seuser_t **) arg2;;
73967b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	const char *name1 = semanage_seuser_get_name(*u1);
74067b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	const char *name2 = semanage_seuser_get_name(*u2);
74167b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
74267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	if (name1[0] == '%' && name2[0] == '%') {
74367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		return 0;
74467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	} else if (name1[0] == '%') {
74567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		return 1;
74667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	} else if (name2[0] == '%') {
74767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		return -1;
74867b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	}
74967b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
75067b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	return strcmp(name1, name2);
75167b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney}
75267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
75313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int user_sort_func(semanage_user_t ** arg1, semanage_user_t ** arg2)
75413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
75513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return strcmp(semanage_user_get_name(*arg1),
75613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		      semanage_user_get_name(*arg2));
75713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
75813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
75913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int name_user_cmp(char *key, semanage_user_t ** val)
76013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
76113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return strcmp(key, semanage_user_get_name(*val));
76213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
76313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
76413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int push_user_entry(genhomedircon_user_entry_t ** list, const char *n,
7653b23f12eb9aa2ee828561ffb414efa8c2031e75fJason Zaman			   const char *u, const char *g, const char *sen,
76667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			   const char *pre, const char *h, const char *l,
76788e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney			   const char *ln, const char *hd_role)
76813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
76913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	genhomedircon_user_entry_t *temp = NULL;
77013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *name = NULL;
7713b23f12eb9aa2ee828561ffb414efa8c2031e75fJason Zaman	char *uid = NULL;
7723b23f12eb9aa2ee828561ffb414efa8c2031e75fJason Zaman	char *gid = NULL;
77313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *sename = NULL;
77413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *prefix = NULL;
77513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *home = NULL;
776d784fd71b56cb8f57d5b9fcd784094e004bf7c6aRussell Coker	char *level = NULL;
77767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	char *lname = NULL;
77888e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney	char *homedir_role = NULL;
77913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
78013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	temp = malloc(sizeof(genhomedircon_user_entry_t));
78113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!temp)
78213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
78313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	name = strdup(n);
78413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!name)
78513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
7863b23f12eb9aa2ee828561ffb414efa8c2031e75fJason Zaman	uid = strdup(u);
7873b23f12eb9aa2ee828561ffb414efa8c2031e75fJason Zaman	if (!uid)
7883b23f12eb9aa2ee828561ffb414efa8c2031e75fJason Zaman		goto cleanup;
7893b23f12eb9aa2ee828561ffb414efa8c2031e75fJason Zaman	gid = strdup(g);
7903b23f12eb9aa2ee828561ffb414efa8c2031e75fJason Zaman	if (!gid)
7913b23f12eb9aa2ee828561ffb414efa8c2031e75fJason Zaman		goto cleanup;
79213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sename = strdup(sen);
79313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!sename)
79413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
79513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	prefix = strdup(pre);
79613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!prefix)
79713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
79813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	home = strdup(h);
79913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!home)
80013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto cleanup;
801d784fd71b56cb8f57d5b9fcd784094e004bf7c6aRussell Coker	level = strdup(l);
802d784fd71b56cb8f57d5b9fcd784094e004bf7c6aRussell Coker	if (!level)
803d784fd71b56cb8f57d5b9fcd784094e004bf7c6aRussell Coker		goto cleanup;
80467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	lname = strdup(ln);
80567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	if (!lname)
80667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		goto cleanup;
80788e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney	if (hd_role) {
80888e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney		homedir_role = strdup(hd_role);
80988e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney		if (!homedir_role)
81088e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney			goto cleanup;
81188e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney	}
81213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
81313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	temp->name = name;
8143b23f12eb9aa2ee828561ffb414efa8c2031e75fJason Zaman	temp->uid = uid;
8153b23f12eb9aa2ee828561ffb414efa8c2031e75fJason Zaman	temp->gid = gid;
81613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	temp->sename = sename;
81713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	temp->prefix = prefix;
81813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	temp->home = home;
819d784fd71b56cb8f57d5b9fcd784094e004bf7c6aRussell Coker	temp->level = level;
82067b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	temp->login = lname;
82188e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney	temp->homedir_role = homedir_role;
82213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	temp->next = (*list);
82313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	(*list) = temp;
82413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
82513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return STATUS_SUCCESS;
82613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
82713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
82813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(name);
8293b23f12eb9aa2ee828561ffb414efa8c2031e75fJason Zaman	free(uid);
8303b23f12eb9aa2ee828561ffb414efa8c2031e75fJason Zaman	free(gid);
83113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(sename);
83213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(prefix);
83313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(home);
834d784fd71b56cb8f57d5b9fcd784094e004bf7c6aRussell Coker	free(level);
83567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	free(lname);
83688e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney	free(homedir_role);
83713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(temp);
83813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return STATUS_ERR;
83913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
84013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
84113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic void pop_user_entry(genhomedircon_user_entry_t ** list)
84213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
84313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	genhomedircon_user_entry_t *temp;
84413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
84513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!list || !(*list))
84613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return;
84713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
84813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	temp = *list;
84913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*list = temp->next;
85013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(temp->name);
8513b23f12eb9aa2ee828561ffb414efa8c2031e75fJason Zaman	free(temp->uid);
8523b23f12eb9aa2ee828561ffb414efa8c2031e75fJason Zaman	free(temp->gid);
85313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(temp->sename);
85413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(temp->prefix);
85513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(temp->home);
856d784fd71b56cb8f57d5b9fcd784094e004bf7c6aRussell Coker	free(temp->level);
85767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	free(temp->login);
85888e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney	free(temp->homedir_role);
85913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(temp);
86013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
86113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
86213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int setup_fallback_user(genhomedircon_settings_t * s)
86313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
86413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_seuser_t **seuser_list = NULL;
86513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int nseusers = 0;
86613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_user_key_t *key = NULL;
86713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_user_t *u = NULL;
86813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	const char *name = NULL;
86913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	const char *seuname = NULL;
87013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	const char *prefix = NULL;
871d784fd71b56cb8f57d5b9fcd784094e004bf7c6aRussell Coker	const char *level = NULL;
87288e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney	const char *homedir_role = NULL;
87313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
87413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval;
87513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int errors = 0;
87613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
87713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval = semanage_seuser_list(s->h_semanage, &seuser_list, &nseusers);
87813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (retval < 0 || (nseusers < 1)) {
87913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* if there are no users, this function can't do any other work */
88013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return errors;
88113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
88213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
88313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < nseusers; i++) {
88413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		name = semanage_seuser_get_name(seuser_list[i]);
88513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (strcmp(name, DEFAULT_LOGIN) == 0) {
88613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			seuname = semanage_seuser_get_sename(seuser_list[i]);
88713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
88813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* find the user structure given the name */
88913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (semanage_user_key_create(s->h_semanage, seuname,
89013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						     &key) < 0) {
89113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				errors = STATUS_ERR;
89213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				break;
89313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
89413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (semanage_user_query(s->h_semanage, key, &u) < 0)
895d784fd71b56cb8f57d5b9fcd784094e004bf7c6aRussell Coker			{
89613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				prefix = name;
897925914acea3e2a95f4ccc9d39498cede345061d5Jason Zaman				level = FALLBACK_LEVEL;
898d784fd71b56cb8f57d5b9fcd784094e004bf7c6aRussell Coker			}
89913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			else
900d784fd71b56cb8f57d5b9fcd784094e004bf7c6aRussell Coker			{
90113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				prefix = semanage_user_get_prefix(u);
902d784fd71b56cb8f57d5b9fcd784094e004bf7c6aRussell Coker				level = semanage_user_get_mlslevel(u);
90318649484eee7e4ca7b0be572365aca368a3471b5Xin Ouyang				if (!level)
904925914acea3e2a95f4ccc9d39498cede345061d5Jason Zaman					level = FALLBACK_LEVEL;
905d784fd71b56cb8f57d5b9fcd784094e004bf7c6aRussell Coker			}
90613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
90788e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney			if (prefix_is_homedir_role(u, prefix)) {
90888e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney				homedir_role = prefix;
90988e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney			}
91088e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney
911c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman			if (push_user_entry(&(s->fallback), FALLBACK_NAME,
9123b23f12eb9aa2ee828561ffb414efa8c2031e75fJason Zaman					    FALLBACK_UIDGID, FALLBACK_UIDGID,
91367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney					    seuname, prefix, "", level,
91488e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney					    FALLBACK_NAME, homedir_role) != 0)
91513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				errors = STATUS_ERR;
91613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			semanage_user_key_free(key);
91713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (u)
91813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				semanage_user_free(u);
91913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
92013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
92113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
92213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
92313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < nseusers; i++)
92413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		semanage_seuser_free(seuser_list[i]);
92513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(seuser_list);
92613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
92713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return errors;
92813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
92913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
93067b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierneystatic genhomedircon_user_entry_t *find_user(genhomedircon_user_entry_t *head,
93167b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney					     const char *name)
93267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney{
93367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	for(; head; head = head->next) {
93467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		if (strcmp(head->name, name) == 0) {
93567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			return head;
93667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		}
93767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	}
93867b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
93967b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	return NULL;
94067b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney}
94167b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
94267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierneystatic int add_user(genhomedircon_settings_t * s,
94367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		    genhomedircon_user_entry_t **head,
94467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		    semanage_user_t *user,
94567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		    const char *name,
94667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		    const char *sename,
94767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		    const char *selogin)
94867b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney{
94967b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	if (selogin[0] == '%') {
95067b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		genhomedircon_user_entry_t *orig = find_user(*head, name);
95167b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		if (orig != NULL && orig->login[0] == '%') {
95267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			ERR(s->h_semanage, "User %s is already mapped to"
95367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			    " group %s, but also belongs to group %s. Add an"
95467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			    " explicit mapping for this user to"
95567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			    " override group mappings.",
95667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			    name, orig->login + 1, selogin + 1);
95767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			return STATUS_ERR;
95867b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		} else if (orig != NULL) {
95967b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			// user mappings take precedence
96067b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			return STATUS_SUCCESS;
96167b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		}
96267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	}
96367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
96467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	int retval = STATUS_ERR;
96567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
96667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	char *rbuf = NULL;
96767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	long rbuflen;
96867b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	struct passwd pwstorage, *pwent = NULL;
96967b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	const char *prefix = NULL;
97067b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	const char *level = NULL;
97188e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney	const char *homedir_role = NULL;
97267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	char uid[11];
97367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	char gid[11];
97467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
97567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	/* Allocate space for the getpwnam_r buffer */
97667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	rbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
97767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	if (rbuflen <= 0)
97867b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		goto cleanup;
97967b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	rbuf = malloc(rbuflen);
98067b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	if (rbuf == NULL)
98167b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		goto cleanup;
98267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
98367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	if (user) {
98467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		prefix = semanage_user_get_prefix(user);
98567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		level = semanage_user_get_mlslevel(user);
98667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
98767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		if (!level) {
98867b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			level = FALLBACK_LEVEL;
98967b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		}
99067b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	} else {
99167b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		prefix = name;
99267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		level = FALLBACK_LEVEL;
99367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	}
99467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
99588e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney	if (prefix_is_homedir_role(user, prefix)) {
99688e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney		homedir_role = prefix;
99788e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney	}
99888e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney
99967b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	retval = getpwnam_r(name, &pwstorage, rbuf, rbuflen, &pwent);
100067b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	if (retval != 0 || pwent == NULL) {
100167b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		if (retval != 0 && retval != ENOENT) {
100267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			goto cleanup;
100367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		}
100467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
100567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		WARN(s->h_semanage,
100667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		     "user %s not in password file", name);
100767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		retval = STATUS_SUCCESS;
100867b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		goto cleanup;
100967b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	}
101067b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
101167b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	int len = strlen(pwent->pw_dir) -1;
101267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	for(; len > 0 && pwent->pw_dir[len] == '/'; len--) {
101367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		pwent->pw_dir[len] = '\0';
101467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	}
101567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
101667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	if (strcmp(pwent->pw_dir, "/") == 0) {
101767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		/* don't relabel / genhomdircon checked to see if root
101867b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		 * was the user and if so, set his home directory to
101967b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		 * /root */
102067b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		retval = STATUS_SUCCESS;
102167b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		goto cleanup;
102267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	}
102367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
102467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	if (ignore(pwent->pw_dir)) {
102567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		retval = STATUS_SUCCESS;
102667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		goto cleanup;
102767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	}
102867b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
102967b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	len = snprintf(uid, sizeof(uid), "%u", pwent->pw_uid);
103067b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	if (len < 0 || len >= (int)sizeof(uid)) {
103167b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		goto cleanup;
103267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	}
103367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
103467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	len = snprintf(gid, sizeof(gid), "%u", pwent->pw_gid);
103567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	if (len < 0 || len >= (int)sizeof(gid)) {
103667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		goto cleanup;
103767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	}
103867b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
103967b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	retval = push_user_entry(head, name, uid, gid, sename, prefix,
104088e334f1923396d5ace56b8439c731dcde0d1f3bGary Tierney				pwent->pw_dir, level, selogin, homedir_role);
104167b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierneycleanup:
104267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	free(rbuf);
104367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	return retval;
104467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney}
104567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
104667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierneystatic int get_group_users(genhomedircon_settings_t * s,
104767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			  genhomedircon_user_entry_t **head,
104867b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			  semanage_user_t *user,
104967b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			  const char *sename,
105067b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			  const char *selogin)
105167b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney{
105267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	int retval = STATUS_ERR;
105367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	unsigned int i;
105467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
105567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	long grbuflen;
105667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	char *grbuf = NULL;
105767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	struct group grstorage, *group = NULL;
10582c651e0a2822368c74587efe6ec920e64e72f37bPatrick Steinhardt	struct passwd *pw = NULL;
105967b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
106067b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	grbuflen = sysconf(_SC_GETGR_R_SIZE_MAX);
106167b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	if (grbuflen <= 0)
106267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		goto cleanup;
106367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	grbuf = malloc(grbuflen);
106467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	if (grbuf == NULL)
106567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		goto cleanup;
106667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
106767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	const char *grname = selogin + 1;
106867b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
106967b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	if (getgrnam_r(grname, &grstorage, grbuf,
107067b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			(size_t) grbuflen, &group) != 0) {
107167b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		goto cleanup;
107267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	}
107367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
107467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	if (group == NULL) {
107567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		ERR(s->h_semanage, "Can't find group named %s\n", grname);
107667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		goto cleanup;
107767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	}
107867b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
107967b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	size_t nmembers = 0;
108067b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	char **members = group->gr_mem;
108167b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
108267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	while (*members != NULL) {
108367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		nmembers++;
108467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		members++;
108567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	}
108667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
108767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	for (i = 0; i < nmembers; i++) {
108867b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		const char *uname = group->gr_mem[i];
108967b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
109067b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		if (add_user(s, head, user, uname, sename, selogin) < 0) {
109167b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			goto cleanup;
109267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		}
109367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	}
109467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
109567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	setpwent();
10962c651e0a2822368c74587efe6ec920e64e72f37bPatrick Steinhardt	while ((pw = getpwent()) != NULL) {
109767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		// skip users who also have this group as their
109867b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		// primary group
109967b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		if (lfind(pw->pw_name, group->gr_mem, &nmembers,
110067b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			  sizeof(char *), &STR_COMPARATOR)) {
110167b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			continue;
110267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		}
110367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
110467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		if (group->gr_gid == pw->pw_gid) {
110567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			if (add_user(s, head, user, pw->pw_name,
110667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney				     sename, selogin) < 0) {
110767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney				goto cleanup;
110867b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			}
110967b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		}
111067b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	}
111167b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
111267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	retval = STATUS_SUCCESS;
111367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierneycleanup:
111467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	endpwent();
111567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	free(grbuf);
111667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
111767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	return retval;
111867b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney}
111967b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney
112013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic genhomedircon_user_entry_t *get_users(genhomedircon_settings_t * s,
112113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					     int *errors)
112213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
112313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	genhomedircon_user_entry_t *head = NULL;
112413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_seuser_t **seuser_list = NULL;
112513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int nseusers = 0;
112613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_user_t **user_list = NULL;
112713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int nusers = 0;
112813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_user_t **u = NULL;
112913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	const char *name = NULL;
113013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	const char *seuname = NULL;
113113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
113213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval;
113313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
113413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*errors = 0;
113513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval = semanage_seuser_list(s->h_semanage, &seuser_list, &nseusers);
113613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (retval < 0 || (nseusers < 1)) {
113713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* if there are no users, this function can't do any other work */
113813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return NULL;
113913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
114013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
114113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (semanage_user_list(s->h_semanage, &user_list, &nusers) < 0) {
114213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		nusers = 0;
114313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
114413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
114567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	qsort(seuser_list, nseusers, sizeof(semanage_seuser_t *),
114667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney	      &seuser_sort_func);
114713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	qsort(user_list, nusers, sizeof(semanage_user_t *),
114813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	      (int (*)(const void *, const void *))&user_sort_func);
114913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
115013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < nseusers; i++) {
115113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		seuname = semanage_seuser_get_sename(seuser_list[i]);
115213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		name = semanage_seuser_get_name(seuser_list[i]);
115313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
115413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (strcmp(name, DEFAULT_LOGIN) == 0)
115513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
115613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
115713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* find the user structure given the name */
115813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		u = bsearch(seuname, user_list, nusers, sizeof(semanage_user_t *),
115913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    (int (*)(const void *, const void *))
116013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    &name_user_cmp);
116113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
116267b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		/* %groupname syntax */
116367b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		if (name[0] == '%') {
116467b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			retval = get_group_users(s, &head, *u, seuname,
116567b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney						name);
116667b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		} else {
116767b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney			retval = add_user(s, &head, *u, name,
116867b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney					  seuname, name);
1169faff0a77c679e8290bac6595c9764dc8929f32d6Daniel J Walsh		}
1170faff0a77c679e8290bac6595c9764dc8929f32d6Daniel J Walsh
117167b328a91c6f6f22d8eaf220aaefe06623112f32Gary Tierney		if (retval != 0) {
11723b23f12eb9aa2ee828561ffb414efa8c2031e75fJason Zaman			*errors = STATUS_ERR;
11733b23f12eb9aa2ee828561ffb414efa8c2031e75fJason Zaman			goto cleanup;
11743b23f12eb9aa2ee828561ffb414efa8c2031e75fJason Zaman		}
117513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
117613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
117713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      cleanup:
117813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (*errors) {
117913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (; head; pop_user_entry(&head)) {
118013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* the pop function takes care of all the cleanup
118113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   so the loop body is just empty */
118213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
118313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
118413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < nseusers; i++) {
118513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		semanage_seuser_free(seuser_list[i]);
118613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
118713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(seuser_list);
118813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
118913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < nusers; i++) {
119013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		semanage_user_free(user_list[i]);
119113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
119213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(user_list);
119313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
119413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return head;
119513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
119613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
119713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int write_gen_home_dir_context(genhomedircon_settings_t * s, FILE * out,
11984bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman				      semanage_list_t * username_context_tpl,
119913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				      semanage_list_t * user_context_tpl,
120013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				      semanage_list_t * homedir_context_tpl)
120113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
120213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	genhomedircon_user_entry_t *users;
120313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int errors = 0;
120413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
120513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	users = get_users(s, &errors);
120613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!users && errors) {
120713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return STATUS_ERR;
120813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
120913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
121013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (; users; pop_user_entry(&users)) {
1211c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman		if (write_home_dir_context(s, out, homedir_context_tpl, users))
12127d83d86ba10e2fc251a249df4745c6f339e9c523Eric Paris			goto err;
12134bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman		if (write_username_context(s, out, username_context_tpl, users))
12144bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman			goto err;
1215c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman		if (write_user_context(s, out, user_context_tpl, users))
12167d83d86ba10e2fc251a249df4745c6f339e9c523Eric Paris			goto err;
121713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
121813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
121913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return STATUS_SUCCESS;
12207d83d86ba10e2fc251a249df4745c6f339e9c523Eric Pariserr:
12217d83d86ba10e2fc251a249df4745c6f339e9c523Eric Paris	for (; users; pop_user_entry(&users)) {
12227d83d86ba10e2fc251a249df4745c6f339e9c523Eric Paris	/* the pop function takes care of all the cleanup
12237d83d86ba10e2fc251a249df4745c6f339e9c523Eric Paris	 * so the loop body is just empty */
12247d83d86ba10e2fc251a249df4745c6f339e9c523Eric Paris	}
12257d83d86ba10e2fc251a249df4745c6f339e9c523Eric Paris
12267d83d86ba10e2fc251a249df4745c6f339e9c523Eric Paris	return STATUS_ERR;
122713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
122813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
122913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/**
123013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * @param	s	settings structure, stores various paths etc. Must never be NULL
123113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * @param	out	the FILE to put all the output in.
123213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * @return	0 on success
123313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
123413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int write_context_file(genhomedircon_settings_t * s, FILE * out)
123513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
123613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_list_t *homedirs = NULL;
123713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_list_t *h = NULL;
123813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_list_t *homedir_context_tpl = NULL;
123913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_list_t *homeroot_context_tpl = NULL;
124008cde98b606cd04e26061d16ec537a2549f5199cJason Zaman	semanage_list_t *username_context_tpl = NULL;
124108cde98b606cd04e26061d16ec537a2549f5199cJason Zaman	semanage_list_t *user_context_tpl = NULL;
124213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval = STATUS_SUCCESS;
124313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
124413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	homedir_context_tpl = make_template(s, &HOME_DIR_PRED);
124513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	homeroot_context_tpl = make_template(s, &HOME_ROOT_PRED);
124608cde98b606cd04e26061d16ec537a2549f5199cJason Zaman	username_context_tpl = make_template(s, &USERNAME_CONTEXT_PRED);
124713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	user_context_tpl = make_template(s, &USER_CONTEXT_PRED);
124813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
124908cde98b606cd04e26061d16ec537a2549f5199cJason Zaman	if (!homedir_context_tpl
125008cde98b606cd04e26061d16ec537a2549f5199cJason Zaman	 && !homeroot_context_tpl
125108cde98b606cd04e26061d16ec537a2549f5199cJason Zaman	 && !username_context_tpl
125208cde98b606cd04e26061d16ec537a2549f5199cJason Zaman	 && !user_context_tpl)
125313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto done;
125413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1255d67b1ea1cbe30afb4894634f06ca25916b03cbd7Eric Paris	if (write_file_context_header(out) != STATUS_SUCCESS) {
125613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		retval = STATUS_ERR;
125713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto done;
125813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
125913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
126013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (setup_fallback_user(s) != 0) {
126113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		retval = STATUS_ERR;
126213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto done;
126313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
126413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
126513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (homedir_context_tpl || homeroot_context_tpl) {
126613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		homedirs = get_home_dirs(s);
126713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!homedirs) {
126813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			WARN(s->h_semanage,
126913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			     "no home directories were available, exiting without writing");
127013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto done;
127113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
127213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
127313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		for (h = homedirs; h; h = h->next) {
1274300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss			char *temp = NULL;
127513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1276300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss			if (asprintf(&temp, "%s/%s", h->data, FALLBACK_NAME) < 0) {
127713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				retval = STATUS_ERR;
127813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto done;
127913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
128013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1281c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman			free(s->fallback->home);
1282300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss			s->fallback->home = temp;
1283c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman
1284c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman			if (write_home_dir_context(s, out, homedir_context_tpl,
1285c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman						   s->fallback) != STATUS_SUCCESS) {
1286300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss				free(temp);
1287c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman				s->fallback->home = NULL;
128813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				retval = STATUS_ERR;
128913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto done;
129013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
129113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (write_home_root_context(s, out,
129213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						    homeroot_context_tpl,
129313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						    h->data) != STATUS_SUCCESS) {
1294300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss				free(temp);
1295c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman				s->fallback->home = NULL;
129613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				retval = STATUS_ERR;
129713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				goto done;
129813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
129913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1300300b8ad4235688171f2a91e7aeb14d0ee3561c13Nicolas Iooss			free(temp);
1301c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman			s->fallback->home = NULL;
130213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
130313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
13044bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman	if (user_context_tpl || username_context_tpl) {
13054bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman		if (write_username_context(s, out, username_context_tpl,
13064bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman					   s->fallback) != STATUS_SUCCESS) {
13074bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman			retval = STATUS_ERR;
13084bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman			goto done;
13094bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman		}
13104bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman
131113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (write_user_context(s, out, user_context_tpl,
1312c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman				       s->fallback) != STATUS_SUCCESS) {
131313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			retval = STATUS_ERR;
131413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto done;
131513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
131613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
13174bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman		if (write_gen_home_dir_context(s, out, username_context_tpl,
13184bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman					       user_context_tpl, homedir_context_tpl)
13194bbec88baa66d1376629fb6f860eb51657429b91Jason Zaman				!= STATUS_SUCCESS) {
132013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			retval = STATUS_ERR;
132113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
132213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
132313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
132413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindledone:
132513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Cleanup */
132613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_list_destroy(&homedirs);
132708cde98b606cd04e26061d16ec537a2549f5199cJason Zaman	semanage_list_destroy(&username_context_tpl);
132813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_list_destroy(&user_context_tpl);
132913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_list_destroy(&homedir_context_tpl);
133013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	semanage_list_destroy(&homeroot_context_tpl);
133113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
133213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return retval;
133313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
133413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
133513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint semanage_genhomedircon(semanage_handle_t * sh,
133613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   sepol_policydb_t * policydb,
1337915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris			   int usepasswd,
1338915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris			   char *ignoredirs)
133913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
134013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	genhomedircon_settings_t s;
134113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	FILE *out = NULL;
134213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval = 0;
134313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
134413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	assert(sh);
134513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
134613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	s.homedir_template_path =
134713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    semanage_path(SEMANAGE_TMP, SEMANAGE_HOMEDIR_TMPL);
13485007687feb62e27678ee961243984bc319a22911Vit Mojzis	s.fcfilepath =
13495007687feb62e27678ee961243984bc319a22911Vit Mojzis		semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC_HOMEDIRS);
135013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1351c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman	s.fallback = calloc(1, sizeof(genhomedircon_user_entry_t));
1352c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman	if (s.fallback == NULL) {
1353c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman		retval = STATUS_ERR;
1354c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman		goto done;
1355c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman	}
1356c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman
1357c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman	s.fallback->name = strdup(FALLBACK_NAME);
1358c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman	s.fallback->sename = strdup(FALLBACK_SENAME);
1359c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman	s.fallback->prefix = strdup(FALLBACK_PREFIX);
1360c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman	s.fallback->level = strdup(FALLBACK_LEVEL);
1361c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman	if (s.fallback->name == NULL
1362c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman	 || s.fallback->sename == NULL
1363c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman	 || s.fallback->prefix == NULL
1364c90780aaf767485fbdc063eab905422d756f22b5Jason Zaman	 || s.fallback->level == NULL) {
13656263ad719c6c75a88dc6eee8e3973ba0ade36c98Thomas Hurd		retval = STATUS_ERR;
13666263ad719c6c75a88dc6eee8e3973ba0ade36c98Thomas Hurd		goto done;
13676263ad719c6c75a88dc6eee8e3973ba0ade36c98Thomas Hurd	}
136813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1369915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris	if (ignoredirs) ignore_setup(ignoredirs);
1370915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris
137113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	s.usepasswd = usepasswd;
137213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	s.h_semanage = sh;
137313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	s.policydb = policydb;
137413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
137513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!(out = fopen(s.fcfilepath, "w"))) {
137613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* couldn't open output file */
137713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(sh, "Could not open the file_context file for writing");
13786263ad719c6c75a88dc6eee8e3973ba0ade36c98Thomas Hurd		retval = STATUS_ERR;
13796263ad719c6c75a88dc6eee8e3973ba0ade36c98Thomas Hurd		goto done;
138013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
138113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
138213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	retval = write_context_file(&s, out);
138313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
13846263ad719c6c75a88dc6eee8e3973ba0ade36c98Thomas Hurddone:
13856263ad719c6c75a88dc6eee8e3973ba0ade36c98Thomas Hurd	if (out != NULL)
13866263ad719c6c75a88dc6eee8e3973ba0ade36c98Thomas Hurd		fclose(out);
138713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1388c15f495a65e26933189b8f7da2f8fb93f5b0d6e8Jan Zarsky	while (s.fallback)
1389c15f495a65e26933189b8f7da2f8fb93f5b0d6e8Jan Zarsky		pop_user_entry(&(s.fallback));
1390c15f495a65e26933189b8f7da2f8fb93f5b0d6e8Jan Zarsky
1391915b5f885f030aa24a2ca648a184fa02cb5bbdcdEric Paris	ignore_free();
139213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
139313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return retval;
139413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
1395