Skip to content

Commit 735fe23

Browse files
KRB5_CHILD: don't check if FILE:/DIR: path accessible in advance
Inaccessible FILE:/DIR: path is a system configuration error that needs to be fixed anyway. It doesn't make much difference to fail before or after credentials check in this case. Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com> Reviewed-by: Sumit Bose <sbose@redhat.com>
1 parent e2273e0 commit 735fe23

File tree

5 files changed

+31
-214
lines changed

5 files changed

+31
-214
lines changed

Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ condconfigexists = ConditionPathExists=\|/etc/sssd/sssd.conf\nConditionDirectory
108108
# - 'ldap_child': read keytab (dac_read_search)
109109
# - 'krb5_child':
110110
# - read keytab (dac_read_search)
111-
# - check old ccache / pre-check ccache path / store TGT for a given user (set*id)
111+
# - check old ccache / store TGT for a given user (set*id)
112112
# - 'selinux_child': use libsemanage (set*id)
113113
# - 'sssd_pam': read keytab in gss ops (dac_read_search)
114114
capabilities = CapabilityBoundingSet= CAP_SETGID CAP_SETUID CAP_DAC_READ_SEARCH

src/providers/krb5/krb5_ccache.c

Lines changed: 0 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -102,108 +102,6 @@ static errno_t switch_to_service(void)
102102
return EOK;
103103
}
104104

105-
static errno_t check_parent_stat(struct stat *parent_stat, uid_t uid)
106-
{
107-
if (parent_stat->st_uid != 0 && parent_stat->st_uid != uid) {
108-
DEBUG(SSSDBG_CRIT_FAILURE,
109-
"Private directory can only be created below a directory "
110-
"belonging to root or to [%"SPRIuid"].\n", uid);
111-
return EINVAL;
112-
}
113-
114-
if (parent_stat->st_uid == uid) {
115-
if ( (parent_stat->st_mode & (S_IXUSR|S_IRUSR|S_IWUSR)) !=
116-
(S_IXUSR|S_IRUSR|S_IWUSR) ) {
117-
DEBUG(SSSDBG_CRIT_FAILURE,
118-
"Parent directory is owned but not accessible by user?!\n");
119-
return EINVAL;
120-
}
121-
} else {
122-
if ( (parent_stat->st_mode & (S_IXOTH|S_IROTH|S_IWOTH)) !=
123-
(S_IXOTH|S_IROTH|S_IWOTH) ) {
124-
DEBUG(SSSDBG_CRIT_FAILURE,
125-
"Parent directory is owned by root and not accessible to "
126-
"user\n");
127-
return EINVAL;
128-
}
129-
}
130-
131-
return EOK;
132-
}
133-
134-
errno_t sss_krb5_precheck_ccache(const char *ccname, uid_t uid, gid_t gid)
135-
{
136-
TALLOC_CTX *tmp_ctx = NULL;
137-
const char *filename;
138-
char *ccdirname;
139-
char *end;
140-
struct stat parent_stat;
141-
errno_t ret;
142-
143-
if (ccname[0] == '/') {
144-
filename = ccname;
145-
} else if (strncmp(ccname, "FILE:", 5) == 0) {
146-
filename = ccname + 5;
147-
} else if (strncmp(ccname, "DIR:", 4) == 0) {
148-
filename = ccname + 4;
149-
} else {
150-
/* only FILE and DIR types need pre-checks, we ignore any
151-
* other type */
152-
DEBUG(SSSDBG_TRACE_ALL, "No checks needed for [%s]\n", ccname);
153-
return EOK;
154-
}
155-
156-
tmp_ctx = talloc_new(NULL);
157-
if (!tmp_ctx) return ENOMEM;
158-
159-
ccdirname = talloc_strdup(tmp_ctx, filename);
160-
if (ccdirname == NULL) {
161-
DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed.\n");
162-
ret = ENOMEM;
163-
goto done;
164-
}
165-
166-
/* Get parent directory of wanted ccache directory/file,
167-
* removing trailing slashes from the back
168-
*/
169-
do {
170-
end = strrchr(ccdirname, '/');
171-
if (end == NULL || end == ccdirname) {
172-
DEBUG(SSSDBG_CRIT_FAILURE, "Cannot find parent directory of [%s], "
173-
"/ is not allowed.\n", ccdirname);
174-
ret = EINVAL;
175-
goto done;
176-
}
177-
*end = '\0';
178-
} while (*(end+1) == '\0');
179-
180-
/* This function is currently called from `privileged_krb5_setup()` only
181-
* so 'krb5_child' runs under service user at this point.
182-
*/
183-
switch_to_user();
184-
ret = stat(ccdirname, &parent_stat);
185-
switch_to_service();
186-
if (ret != 0) {
187-
DEBUG(SSSDBG_CRIT_FAILURE, "Cannot stat() [%s]\n", ccdirname);
188-
ret = EINVAL;
189-
goto done;
190-
}
191-
192-
ret = check_parent_stat(&parent_stat, uid);
193-
if (ret != EOK) {
194-
DEBUG(SSSDBG_FATAL_FAILURE,
195-
"Check the ownership and permissions of krb5_ccachedir: [%s].\n",
196-
ccdirname);
197-
goto done;
198-
}
199-
200-
ret = EOK;
201-
202-
done:
203-
talloc_free(tmp_ctx);
204-
return ret;
205-
}
206-
207105
struct sss_krb5_ccache {
208106
krb5_context context;
209107
krb5_ccache ccache;

src/providers/krb5/krb5_ccache.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@ struct tgt_times {
3535
time_t renew_till;
3636
};
3737

38-
errno_t sss_krb5_precheck_ccache(const char *ccname, uid_t uid, gid_t gid);
39-
4038
errno_t sss_krb5_check_ccache_princ(krb5_context kctx,
4139
const char *ccname,
4240
krb5_principal user_princ);

src/providers/krb5/krb5_child.c

Lines changed: 30 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -3873,88 +3873,53 @@ static errno_t old_ccache_valid(struct krb5_req *kr, bool *_valid)
38733873
return EOK;
38743874
}
38753875

