Skip to content
Open
Show file tree
Hide file tree
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
3 changes: 3 additions & 0 deletions src/confdb/confdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,9 @@
#define CONFDB_PC_PASSKEY_INTERACTIVE_PROMPT "interactive_prompt"
#define CONFDB_PC_PASSKEY_TOUCH "touch"
#define CONFDB_PC_PASSKEY_TOUCH_PROMPT "touch_prompt"
#define CONFDB_PC_TYPE_OAUTH2 "oauth2"
#define CONFDB_PC_OAUTH2_INTERACTIVE "interactive"
#define CONFDB_PC_OAUTH2_INTERACTIVE_PROMPT "interactive_prompt"

struct confdb_ctx;

Expand Down
2 changes: 2 additions & 0 deletions src/config/cfg_rules.ini
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ section_re = ^prompting/2fa$
section_re = ^prompting/2fa/[^/\@]\{1,\}$
section_re = ^prompting/passkey$
section_re = ^prompting/passkey/[^/\@]\{1,\}$
section_re = ^prompting/oauth2$
section_re = ^prompting/oauth2/[^/\@]\{1,\}$
section_re = ^domain/[^/\@]\{1,\}$
section_re = ^domain/[^/\@]\{1,\}/[^/\@]\{1,\}$
section_re = ^application/[^/\@]\{1,\}$
Expand Down
35 changes: 35 additions & 0 deletions src/man/sssd.conf.5.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4496,6 +4496,41 @@ ldap_user_extra_attrs = phone:telephoneNumber
</listitem>
</varlistentry>
</variablelist>
<variablelist>
<varlistentry condition="with_idp_provider">
<term>[prompting/oauth2]</term>
<listitem>
<para>to configure OAuth2 authentication prompting,
allowed options are:
<variablelist>
<varlistentry>
<term>interactive</term>
<listitem>
<para>boolean value, if True prompt a message after
asking the user to authenticate, and wait
before requesting the access token.
</para>
<para>If False, make sure to set the
<quote>idp_request_timeout</quote>
sufficiently high, to give the user time to
authenticate.
</para>
<para>Default: true
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>interactive_prompt</term>
<listitem>
<para>to change the message of the interactive prompt.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
It is possible to add a subsection for specific PAM services,
Expand Down
47 changes: 47 additions & 0 deletions src/responder/pam/pam_prompting_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#define DEFAULT_PASSKEY_PROMPT_INTERACTIVE _("Insert your Passkey device, then press ENTER.")
#define DEFAULT_PASSKEY_PROMPT_TOUCH _("Please touch the device.")
#define DEFAULT_OAUTH2_PROMPT_INTERACTIVE _("Press ENTER to continue.")

typedef errno_t (pam_set_prompting_fn_t)(TALLOC_CTX *, struct confdb_ctx *,
const char *,
Expand Down Expand Up @@ -147,6 +148,39 @@ static errno_t pam_set_passkey_prompting_options(TALLOC_CTX *tmp_ctx,

return ret;
}

static errno_t pam_set_oauth2_prompting_options(TALLOC_CTX *tmp_ctx,
struct confdb_ctx *cdb,
const char *section,
struct prompt_config ***pc_list)
{
bool oauth2_interactive = false;
char *oauth2_interactive_prompt = NULL;
int ret;


ret = confdb_get_bool(cdb, section, CONFDB_PC_OAUTH2_INTERACTIVE, true,
&oauth2_interactive);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "confdb_get_bool failed, using defaults");
}

if (oauth2_interactive) {
ret = confdb_get_string(cdb, tmp_ctx, section, CONFDB_PC_OAUTH2_INTERACTIVE_PROMPT,
DEFAULT_OAUTH2_PROMPT_INTERACTIVE, &oauth2_interactive_prompt);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "confdb_get_string failed, using defaults");
}
}

ret = pc_list_add_oauth2(pc_list, oauth2_interactive_prompt);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "pc_list_add_oauth2 failed.\n");
}

return ret;
}

static errno_t pam_set_prompting_options(struct confdb_ctx *cdb,
const char *service_name,
char **sections,
Expand Down Expand Up @@ -232,6 +266,19 @@ errno_t pam_eval_prompting_config(struct pam_ctx *pctx, struct pam_data *pd,
goto done;
}

if (types.oauth2_auth) {
ret = pam_set_prompting_options(pctx->rctx->cdb, pd->service,
pctx->prompting_config_sections,
pctx->num_prompting_config_sections,
CONFDB_PC_TYPE_OAUTH2,
pam_set_oauth2_prompting_options,
&pc_list);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "pam_set_prompting_options failed.\n");
goto done;
}
}

