1*2d543d20SAndroid Build Coastguard Worker /* Author: Mark Goldman <[email protected]>
2*2d543d20SAndroid Build Coastguard Worker * Paul Rosenfeld <[email protected]>
3*2d543d20SAndroid Build Coastguard Worker * Todd C. Miller <[email protected]>
4*2d543d20SAndroid Build Coastguard Worker *
5*2d543d20SAndroid Build Coastguard Worker * Copyright (C) 2007 Tresys Technology, LLC
6*2d543d20SAndroid Build Coastguard Worker *
7*2d543d20SAndroid Build Coastguard Worker * This library is free software; you can redistribute it and/or modify
8*2d543d20SAndroid Build Coastguard Worker * it under the terms of the GNU Lesser General Public License as
9*2d543d20SAndroid Build Coastguard Worker * published by the Free Software Foundation; either version 2.1 of the
10*2d543d20SAndroid Build Coastguard Worker * License, or (at your option) any later version.
11*2d543d20SAndroid Build Coastguard Worker *
12*2d543d20SAndroid Build Coastguard Worker * This library is distributed in the hope that it will be useful, but
13*2d543d20SAndroid Build Coastguard Worker * WITHOUT ANY WARRANTY; without even the implied warranty of
14*2d543d20SAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15*2d543d20SAndroid Build Coastguard Worker * Lesser General Public License for more details.
16*2d543d20SAndroid Build Coastguard Worker *
17*2d543d20SAndroid Build Coastguard Worker * You should have received a copy of the GNU Lesser General Public
18*2d543d20SAndroid Build Coastguard Worker * License along with this library; if not, write to the Free Software
19*2d543d20SAndroid Build Coastguard Worker * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20*2d543d20SAndroid Build Coastguard Worker * 02110-1301 USA
21*2d543d20SAndroid Build Coastguard Worker */
22*2d543d20SAndroid Build Coastguard Worker
23*2d543d20SAndroid Build Coastguard Worker #include <semanage/handle.h>
24*2d543d20SAndroid Build Coastguard Worker #include <semanage/seusers_policy.h>
25*2d543d20SAndroid Build Coastguard Worker #include <semanage/users_policy.h>
26*2d543d20SAndroid Build Coastguard Worker #include <semanage/user_record.h>
27*2d543d20SAndroid Build Coastguard Worker #include <semanage/fcontext_record.h>
28*2d543d20SAndroid Build Coastguard Worker #include <semanage/fcontexts_policy.h>
29*2d543d20SAndroid Build Coastguard Worker #include <sepol/context.h>
30*2d543d20SAndroid Build Coastguard Worker #include <sepol/context_record.h>
31*2d543d20SAndroid Build Coastguard Worker #include "fcontext_internal.h"
32*2d543d20SAndroid Build Coastguard Worker #include "semanage_store.h"
33*2d543d20SAndroid Build Coastguard Worker #include "seuser_internal.h"
34*2d543d20SAndroid Build Coastguard Worker #include "user_internal.h"
35*2d543d20SAndroid Build Coastguard Worker #include "debug.h"
36*2d543d20SAndroid Build Coastguard Worker
37*2d543d20SAndroid Build Coastguard Worker #include "utilities.h"
38*2d543d20SAndroid Build Coastguard Worker #include "genhomedircon.h"
39*2d543d20SAndroid Build Coastguard Worker
40*2d543d20SAndroid Build Coastguard Worker #include <assert.h>
41*2d543d20SAndroid Build Coastguard Worker #include <ctype.h>
42*2d543d20SAndroid Build Coastguard Worker #include <limits.h>
43*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
44*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
45*2d543d20SAndroid Build Coastguard Worker #include <string.h>
46*2d543d20SAndroid Build Coastguard Worker #include <sys/types.h>
47*2d543d20SAndroid Build Coastguard Worker #include <sys/stat.h>
48*2d543d20SAndroid Build Coastguard Worker #include <fcntl.h>
49*2d543d20SAndroid Build Coastguard Worker #include <pwd.h>
50*2d543d20SAndroid Build Coastguard Worker #include <errno.h>
51*2d543d20SAndroid Build Coastguard Worker #include <unistd.h>
52*2d543d20SAndroid Build Coastguard Worker #include <regex.h>
53*2d543d20SAndroid Build Coastguard Worker #include <grp.h>
54*2d543d20SAndroid Build Coastguard Worker #include <search.h>
55*2d543d20SAndroid Build Coastguard Worker
56*2d543d20SAndroid Build Coastguard Worker /* paths used in get_home_dirs() */
57*2d543d20SAndroid Build Coastguard Worker #define PATH_ETC_USERADD "/etc/default/useradd"
58*2d543d20SAndroid Build Coastguard Worker #define PATH_ETC_LIBUSER "/etc/libuser.conf"
59*2d543d20SAndroid Build Coastguard Worker #define PATH_DEFAULT_HOME "/home"
60*2d543d20SAndroid Build Coastguard Worker #define PATH_EXPORT_HOME "/export/home"
61*2d543d20SAndroid Build Coastguard Worker #define PATH_ETC_LOGIN_DEFS "/etc/login.defs"
62*2d543d20SAndroid Build Coastguard Worker
63*2d543d20SAndroid Build Coastguard Worker /* other paths */
64*2d543d20SAndroid Build Coastguard Worker #define PATH_SHELLS_FILE "/etc/shells"
65*2d543d20SAndroid Build Coastguard Worker #define PATH_NOLOGIN_SHELL "/sbin/nologin"
66*2d543d20SAndroid Build Coastguard Worker
67*2d543d20SAndroid Build Coastguard Worker /* comments written to context file */
68*2d543d20SAndroid Build Coastguard Worker #define COMMENT_FILE_CONTEXT_HEADER "#\n#\n# " \
69*2d543d20SAndroid Build Coastguard Worker "User-specific file contexts, generated via libsemanage\n" \
70*2d543d20SAndroid Build Coastguard Worker "# use semanage command to manage system users to change" \
71*2d543d20SAndroid Build Coastguard Worker " the file_context\n#\n#\n"
72*2d543d20SAndroid Build Coastguard Worker
73*2d543d20SAndroid Build Coastguard Worker #define COMMENT_USER_HOME_CONTEXT "\n\n#\n# Home Context for user %s" \
74*2d543d20SAndroid Build Coastguard Worker "\n#\n\n"
75*2d543d20SAndroid Build Coastguard Worker
76*2d543d20SAndroid Build Coastguard Worker /* placeholders used in the template file
77*2d543d20SAndroid Build Coastguard Worker which are searched for and replaced */
78*2d543d20SAndroid Build Coastguard Worker #define TEMPLATE_HOME_ROOT "HOME_ROOT"
79*2d543d20SAndroid Build Coastguard Worker #define TEMPLATE_HOME_DIR "HOME_DIR"
80*2d543d20SAndroid Build Coastguard Worker /* these are legacy */
81*2d543d20SAndroid Build Coastguard Worker #define TEMPLATE_USER "USER"
82*2d543d20SAndroid Build Coastguard Worker #define TEMPLATE_ROLE "ROLE"
83*2d543d20SAndroid Build Coastguard Worker /* new names */
84*2d543d20SAndroid Build Coastguard Worker #define TEMPLATE_USERNAME "%{USERNAME}"
85*2d543d20SAndroid Build Coastguard Worker #define TEMPLATE_USERID "%{USERID}"
86*2d543d20SAndroid Build Coastguard Worker
87*2d543d20SAndroid Build Coastguard Worker #define FALLBACK_SENAME "user_u"
88*2d543d20SAndroid Build Coastguard Worker #define FALLBACK_PREFIX "user"
89*2d543d20SAndroid Build Coastguard Worker #define FALLBACK_LEVEL "s0"
90*2d543d20SAndroid Build Coastguard Worker #define FALLBACK_NAME "[^/]+"
91*2d543d20SAndroid Build Coastguard Worker #define FALLBACK_UIDGID "[0-9]+"
92*2d543d20SAndroid Build Coastguard Worker #define DEFAULT_LOGIN "__default__"
93*2d543d20SAndroid Build Coastguard Worker
94*2d543d20SAndroid Build Coastguard Worker #define CONTEXT_NONE "<<none>>"
95*2d543d20SAndroid Build Coastguard Worker
96*2d543d20SAndroid Build Coastguard Worker typedef struct user_entry {
97*2d543d20SAndroid Build Coastguard Worker char *name;
98*2d543d20SAndroid Build Coastguard Worker char *uid;
99*2d543d20SAndroid Build Coastguard Worker char *gid;
100*2d543d20SAndroid Build Coastguard Worker char *sename;
101*2d543d20SAndroid Build Coastguard Worker char *prefix;
102*2d543d20SAndroid Build Coastguard Worker char *home;
103*2d543d20SAndroid Build Coastguard Worker char *level;
104*2d543d20SAndroid Build Coastguard Worker char *login;
105*2d543d20SAndroid Build Coastguard Worker char *homedir_role;
106*2d543d20SAndroid Build Coastguard Worker struct user_entry *next;
107*2d543d20SAndroid Build Coastguard Worker } genhomedircon_user_entry_t;
108*2d543d20SAndroid Build Coastguard Worker
109*2d543d20SAndroid Build Coastguard Worker typedef struct {
110*2d543d20SAndroid Build Coastguard Worker const char *fcfilepath;
111*2d543d20SAndroid Build Coastguard Worker int usepasswd;
112*2d543d20SAndroid Build Coastguard Worker const char *homedir_template_path;
113*2d543d20SAndroid Build Coastguard Worker genhomedircon_user_entry_t *fallback;
114*2d543d20SAndroid Build Coastguard Worker semanage_handle_t *h_semanage;
115*2d543d20SAndroid Build Coastguard Worker sepol_policydb_t *policydb;
116*2d543d20SAndroid Build Coastguard Worker } genhomedircon_settings_t;
117*2d543d20SAndroid Build Coastguard Worker
118*2d543d20SAndroid Build Coastguard Worker typedef struct {
119*2d543d20SAndroid Build Coastguard Worker const char *search_for;
120*2d543d20SAndroid Build Coastguard Worker const char *replace_with;
121*2d543d20SAndroid Build Coastguard Worker } replacement_pair_t;
122*2d543d20SAndroid Build Coastguard Worker
123*2d543d20SAndroid Build Coastguard Worker typedef struct {
124*2d543d20SAndroid Build Coastguard Worker const char *dir;
125*2d543d20SAndroid Build Coastguard Worker int matched;
126*2d543d20SAndroid Build Coastguard Worker } fc_match_handle_t;
127*2d543d20SAndroid Build Coastguard Worker
128*2d543d20SAndroid Build Coastguard Worker typedef struct IgnoreDir {
129*2d543d20SAndroid Build Coastguard Worker struct IgnoreDir *next;
130*2d543d20SAndroid Build Coastguard Worker char *dir;
131*2d543d20SAndroid Build Coastguard Worker } ignoredir_t;
132*2d543d20SAndroid Build Coastguard Worker
133*2d543d20SAndroid Build Coastguard Worker ignoredir_t *ignore_head = NULL;
134*2d543d20SAndroid Build Coastguard Worker
ignore_free(void)135*2d543d20SAndroid Build Coastguard Worker static void ignore_free(void) {
136*2d543d20SAndroid Build Coastguard Worker ignoredir_t *next;
137*2d543d20SAndroid Build Coastguard Worker
138*2d543d20SAndroid Build Coastguard Worker while (ignore_head) {
139*2d543d20SAndroid Build Coastguard Worker next = ignore_head->next;
140*2d543d20SAndroid Build Coastguard Worker free(ignore_head->dir);
141*2d543d20SAndroid Build Coastguard Worker free(ignore_head);
142*2d543d20SAndroid Build Coastguard Worker ignore_head = next;
143*2d543d20SAndroid Build Coastguard Worker }
144*2d543d20SAndroid Build Coastguard Worker }
145*2d543d20SAndroid Build Coastguard Worker
ignore_setup(char * ignoredirs)146*2d543d20SAndroid Build Coastguard Worker static int ignore_setup(char *ignoredirs) {
147*2d543d20SAndroid Build Coastguard Worker char *tok;
148*2d543d20SAndroid Build Coastguard Worker ignoredir_t *ptr = NULL;
149*2d543d20SAndroid Build Coastguard Worker
150*2d543d20SAndroid Build Coastguard Worker tok = strtok(ignoredirs, ";");
151*2d543d20SAndroid Build Coastguard Worker while(tok) {
152*2d543d20SAndroid Build Coastguard Worker ptr = calloc(1, sizeof(ignoredir_t));
153*2d543d20SAndroid Build Coastguard Worker if (!ptr)
154*2d543d20SAndroid Build Coastguard Worker goto err;
155*2d543d20SAndroid Build Coastguard Worker ptr->dir = strdup(tok);
156*2d543d20SAndroid Build Coastguard Worker if (!ptr->dir)
157*2d543d20SAndroid Build Coastguard Worker goto err;
158*2d543d20SAndroid Build Coastguard Worker
159*2d543d20SAndroid Build Coastguard Worker ptr->next = ignore_head;
160*2d543d20SAndroid Build Coastguard Worker ignore_head = ptr;
161*2d543d20SAndroid Build Coastguard Worker
162*2d543d20SAndroid Build Coastguard Worker tok = strtok(NULL, ";");
163*2d543d20SAndroid Build Coastguard Worker }
164*2d543d20SAndroid Build Coastguard Worker
165*2d543d20SAndroid Build Coastguard Worker return 0;
166*2d543d20SAndroid Build Coastguard Worker err:
167*2d543d20SAndroid Build Coastguard Worker free(ptr);
168*2d543d20SAndroid Build Coastguard Worker ignore_free();
169*2d543d20SAndroid Build Coastguard Worker return -1;
170*2d543d20SAndroid Build Coastguard Worker }
171*2d543d20SAndroid Build Coastguard Worker
ignore(const char * homedir)172*2d543d20SAndroid Build Coastguard Worker static int ignore(const char *homedir) {
173*2d543d20SAndroid Build Coastguard Worker ignoredir_t *ptr = ignore_head;
174*2d543d20SAndroid Build Coastguard Worker while (ptr) {
175*2d543d20SAndroid Build Coastguard Worker if (strcmp(ptr->dir, homedir) == 0) {
176*2d543d20SAndroid Build Coastguard Worker return 1;
177*2d543d20SAndroid Build Coastguard Worker }
178*2d543d20SAndroid Build Coastguard Worker ptr = ptr->next;
179*2d543d20SAndroid Build Coastguard Worker }
180*2d543d20SAndroid Build Coastguard Worker return 0;
181*2d543d20SAndroid Build Coastguard Worker }
182*2d543d20SAndroid Build Coastguard Worker
prefix_is_homedir_role(const semanage_user_t * user,const char * prefix)183*2d543d20SAndroid Build Coastguard Worker static int prefix_is_homedir_role(const semanage_user_t *user,
184*2d543d20SAndroid Build Coastguard Worker const char *prefix)
185*2d543d20SAndroid Build Coastguard Worker {
186*2d543d20SAndroid Build Coastguard Worker return strcmp(OBJECT_R, prefix) == 0 ||
187*2d543d20SAndroid Build Coastguard Worker semanage_user_has_role(user, prefix);
188*2d543d20SAndroid Build Coastguard Worker }
189*2d543d20SAndroid Build Coastguard Worker
default_shell_list(void)190*2d543d20SAndroid Build Coastguard Worker static semanage_list_t *default_shell_list(void)
191*2d543d20SAndroid Build Coastguard Worker {
192*2d543d20SAndroid Build Coastguard Worker semanage_list_t *list = NULL;
193*2d543d20SAndroid Build Coastguard Worker
194*2d543d20SAndroid Build Coastguard Worker if (semanage_list_push(&list, "/bin/csh")
195*2d543d20SAndroid Build Coastguard Worker || semanage_list_push(&list, "/bin/tcsh")
196*2d543d20SAndroid Build Coastguard Worker || semanage_list_push(&list, "/bin/ksh")
197*2d543d20SAndroid Build Coastguard Worker || semanage_list_push(&list, "/bin/bsh")
198*2d543d20SAndroid Build Coastguard Worker || semanage_list_push(&list, "/bin/ash")
199*2d543d20SAndroid Build Coastguard Worker || semanage_list_push(&list, "/usr/bin/ksh")
200*2d543d20SAndroid Build Coastguard Worker || semanage_list_push(&list, "/usr/bin/pdksh")
201*2d543d20SAndroid Build Coastguard Worker || semanage_list_push(&list, "/bin/zsh")
202*2d543d20SAndroid Build Coastguard Worker || semanage_list_push(&list, "/bin/sh")
203*2d543d20SAndroid Build Coastguard Worker || semanage_list_push(&list, "/bin/bash"))
204*2d543d20SAndroid Build Coastguard Worker goto fail;
205*2d543d20SAndroid Build Coastguard Worker
206*2d543d20SAndroid Build Coastguard Worker return list;
207*2d543d20SAndroid Build Coastguard Worker
208*2d543d20SAndroid Build Coastguard Worker fail:
209*2d543d20SAndroid Build Coastguard Worker semanage_list_destroy(&list);
210*2d543d20SAndroid Build Coastguard Worker return NULL;
211*2d543d20SAndroid Build Coastguard Worker }
212*2d543d20SAndroid Build Coastguard Worker
get_shell_list(void)213*2d543d20SAndroid Build Coastguard Worker static semanage_list_t *get_shell_list(void)
214*2d543d20SAndroid Build Coastguard Worker {
215*2d543d20SAndroid Build Coastguard Worker FILE *shells;
216*2d543d20SAndroid Build Coastguard Worker char *temp = NULL;
217*2d543d20SAndroid Build Coastguard Worker semanage_list_t *list = NULL;
218*2d543d20SAndroid Build Coastguard Worker size_t buff_len = 0;
219*2d543d20SAndroid Build Coastguard Worker ssize_t len;
220*2d543d20SAndroid Build Coastguard Worker
221*2d543d20SAndroid Build Coastguard Worker shells = fopen(PATH_SHELLS_FILE, "r");
222*2d543d20SAndroid Build Coastguard Worker if (!shells)
223*2d543d20SAndroid Build Coastguard Worker return default_shell_list();
224*2d543d20SAndroid Build Coastguard Worker while ((len = getline(&temp, &buff_len, shells)) > 0) {
225*2d543d20SAndroid Build Coastguard Worker if (temp[len-1] == '\n') temp[len-1] = 0;
226*2d543d20SAndroid Build Coastguard Worker if (strcmp(temp, PATH_NOLOGIN_SHELL)) {
227*2d543d20SAndroid Build Coastguard Worker if (semanage_list_push(&list, temp)) {
228*2d543d20SAndroid Build Coastguard Worker free(temp);
229*2d543d20SAndroid Build Coastguard Worker semanage_list_destroy(&list);
230*2d543d20SAndroid Build Coastguard Worker return default_shell_list();
231*2d543d20SAndroid Build Coastguard Worker }
232*2d543d20SAndroid Build Coastguard Worker }
233*2d543d20SAndroid Build Coastguard Worker }
234*2d543d20SAndroid Build Coastguard Worker free(temp);
235*2d543d20SAndroid Build Coastguard Worker
236*2d543d20SAndroid Build Coastguard Worker return list;
237*2d543d20SAndroid Build Coastguard Worker }
238*2d543d20SAndroid Build Coastguard Worker
239*2d543d20SAndroid Build Coastguard Worker /* Helper function called via semanage_fcontext_iterate() */
fcontext_matches(const semanage_fcontext_t * fcontext,void * varg)240*2d543d20SAndroid Build Coastguard Worker static int fcontext_matches(const semanage_fcontext_t *fcontext, void *varg)
241*2d543d20SAndroid Build Coastguard Worker {
242*2d543d20SAndroid Build Coastguard Worker const char *oexpr = semanage_fcontext_get_expr(fcontext);
243*2d543d20SAndroid Build Coastguard Worker fc_match_handle_t *handp = varg;
244*2d543d20SAndroid Build Coastguard Worker char *expr = NULL;
245*2d543d20SAndroid Build Coastguard Worker regex_t re;
246*2d543d20SAndroid Build Coastguard Worker int type, retval = -1;
247*2d543d20SAndroid Build Coastguard Worker size_t len;
248*2d543d20SAndroid Build Coastguard Worker
249*2d543d20SAndroid Build Coastguard Worker /* Only match ALL or DIR */
250*2d543d20SAndroid Build Coastguard Worker type = semanage_fcontext_get_type(fcontext);
251*2d543d20SAndroid Build Coastguard Worker if (type != SEMANAGE_FCONTEXT_ALL && type != SEMANAGE_FCONTEXT_DIR)
252*2d543d20SAndroid Build Coastguard Worker return 0;
253*2d543d20SAndroid Build Coastguard Worker
254*2d543d20SAndroid Build Coastguard Worker len = strlen(oexpr);
255*2d543d20SAndroid Build Coastguard Worker /* Define a macro to strip a literal string from the end of oexpr */
256*2d543d20SAndroid Build Coastguard Worker #define rstrip_oexpr_len(cstr, cstrlen) \
257*2d543d20SAndroid Build Coastguard Worker do { \
258*2d543d20SAndroid Build Coastguard Worker if (len >= (cstrlen) && !strncmp(oexpr + len - (cstrlen), (cstr), (cstrlen))) \
259*2d543d20SAndroid Build Coastguard Worker len -= (cstrlen); \
260*2d543d20SAndroid Build Coastguard Worker } while (0)
261*2d543d20SAndroid Build Coastguard Worker #define rstrip_oexpr(cstr) rstrip_oexpr_len(cstr, sizeof(cstr) - 1)
262*2d543d20SAndroid Build Coastguard Worker
263*2d543d20SAndroid Build Coastguard Worker rstrip_oexpr(".+");
264*2d543d20SAndroid Build Coastguard Worker rstrip_oexpr(".*");
265*2d543d20SAndroid Build Coastguard Worker rstrip_oexpr("(/.*)?");
266*2d543d20SAndroid Build Coastguard Worker rstrip_oexpr("/");
267*2d543d20SAndroid Build Coastguard Worker
268*2d543d20SAndroid Build Coastguard Worker #undef rstrip_oexpr_len
269*2d543d20SAndroid Build Coastguard Worker #undef rstrip_oexpr
270*2d543d20SAndroid Build Coastguard Worker
271*2d543d20SAndroid Build Coastguard Worker /* Anchor oexpr at the beginning and append pattern to eat up trailing slashes */
272*2d543d20SAndroid Build Coastguard Worker if (asprintf(&expr, "^%.*s/*$", (int)len, oexpr) < 0)
273*2d543d20SAndroid Build Coastguard Worker return -1;
274*2d543d20SAndroid Build Coastguard Worker
275*2d543d20SAndroid Build Coastguard Worker /* Check dir against expr */
276*2d543d20SAndroid Build Coastguard Worker if (regcomp(&re, expr, REG_EXTENDED) != 0)
277*2d543d20SAndroid Build Coastguard Worker goto done;
278*2d543d20SAndroid Build Coastguard Worker if (regexec(&re, handp->dir, 0, NULL, 0) == 0)
279*2d543d20SAndroid Build Coastguard Worker handp->matched = 1;
280*2d543d20SAndroid Build Coastguard Worker regfree(&re);
281*2d543d20SAndroid Build Coastguard Worker
282*2d543d20SAndroid Build Coastguard Worker retval = 0;
283*2d543d20SAndroid Build Coastguard Worker
284*2d543d20SAndroid Build Coastguard Worker done:
285*2d543d20SAndroid Build Coastguard Worker free(expr);
286*2d543d20SAndroid Build Coastguard Worker
287*2d543d20SAndroid Build Coastguard Worker return retval;
288*2d543d20SAndroid Build Coastguard Worker }
289*2d543d20SAndroid Build Coastguard Worker
get_home_dirs(genhomedircon_settings_t * s)290*2d543d20SAndroid Build Coastguard Worker static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
291*2d543d20SAndroid Build Coastguard Worker {
292*2d543d20SAndroid Build Coastguard Worker semanage_list_t *homedir_list = NULL;
293*2d543d20SAndroid Build Coastguard Worker semanage_list_t *shells = NULL;
294*2d543d20SAndroid Build Coastguard Worker fc_match_handle_t hand;
295*2d543d20SAndroid Build Coastguard Worker char *path = NULL;
296*2d543d20SAndroid Build Coastguard Worker uid_t temp, minuid = 500, maxuid = 60000;
297*2d543d20SAndroid Build Coastguard Worker int minuid_set = 0;
298*2d543d20SAndroid Build Coastguard Worker struct passwd *pwbuf;
299*2d543d20SAndroid Build Coastguard Worker struct stat buf;
300*2d543d20SAndroid Build Coastguard Worker
301*2d543d20SAndroid Build Coastguard Worker path = semanage_findval(PATH_ETC_USERADD, "HOME", "=");
302*2d543d20SAndroid Build Coastguard Worker if (path && *path) {
303*2d543d20SAndroid Build Coastguard Worker if (semanage_list_push(&homedir_list, path))
304*2d543d20SAndroid Build Coastguard Worker goto fail;
305*2d543d20SAndroid Build Coastguard Worker }
306*2d543d20SAndroid Build Coastguard Worker free(path);
307*2d543d20SAndroid Build Coastguard Worker
308*2d543d20SAndroid Build Coastguard Worker path = semanage_findval(PATH_ETC_LIBUSER, "LU_HOMEDIRECTORY", "=");
309*2d543d20SAndroid Build Coastguard Worker if (path && *path) {
310*2d543d20SAndroid Build Coastguard Worker if (semanage_list_push(&homedir_list, path))
311*2d543d20SAndroid Build Coastguard Worker goto fail;
312*2d543d20SAndroid Build Coastguard Worker }
313*2d543d20SAndroid Build Coastguard Worker free(path);
314*2d543d20SAndroid Build Coastguard Worker path = NULL;
315*2d543d20SAndroid Build Coastguard Worker
316*2d543d20SAndroid Build Coastguard Worker if (!homedir_list) {
317*2d543d20SAndroid Build Coastguard Worker if (semanage_list_push(&homedir_list, PATH_DEFAULT_HOME)) {
318*2d543d20SAndroid Build Coastguard Worker goto fail;
319*2d543d20SAndroid Build Coastguard Worker }
320*2d543d20SAndroid Build Coastguard Worker }
321*2d543d20SAndroid Build Coastguard Worker
322*2d543d20SAndroid Build Coastguard Worker if (!stat(PATH_EXPORT_HOME, &buf)) {
323*2d543d20SAndroid Build Coastguard Worker if (S_ISDIR(buf.st_mode)) {
324*2d543d20SAndroid Build Coastguard Worker if (semanage_list_push(&homedir_list, PATH_EXPORT_HOME)) {
325*2d543d20SAndroid Build Coastguard Worker goto fail;
326*2d543d20SAndroid Build Coastguard Worker }
327*2d543d20SAndroid Build Coastguard Worker }
328*2d543d20SAndroid Build Coastguard Worker }
329*2d543d20SAndroid Build Coastguard Worker
330*2d543d20SAndroid Build Coastguard Worker if (!(s->usepasswd))
331*2d543d20SAndroid Build Coastguard Worker return homedir_list;
332*2d543d20SAndroid Build Coastguard Worker
333*2d543d20SAndroid Build Coastguard Worker shells = get_shell_list();
334*2d543d20SAndroid Build Coastguard Worker assert(shells);
335*2d543d20SAndroid Build Coastguard Worker
336*2d543d20SAndroid Build Coastguard Worker path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL);
337*2d543d20SAndroid Build Coastguard Worker if (path && *path) {
338*2d543d20SAndroid Build Coastguard Worker temp = atoi(path);
339*2d543d20SAndroid Build Coastguard Worker minuid = temp;
340*2d543d20SAndroid Build Coastguard Worker minuid_set = 1;
341*2d543d20SAndroid Build Coastguard Worker }
342*2d543d20SAndroid Build Coastguard Worker free(path);
343*2d543d20SAndroid Build Coastguard Worker path = NULL;
344*2d543d20SAndroid Build Coastguard Worker
345*2d543d20SAndroid Build Coastguard Worker path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL);
346*2d543d20SAndroid Build Coastguard Worker if (path && *path) {
347*2d543d20SAndroid Build Coastguard Worker temp = atoi(path);
348*2d543d20SAndroid Build Coastguard Worker maxuid = temp;
349*2d543d20SAndroid Build Coastguard Worker }
350*2d543d20SAndroid Build Coastguard Worker free(path);
351*2d543d20SAndroid Build Coastguard Worker path = NULL;
352*2d543d20SAndroid Build Coastguard Worker
353*2d543d20SAndroid Build Coastguard Worker path = semanage_findval(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=");
354*2d543d20SAndroid Build Coastguard Worker if (path && *path) {
355*2d543d20SAndroid Build Coastguard Worker temp = atoi(path);
356*2d543d20SAndroid Build Coastguard Worker if (!minuid_set || temp < minuid) {
357*2d543d20SAndroid Build Coastguard Worker minuid = temp;
358*2d543d20SAndroid Build Coastguard Worker minuid_set = 1;
359*2d543d20SAndroid Build Coastguard Worker }
360*2d543d20SAndroid Build Coastguard Worker }
361*2d543d20SAndroid Build Coastguard Worker free(path);
362*2d543d20SAndroid Build Coastguard Worker path = NULL;
363*2d543d20SAndroid Build Coastguard Worker
364*2d543d20SAndroid Build Coastguard Worker errno = 0;
365*2d543d20SAndroid Build Coastguard Worker setpwent();
366*2d543d20SAndroid Build Coastguard Worker while (1) {
367*2d543d20SAndroid Build Coastguard Worker errno = 0;
368*2d543d20SAndroid Build Coastguard Worker pwbuf = getpwent();
369*2d543d20SAndroid Build Coastguard Worker if (pwbuf == NULL)
370*2d543d20SAndroid Build Coastguard Worker break;
371*2d543d20SAndroid Build Coastguard Worker if (pwbuf->pw_uid < minuid || pwbuf->pw_uid > maxuid)
372*2d543d20SAndroid Build Coastguard Worker continue;
373*2d543d20SAndroid Build Coastguard Worker if (!semanage_list_find(shells, pwbuf->pw_shell))
374*2d543d20SAndroid Build Coastguard Worker continue;
375*2d543d20SAndroid Build Coastguard Worker int len = strlen(pwbuf->pw_dir) -1;
376*2d543d20SAndroid Build Coastguard Worker for(; len > 0 && pwbuf->pw_dir[len] == '/'; len--) {
377*2d543d20SAndroid Build Coastguard Worker pwbuf->pw_dir[len] = '\0';
378*2d543d20SAndroid Build Coastguard Worker }
379*2d543d20SAndroid Build Coastguard Worker if (strcmp(pwbuf->pw_dir, "/") == 0)
380*2d543d20SAndroid Build Coastguard Worker continue;
381*2d543d20SAndroid Build Coastguard Worker if (ignore(pwbuf->pw_dir))
382*2d543d20SAndroid Build Coastguard Worker continue;
383*2d543d20SAndroid Build Coastguard Worker if (semanage_str_count(pwbuf->pw_dir, '/') <= 1)
384*2d543d20SAndroid Build Coastguard Worker continue;
385*2d543d20SAndroid Build Coastguard Worker if (!(path = strdup(pwbuf->pw_dir))) {
386*2d543d20SAndroid Build Coastguard Worker break;
387*2d543d20SAndroid Build Coastguard Worker }
388*2d543d20SAndroid Build Coastguard Worker
389*2d543d20SAndroid Build Coastguard Worker semanage_rtrim(path, '/');
390*2d543d20SAndroid Build Coastguard Worker
391*2d543d20SAndroid Build Coastguard Worker if (!semanage_list_find(homedir_list, path)) {
392*2d543d20SAndroid Build Coastguard Worker /*
393*2d543d20SAndroid Build Coastguard Worker * Now check for an existing file context that matches
394*2d543d20SAndroid Build Coastguard Worker * so we don't label a non-homedir as a homedir.
395*2d543d20SAndroid Build Coastguard Worker */
396*2d543d20SAndroid Build Coastguard Worker hand.dir = path;
397*2d543d20SAndroid Build Coastguard Worker hand.matched = 0;
398*2d543d20SAndroid Build Coastguard Worker if (semanage_fcontext_iterate(s->h_semanage,
399*2d543d20SAndroid Build Coastguard Worker fcontext_matches, &hand) == STATUS_ERR)
400*2d543d20SAndroid Build Coastguard Worker goto fail;
401*2d543d20SAndroid Build Coastguard Worker
402*2d543d20SAndroid Build Coastguard Worker /* NOTE: old genhomedircon printed a warning on match */
403*2d543d20SAndroid Build Coastguard Worker if (hand.matched) {
404*2d543d20SAndroid Build Coastguard Worker 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);
405*2d543d20SAndroid Build Coastguard Worker } else {
406*2d543d20SAndroid Build Coastguard Worker if (semanage_list_push(&homedir_list, path))
407*2d543d20SAndroid Build Coastguard Worker goto fail;
408*2d543d20SAndroid Build Coastguard Worker }
409*2d543d20SAndroid Build Coastguard Worker }
410*2d543d20SAndroid Build Coastguard Worker free(path);
411*2d543d20SAndroid Build Coastguard Worker path = NULL;
412*2d543d20SAndroid Build Coastguard Worker }
413*2d543d20SAndroid Build Coastguard Worker
414*2d543d20SAndroid Build Coastguard Worker if (errno) {
415*2d543d20SAndroid Build Coastguard Worker WARN(s->h_semanage, "Error while fetching users. "
416*2d543d20SAndroid Build Coastguard Worker "Returning list so far.");
417*2d543d20SAndroid Build Coastguard Worker }
418*2d543d20SAndroid Build Coastguard Worker
419*2d543d20SAndroid Build Coastguard Worker if (semanage_list_sort(&homedir_list))
420*2d543d20SAndroid Build Coastguard Worker goto fail;
421*2d543d20SAndroid Build Coastguard Worker
422*2d543d20SAndroid Build Coastguard Worker endpwent();
423*2d543d20SAndroid Build Coastguard Worker semanage_list_destroy(&shells);
424*2d543d20SAndroid Build Coastguard Worker
425*2d543d20SAndroid Build Coastguard Worker return homedir_list;
426*2d543d20SAndroid Build Coastguard Worker
427*2d543d20SAndroid Build Coastguard Worker fail:
428*2d543d20SAndroid Build Coastguard Worker endpwent();
429*2d543d20SAndroid Build Coastguard Worker free(path);
430*2d543d20SAndroid Build Coastguard Worker semanage_list_destroy(&homedir_list);
431*2d543d20SAndroid Build Coastguard Worker semanage_list_destroy(&shells);
432*2d543d20SAndroid Build Coastguard Worker return NULL;
433*2d543d20SAndroid Build Coastguard Worker }
434*2d543d20SAndroid Build Coastguard Worker
435*2d543d20SAndroid Build Coastguard Worker /**
436*2d543d20SAndroid Build Coastguard Worker * @param out the FILE to put all the output in.
437*2d543d20SAndroid Build Coastguard Worker * @return 0 on success
438*2d543d20SAndroid Build Coastguard Worker */
write_file_context_header(FILE * out)439*2d543d20SAndroid Build Coastguard Worker static int write_file_context_header(FILE * out)
440*2d543d20SAndroid Build Coastguard Worker {
441*2d543d20SAndroid Build Coastguard Worker if (fprintf(out, COMMENT_FILE_CONTEXT_HEADER) < 0) {
442*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
443*2d543d20SAndroid Build Coastguard Worker }
444*2d543d20SAndroid Build Coastguard Worker
445*2d543d20SAndroid Build Coastguard Worker return STATUS_SUCCESS;
446*2d543d20SAndroid Build Coastguard Worker }
447*2d543d20SAndroid Build Coastguard Worker
448*2d543d20SAndroid Build Coastguard Worker /* Predicates for use with semanage_slurp_file_filter() the homedir_template
449*2d543d20SAndroid Build Coastguard Worker * file currently contains lines that serve as the template for a user's
450*2d543d20SAndroid Build Coastguard Worker * homedir.
451*2d543d20SAndroid Build Coastguard Worker *
452*2d543d20SAndroid Build Coastguard Worker * It also contains lines that are the template for the parent of a
453*2d543d20SAndroid Build Coastguard Worker * user's home directory.
454*2d543d20SAndroid Build Coastguard Worker *
455*2d543d20SAndroid Build Coastguard Worker * Currently, the only lines that apply to the the root of a user's home
456*2d543d20SAndroid Build Coastguard Worker * directory are all prefixed with the string "HOME_ROOT". All other
457*2d543d20SAndroid Build Coastguard Worker * lines apply to a user's home directory. If this changes the
458*2d543d20SAndroid Build Coastguard Worker * following predicates need to change to reflect that.
459*2d543d20SAndroid Build Coastguard Worker */
HOME_ROOT_PRED(const char * string)460*2d543d20SAndroid Build Coastguard Worker static int HOME_ROOT_PRED(const char *string)
461*2d543d20SAndroid Build Coastguard Worker {
462*2d543d20SAndroid Build Coastguard Worker return semanage_is_prefix(string, TEMPLATE_HOME_ROOT);
463*2d543d20SAndroid Build Coastguard Worker }
464*2d543d20SAndroid Build Coastguard Worker
HOME_DIR_PRED(const char * string)465*2d543d20SAndroid Build Coastguard Worker static int HOME_DIR_PRED(const char *string)
466*2d543d20SAndroid Build Coastguard Worker {
467*2d543d20SAndroid Build Coastguard Worker return semanage_is_prefix(string, TEMPLATE_HOME_DIR);
468*2d543d20SAndroid Build Coastguard Worker }
469*2d543d20SAndroid Build Coastguard Worker
470*2d543d20SAndroid Build Coastguard Worker /* new names */
USERNAME_CONTEXT_PRED(const char * string)471*2d543d20SAndroid Build Coastguard Worker static int USERNAME_CONTEXT_PRED(const char *string)
472*2d543d20SAndroid Build Coastguard Worker {
473*2d543d20SAndroid Build Coastguard Worker return (int)(
474*2d543d20SAndroid Build Coastguard Worker (strstr(string, TEMPLATE_USERNAME) != NULL) ||
475*2d543d20SAndroid Build Coastguard Worker (strstr(string, TEMPLATE_USERID) != NULL)
476*2d543d20SAndroid Build Coastguard Worker );
477*2d543d20SAndroid Build Coastguard Worker }
478*2d543d20SAndroid Build Coastguard Worker
479*2d543d20SAndroid Build Coastguard Worker /* This will never match USER if USERNAME or USERID are found. */
USER_CONTEXT_PRED(const char * string)480*2d543d20SAndroid Build Coastguard Worker static int USER_CONTEXT_PRED(const char *string)
481*2d543d20SAndroid Build Coastguard Worker {
482*2d543d20SAndroid Build Coastguard Worker if (USERNAME_CONTEXT_PRED(string))
483*2d543d20SAndroid Build Coastguard Worker return 0;
484*2d543d20SAndroid Build Coastguard Worker
485*2d543d20SAndroid Build Coastguard Worker return (int)(strstr(string, TEMPLATE_USER) != NULL);
486*2d543d20SAndroid Build Coastguard Worker }
487*2d543d20SAndroid Build Coastguard Worker
STR_COMPARATOR(const void * a,const void * b)488*2d543d20SAndroid Build Coastguard Worker static int STR_COMPARATOR(const void *a, const void *b)
489*2d543d20SAndroid Build Coastguard Worker {
490*2d543d20SAndroid Build Coastguard Worker return strcmp((const char *) a, (const char *) b);
491*2d543d20SAndroid Build Coastguard Worker }
492*2d543d20SAndroid Build Coastguard Worker
493*2d543d20SAndroid Build Coastguard Worker /* make_template
494*2d543d20SAndroid Build Coastguard Worker * @param s the settings holding the paths to various files
495*2d543d20SAndroid Build Coastguard Worker * @param pred function pointer to function to use as filter for slurp
496*2d543d20SAndroid Build Coastguard Worker * file filter
497*2d543d20SAndroid Build Coastguard Worker * @return a list of lines from the template file with inappropriate
498*2d543d20SAndroid Build Coastguard Worker * lines filtered out.
499*2d543d20SAndroid Build Coastguard Worker */
make_template(genhomedircon_settings_t * s,int (* pred)(const char *))500*2d543d20SAndroid Build Coastguard Worker static semanage_list_t *make_template(genhomedircon_settings_t * s,
501*2d543d20SAndroid Build Coastguard Worker int (*pred) (const char *))
502*2d543d20SAndroid Build Coastguard Worker {
503*2d543d20SAndroid Build Coastguard Worker FILE *template_file = NULL;
504*2d543d20SAndroid Build Coastguard Worker semanage_list_t *template_data = NULL;
505*2d543d20SAndroid Build Coastguard Worker
506*2d543d20SAndroid Build Coastguard Worker template_file = fopen(s->homedir_template_path, "r");
507*2d543d20SAndroid Build Coastguard Worker if (!template_file)
508*2d543d20SAndroid Build Coastguard Worker return NULL;
509*2d543d20SAndroid Build Coastguard Worker template_data = semanage_slurp_file_filter(template_file, pred);
510*2d543d20SAndroid Build Coastguard Worker fclose(template_file);
511*2d543d20SAndroid Build Coastguard Worker
512*2d543d20SAndroid Build Coastguard Worker return template_data;
513*2d543d20SAndroid Build Coastguard Worker }
514*2d543d20SAndroid Build Coastguard Worker
replace_all(const char * str,const replacement_pair_t * repl)515*2d543d20SAndroid Build Coastguard Worker static char *replace_all(const char *str, const replacement_pair_t * repl)
516*2d543d20SAndroid Build Coastguard Worker {
517*2d543d20SAndroid Build Coastguard Worker char *retval, *retval2;
518*2d543d20SAndroid Build Coastguard Worker int i;
519*2d543d20SAndroid Build Coastguard Worker
520*2d543d20SAndroid Build Coastguard Worker if (!str || !repl)
521*2d543d20SAndroid Build Coastguard Worker return NULL;
522*2d543d20SAndroid Build Coastguard Worker
523*2d543d20SAndroid Build Coastguard Worker retval = strdup(str);
524*2d543d20SAndroid Build Coastguard Worker for (i = 0; retval != NULL && repl[i].search_for; i++) {
525*2d543d20SAndroid Build Coastguard Worker retval2 = semanage_str_replace(repl[i].search_for,
526*2d543d20SAndroid Build Coastguard Worker repl[i].replace_with, retval, 0);
527*2d543d20SAndroid Build Coastguard Worker free(retval);
528*2d543d20SAndroid Build Coastguard Worker retval = retval2;
529*2d543d20SAndroid Build Coastguard Worker }
530*2d543d20SAndroid Build Coastguard Worker return retval;
531*2d543d20SAndroid Build Coastguard Worker }
532*2d543d20SAndroid Build Coastguard Worker
extract_context(const char * line)533*2d543d20SAndroid Build Coastguard Worker static const char *extract_context(const char *line)
534*2d543d20SAndroid Build Coastguard Worker {
535*2d543d20SAndroid Build Coastguard Worker const char *p = line;
536*2d543d20SAndroid Build Coastguard Worker size_t off;
537*2d543d20SAndroid Build Coastguard Worker
538*2d543d20SAndroid Build Coastguard Worker off = strlen(p);
539*2d543d20SAndroid Build Coastguard Worker p += off;
540*2d543d20SAndroid Build Coastguard Worker /* consider trailing whitespaces */
541*2d543d20SAndroid Build Coastguard Worker while (off > 0) {
542*2d543d20SAndroid Build Coastguard Worker p--;
543*2d543d20SAndroid Build Coastguard Worker off--;
544*2d543d20SAndroid Build Coastguard Worker if (!isspace(*p))
545*2d543d20SAndroid Build Coastguard Worker break;
546*2d543d20SAndroid Build Coastguard Worker }
547*2d543d20SAndroid Build Coastguard Worker if (off == 0)
548*2d543d20SAndroid Build Coastguard Worker return NULL;
549*2d543d20SAndroid Build Coastguard Worker
550*2d543d20SAndroid Build Coastguard Worker /* find the last field in line */
551*2d543d20SAndroid Build Coastguard Worker while (off > 0 && !isspace(*(p - 1))) {
552*2d543d20SAndroid Build Coastguard Worker p--;
553*2d543d20SAndroid Build Coastguard Worker off--;
554*2d543d20SAndroid Build Coastguard Worker }
555*2d543d20SAndroid Build Coastguard Worker return p;
556*2d543d20SAndroid Build Coastguard Worker }
557*2d543d20SAndroid Build Coastguard Worker
check_line(genhomedircon_settings_t * s,const char * line)558*2d543d20SAndroid Build Coastguard Worker static int check_line(genhomedircon_settings_t * s, const char *line)
559*2d543d20SAndroid Build Coastguard Worker {
560*2d543d20SAndroid Build Coastguard Worker sepol_context_t *ctx_record = NULL;
561*2d543d20SAndroid Build Coastguard Worker const char *ctx_str;
562*2d543d20SAndroid Build Coastguard Worker int result;
563*2d543d20SAndroid Build Coastguard Worker
564*2d543d20SAndroid Build Coastguard Worker ctx_str = extract_context(line);
565*2d543d20SAndroid Build Coastguard Worker if (!ctx_str)
566*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
567*2d543d20SAndroid Build Coastguard Worker
568*2d543d20SAndroid Build Coastguard Worker result = sepol_context_from_string(s->h_semanage->sepolh,
569*2d543d20SAndroid Build Coastguard Worker ctx_str, &ctx_record);
570*2d543d20SAndroid Build Coastguard Worker if (result == STATUS_SUCCESS && ctx_record != NULL) {
571*2d543d20SAndroid Build Coastguard Worker result = sepol_context_check(s->h_semanage->sepolh,
572*2d543d20SAndroid Build Coastguard Worker s->policydb, ctx_record);
573*2d543d20SAndroid Build Coastguard Worker sepol_context_free(ctx_record);
574*2d543d20SAndroid Build Coastguard Worker }
575*2d543d20SAndroid Build Coastguard Worker return result;
576*2d543d20SAndroid Build Coastguard Worker }
577*2d543d20SAndroid Build Coastguard Worker
write_replacements(genhomedircon_settings_t * s,FILE * out,const semanage_list_t * tpl,const replacement_pair_t * repl)578*2d543d20SAndroid Build Coastguard Worker static int write_replacements(genhomedircon_settings_t * s, FILE * out,
579*2d543d20SAndroid Build Coastguard Worker const semanage_list_t * tpl,
580*2d543d20SAndroid Build Coastguard Worker const replacement_pair_t *repl)
581*2d543d20SAndroid Build Coastguard Worker {
582*2d543d20SAndroid Build Coastguard Worker char *line;
583*2d543d20SAndroid Build Coastguard Worker
584*2d543d20SAndroid Build Coastguard Worker for (; tpl; tpl = tpl->next) {
585*2d543d20SAndroid Build Coastguard Worker line = replace_all(tpl->data, repl);
586*2d543d20SAndroid Build Coastguard Worker if (!line)
587*2d543d20SAndroid Build Coastguard Worker goto fail;
588*2d543d20SAndroid Build Coastguard Worker if (check_line(s, line) == STATUS_SUCCESS) {
589*2d543d20SAndroid Build Coastguard Worker if (fprintf(out, "%s\n", line) < 0)
590*2d543d20SAndroid Build Coastguard Worker goto fail;
591*2d543d20SAndroid Build Coastguard Worker }
592*2d543d20SAndroid Build Coastguard Worker free(line);
593*2d543d20SAndroid Build Coastguard Worker }
594*2d543d20SAndroid Build Coastguard Worker return STATUS_SUCCESS;
595*2d543d20SAndroid Build Coastguard Worker
596*2d543d20SAndroid Build Coastguard Worker fail:
597*2d543d20SAndroid Build Coastguard Worker free(line);
598*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
599*2d543d20SAndroid Build Coastguard Worker }
600*2d543d20SAndroid Build Coastguard Worker
write_contexts(genhomedircon_settings_t * s,FILE * out,semanage_list_t * tpl,const replacement_pair_t * repl,const genhomedircon_user_entry_t * user)601*2d543d20SAndroid Build Coastguard Worker static int write_contexts(genhomedircon_settings_t *s, FILE *out,
602*2d543d20SAndroid Build Coastguard Worker semanage_list_t *tpl, const replacement_pair_t *repl,
603*2d543d20SAndroid Build Coastguard Worker const genhomedircon_user_entry_t *user)
604*2d543d20SAndroid Build Coastguard Worker {
605*2d543d20SAndroid Build Coastguard Worker char *line, *temp;
606*2d543d20SAndroid Build Coastguard Worker sepol_context_t *context;
607*2d543d20SAndroid Build Coastguard Worker char *new_context_str;
608*2d543d20SAndroid Build Coastguard Worker
609*2d543d20SAndroid Build Coastguard Worker for (; tpl; tpl = tpl->next) {
610*2d543d20SAndroid Build Coastguard Worker context = NULL;
611*2d543d20SAndroid Build Coastguard Worker new_context_str = NULL;
612*2d543d20SAndroid Build Coastguard Worker line = replace_all(tpl->data, repl);
613*2d543d20SAndroid Build Coastguard Worker if (!line) {
614*2d543d20SAndroid Build Coastguard Worker goto fail;
615*2d543d20SAndroid Build Coastguard Worker }
616*2d543d20SAndroid Build Coastguard Worker
617*2d543d20SAndroid Build Coastguard Worker const char *old_context_str = extract_context(line);
618*2d543d20SAndroid Build Coastguard Worker if (!old_context_str) {
619*2d543d20SAndroid Build Coastguard Worker goto fail;
620*2d543d20SAndroid Build Coastguard Worker }
621*2d543d20SAndroid Build Coastguard Worker
622*2d543d20SAndroid Build Coastguard Worker if (strcmp(old_context_str, CONTEXT_NONE) == 0) {
623*2d543d20SAndroid Build Coastguard Worker if (check_line(s, line) == STATUS_SUCCESS &&
624*2d543d20SAndroid Build Coastguard Worker fprintf(out, "%s\n", line) < 0) {
625*2d543d20SAndroid Build Coastguard Worker goto fail;
626*2d543d20SAndroid Build Coastguard Worker }
627*2d543d20SAndroid Build Coastguard Worker free(line);
628*2d543d20SAndroid Build Coastguard Worker continue;
629*2d543d20SAndroid Build Coastguard Worker }
630*2d543d20SAndroid Build Coastguard Worker
631*2d543d20SAndroid Build Coastguard Worker sepol_handle_t *sepolh = s->h_semanage->sepolh;
632*2d543d20SAndroid Build Coastguard Worker
633*2d543d20SAndroid Build Coastguard Worker if (sepol_context_from_string(sepolh, old_context_str,
634*2d543d20SAndroid Build Coastguard Worker &context) < 0) {
635*2d543d20SAndroid Build Coastguard Worker goto fail;
636*2d543d20SAndroid Build Coastguard Worker }
637*2d543d20SAndroid Build Coastguard Worker
638*2d543d20SAndroid Build Coastguard Worker if (sepol_context_set_user(sepolh, context, user->sename) < 0) {
639*2d543d20SAndroid Build Coastguard Worker goto fail;
640*2d543d20SAndroid Build Coastguard Worker }
641*2d543d20SAndroid Build Coastguard Worker
642*2d543d20SAndroid Build Coastguard Worker if (sepol_policydb_mls_enabled(s->policydb) &&
643*2d543d20SAndroid Build Coastguard Worker sepol_context_set_mls(sepolh, context, user->level) < 0) {
644*2d543d20SAndroid Build Coastguard Worker goto fail;
645*2d543d20SAndroid Build Coastguard Worker }
646*2d543d20SAndroid Build Coastguard Worker
647*2d543d20SAndroid Build Coastguard Worker if (user->homedir_role &&
648*2d543d20SAndroid Build Coastguard Worker sepol_context_set_role(sepolh, context, user->homedir_role) < 0) {
649*2d543d20SAndroid Build Coastguard Worker goto fail;
650*2d543d20SAndroid Build Coastguard Worker }
651*2d543d20SAndroid Build Coastguard Worker
652*2d543d20SAndroid Build Coastguard Worker if (sepol_context_to_string(sepolh, context,
653*2d543d20SAndroid Build Coastguard Worker &new_context_str) < 0) {
654*2d543d20SAndroid Build Coastguard Worker goto fail;
655*2d543d20SAndroid Build Coastguard Worker }
656*2d543d20SAndroid Build Coastguard Worker
657*2d543d20SAndroid Build Coastguard Worker temp = semanage_str_replace(old_context_str, new_context_str,
658*2d543d20SAndroid Build Coastguard Worker line, 1);
659*2d543d20SAndroid Build Coastguard Worker if (!temp) {
660*2d543d20SAndroid Build Coastguard Worker goto fail;
661*2d543d20SAndroid Build Coastguard Worker }
662*2d543d20SAndroid Build Coastguard Worker free(line);
663*2d543d20SAndroid Build Coastguard Worker line = temp;
664*2d543d20SAndroid Build Coastguard Worker
665*2d543d20SAndroid Build Coastguard Worker if (check_line(s, line) == STATUS_SUCCESS) {
666*2d543d20SAndroid Build Coastguard Worker if (fprintf(out, "%s\n", line) < 0)
667*2d543d20SAndroid Build Coastguard Worker goto fail;
668*2d543d20SAndroid Build Coastguard Worker }
669*2d543d20SAndroid Build Coastguard Worker
670*2d543d20SAndroid Build Coastguard Worker free(line);
671*2d543d20SAndroid Build Coastguard Worker sepol_context_free(context);
672*2d543d20SAndroid Build Coastguard Worker free(new_context_str);
673*2d543d20SAndroid Build Coastguard Worker }
674*2d543d20SAndroid Build Coastguard Worker
675*2d543d20SAndroid Build Coastguard Worker return STATUS_SUCCESS;
676*2d543d20SAndroid Build Coastguard Worker fail:
677*2d543d20SAndroid Build Coastguard Worker free(line);
678*2d543d20SAndroid Build Coastguard Worker sepol_context_free(context);
679*2d543d20SAndroid Build Coastguard Worker free(new_context_str);
680*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
681*2d543d20SAndroid Build Coastguard Worker }
682*2d543d20SAndroid Build Coastguard Worker
write_home_dir_context(genhomedircon_settings_t * s,FILE * out,semanage_list_t * tpl,const genhomedircon_user_entry_t * user)683*2d543d20SAndroid Build Coastguard Worker static int write_home_dir_context(genhomedircon_settings_t * s, FILE * out,
684*2d543d20SAndroid Build Coastguard Worker semanage_list_t * tpl, const genhomedircon_user_entry_t *user)
685*2d543d20SAndroid Build Coastguard Worker {
686*2d543d20SAndroid Build Coastguard Worker replacement_pair_t repl[] = {
687*2d543d20SAndroid Build Coastguard Worker {.search_for = TEMPLATE_HOME_DIR,.replace_with = user->home},
688*2d543d20SAndroid Build Coastguard Worker {.search_for = TEMPLATE_ROLE,.replace_with = user->prefix},
689*2d543d20SAndroid Build Coastguard Worker {NULL, NULL}
690*2d543d20SAndroid Build Coastguard Worker };
691*2d543d20SAndroid Build Coastguard Worker
692*2d543d20SAndroid Build Coastguard Worker if (strcmp(user->name, FALLBACK_NAME) == 0) {
693*2d543d20SAndroid Build Coastguard Worker if (fprintf(out, COMMENT_USER_HOME_CONTEXT, FALLBACK_SENAME) < 0)
694*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
695*2d543d20SAndroid Build Coastguard Worker } else {
696*2d543d20SAndroid Build Coastguard Worker if (fprintf(out, COMMENT_USER_HOME_CONTEXT, user->name) < 0)
697*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
698*2d543d20SAndroid Build Coastguard Worker }
699*2d543d20SAndroid Build Coastguard Worker
700*2d543d20SAndroid Build Coastguard Worker return write_contexts(s, out, tpl, repl, user);
701*2d543d20SAndroid Build Coastguard Worker }
702*2d543d20SAndroid Build Coastguard Worker
write_home_root_context(genhomedircon_settings_t * s,FILE * out,semanage_list_t * tpl,char * homedir)703*2d543d20SAndroid Build Coastguard Worker static int write_home_root_context(genhomedircon_settings_t * s, FILE * out,
704*2d543d20SAndroid Build Coastguard Worker semanage_list_t * tpl, char *homedir)
705*2d543d20SAndroid Build Coastguard Worker {
706*2d543d20SAndroid Build Coastguard Worker replacement_pair_t repl[] = {
707*2d543d20SAndroid Build Coastguard Worker {.search_for = TEMPLATE_HOME_ROOT,.replace_with = homedir},
708*2d543d20SAndroid Build Coastguard Worker {NULL, NULL}
709*2d543d20SAndroid Build Coastguard Worker };
710*2d543d20SAndroid Build Coastguard Worker
711*2d543d20SAndroid Build Coastguard Worker return write_replacements(s, out, tpl, repl);
712*2d543d20SAndroid Build Coastguard Worker }
713*2d543d20SAndroid Build Coastguard Worker
write_username_context(genhomedircon_settings_t * s,FILE * out,semanage_list_t * tpl,const genhomedircon_user_entry_t * user)714*2d543d20SAndroid Build Coastguard Worker static int write_username_context(genhomedircon_settings_t * s, FILE * out,
715*2d543d20SAndroid Build Coastguard Worker semanage_list_t * tpl,
716*2d543d20SAndroid Build Coastguard Worker const genhomedircon_user_entry_t *user)
717*2d543d20SAndroid Build Coastguard Worker {
718*2d543d20SAndroid Build Coastguard Worker replacement_pair_t repl[] = {
719*2d543d20SAndroid Build Coastguard Worker {.search_for = TEMPLATE_USERNAME,.replace_with = user->name},
720*2d543d20SAndroid Build Coastguard Worker {.search_for = TEMPLATE_USERID,.replace_with = user->uid},
721*2d543d20SAndroid Build Coastguard Worker {.search_for = TEMPLATE_ROLE,.replace_with = user->prefix},
722*2d543d20SAndroid Build Coastguard Worker {NULL, NULL}
723*2d543d20SAndroid Build Coastguard Worker };
724*2d543d20SAndroid Build Coastguard Worker
725*2d543d20SAndroid Build Coastguard Worker return write_contexts(s, out, tpl, repl, user);
726*2d543d20SAndroid Build Coastguard Worker }
727*2d543d20SAndroid Build Coastguard Worker
write_user_context(genhomedircon_settings_t * s,FILE * out,semanage_list_t * tpl,const genhomedircon_user_entry_t * user)728*2d543d20SAndroid Build Coastguard Worker static int write_user_context(genhomedircon_settings_t * s, FILE * out,
729*2d543d20SAndroid Build Coastguard Worker semanage_list_t * tpl, const genhomedircon_user_entry_t *user)
730*2d543d20SAndroid Build Coastguard Worker {
731*2d543d20SAndroid Build Coastguard Worker replacement_pair_t repl[] = {
732*2d543d20SAndroid Build Coastguard Worker {.search_for = TEMPLATE_USER,.replace_with = user->name},
733*2d543d20SAndroid Build Coastguard Worker {.search_for = TEMPLATE_ROLE,.replace_with = user->prefix},
734*2d543d20SAndroid Build Coastguard Worker {NULL, NULL}
735*2d543d20SAndroid Build Coastguard Worker };
736*2d543d20SAndroid Build Coastguard Worker
737*2d543d20SAndroid Build Coastguard Worker return write_contexts(s, out, tpl, repl, user);
738*2d543d20SAndroid Build Coastguard Worker }
739*2d543d20SAndroid Build Coastguard Worker
seuser_sort_func(const void * arg1,const void * arg2)740*2d543d20SAndroid Build Coastguard Worker static int seuser_sort_func(const void *arg1, const void *arg2)
741*2d543d20SAndroid Build Coastguard Worker {
742*2d543d20SAndroid Build Coastguard Worker const semanage_seuser_t **u1 = (const semanage_seuser_t **) arg1;
743*2d543d20SAndroid Build Coastguard Worker const semanage_seuser_t **u2 = (const semanage_seuser_t **) arg2;
744*2d543d20SAndroid Build Coastguard Worker const char *name1 = semanage_seuser_get_name(*u1);
745*2d543d20SAndroid Build Coastguard Worker const char *name2 = semanage_seuser_get_name(*u2);
746*2d543d20SAndroid Build Coastguard Worker
747*2d543d20SAndroid Build Coastguard Worker if (name1[0] == '%' && name2[0] == '%') {
748*2d543d20SAndroid Build Coastguard Worker return 0;
749*2d543d20SAndroid Build Coastguard Worker } else if (name1[0] == '%') {
750*2d543d20SAndroid Build Coastguard Worker return 1;
751*2d543d20SAndroid Build Coastguard Worker } else if (name2[0] == '%') {
752*2d543d20SAndroid Build Coastguard Worker return -1;
753*2d543d20SAndroid Build Coastguard Worker }
754*2d543d20SAndroid Build Coastguard Worker
755*2d543d20SAndroid Build Coastguard Worker return strcmp(name1, name2);
756*2d543d20SAndroid Build Coastguard Worker }
757*2d543d20SAndroid Build Coastguard Worker
user_sort_func(semanage_user_t ** arg1,semanage_user_t ** arg2)758*2d543d20SAndroid Build Coastguard Worker static int user_sort_func(semanage_user_t ** arg1, semanage_user_t ** arg2)
759*2d543d20SAndroid Build Coastguard Worker {
760*2d543d20SAndroid Build Coastguard Worker return strcmp(semanage_user_get_name(*arg1),
761*2d543d20SAndroid Build Coastguard Worker semanage_user_get_name(*arg2));
762*2d543d20SAndroid Build Coastguard Worker }
763*2d543d20SAndroid Build Coastguard Worker
name_user_cmp(char * key,semanage_user_t ** val)764*2d543d20SAndroid Build Coastguard Worker static int name_user_cmp(char *key, semanage_user_t ** val)
765*2d543d20SAndroid Build Coastguard Worker {
766*2d543d20SAndroid Build Coastguard Worker return strcmp(key, semanage_user_get_name(*val));
767*2d543d20SAndroid Build Coastguard Worker }
768*2d543d20SAndroid Build Coastguard Worker
push_user_entry(genhomedircon_user_entry_t ** list,const char * n,const char * u,const char * g,const char * sen,const char * pre,const char * h,const char * l,const char * ln,const char * hd_role)769*2d543d20SAndroid Build Coastguard Worker static int push_user_entry(genhomedircon_user_entry_t ** list, const char *n,
770*2d543d20SAndroid Build Coastguard Worker const char *u, const char *g, const char *sen,
771*2d543d20SAndroid Build Coastguard Worker const char *pre, const char *h, const char *l,
772*2d543d20SAndroid Build Coastguard Worker const char *ln, const char *hd_role)
773*2d543d20SAndroid Build Coastguard Worker {
774*2d543d20SAndroid Build Coastguard Worker genhomedircon_user_entry_t *temp = NULL;
775*2d543d20SAndroid Build Coastguard Worker char *name = NULL;
776*2d543d20SAndroid Build Coastguard Worker char *uid = NULL;
777*2d543d20SAndroid Build Coastguard Worker char *gid = NULL;
778*2d543d20SAndroid Build Coastguard Worker char *sename = NULL;
779*2d543d20SAndroid Build Coastguard Worker char *prefix = NULL;
780*2d543d20SAndroid Build Coastguard Worker char *home = NULL;
781*2d543d20SAndroid Build Coastguard Worker char *level = NULL;
782*2d543d20SAndroid Build Coastguard Worker char *lname = NULL;
783*2d543d20SAndroid Build Coastguard Worker char *homedir_role = NULL;
784*2d543d20SAndroid Build Coastguard Worker
785*2d543d20SAndroid Build Coastguard Worker temp = malloc(sizeof(genhomedircon_user_entry_t));
786*2d543d20SAndroid Build Coastguard Worker if (!temp)
787*2d543d20SAndroid Build Coastguard Worker goto cleanup;
788*2d543d20SAndroid Build Coastguard Worker name = strdup(n);
789*2d543d20SAndroid Build Coastguard Worker if (!name)
790*2d543d20SAndroid Build Coastguard Worker goto cleanup;
791*2d543d20SAndroid Build Coastguard Worker uid = strdup(u);
792*2d543d20SAndroid Build Coastguard Worker if (!uid)
793*2d543d20SAndroid Build Coastguard Worker goto cleanup;
794*2d543d20SAndroid Build Coastguard Worker gid = strdup(g);
795*2d543d20SAndroid Build Coastguard Worker if (!gid)
796*2d543d20SAndroid Build Coastguard Worker goto cleanup;
797*2d543d20SAndroid Build Coastguard Worker sename = strdup(sen);
798*2d543d20SAndroid Build Coastguard Worker if (!sename)
799*2d543d20SAndroid Build Coastguard Worker goto cleanup;
800*2d543d20SAndroid Build Coastguard Worker prefix = strdup(pre);
801*2d543d20SAndroid Build Coastguard Worker if (!prefix)
802*2d543d20SAndroid Build Coastguard Worker goto cleanup;
803*2d543d20SAndroid Build Coastguard Worker home = strdup(h);
804*2d543d20SAndroid Build Coastguard Worker if (!home)
805*2d543d20SAndroid Build Coastguard Worker goto cleanup;
806*2d543d20SAndroid Build Coastguard Worker level = strdup(l);
807*2d543d20SAndroid Build Coastguard Worker if (!level)
808*2d543d20SAndroid Build Coastguard Worker goto cleanup;
809*2d543d20SAndroid Build Coastguard Worker lname = strdup(ln);
810*2d543d20SAndroid Build Coastguard Worker if (!lname)
811*2d543d20SAndroid Build Coastguard Worker goto cleanup;
812*2d543d20SAndroid Build Coastguard Worker if (hd_role) {
813*2d543d20SAndroid Build Coastguard Worker homedir_role = strdup(hd_role);
814*2d543d20SAndroid Build Coastguard Worker if (!homedir_role)
815*2d543d20SAndroid Build Coastguard Worker goto cleanup;
816*2d543d20SAndroid Build Coastguard Worker }
817*2d543d20SAndroid Build Coastguard Worker
818*2d543d20SAndroid Build Coastguard Worker temp->name = name;
819*2d543d20SAndroid Build Coastguard Worker temp->uid = uid;
820*2d543d20SAndroid Build Coastguard Worker temp->gid = gid;
821*2d543d20SAndroid Build Coastguard Worker temp->sename = sename;
822*2d543d20SAndroid Build Coastguard Worker temp->prefix = prefix;
823*2d543d20SAndroid Build Coastguard Worker temp->home = home;
824*2d543d20SAndroid Build Coastguard Worker temp->level = level;
825*2d543d20SAndroid Build Coastguard Worker temp->login = lname;
826*2d543d20SAndroid Build Coastguard Worker temp->homedir_role = homedir_role;
827*2d543d20SAndroid Build Coastguard Worker temp->next = (*list);
828*2d543d20SAndroid Build Coastguard Worker (*list) = temp;
829*2d543d20SAndroid Build Coastguard Worker
830*2d543d20SAndroid Build Coastguard Worker return STATUS_SUCCESS;
831*2d543d20SAndroid Build Coastguard Worker
832*2d543d20SAndroid Build Coastguard Worker cleanup:
833*2d543d20SAndroid Build Coastguard Worker free(name);
834*2d543d20SAndroid Build Coastguard Worker free(uid);
835*2d543d20SAndroid Build Coastguard Worker free(gid);
836*2d543d20SAndroid Build Coastguard Worker free(sename);
837*2d543d20SAndroid Build Coastguard Worker free(prefix);
838*2d543d20SAndroid Build Coastguard Worker free(home);
839*2d543d20SAndroid Build Coastguard Worker free(level);
840*2d543d20SAndroid Build Coastguard Worker free(lname);
841*2d543d20SAndroid Build Coastguard Worker free(homedir_role);
842*2d543d20SAndroid Build Coastguard Worker free(temp);
843*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
844*2d543d20SAndroid Build Coastguard Worker }
845*2d543d20SAndroid Build Coastguard Worker
pop_user_entry(genhomedircon_user_entry_t ** list)846*2d543d20SAndroid Build Coastguard Worker static void pop_user_entry(genhomedircon_user_entry_t ** list)
847*2d543d20SAndroid Build Coastguard Worker {
848*2d543d20SAndroid Build Coastguard Worker genhomedircon_user_entry_t *temp;
849*2d543d20SAndroid Build Coastguard Worker
850*2d543d20SAndroid Build Coastguard Worker if (!list || !(*list))
851*2d543d20SAndroid Build Coastguard Worker return;
852*2d543d20SAndroid Build Coastguard Worker
853*2d543d20SAndroid Build Coastguard Worker temp = *list;
854*2d543d20SAndroid Build Coastguard Worker *list = temp->next;
855*2d543d20SAndroid Build Coastguard Worker free(temp->name);
856*2d543d20SAndroid Build Coastguard Worker free(temp->uid);
857*2d543d20SAndroid Build Coastguard Worker free(temp->gid);
858*2d543d20SAndroid Build Coastguard Worker free(temp->sename);
859*2d543d20SAndroid Build Coastguard Worker free(temp->prefix);
860*2d543d20SAndroid Build Coastguard Worker free(temp->home);
861*2d543d20SAndroid Build Coastguard Worker free(temp->level);
862*2d543d20SAndroid Build Coastguard Worker free(temp->login);
863*2d543d20SAndroid Build Coastguard Worker free(temp->homedir_role);
864*2d543d20SAndroid Build Coastguard Worker free(temp);
865*2d543d20SAndroid Build Coastguard Worker }
866*2d543d20SAndroid Build Coastguard Worker
setup_fallback_user(genhomedircon_settings_t * s)867*2d543d20SAndroid Build Coastguard Worker static int setup_fallback_user(genhomedircon_settings_t * s)
868*2d543d20SAndroid Build Coastguard Worker {
869*2d543d20SAndroid Build Coastguard Worker semanage_seuser_t **seuser_list = NULL;
870*2d543d20SAndroid Build Coastguard Worker unsigned int nseusers = 0;
871*2d543d20SAndroid Build Coastguard Worker semanage_user_key_t *key = NULL;
872*2d543d20SAndroid Build Coastguard Worker semanage_user_t *u = NULL;
873*2d543d20SAndroid Build Coastguard Worker const char *name = NULL;
874*2d543d20SAndroid Build Coastguard Worker const char *seuname = NULL;
875*2d543d20SAndroid Build Coastguard Worker const char *prefix = NULL;
876*2d543d20SAndroid Build Coastguard Worker const char *level = NULL;
877*2d543d20SAndroid Build Coastguard Worker const char *homedir_role = NULL;
878*2d543d20SAndroid Build Coastguard Worker unsigned int i;
879*2d543d20SAndroid Build Coastguard Worker int retval;
880*2d543d20SAndroid Build Coastguard Worker int errors = 0;
881*2d543d20SAndroid Build Coastguard Worker
882*2d543d20SAndroid Build Coastguard Worker retval = semanage_seuser_list(s->h_semanage, &seuser_list, &nseusers);
883*2d543d20SAndroid Build Coastguard Worker if (retval < 0 || (nseusers < 1)) {
884*2d543d20SAndroid Build Coastguard Worker /* if there are no users, this function can't do any other work */
885*2d543d20SAndroid Build Coastguard Worker return errors;
886*2d543d20SAndroid Build Coastguard Worker }
887*2d543d20SAndroid Build Coastguard Worker
888*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < nseusers; i++) {
889*2d543d20SAndroid Build Coastguard Worker name = semanage_seuser_get_name(seuser_list[i]);
890*2d543d20SAndroid Build Coastguard Worker if (strcmp(name, DEFAULT_LOGIN) == 0) {
891*2d543d20SAndroid Build Coastguard Worker seuname = semanage_seuser_get_sename(seuser_list[i]);
892*2d543d20SAndroid Build Coastguard Worker
893*2d543d20SAndroid Build Coastguard Worker /* find the user structure given the name */
894*2d543d20SAndroid Build Coastguard Worker if (semanage_user_key_create(s->h_semanage, seuname,
895*2d543d20SAndroid Build Coastguard Worker &key) < 0) {
896*2d543d20SAndroid Build Coastguard Worker errors = STATUS_ERR;
897*2d543d20SAndroid Build Coastguard Worker break;
898*2d543d20SAndroid Build Coastguard Worker }
899*2d543d20SAndroid Build Coastguard Worker if (semanage_user_query(s->h_semanage, key, &u) < 0)
900*2d543d20SAndroid Build Coastguard Worker {
901*2d543d20SAndroid Build Coastguard Worker prefix = name;
902*2d543d20SAndroid Build Coastguard Worker level = FALLBACK_LEVEL;
903*2d543d20SAndroid Build Coastguard Worker }
904*2d543d20SAndroid Build Coastguard Worker else
905*2d543d20SAndroid Build Coastguard Worker {
906*2d543d20SAndroid Build Coastguard Worker prefix = semanage_user_get_prefix(u);
907*2d543d20SAndroid Build Coastguard Worker level = semanage_user_get_mlslevel(u);
908*2d543d20SAndroid Build Coastguard Worker if (!level)
909*2d543d20SAndroid Build Coastguard Worker level = FALLBACK_LEVEL;
910*2d543d20SAndroid Build Coastguard Worker }
911*2d543d20SAndroid Build Coastguard Worker
912*2d543d20SAndroid Build Coastguard Worker if (prefix_is_homedir_role(u, prefix)) {
913*2d543d20SAndroid Build Coastguard Worker homedir_role = prefix;
914*2d543d20SAndroid Build Coastguard Worker }
915*2d543d20SAndroid Build Coastguard Worker
916*2d543d20SAndroid Build Coastguard Worker if (push_user_entry(&(s->fallback), FALLBACK_NAME,
917*2d543d20SAndroid Build Coastguard Worker FALLBACK_UIDGID, FALLBACK_UIDGID,
918*2d543d20SAndroid Build Coastguard Worker seuname, prefix, "", level,
919*2d543d20SAndroid Build Coastguard Worker FALLBACK_NAME, homedir_role) != 0)
920*2d543d20SAndroid Build Coastguard Worker errors = STATUS_ERR;
921*2d543d20SAndroid Build Coastguard Worker semanage_user_key_free(key);
922*2d543d20SAndroid Build Coastguard Worker if (u)
923*2d543d20SAndroid Build Coastguard Worker semanage_user_free(u);
924*2d543d20SAndroid Build Coastguard Worker break;
925*2d543d20SAndroid Build Coastguard Worker }
926*2d543d20SAndroid Build Coastguard Worker }
927*2d543d20SAndroid Build Coastguard Worker
928*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < nseusers; i++)
929*2d543d20SAndroid Build Coastguard Worker semanage_seuser_free(seuser_list[i]);
930*2d543d20SAndroid Build Coastguard Worker free(seuser_list);
931*2d543d20SAndroid Build Coastguard Worker
932*2d543d20SAndroid Build Coastguard Worker return errors;
933*2d543d20SAndroid Build Coastguard Worker }
934*2d543d20SAndroid Build Coastguard Worker
find_user(genhomedircon_user_entry_t * head,const char * name)935*2d543d20SAndroid Build Coastguard Worker static genhomedircon_user_entry_t *find_user(genhomedircon_user_entry_t *head,
936*2d543d20SAndroid Build Coastguard Worker const char *name)
937*2d543d20SAndroid Build Coastguard Worker {
938*2d543d20SAndroid Build Coastguard Worker for(; head; head = head->next) {
939*2d543d20SAndroid Build Coastguard Worker if (strcmp(head->name, name) == 0) {
940*2d543d20SAndroid Build Coastguard Worker return head;
941*2d543d20SAndroid Build Coastguard Worker }
942*2d543d20SAndroid Build Coastguard Worker }
943*2d543d20SAndroid Build Coastguard Worker
944*2d543d20SAndroid Build Coastguard Worker return NULL;
945*2d543d20SAndroid Build Coastguard Worker }
946*2d543d20SAndroid Build Coastguard Worker
add_user(genhomedircon_settings_t * s,genhomedircon_user_entry_t ** head,semanage_user_t * user,const char * name,const char * sename,const char * selogin)947*2d543d20SAndroid Build Coastguard Worker static int add_user(genhomedircon_settings_t * s,
948*2d543d20SAndroid Build Coastguard Worker genhomedircon_user_entry_t **head,
949*2d543d20SAndroid Build Coastguard Worker semanage_user_t *user,
950*2d543d20SAndroid Build Coastguard Worker const char *name,
951*2d543d20SAndroid Build Coastguard Worker const char *sename,
952*2d543d20SAndroid Build Coastguard Worker const char *selogin)
953*2d543d20SAndroid Build Coastguard Worker {
954*2d543d20SAndroid Build Coastguard Worker if (selogin[0] == '%') {
955*2d543d20SAndroid Build Coastguard Worker genhomedircon_user_entry_t *orig = find_user(*head, name);
956*2d543d20SAndroid Build Coastguard Worker if (orig != NULL && orig->login[0] == '%') {
957*2d543d20SAndroid Build Coastguard Worker ERR(s->h_semanage, "User %s is already mapped to"
958*2d543d20SAndroid Build Coastguard Worker " group %s, but also belongs to group %s. Add an"
959*2d543d20SAndroid Build Coastguard Worker " explicit mapping for this user to"
960*2d543d20SAndroid Build Coastguard Worker " override group mappings.",
961*2d543d20SAndroid Build Coastguard Worker name, orig->login + 1, selogin + 1);
962*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
963*2d543d20SAndroid Build Coastguard Worker } else if (orig != NULL) {
964*2d543d20SAndroid Build Coastguard Worker // user mappings take precedence
965*2d543d20SAndroid Build Coastguard Worker return STATUS_SUCCESS;
966*2d543d20SAndroid Build Coastguard Worker }
967*2d543d20SAndroid Build Coastguard Worker }
968*2d543d20SAndroid Build Coastguard Worker
969*2d543d20SAndroid Build Coastguard Worker int retval = STATUS_ERR;
970*2d543d20SAndroid Build Coastguard Worker
971*2d543d20SAndroid Build Coastguard Worker char *rbuf = NULL;
972*2d543d20SAndroid Build Coastguard Worker long rbuflen;
973*2d543d20SAndroid Build Coastguard Worker struct passwd pwstorage, *pwent = NULL;
974*2d543d20SAndroid Build Coastguard Worker const char *prefix = NULL;
975*2d543d20SAndroid Build Coastguard Worker const char *level = NULL;
976*2d543d20SAndroid Build Coastguard Worker const char *homedir_role = NULL;
977*2d543d20SAndroid Build Coastguard Worker char uid[11];
978*2d543d20SAndroid Build Coastguard Worker char gid[11];
979*2d543d20SAndroid Build Coastguard Worker
980*2d543d20SAndroid Build Coastguard Worker errno = 0;
981*2d543d20SAndroid Build Coastguard Worker /* Allocate space for the getpwnam_r buffer */
982*2d543d20SAndroid Build Coastguard Worker rbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
983*2d543d20SAndroid Build Coastguard Worker if (rbuflen == -1 && errno == 0)
984*2d543d20SAndroid Build Coastguard Worker /* sysconf returning -1 with no errno means indeterminate size */
985*2d543d20SAndroid Build Coastguard Worker rbuflen = 1024;
986*2d543d20SAndroid Build Coastguard Worker else if (rbuflen <= 0)
987*2d543d20SAndroid Build Coastguard Worker goto cleanup;
988*2d543d20SAndroid Build Coastguard Worker
989*2d543d20SAndroid Build Coastguard Worker if (user) {
990*2d543d20SAndroid Build Coastguard Worker prefix = semanage_user_get_prefix(user);
991*2d543d20SAndroid Build Coastguard Worker level = semanage_user_get_mlslevel(user);
992*2d543d20SAndroid Build Coastguard Worker
993*2d543d20SAndroid Build Coastguard Worker if (!level) {
994*2d543d20SAndroid Build Coastguard Worker level = FALLBACK_LEVEL;
995*2d543d20SAndroid Build Coastguard Worker }
996*2d543d20SAndroid Build Coastguard Worker } else {
997*2d543d20SAndroid Build Coastguard Worker prefix = name;
998*2d543d20SAndroid Build Coastguard Worker level = FALLBACK_LEVEL;
999*2d543d20SAndroid Build Coastguard Worker }
1000*2d543d20SAndroid Build Coastguard Worker
1001*2d543d20SAndroid Build Coastguard Worker if (prefix_is_homedir_role(user, prefix)) {
1002*2d543d20SAndroid Build Coastguard Worker homedir_role = prefix;
1003*2d543d20SAndroid Build Coastguard Worker }
1004*2d543d20SAndroid Build Coastguard Worker
1005*2d543d20SAndroid Build Coastguard Worker retry:
1006*2d543d20SAndroid Build Coastguard Worker rbuf = malloc(rbuflen);
1007*2d543d20SAndroid Build Coastguard Worker if (rbuf == NULL)
1008*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1009*2d543d20SAndroid Build Coastguard Worker
1010*2d543d20SAndroid Build Coastguard Worker retval = getpwnam_r(name, &pwstorage, rbuf, rbuflen, &pwent);
1011*2d543d20SAndroid Build Coastguard Worker if (retval == ERANGE && rbuflen < LONG_MAX / 2) {
1012*2d543d20SAndroid Build Coastguard Worker free(rbuf);
1013*2d543d20SAndroid Build Coastguard Worker rbuflen *= 2;
1014*2d543d20SAndroid Build Coastguard Worker goto retry;
1015*2d543d20SAndroid Build Coastguard Worker }
1016*2d543d20SAndroid Build Coastguard Worker if (retval != 0 || pwent == NULL) {
1017*2d543d20SAndroid Build Coastguard Worker if (retval != 0 && retval != ENOENT) {
1018*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1019*2d543d20SAndroid Build Coastguard Worker }
1020*2d543d20SAndroid Build Coastguard Worker
1021*2d543d20SAndroid Build Coastguard Worker WARN(s->h_semanage,
1022*2d543d20SAndroid Build Coastguard Worker "user %s not in password file", name);
1023*2d543d20SAndroid Build Coastguard Worker retval = STATUS_SUCCESS;
1024*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1025*2d543d20SAndroid Build Coastguard Worker }
1026*2d543d20SAndroid Build Coastguard Worker
1027*2d543d20SAndroid Build Coastguard Worker int len = strlen(pwent->pw_dir) -1;
1028*2d543d20SAndroid Build Coastguard Worker for(; len > 0 && pwent->pw_dir[len] == '/'; len--) {
1029*2d543d20SAndroid Build Coastguard Worker pwent->pw_dir[len] = '\0';
1030*2d543d20SAndroid Build Coastguard Worker }
1031*2d543d20SAndroid Build Coastguard Worker
1032*2d543d20SAndroid Build Coastguard Worker if (strcmp(pwent->pw_dir, "/") == 0) {
1033*2d543d20SAndroid Build Coastguard Worker /* don't relabel / genhomdircon checked to see if root
1034*2d543d20SAndroid Build Coastguard Worker * was the user and if so, set his home directory to
1035*2d543d20SAndroid Build Coastguard Worker * /root */
1036*2d543d20SAndroid Build Coastguard Worker retval = STATUS_SUCCESS;
1037*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1038*2d543d20SAndroid Build Coastguard Worker }
1039*2d543d20SAndroid Build Coastguard Worker
1040*2d543d20SAndroid Build Coastguard Worker if (ignore(pwent->pw_dir)) {
1041*2d543d20SAndroid Build Coastguard Worker retval = STATUS_SUCCESS;
1042*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1043*2d543d20SAndroid Build Coastguard Worker }
1044*2d543d20SAndroid Build Coastguard Worker
1045*2d543d20SAndroid Build Coastguard Worker len = snprintf(uid, sizeof(uid), "%u", pwent->pw_uid);
1046*2d543d20SAndroid Build Coastguard Worker if (len < 0 || len >= (int)sizeof(uid)) {
1047*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1048*2d543d20SAndroid Build Coastguard Worker }
1049*2d543d20SAndroid Build Coastguard Worker
1050*2d543d20SAndroid Build Coastguard Worker len = snprintf(gid, sizeof(gid), "%u", pwent->pw_gid);
1051*2d543d20SAndroid Build Coastguard Worker if (len < 0 || len >= (int)sizeof(gid)) {
1052*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1053*2d543d20SAndroid Build Coastguard Worker }
1054*2d543d20SAndroid Build Coastguard Worker
1055*2d543d20SAndroid Build Coastguard Worker retval = push_user_entry(head, name, uid, gid, sename, prefix,
1056*2d543d20SAndroid Build Coastguard Worker pwent->pw_dir, level, selogin, homedir_role);
1057*2d543d20SAndroid Build Coastguard Worker cleanup:
1058*2d543d20SAndroid Build Coastguard Worker free(rbuf);
1059*2d543d20SAndroid Build Coastguard Worker return retval;
1060*2d543d20SAndroid Build Coastguard Worker }
1061*2d543d20SAndroid Build Coastguard Worker
get_group_users(genhomedircon_settings_t * s,genhomedircon_user_entry_t ** head,semanage_user_t * user,const char * sename,const char * selogin)1062*2d543d20SAndroid Build Coastguard Worker static int get_group_users(genhomedircon_settings_t * s,
1063*2d543d20SAndroid Build Coastguard Worker genhomedircon_user_entry_t **head,
1064*2d543d20SAndroid Build Coastguard Worker semanage_user_t *user,
1065*2d543d20SAndroid Build Coastguard Worker const char *sename,
1066*2d543d20SAndroid Build Coastguard Worker const char *selogin)
1067*2d543d20SAndroid Build Coastguard Worker {
1068*2d543d20SAndroid Build Coastguard Worker int retval = STATUS_ERR;
1069*2d543d20SAndroid Build Coastguard Worker unsigned int i;
1070*2d543d20SAndroid Build Coastguard Worker
1071*2d543d20SAndroid Build Coastguard Worker long grbuflen;
1072*2d543d20SAndroid Build Coastguard Worker char *grbuf = NULL;
1073*2d543d20SAndroid Build Coastguard Worker struct group grstorage, *group = NULL;
1074*2d543d20SAndroid Build Coastguard Worker struct passwd *pw = NULL;
1075*2d543d20SAndroid Build Coastguard Worker
1076*2d543d20SAndroid Build Coastguard Worker errno = 0;
1077*2d543d20SAndroid Build Coastguard Worker grbuflen = sysconf(_SC_GETGR_R_SIZE_MAX);
1078*2d543d20SAndroid Build Coastguard Worker if (grbuflen == -1 && errno == 0)
1079*2d543d20SAndroid Build Coastguard Worker /* sysconf returning -1 with no errno means indeterminate size */
1080*2d543d20SAndroid Build Coastguard Worker grbuflen = 1024;
1081*2d543d20SAndroid Build Coastguard Worker else if (grbuflen <= 0)
1082*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1083*2d543d20SAndroid Build Coastguard Worker grbuf = malloc(grbuflen);
1084*2d543d20SAndroid Build Coastguard Worker if (grbuf == NULL)
1085*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1086*2d543d20SAndroid Build Coastguard Worker
1087*2d543d20SAndroid Build Coastguard Worker const char *grname = selogin + 1;
1088*2d543d20SAndroid Build Coastguard Worker
1089*2d543d20SAndroid Build Coastguard Worker errno = 0;
1090*2d543d20SAndroid Build Coastguard Worker while (
1091*2d543d20SAndroid Build Coastguard Worker (retval = getgrnam_r(grname, &grstorage, grbuf, (size_t) grbuflen, &group)) != 0 &&
1092*2d543d20SAndroid Build Coastguard Worker errno == ERANGE
1093*2d543d20SAndroid Build Coastguard Worker ) {
1094*2d543d20SAndroid Build Coastguard Worker char *new_grbuf;
1095*2d543d20SAndroid Build Coastguard Worker grbuflen *= 2;
1096*2d543d20SAndroid Build Coastguard Worker if (grbuflen < 0)
1097*2d543d20SAndroid Build Coastguard Worker /* the member list could exceed 2Gb on a system with a 32-bit CPU (where
1098*2d543d20SAndroid Build Coastguard Worker * sizeof(long) = 4) - if this ever happened, the loop would become infinite. */
1099*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1100*2d543d20SAndroid Build Coastguard Worker new_grbuf = realloc(grbuf, grbuflen);
1101*2d543d20SAndroid Build Coastguard Worker if (new_grbuf == NULL)
1102*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1103*2d543d20SAndroid Build Coastguard Worker grbuf = new_grbuf;
1104*2d543d20SAndroid Build Coastguard Worker }
1105*2d543d20SAndroid Build Coastguard Worker if (retval != 0)
1106*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1107*2d543d20SAndroid Build Coastguard Worker
1108*2d543d20SAndroid Build Coastguard Worker if (group == NULL) {
1109*2d543d20SAndroid Build Coastguard Worker ERR(s->h_semanage, "Can't find group named %s\n", grname);
1110*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1111*2d543d20SAndroid Build Coastguard Worker }
1112*2d543d20SAndroid Build Coastguard Worker
1113*2d543d20SAndroid Build Coastguard Worker size_t nmembers = 0;
1114*2d543d20SAndroid Build Coastguard Worker char **members = group->gr_mem;
1115*2d543d20SAndroid Build Coastguard Worker
1116*2d543d20SAndroid Build Coastguard Worker while (*members != NULL) {
1117*2d543d20SAndroid Build Coastguard Worker nmembers++;
1118*2d543d20SAndroid Build Coastguard Worker members++;
1119*2d543d20SAndroid Build Coastguard Worker }
1120*2d543d20SAndroid Build Coastguard Worker
1121*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < nmembers; i++) {
1122*2d543d20SAndroid Build Coastguard Worker const char *uname = group->gr_mem[i];
1123*2d543d20SAndroid Build Coastguard Worker
1124*2d543d20SAndroid Build Coastguard Worker if (add_user(s, head, user, uname, sename, selogin) < 0) {
1125*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1126*2d543d20SAndroid Build Coastguard Worker }
1127*2d543d20SAndroid Build Coastguard Worker }
1128*2d543d20SAndroid Build Coastguard Worker
1129*2d543d20SAndroid Build Coastguard Worker setpwent();
1130*2d543d20SAndroid Build Coastguard Worker while (1) {
1131*2d543d20SAndroid Build Coastguard Worker errno = 0;
1132*2d543d20SAndroid Build Coastguard Worker pw = getpwent();
1133*2d543d20SAndroid Build Coastguard Worker if (pw == NULL)
1134*2d543d20SAndroid Build Coastguard Worker break;
1135*2d543d20SAndroid Build Coastguard Worker // skip users who also have this group as their
1136*2d543d20SAndroid Build Coastguard Worker // primary group
1137*2d543d20SAndroid Build Coastguard Worker if (lfind(pw->pw_name, group->gr_mem, &nmembers,
1138*2d543d20SAndroid Build Coastguard Worker sizeof(char *), &STR_COMPARATOR)) {
1139*2d543d20SAndroid Build Coastguard Worker continue;
1140*2d543d20SAndroid Build Coastguard Worker }
1141*2d543d20SAndroid Build Coastguard Worker
1142*2d543d20SAndroid Build Coastguard Worker if (group->gr_gid == pw->pw_gid) {
1143*2d543d20SAndroid Build Coastguard Worker if (add_user(s, head, user, pw->pw_name,
1144*2d543d20SAndroid Build Coastguard Worker sename, selogin) < 0) {
1145*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1146*2d543d20SAndroid Build Coastguard Worker }
1147*2d543d20SAndroid Build Coastguard Worker }
1148*2d543d20SAndroid Build Coastguard Worker }
1149*2d543d20SAndroid Build Coastguard Worker
1150*2d543d20SAndroid Build Coastguard Worker retval = STATUS_SUCCESS;
1151*2d543d20SAndroid Build Coastguard Worker cleanup:
1152*2d543d20SAndroid Build Coastguard Worker endpwent();
1153*2d543d20SAndroid Build Coastguard Worker free(grbuf);
1154*2d543d20SAndroid Build Coastguard Worker
1155*2d543d20SAndroid Build Coastguard Worker return retval;
1156*2d543d20SAndroid Build Coastguard Worker }
1157*2d543d20SAndroid Build Coastguard Worker
get_users(genhomedircon_settings_t * s,int * errors)1158*2d543d20SAndroid Build Coastguard Worker static genhomedircon_user_entry_t *get_users(genhomedircon_settings_t * s,
1159*2d543d20SAndroid Build Coastguard Worker int *errors)
1160*2d543d20SAndroid Build Coastguard Worker {
1161*2d543d20SAndroid Build Coastguard Worker genhomedircon_user_entry_t *head = NULL;
1162*2d543d20SAndroid Build Coastguard Worker semanage_seuser_t **seuser_list = NULL;
1163*2d543d20SAndroid Build Coastguard Worker unsigned int nseusers = 0;
1164*2d543d20SAndroid Build Coastguard Worker semanage_user_t **user_list = NULL;
1165*2d543d20SAndroid Build Coastguard Worker unsigned int nusers = 0;
1166*2d543d20SAndroid Build Coastguard Worker semanage_user_t **u = NULL;
1167*2d543d20SAndroid Build Coastguard Worker const char *name = NULL;
1168*2d543d20SAndroid Build Coastguard Worker const char *seuname = NULL;
1169*2d543d20SAndroid Build Coastguard Worker unsigned int i;
1170*2d543d20SAndroid Build Coastguard Worker int retval;
1171*2d543d20SAndroid Build Coastguard Worker
1172*2d543d20SAndroid Build Coastguard Worker *errors = 0;
1173*2d543d20SAndroid Build Coastguard Worker retval = semanage_seuser_list(s->h_semanage, &seuser_list, &nseusers);
1174*2d543d20SAndroid Build Coastguard Worker if (retval < 0 || (nseusers < 1)) {
1175*2d543d20SAndroid Build Coastguard Worker /* if there are no users, this function can't do any other work */
1176*2d543d20SAndroid Build Coastguard Worker return NULL;
1177*2d543d20SAndroid Build Coastguard Worker }
1178*2d543d20SAndroid Build Coastguard Worker
1179*2d543d20SAndroid Build Coastguard Worker if (semanage_user_list(s->h_semanage, &user_list, &nusers) < 0) {
1180*2d543d20SAndroid Build Coastguard Worker nusers = 0;
1181*2d543d20SAndroid Build Coastguard Worker }
1182*2d543d20SAndroid Build Coastguard Worker
1183*2d543d20SAndroid Build Coastguard Worker qsort(seuser_list, nseusers, sizeof(semanage_seuser_t *),
1184*2d543d20SAndroid Build Coastguard Worker &seuser_sort_func);
1185*2d543d20SAndroid Build Coastguard Worker qsort(user_list, nusers, sizeof(semanage_user_t *),
1186*2d543d20SAndroid Build Coastguard Worker (int (*)(const void *, const void *))&user_sort_func);
1187*2d543d20SAndroid Build Coastguard Worker
1188*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < nseusers; i++) {
1189*2d543d20SAndroid Build Coastguard Worker seuname = semanage_seuser_get_sename(seuser_list[i]);
1190*2d543d20SAndroid Build Coastguard Worker name = semanage_seuser_get_name(seuser_list[i]);
1191*2d543d20SAndroid Build Coastguard Worker
1192*2d543d20SAndroid Build Coastguard Worker if (strcmp(name, DEFAULT_LOGIN) == 0)
1193*2d543d20SAndroid Build Coastguard Worker continue;
1194*2d543d20SAndroid Build Coastguard Worker
1195*2d543d20SAndroid Build Coastguard Worker /* find the user structure given the name */
1196*2d543d20SAndroid Build Coastguard Worker u = bsearch(seuname, user_list, nusers, sizeof(semanage_user_t *),
1197*2d543d20SAndroid Build Coastguard Worker (int (*)(const void *, const void *))
1198*2d543d20SAndroid Build Coastguard Worker &name_user_cmp);
1199*2d543d20SAndroid Build Coastguard Worker
1200*2d543d20SAndroid Build Coastguard Worker /* %groupname syntax */
1201*2d543d20SAndroid Build Coastguard Worker if (name[0] == '%') {
1202*2d543d20SAndroid Build Coastguard Worker retval = get_group_users(s, &head, *u, seuname,
1203*2d543d20SAndroid Build Coastguard Worker name);
1204*2d543d20SAndroid Build Coastguard Worker } else {
1205*2d543d20SAndroid Build Coastguard Worker retval = add_user(s, &head, *u, name,
1206*2d543d20SAndroid Build Coastguard Worker seuname, name);
1207*2d543d20SAndroid Build Coastguard Worker }
1208*2d543d20SAndroid Build Coastguard Worker
1209*2d543d20SAndroid Build Coastguard Worker if (retval != 0) {
1210*2d543d20SAndroid Build Coastguard Worker *errors = STATUS_ERR;
1211*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1212*2d543d20SAndroid Build Coastguard Worker }
1213*2d543d20SAndroid Build Coastguard Worker }
1214*2d543d20SAndroid Build Coastguard Worker
1215*2d543d20SAndroid Build Coastguard Worker cleanup:
1216*2d543d20SAndroid Build Coastguard Worker if (*errors) {
1217*2d543d20SAndroid Build Coastguard Worker for (; head; pop_user_entry(&head)) {
1218*2d543d20SAndroid Build Coastguard Worker /* the pop function takes care of all the cleanup
1219*2d543d20SAndroid Build Coastguard Worker so the loop body is just empty */
1220*2d543d20SAndroid Build Coastguard Worker }
1221*2d543d20SAndroid Build Coastguard Worker }
1222*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < nseusers; i++) {
1223*2d543d20SAndroid Build Coastguard Worker semanage_seuser_free(seuser_list[i]);
1224*2d543d20SAndroid Build Coastguard Worker }
1225*2d543d20SAndroid Build Coastguard Worker free(seuser_list);
1226*2d543d20SAndroid Build Coastguard Worker
1227*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < nusers; i++) {
1228*2d543d20SAndroid Build Coastguard Worker semanage_user_free(user_list[i]);
1229*2d543d20SAndroid Build Coastguard Worker }
1230*2d543d20SAndroid Build Coastguard Worker free(user_list);
1231*2d543d20SAndroid Build Coastguard Worker
1232*2d543d20SAndroid Build Coastguard Worker return head;
1233*2d543d20SAndroid Build Coastguard Worker }
1234*2d543d20SAndroid Build Coastguard Worker
write_gen_home_dir_context(genhomedircon_settings_t * s,FILE * out,semanage_list_t * username_context_tpl,semanage_list_t * user_context_tpl,semanage_list_t * homedir_context_tpl)1235*2d543d20SAndroid Build Coastguard Worker static int write_gen_home_dir_context(genhomedircon_settings_t * s, FILE * out,
1236*2d543d20SAndroid Build Coastguard Worker semanage_list_t * username_context_tpl,
1237*2d543d20SAndroid Build Coastguard Worker semanage_list_t * user_context_tpl,
1238*2d543d20SAndroid Build Coastguard Worker semanage_list_t * homedir_context_tpl)
1239*2d543d20SAndroid Build Coastguard Worker {
1240*2d543d20SAndroid Build Coastguard Worker genhomedircon_user_entry_t *users;
1241*2d543d20SAndroid Build Coastguard Worker int errors = 0;
1242*2d543d20SAndroid Build Coastguard Worker
1243*2d543d20SAndroid Build Coastguard Worker users = get_users(s, &errors);
1244*2d543d20SAndroid Build Coastguard Worker if (!users && errors) {
1245*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
1246*2d543d20SAndroid Build Coastguard Worker }
1247*2d543d20SAndroid Build Coastguard Worker
1248*2d543d20SAndroid Build Coastguard Worker for (; users; pop_user_entry(&users)) {
1249*2d543d20SAndroid Build Coastguard Worker if (write_home_dir_context(s, out, homedir_context_tpl, users))
1250*2d543d20SAndroid Build Coastguard Worker goto err;
1251*2d543d20SAndroid Build Coastguard Worker if (write_username_context(s, out, username_context_tpl, users))
1252*2d543d20SAndroid Build Coastguard Worker goto err;
1253*2d543d20SAndroid Build Coastguard Worker if (write_user_context(s, out, user_context_tpl, users))
1254*2d543d20SAndroid Build Coastguard Worker goto err;
1255*2d543d20SAndroid Build Coastguard Worker }
1256*2d543d20SAndroid Build Coastguard Worker
1257*2d543d20SAndroid Build Coastguard Worker return STATUS_SUCCESS;
1258*2d543d20SAndroid Build Coastguard Worker err:
1259*2d543d20SAndroid Build Coastguard Worker for (; users; pop_user_entry(&users)) {
1260*2d543d20SAndroid Build Coastguard Worker /* the pop function takes care of all the cleanup
1261*2d543d20SAndroid Build Coastguard Worker * so the loop body is just empty */
1262*2d543d20SAndroid Build Coastguard Worker }
1263*2d543d20SAndroid Build Coastguard Worker
1264*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
1265*2d543d20SAndroid Build Coastguard Worker }
1266*2d543d20SAndroid Build Coastguard Worker
1267*2d543d20SAndroid Build Coastguard Worker /**
1268*2d543d20SAndroid Build Coastguard Worker * @param s settings structure, stores various paths etc. Must never be NULL
1269*2d543d20SAndroid Build Coastguard Worker * @param out the FILE to put all the output in.
1270*2d543d20SAndroid Build Coastguard Worker * @return 0 on success
1271*2d543d20SAndroid Build Coastguard Worker */
write_context_file(genhomedircon_settings_t * s,FILE * out)1272*2d543d20SAndroid Build Coastguard Worker static int write_context_file(genhomedircon_settings_t * s, FILE * out)
1273*2d543d20SAndroid Build Coastguard Worker {
1274*2d543d20SAndroid Build Coastguard Worker semanage_list_t *homedirs = NULL;
1275*2d543d20SAndroid Build Coastguard Worker semanage_list_t *h = NULL;
1276*2d543d20SAndroid Build Coastguard Worker semanage_list_t *homedir_context_tpl = NULL;
1277*2d543d20SAndroid Build Coastguard Worker semanage_list_t *homeroot_context_tpl = NULL;
1278*2d543d20SAndroid Build Coastguard Worker semanage_list_t *username_context_tpl = NULL;
1279*2d543d20SAndroid Build Coastguard Worker semanage_list_t *user_context_tpl = NULL;
1280*2d543d20SAndroid Build Coastguard Worker int retval = STATUS_SUCCESS;
1281*2d543d20SAndroid Build Coastguard Worker
1282*2d543d20SAndroid Build Coastguard Worker homedir_context_tpl = make_template(s, &HOME_DIR_PRED);
1283*2d543d20SAndroid Build Coastguard Worker homeroot_context_tpl = make_template(s, &HOME_ROOT_PRED);
1284*2d543d20SAndroid Build Coastguard Worker username_context_tpl = make_template(s, &USERNAME_CONTEXT_PRED);
1285*2d543d20SAndroid Build Coastguard Worker user_context_tpl = make_template(s, &USER_CONTEXT_PRED);
1286*2d543d20SAndroid Build Coastguard Worker
1287*2d543d20SAndroid Build Coastguard Worker if (!homedir_context_tpl
1288*2d543d20SAndroid Build Coastguard Worker && !homeroot_context_tpl
1289*2d543d20SAndroid Build Coastguard Worker && !username_context_tpl
1290*2d543d20SAndroid Build Coastguard Worker && !user_context_tpl)
1291*2d543d20SAndroid Build Coastguard Worker goto done;
1292*2d543d20SAndroid Build Coastguard Worker
1293*2d543d20SAndroid Build Coastguard Worker if (write_file_context_header(out) != STATUS_SUCCESS) {
1294*2d543d20SAndroid Build Coastguard Worker retval = STATUS_ERR;
1295*2d543d20SAndroid Build Coastguard Worker goto done;
1296*2d543d20SAndroid Build Coastguard Worker }
1297*2d543d20SAndroid Build Coastguard Worker
1298*2d543d20SAndroid Build Coastguard Worker if (setup_fallback_user(s) != 0) {
1299*2d543d20SAndroid Build Coastguard Worker retval = STATUS_ERR;
1300*2d543d20SAndroid Build Coastguard Worker goto done;
1301*2d543d20SAndroid Build Coastguard Worker }
1302*2d543d20SAndroid Build Coastguard Worker
1303*2d543d20SAndroid Build Coastguard Worker if (homedir_context_tpl || homeroot_context_tpl) {
1304*2d543d20SAndroid Build Coastguard Worker homedirs = get_home_dirs(s);
1305*2d543d20SAndroid Build Coastguard Worker if (!homedirs) {
1306*2d543d20SAndroid Build Coastguard Worker WARN(s->h_semanage,
1307*2d543d20SAndroid Build Coastguard Worker "no home directories were available, exiting without writing");
1308*2d543d20SAndroid Build Coastguard Worker goto done;
1309*2d543d20SAndroid Build Coastguard Worker }
1310*2d543d20SAndroid Build Coastguard Worker
1311*2d543d20SAndroid Build Coastguard Worker for (h = homedirs; h; h = h->next) {
1312*2d543d20SAndroid Build Coastguard Worker char *temp = NULL;
1313*2d543d20SAndroid Build Coastguard Worker
1314*2d543d20SAndroid Build Coastguard Worker if (asprintf(&temp, "%s/%s", h->data, FALLBACK_NAME) < 0) {
1315*2d543d20SAndroid Build Coastguard Worker retval = STATUS_ERR;
1316*2d543d20SAndroid Build Coastguard Worker goto done;
1317*2d543d20SAndroid Build Coastguard Worker }
1318*2d543d20SAndroid Build Coastguard Worker
1319*2d543d20SAndroid Build Coastguard Worker free(s->fallback->home);
1320*2d543d20SAndroid Build Coastguard Worker s->fallback->home = temp;
1321*2d543d20SAndroid Build Coastguard Worker
1322*2d543d20SAndroid Build Coastguard Worker if (write_home_dir_context(s, out, homedir_context_tpl,
1323*2d543d20SAndroid Build Coastguard Worker s->fallback) != STATUS_SUCCESS) {
1324*2d543d20SAndroid Build Coastguard Worker free(temp);
1325*2d543d20SAndroid Build Coastguard Worker s->fallback->home = NULL;
1326*2d543d20SAndroid Build Coastguard Worker retval = STATUS_ERR;
1327*2d543d20SAndroid Build Coastguard Worker goto done;
1328*2d543d20SAndroid Build Coastguard Worker }
1329*2d543d20SAndroid Build Coastguard Worker if (write_home_root_context(s, out,
1330*2d543d20SAndroid Build Coastguard Worker homeroot_context_tpl,
1331*2d543d20SAndroid Build Coastguard Worker h->data) != STATUS_SUCCESS) {
1332*2d543d20SAndroid Build Coastguard Worker free(temp);
1333*2d543d20SAndroid Build Coastguard Worker s->fallback->home = NULL;
1334*2d543d20SAndroid Build Coastguard Worker retval = STATUS_ERR;
1335*2d543d20SAndroid Build Coastguard Worker goto done;
1336*2d543d20SAndroid Build Coastguard Worker }
1337*2d543d20SAndroid Build Coastguard Worker
1338*2d543d20SAndroid Build Coastguard Worker free(temp);
1339*2d543d20SAndroid Build Coastguard Worker s->fallback->home = NULL;
1340*2d543d20SAndroid Build Coastguard Worker }
1341*2d543d20SAndroid Build Coastguard Worker }
1342*2d543d20SAndroid Build Coastguard Worker if (user_context_tpl || username_context_tpl) {
1343*2d543d20SAndroid Build Coastguard Worker if (write_username_context(s, out, username_context_tpl,
1344*2d543d20SAndroid Build Coastguard Worker s->fallback) != STATUS_SUCCESS) {
1345*2d543d20SAndroid Build Coastguard Worker retval = STATUS_ERR;
1346*2d543d20SAndroid Build Coastguard Worker goto done;
1347*2d543d20SAndroid Build Coastguard Worker }
1348*2d543d20SAndroid Build Coastguard Worker
1349*2d543d20SAndroid Build Coastguard Worker if (write_user_context(s, out, user_context_tpl,
1350*2d543d20SAndroid Build Coastguard Worker s->fallback) != STATUS_SUCCESS) {
1351*2d543d20SAndroid Build Coastguard Worker retval = STATUS_ERR;
1352*2d543d20SAndroid Build Coastguard Worker goto done;
1353*2d543d20SAndroid Build Coastguard Worker }
1354*2d543d20SAndroid Build Coastguard Worker
1355*2d543d20SAndroid Build Coastguard Worker if (write_gen_home_dir_context(s, out, username_context_tpl,
1356*2d543d20SAndroid Build Coastguard Worker user_context_tpl, homedir_context_tpl)
1357*2d543d20SAndroid Build Coastguard Worker != STATUS_SUCCESS) {
1358*2d543d20SAndroid Build Coastguard Worker retval = STATUS_ERR;
1359*2d543d20SAndroid Build Coastguard Worker }
1360*2d543d20SAndroid Build Coastguard Worker }
1361*2d543d20SAndroid Build Coastguard Worker
1362*2d543d20SAndroid Build Coastguard Worker done:
1363*2d543d20SAndroid Build Coastguard Worker /* Cleanup */
1364*2d543d20SAndroid Build Coastguard Worker semanage_list_destroy(&homedirs);
1365*2d543d20SAndroid Build Coastguard Worker semanage_list_destroy(&username_context_tpl);
1366*2d543d20SAndroid Build Coastguard Worker semanage_list_destroy(&user_context_tpl);
1367*2d543d20SAndroid Build Coastguard Worker semanage_list_destroy(&homedir_context_tpl);
1368*2d543d20SAndroid Build Coastguard Worker semanage_list_destroy(&homeroot_context_tpl);
1369*2d543d20SAndroid Build Coastguard Worker
1370*2d543d20SAndroid Build Coastguard Worker return retval;
1371*2d543d20SAndroid Build Coastguard Worker }
1372*2d543d20SAndroid Build Coastguard Worker
semanage_genhomedircon(semanage_handle_t * sh,sepol_policydb_t * policydb,int usepasswd,char * ignoredirs)1373*2d543d20SAndroid Build Coastguard Worker int semanage_genhomedircon(semanage_handle_t * sh,
1374*2d543d20SAndroid Build Coastguard Worker sepol_policydb_t * policydb,
1375*2d543d20SAndroid Build Coastguard Worker int usepasswd,
1376*2d543d20SAndroid Build Coastguard Worker char *ignoredirs)
1377*2d543d20SAndroid Build Coastguard Worker {
1378*2d543d20SAndroid Build Coastguard Worker genhomedircon_settings_t s;
1379*2d543d20SAndroid Build Coastguard Worker FILE *out = NULL;
1380*2d543d20SAndroid Build Coastguard Worker int retval = 0;
1381*2d543d20SAndroid Build Coastguard Worker
1382*2d543d20SAndroid Build Coastguard Worker assert(sh);
1383*2d543d20SAndroid Build Coastguard Worker
1384*2d543d20SAndroid Build Coastguard Worker s.homedir_template_path =
1385*2d543d20SAndroid Build Coastguard Worker semanage_path(SEMANAGE_TMP, SEMANAGE_HOMEDIR_TMPL);
1386*2d543d20SAndroid Build Coastguard Worker s.fcfilepath =
1387*2d543d20SAndroid Build Coastguard Worker semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC_HOMEDIRS);
1388*2d543d20SAndroid Build Coastguard Worker
1389*2d543d20SAndroid Build Coastguard Worker s.fallback = calloc(1, sizeof(genhomedircon_user_entry_t));
1390*2d543d20SAndroid Build Coastguard Worker if (s.fallback == NULL) {
1391*2d543d20SAndroid Build Coastguard Worker retval = STATUS_ERR;
1392*2d543d20SAndroid Build Coastguard Worker goto done;
1393*2d543d20SAndroid Build Coastguard Worker }
1394*2d543d20SAndroid Build Coastguard Worker
1395*2d543d20SAndroid Build Coastguard Worker s.fallback->name = strdup(FALLBACK_NAME);
1396*2d543d20SAndroid Build Coastguard Worker s.fallback->sename = strdup(FALLBACK_SENAME);
1397*2d543d20SAndroid Build Coastguard Worker s.fallback->prefix = strdup(FALLBACK_PREFIX);
1398*2d543d20SAndroid Build Coastguard Worker s.fallback->level = strdup(FALLBACK_LEVEL);
1399*2d543d20SAndroid Build Coastguard Worker if (s.fallback->name == NULL
1400*2d543d20SAndroid Build Coastguard Worker || s.fallback->sename == NULL
1401*2d543d20SAndroid Build Coastguard Worker || s.fallback->prefix == NULL
1402*2d543d20SAndroid Build Coastguard Worker || s.fallback->level == NULL) {
1403*2d543d20SAndroid Build Coastguard Worker retval = STATUS_ERR;
1404*2d543d20SAndroid Build Coastguard Worker goto done;
1405*2d543d20SAndroid Build Coastguard Worker }
1406*2d543d20SAndroid Build Coastguard Worker
1407*2d543d20SAndroid Build Coastguard Worker if (ignoredirs) ignore_setup(ignoredirs);
1408*2d543d20SAndroid Build Coastguard Worker
1409*2d543d20SAndroid Build Coastguard Worker s.usepasswd = usepasswd;
1410*2d543d20SAndroid Build Coastguard Worker s.h_semanage = sh;
1411*2d543d20SAndroid Build Coastguard Worker s.policydb = policydb;
1412*2d543d20SAndroid Build Coastguard Worker
1413*2d543d20SAndroid Build Coastguard Worker if (!(out = fopen(s.fcfilepath, "w"))) {
1414*2d543d20SAndroid Build Coastguard Worker /* couldn't open output file */
1415*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Could not open the file_context file for writing");
1416*2d543d20SAndroid Build Coastguard Worker retval = STATUS_ERR;
1417*2d543d20SAndroid Build Coastguard Worker goto done;
1418*2d543d20SAndroid Build Coastguard Worker }
1419*2d543d20SAndroid Build Coastguard Worker
1420*2d543d20SAndroid Build Coastguard Worker retval = write_context_file(&s, out);
1421*2d543d20SAndroid Build Coastguard Worker
1422*2d543d20SAndroid Build Coastguard Worker done:
1423*2d543d20SAndroid Build Coastguard Worker if (out != NULL)
1424*2d543d20SAndroid Build Coastguard Worker fclose(out);
1425*2d543d20SAndroid Build Coastguard Worker
1426*2d543d20SAndroid Build Coastguard Worker while (s.fallback)
1427*2d543d20SAndroid Build Coastguard Worker pop_user_entry(&(s.fallback));
1428*2d543d20SAndroid Build Coastguard Worker
1429*2d543d20SAndroid Build Coastguard Worker ignore_free();
1430*2d543d20SAndroid Build Coastguard Worker
1431*2d543d20SAndroid Build Coastguard Worker return retval;
1432*2d543d20SAndroid Build Coastguard Worker }
1433