3876-
static int k5c_check_old_ccache(struct krb5_req *kr)
3876+
static void k5c_ccache_check(struct krb5_req *kr, uint32_t offline)
38773877
{
38783878
errno_t ret;
38793879

3880-
if (kr->old_ccname) {
3881-
ret = old_ccache_valid(kr, &kr->old_cc_valid);
3882-
if (ret != EOK) {
3883-
DEBUG(SSSDBG_OP_FAILURE, "old_ccache_valid() failed.\n");
3884-
return ret;
3885-
}
3880+
kr->old_cc_valid = false;
3881+
kr->old_cc_active = false;
3882+
3883+
if (kr->pd->cmd == SSS_PAM_ACCT_MGMT) {
3884+
return;
3885+
}
3886+
3887+
if (kr->old_ccname == NULL) {
3888+
return;
3889+
}
38863890

3891+
ret = old_ccache_valid(kr, &kr->old_cc_valid);
3892+
if (ret != EOK) {
3893+
DEBUG(SSSDBG_OP_FAILURE, "old_ccache_valid() failed.\n");
3894+
} else {
38873895
ret = check_if_uid_is_active(kr->uid, &kr->old_cc_active);
38883896
if (ret != EOK) {
38893897
DEBUG(SSSDBG_OP_FAILURE, "check_if_uid_is_active() failed.\n");
3890-
return ret;
3898+
kr->old_cc_valid = false;
38913899
}
3892-
3893-
DEBUG(SSSDBG_TRACE_ALL,
3894-
"Old ccache is [%s] and is %s active and TGT is %s valid.\n",
3895-
kr->old_ccname ? kr->old_ccname : "not set",
3896-
kr->old_cc_active ? "" : "not",
3897-
kr->old_cc_valid ? "" : "not");
38983900
}
38993901

3900-
return EOK;
3901-
}
3902-
3903-
static int k5c_precheck_ccache(struct krb5_req *kr, uint32_t offline)
3904-
{
3905-
errno_t ret;
3902+
DEBUG(SSSDBG_TRACE_ALL,
3903+
"Old ccache is [%s] and is %s active and TGT is %s valid.\n",
3904+
kr->old_ccname ? kr->old_ccname : "not set",
3905+
kr->old_cc_active ? "" : "not",
3906+
kr->old_cc_valid ? "" : "not");
39063907

3907-
/* The ccache path should be checked if one of the following conditions
3908+
/* Old ccache can't be used if one of the following conditions
39083909
* is true:
3909-
* - it doesn't exist (kr->old_ccname == NULL)
3910+
* - the backend is offline and the current cache file not used and
3911+
* it does not contain a valid TGT (1)
39103912
* - the backend is online and the current ccache file is not used, i.e
39113913
* the related user is currently not logged in and it is not a renewal
3912-
* request
3913-
* (offline && !kr->old_cc_active && kr->pd->cmd != SSS_CMD_RENEW)
3914-
* - the backend is offline and the current cache file not used and
3915-
* it does not contain a valid TGT
3916-
* (offline && !kr->old_cc_active && !kr->valid_tgt)
3914+
* request (2)
39173915
*/
3918-
if (kr->old_ccname == NULL ||
3919-
(offline && !kr->old_cc_active && !kr->old_cc_valid) ||
3920-
(!offline && !kr->old_cc_active && kr->pd->cmd != SSS_CMD_RENEW)) {
3921-
DEBUG(SSSDBG_TRACE_ALL, "Pre-checking ccache [%s]\n", kr->ccname);
3922-
ret = sss_krb5_precheck_ccache(kr->ccname, kr->uid, kr->gid);
3923-
if (ret != EOK) {
3924-
DEBUG(SSSDBG_OP_FAILURE, "ccache check failed.\n");
3925-
return ret;
3926-
}
3916+
if ((offline && !kr->old_cc_active && !kr->old_cc_valid) || /* (1) */
3917+
(!offline && !kr->old_cc_active && kr->pd->cmd != SSS_CMD_RENEW)) /* (2) */ {
3918+
DEBUG(SSSDBG_TRACE_ALL, "Ignoring old ccache\n");
39273919
} else {
39283920
DEBUG(SSSDBG_TRACE_ALL, "Reusing old ccache [%s]\n", kr->old_ccname);
39293921
kr->ccname = kr->old_ccname;
39303922
}
3931-
3932-
return EOK;
3933-
}
3934-
3935-
static int k5c_ccache_check(struct krb5_req *kr, uint32_t offline)
3936-
{
3937-
errno_t ret;
3938-
3939-
if (kr->pd->cmd == SSS_PAM_ACCT_MGMT) {
3940-
return EOK;
3941-
}
3942-
3943-
ret = k5c_check_old_ccache(kr);
3944-
if (ret != 0) {
3945-
DEBUG(SSSDBG_CRIT_FAILURE, "Cannot check old ccache [%s]: [%d][%s]. " \
3946-
"Assuming old cache is invalid " \
3947-
"and not used.\n",
3948-
kr->old_ccname, ret, sss_strerror(ret));
3949-
}
3950-
3951-
ret = k5c_precheck_ccache(kr, offline);
3952-
if (ret != 0) {
3953-
DEBUG(SSSDBG_OP_FAILURE, "ccache pre-check failed\n");
3954-
return ret;
3955-
}
3956-
3957-
return EOK;
39583923
}
39593924

39603925
static int k5c_setup(struct krb5_req *kr, uint32_t offline)
@@ -4163,15 +4128,9 @@ static krb5_error_code privileged_krb5_setup(struct krb5_req *kr,
41634128
return ret;
41644129
}
41654130

4166-
/* Determine if old FILE:/DIR: ccache needs to be re-used and if
4167-
* path is accessible.
4168-
*/
4131+
/* Determine if old ccache name can and needs to be re-used */
41694132
if (kr->krb5_child_has_setid_caps) {
4170-
ret = k5c_ccache_check(kr, offline);
4171-
if (ret != EOK) {
4172-
DEBUG(SSSDBG_CRIT_FAILURE, "k5c_ccache_check() failed.\n");
4173-
return ret;
4174-
}
4133+
k5c_ccache_check(kr, offline);
41754134
}
41764135

41774136
if (!(offline ||

src/tests/krb5_utils-tests.c

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -74,39 +74,6 @@ void teardown_create_dir(void)
7474
ck_assert_msg(ret == 0, "Cannot free talloc context.");
7575
}
7676

77-
START_TEST(test_private_ccache_dir_in_wrong_user_dir)
78-
{
79-
int ret;
80-
char *cwd;
81-
char *dirname;
82-
char *subdirname;
83-
char *filename;
84-
85-
ck_assert_msg(getuid() == 0, "This test must be run as root.");
86-
87-
cwd = getcwd(NULL, 0);
88-
ck_assert_msg(cwd != NULL, "getcwd failed.");
89-
90-
dirname = talloc_asprintf(tmp_ctx, "%s/%s/priv_ccdir", cwd, TESTS_PATH);
91-
free(cwd);
92-
ck_assert_msg(dirname != NULL, "talloc_asprintf failed.");
93-
ret = mkdir(dirname, 0700);
94-
ck_assert_msg(ret == EOK, "mkdir failed.\n");
95-
ret = chown(dirname, 12346, 12346);
96-
ck_assert_msg(ret == EOK, "chown failed.\n");
97-
subdirname = talloc_asprintf(tmp_ctx, "%s/subdir", dirname);
98-
ck_assert_msg(subdirname != NULL, "talloc_asprintf failed.");
99-
filename = talloc_asprintf(tmp_ctx, "%s/ccfile", subdirname);
100-
ck_assert_msg(filename != NULL, "talloc_asprintf failed.");
101-
102-
ret = sss_krb5_precheck_ccache(filename, 12345, 12345);
103-
ck_assert_msg(ret == EINVAL, "Creating private ccache dir in wrong user "
104-
"dir does not failed with EINVAL.");
105-
106-
RMDIR(dirname);
107-
}
108-
END_TEST
109-
11077
START_TEST(test_illegal_patterns)
11178
{
11279
char *cwd;
@@ -650,11 +617,6 @@ Suite *krb5_utils_suite (void)
650617
tcase_add_checked_fixture (tc_create_dir, setup_create_dir,
651618
teardown_create_dir);
652619
tcase_add_test (tc_create_dir, test_illegal_patterns);
653-
if (getuid() == 0) {
654-
tcase_add_test (tc_create_dir, test_private_ccache_dir_in_wrong_user_dir);
655-
} else {
656-
printf("Run as root to enable more tests.\n");
657-
}
658620
suite_add_tcase (s, tc_create_dir);
659621

660622
TCase *tc_krb5_helpers = tcase_create("Helper functions");

0 commit comments

Comments
 (0)