if (types.passkey_auth) {
ret = pam_set_prompting_options(pctx->rctx->cdb, pd->service,
pctx->prompting_config_sections,
Expand Down
1 change: 1 addition & 0 deletions src/responder/pam/pamsrv.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ struct pam_resp_auth_type {
bool cert_auth;
bool passkey_auth;
bool backend_returned_no_auth_type;
bool oauth2_auth;
};

struct sss_cmd_table *get_pam_cmds(void);
Expand Down
9 changes: 7 additions & 2 deletions src/responder/pam/pamsrv_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,9 @@ static void evaluate_pam_resp_list(struct pam_data *pd,
case SSS_PAM_PASSKEY_KRB_INFO:
types.passkey_auth = true;
break;
case SSS_PAM_OAUTH2_INFO:
types.oauth2_auth = true;
break;
case SSS_PASSWORD_PROMPTING:
types.password_auth = true;
break;
Expand Down Expand Up @@ -954,18 +957,20 @@ errno_t pam_get_auth_types(struct pam_data *pd,

evaluate_pam_resp_list(pd, &types, NULL);

if (!types.password_auth && !types.otp_auth && !types.cert_auth && !types.passkey_auth) {
if (!types.password_auth && !types.otp_auth && !types.cert_auth &&
!types.oauth2_auth && !types.passkey_auth) {
/* If the backend cannot determine which authentication types are
* available the default would be to prompt for a password. */
types.password_auth = true;
types.backend_returned_no_auth_type = true;
}

DEBUG(SSSDBG_TRACE_ALL, "Authentication types for user [%s] and service "
"[%s]:%s%s%s%s\n", pd->user, pd->service,
"[%s]:%s%s%s%s%s\n", pd->user, pd->service,
types.password_auth ? " password": "",
types.otp_auth ? " two-factor" : "",
types.passkey_auth ? " passkey" : "",
types.oauth2_auth ? " oauth2" : "",
types.cert_auth ? " smartcard" : "");

ret = EOK;
Expand Down
44 changes: 29 additions & 15 deletions src/sss_client/pam_sss.c
Original file line number Diff line number Diff line change
Expand Up @@ -1849,37 +1849,47 @@ static int prompt_2fa_single(pam_handle_t *pamh, struct pam_items *pi,
return PAM_SUCCESS;
}

static int prompt_oauth2(pam_handle_t *pamh, struct pam_items *pi)
static int prompt_oauth2(pam_handle_t *pamh, struct pam_items *pi,
const char *prompt)
{
char *answer = NULL;
char *msg;
int ret;

if (pi->oauth2_url_complete != NULL) {
ret = asprintf(&msg, _("Authenticate at %1$s and press ENTER."),
ret = asprintf(&msg, _("Authenticate at \"%1$s\"."),
pi->oauth2_url_complete);
} else {
ret = asprintf(&msg, _("Authenticate with PIN %1$s at %2$s and press "
"ENTER."), pi->oauth2_pin, pi->oauth2_url);
ret = asprintf(&msg, _("Authenticate with PIN \"%1$s\" at \"%2$s\"."),
pi->oauth2_pin, pi->oauth2_url);
}
if (ret == -1) {
return PAM_SYSTEM_ERR;
}

ret = do_pam_conversation(pamh, PAM_PROMPT_ECHO_OFF, msg, NULL, &answer);
ret = do_pam_conversation(pamh, PAM_TEXT_INFO, msg, NULL, NULL);
free(msg);
if (ret != PAM_SUCCESS) {
D(("do_pam_conversation failed."));
return ret;
}

/* We don't care about answer here. We just need to notify that the
* authentication has finished. */
free(answer);
if (prompt != NULL && prompt[0] != '\0') {
char *answer = NULL;

ret = do_pam_conversation(pamh, PAM_PROMPT_ECHO_OFF, prompt, NULL, &answer);
if (ret != PAM_SUCCESS) {
D(("do_pam_conversation failed."));
return ret;
}

/* We don't care about answer here. We just need to notify that the
* authentication has finished. */
free(answer);
}

pi->pam_authtok = strdup(pi->oauth2_pin);
pi->pam_authtok_type = SSS_AUTHTOK_TYPE_OAUTH2;
pi->pam_authtok_size=strlen(pi->oauth2_pin);
pi->pam_authtok_size = strlen(pi->oauth2_pin);

return PAM_SUCCESS;
}
Expand Down Expand Up @@ -2608,6 +2618,10 @@ static int prompt_by_config(pam_handle_t *pamh, struct pam_items *pi)
pc_get_passkey_inter_prompt(pi->pc[c]),
pc_get_passkey_touch_prompt(pi->pc[c]));
break;
case PC_TYPE_OAUTH2:
ret = prompt_oauth2(pamh, pi,
pc_get_oauth2_inter_prompt(pi->pc[c]));
break;
case PC_TYPE_SMARTCARD:
ret = prompt_sc_pin(pamh, pi);
/* Todo: add extra string option */
Expand Down Expand Up @@ -2647,13 +2661,13 @@ static int get_authtok_for_authentication(pam_handle_t *pamh,
}
pi->pam_authtok_size = strlen(pi->pam_authtok);
} else {
if (pi->oauth2_url != NULL) {
/* Prompt config is not supported for OAuth2. */
ret = prompt_oauth2(pamh, pi);
} else if (pi->pc != NULL) {
if (pi->pc != NULL) {
ret = prompt_by_config(pamh, pi);
} else {
if (pi->cert_list != NULL) {
if (pi->oauth2_url != NULL) {
/* Prompt config is not supported for OAuth2. */
ret = prompt_oauth2(pamh, pi, _("Press ENTER to continue."));
} else if (pi->cert_list != NULL) {
if (pi->cert_list->next == NULL) {
/* Only one certificate */
pi->selected_cert = pi->cert_list;
Expand Down
Loading