Skip to content

Commit c331c8a

Browse files
KRB5: let 'krb5_child' tolerate missing cap-set-id
If CAP_SETUID and/or CAP_SETGID are missing, 'krb5_child' will skip operation that require those capabilities, namely any manipulations with user ccache. :packaging:This update makes it possible to not grant CAP_SETUID and CAP_SETGID to 'krb5_child' binary in a situation where it is not required to store acquired TGT after user authentication. Taking into account that it is already possible to avoid using CAP_DAC_READ_SEARCH if keytab is readable by SSSD service user, and usage of 'selinux_child' isn't always required, this allows to build a setup with completely privilege-less SSSD to serve certain use cases. In particular, this might be used to build a container running SSSD on OCP with a restricted profile.
1 parent 9579e08 commit c331c8a

File tree

2 files changed

+58
-26
lines changed

2 files changed

+58
-26
lines changed

src/providers/krb5/krb5_ccache.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@
3737
#include "util/util.h"
3838

3939

40-
/* real id == user id; set id == service id */
40+
/* `switch_to_()` functions expect that
41+
* real id == user id; set id == service id.
42+
* This is prepared (set) in `privileged_krb5_setup()`
43+
* if process has corresponding capabilities.
44+
*/
4145
errno_t switch_to_user(void)
4246
{
4347
int ret;

src/providers/krb5/krb5_child.c

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ struct cli_opts {
8282
};
8383

8484
struct krb5_req {
85+
bool krb5_child_has_setid_caps;
86+
8587
krb5_context ctx;
8688
krb5_principal princ;
8789
krb5_principal princ_orig;
@@ -1845,6 +1847,10 @@ static errno_t k5c_attach_ccname_msg(struct krb5_req *kr)
18451847
char *msg = NULL;
18461848
int ret;
18471849

1850+
if (!kr->krb5_child_has_setid_caps) {
1851+
return EOK;
1852+
}
1853+
18481854
if (kr->ccname == NULL) {
18491855
DEBUG(SSSDBG_CRIT_FAILURE, "Error obtaining ccname.\n");
18501856
return ERR_INTERNAL;
@@ -2523,6 +2529,12 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
25232529
goto done;
25242530
}
25252531

2532+
if (!kr->krb5_child_has_setid_caps) {
2533+
/* no set-id capability => can't populate user ccache */
2534+
kerr = 0;
2535+
goto done;
2536+
}
2537+
25262538
/* Make sure ccache is created and written as the user */
25272539
kerr = switch_to_user();
25282540
if (kerr != EOK) {
@@ -4085,29 +4097,37 @@ static krb5_error_code privileged_krb5_setup(struct krb5_req *kr,
40854097
int ret;
40864098
char *mem_keytab;
40874099

4088-
/* Make use of cap_set*id first to bootstap process */
4089-
sss_set_cap_effective(CAP_SETGID, true);
4090-
if (geteuid() != 0) {
4091-
ret = setgroups(0, NULL);
4100+
/* Make use of cap_set*id (if available) first to bootstrap process */
4101+
kr->krb5_child_has_setid_caps =
4102+
((sss_set_cap_effective(CAP_SETGID, true) == EOK) &&
4103+
(sss_set_cap_effective(CAP_SETUID, true) == EOK));
4104+
4105+
if (kr->krb5_child_has_setid_caps) {
4106+
if (geteuid() != 0) {
4107+
ret = setgroups(0, NULL);
4108+
if (ret != 0) {
4109+
ret = errno;
4110+
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to drop supplementary groups: %d\n", ret);
4111+
return ret;
4112+
}
4113+
} /* Otherwise keep supplementary groups to have access to DB_PATH to store FAST ccache */
4114+
ret = setresgid(kr->gid, -1, -1);
40924115
if (ret != 0) {
40934116
ret = errno;
4094-
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to drop supplementary groups: %d\n", ret);
4117+
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to set real GID: %d\n", ret);
40954118
return ret;
40964119
}
4097-
} /* Otherwise keep supplementary groups to have access to DB_PATH to store FAST ccache */
4098-
ret = setresgid(kr->gid, -1, -1);
4099-
if (ret != 0) {
4100-
ret = errno;
4101-
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to set real GID: %d\n", ret);
4102-
return ret;
4103-
}
4104-
sss_set_cap_effective(CAP_SETUID, true);
4105-
ret = setresuid(kr->uid, -1, -1);
4106-
if (ret != 0) {
4107-
ret = errno;
4108-
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to set real UID: %d\n", ret);
4109-
return ret;
4120+
ret = setresuid(kr->uid, -1, -1);
4121+
if (ret != 0) {
4122+
ret = errno;
4123+
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to set real UID: %d\n", ret);
4124+
return ret;
4125+
}
4126+
} else {
4127+
DEBUG(SSSDBG_CONF_SETTINGS, "'krb5_child' doesn't have CAP_SETUID and/or "
4128+
"CAP_SETGID. User ccache won't be updated.\n");
41104129
}
4130+
41114131
sss_drop_cap(CAP_SETUID);
41124132
sss_drop_cap(CAP_SETGID);
41134133

@@ -4337,7 +4357,7 @@ int main(int argc, const char *argv[])
43374357
* is only allowed for authenticated users. Since PKINIT is part of
43384358
* the authentication and the user is not authenticated yet, we have
43394359
* to use different privileges and can only drop it after the TGT is
4340-
* received. IDs the backend (and thus 'krb5_child) is running with are
4360+
* received. IDs the backend (and thus 'krb5_child') is running with are
43414361
* either root or the 'sssd' user. Root is allowed by default and
43424362
* the 'sssd' user is allowed with the help of the sssd-pcsc.rules
43434363
* policy-kit rule. So those IDs are a suitable choice and needs to
@@ -4346,11 +4366,13 @@ int main(int argc, const char *argv[])
43464366
* to make sure the empty ccache is created with the expected
43474367
* ownership. */
43484368
if (!IS_SC_AUTHTOK(kr->pd->authtok) || offline) {
4349-
ret = switch_to_user();
4350-
if (ret != EOK) {
4351-
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to switch to user IDs: %d\n", ret);
4352-
ret = EFAULT;
4353-
goto done;
4369+
if (kr->krb5_child_has_setid_caps) {
4370+
ret = switch_to_user();
4371+
if (ret != EOK) {
4372+
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to switch to user IDs: %d\n", ret);
4373+
ret = EFAULT;
4374+
goto done;
4375+
}
43544376
}
43554377
}
43564378

@@ -4370,7 +4392,9 @@ int main(int argc, const char *argv[])
43704392
case SSS_PAM_AUTHENTICATE:
43714393
/* If we are offline, we need to create an empty ccache file */
43724394
if (offline) {
4373-
ret = create_empty_ccache(kr);
4395+
if (kr->krb5_child_has_setid_caps) {
4396+
ret = create_empty_ccache(kr);
4397+
}
43744398
} else {
43754399
DEBUG(SSSDBG_TRACE_FUNC, "Will perform online auth\n");
43764400
ret = tgt_req_child(kr);
@@ -4391,6 +4415,10 @@ int main(int argc, const char *argv[])
43914415
ret = KRB5_KDC_UNREACH;
43924416
goto done;
43934417
}
4418+
if (!kr->krb5_child_has_setid_caps) {
4419+
ret = KRB5_CC_NOTFOUND;
4420+
goto done;
4421+
}
43944422
ret = renew_tgt_child(kr);
43954423
break;
43964424
case SSS_PAM_PREAUTH:

0 commit comments

Comments
 (0)