Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 69 additions & 31 deletions src/providers/krb5/krb5_child.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ static errno_t k5c_attach_passkey_msg(struct krb5_req *kr, struct sss_passkey_ch
static errno_t k5c_attach_keep_alive_msg(struct krb5_req *kr);
static errno_t k5c_recv_data(struct krb5_req *kr, int fd, uint32_t *offline);
static errno_t k5c_send_data(struct krb5_req *kr, int fd, errno_t error);
static errno_t k5c_drop_to_user(struct krb5_req *kr);
static int k5c_ccache_setup(struct krb5_req *kr, uint32_t offline);

static krb5_error_code set_lifetime_options(struct cli_opts *cli_opts,
krb5_get_init_creds_opt *options)
Expand Down Expand Up @@ -901,10 +903,10 @@ static krb5_error_code idp_oauth2_method_req(struct krb5_req *kr,
return ret;
}

static krb5_error_code k5c_send_and_recv(struct krb5_req *kr)
static krb5_error_code k5c_send_and_recv(struct krb5_req *kr,
uint32_t *offline)
{
struct krb5_req *tmpkr = NULL;
uint32_t offline;
errno_t ret;

/* Challenge was presented. We need to continue the authentication
Expand All @@ -929,7 +931,7 @@ static krb5_error_code k5c_send_and_recv(struct krb5_req *kr)
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to send reply\n");
}

ret = k5c_recv_data(tmpkr, STDIN_FILENO, &offline);
ret = k5c_recv_data(tmpkr, STDIN_FILENO, offline);
if (ret != EOK) {
goto done;
}
Expand Down Expand Up @@ -1313,6 +1315,7 @@ static krb5_error_code sss_krb5_auth_methods_request(krb5_context ctx,
{
size_t c;
int count = 0;
uint32_t offline;
krb5_error_code kerr = EINVAL;

if (kr->pd->cmd != SSS_PAM_PREAUTH) {
Expand Down Expand Up @@ -1355,8 +1358,24 @@ static krb5_error_code sss_krb5_auth_methods_request(krb5_context ctx,
goto done;
}

kerr = k5c_send_and_recv(kr);
kerr = k5c_send_and_recv(kr, &offline);
if (kerr != EOK) {
goto done;
}

/* During keep-alive sessions, we need to ensure the process has the correct
* user privileges before ccache operations. */
kerr = k5c_drop_to_user(kr);
if (kerr != 0) {
DEBUG(SSSDBG_CRIT_FAILURE, "k5c_drop_to_user failed.\n");
goto done;
}

/* Set up ccache for authentication commands during keep-alive session.
* This ensures ccache reuse logic runs for concurrent logins. */
kerr = k5c_ccache_setup(kr, offline);
if (kerr != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "k5c_ccache_setup failed during keep-alive.\n");
goto done;
}

Expand Down Expand Up @@ -4090,47 +4109,66 @@ static krb5_error_code check_keytab_name(struct krb5_req *kr)
return 0;
}

static krb5_error_code privileged_krb5_setup(struct krb5_req *kr,
uint32_t offline)
static errno_t k5c_drop_to_user(struct krb5_req *kr)
{
krb5_error_code kerr;
int ret;
char *mem_keytab;

/* Make use of cap_set*id (if available) first to bootstrap process */
kr->krb5_child_has_setid_caps =
((sss_set_cap_effective(CAP_SETGID, true) == EOK) &&
(sss_set_cap_effective(CAP_SETUID, true) == EOK));
if (getuid() == kr->uid && getgid() == kr->gid) {
/* Already the correct user, assume we have sufficient privileges for ccache operations */
kr->krb5_child_has_setid_caps = true;
DEBUG(SSSDBG_TRACE_FUNC, "Already running as target user %d:%d\n", kr->uid, kr->gid);
} else {
/* Make use of cap_set*id (if available) first to bootstrap process */
kr->krb5_child_has_setid_caps =
((sss_set_cap_effective(CAP_SETGID, true) == EOK) &&
(sss_set_cap_effective(CAP_SETUID, true) == EOK));

if (kr->krb5_child_has_setid_caps) {
if (geteuid() != 0) {
ret = setgroups(0, NULL);
if (kr->krb5_child_has_setid_caps) {
if (geteuid() != 0) {
ret = setgroups(0, NULL);
if (ret != 0) {
ret = errno;
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to drop supplementary groups: %d\n", ret);
return ret;
}
} /* Otherwise keep supplementary groups to have access to DB_PATH to store FAST ccache */
ret = setresgid(kr->gid, -1, -1);
if (ret != 0) {
ret = errno;
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to drop supplementary groups: %d\n", ret);
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to set real GID: %d\n", ret);
return ret;
}
} /* Otherwise keep supplementary groups to have access to DB_PATH to store FAST ccache */
ret = setresgid(kr->gid, -1, -1);
if (ret != 0) {
ret = errno;
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to set real GID: %d\n", ret);
return ret;
}
ret = setresuid(kr->uid, -1, -1);
if (ret != 0) {
ret = errno;
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to set real UID: %d\n", ret);
return ret;
ret = setresuid(kr->uid, -1, -1);
if (ret != 0) {
ret = errno;
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to set real UID: %d\n", ret);
return ret;
}
} else {
DEBUG(SSSDBG_CONF_SETTINGS, "'krb5_child' doesn't have CAP_SETUID and/or "
"CAP_SETGID. User ccache won't be updated.\n");
}
} else {
DEBUG(SSSDBG_CONF_SETTINGS, "'krb5_child' doesn't have CAP_SETUID and/or "
"CAP_SETGID. User ccache won't be updated.\n");
}

sss_drop_cap(CAP_SETUID);
sss_drop_cap(CAP_SETGID);

return 0;
}

static krb5_error_code privileged_krb5_setup(struct krb5_req *kr,
uint32_t offline)
{
krb5_error_code kerr;
int ret;
char *mem_keytab;

ret = k5c_drop_to_user(kr);
if (ret != 0) {
DEBUG(SSSDBG_CRIT_FAILURE, "k5c_drop_to_user failed.\n");
return ret;
}

kr->realm = kr->cli_opts->realm;
if (kr->realm == NULL) {
DEBUG(SSSDBG_MINOR_FAILURE, "Realm not available.\n");
Expand Down
Loading