Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Passwordless-GDM: enable authentication method selection and EIdP login #9

Closed
wants to merge 12 commits into from
61 changes: 61 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,8 @@ if HAVE_CMOCKA
test_sssd_krb5_locator_plugin \
test_confdb \
test_krb5_idp_plugin \
test_sss_pam_data \
test_pamsrv_json \
$(NULL)


Expand Down Expand Up @@ -743,6 +745,7 @@ dist_noinst_HEADERS = \
src/responder/common/cache_req/cache_req_private.h \
src/responder/pam/pamsrv.h \
src/responder/pam/pam_helpers.h \
src/responder/pam/pamsrv_json.h \
src/responder/pam/pamsrv_passkey.h \
src/responder/nss/nss_private.h \
src/responder/nss/nss_protocol.h \
Expand Down Expand Up @@ -1561,6 +1564,7 @@ endif
sssd_pam_SOURCES = \
src/responder/pam/pamsrv.c \
src/responder/pam/pamsrv_cmd.c \
src/responder/pam/pamsrv_json.c \
src/responder/pam/pamsrv_p11.c \
src/responder/pam/pamsrv_dp.c \
src/responder/pam/pamsrv_gssapi.c \
Expand All @@ -1583,6 +1587,7 @@ sssd_pam_LDADD = \
$(PAM_LIBS) \
$(SYSTEMD_DAEMON_LIBS) \
$(GSSAPI_KRB5_LIBS) \
$(JANSSON_LIBS) \
libsss_certmap.la \
$(SSSD_INTERNAL_LTLIBS) \
libsss_iface.la \
Expand Down Expand Up @@ -2634,6 +2639,7 @@ pam_srv_tests_SOURCES = \
src/tests/cmocka/common_utils.c \
src/sss_client/pam_message.c \
src/responder/pam/pamsrv_cmd.c \
src/responder/pam/pamsrv_json.c \
src/responder/pam/pamsrv_p11.c \
src/responder/pam/pamsrv_gssapi.c \
src/responder/pam/pam_helpers.c \
Expand Down Expand Up @@ -2663,6 +2669,7 @@ pam_srv_tests_LDADD = \
$(SSSD_INTERNAL_LTLIBS) \
$(SYSTEMD_DAEMON_LIBS) \
$(GSSAPI_KRB5_LIBS) \
$(JANSSON_LIBS) \
libsss_test_common.la \
libsss_idmap.la \
libsss_certmap.la \
Expand All @@ -2673,6 +2680,60 @@ if BUILD_PASSKEY
pam_srv_tests_SOURCES += src/responder/pam/pamsrv_passkey.c
endif # BUILD_PASSKEY

test_pamsrv_json_SOURCES = \
$(TEST_MOCK_RESP_OBJ) \
src/responder/pam/pamsrv_cmd.c \
src/responder/pam/pamsrv_json.c \
src/responder/pam/pamsrv_p11.c \
src/responder/pam/pamsrv_gssapi.c \
src/responder/pam/pam_helpers.c \
src/responder/pam/pamsrv_dp.c \
src/responder/pam/pam_prompting_config.c \
src/sss_client/pam_sss_prompt_config.c \
src/tests/cmocka/test_pamsrv_json.c \
$(NULL)
if BUILD_PASSKEY
test_pamsrv_json_SOURCES += src/responder/pam/pamsrv_passkey.c
endif # BUILD_PASSKEY
test_pamsrv_json_CFLAGS = \
$(AM_CFLAGS) \
$(NULL)
test_pamsrv_json_LDFLAGS = \
-Wl,-wrap,json_array_append_new \
$(NULL)
test_pamsrv_json_LDADD = \
$(LIBADD_DL) \
$(CMOCKA_LIBS) \
$(PAM_LIBS) \
$(SSSD_LIBS) \
$(SSSD_INTERNAL_LTLIBS) \
$(JANSSON_LIBS) \
$(GSSAPI_KRB5_LIBS) \
$(TALLOC_LIBS) \
libsss_test_common.la \
libsss_idmap.la \
libsss_certmap.la \
libsss_iface.la \
libsss_sbus.la \
$(NULL)

test_sss_pam_data_SOURCES = \
src/util/sss_pam_data.c \
src/tests/cmocka/test_sss_pam_data.c \
$(NULL)
test_sss_pam_data_CFLAGS = \
$(AM_CFLAGS) \
$(NULL)
test_sss_pam_data_LDFLAGS = \
$(NULL)
test_sss_pam_data_LDADD = \
$(CMOCKA_LIBS) \
$(SSSD_LIBS) \
$(SSSD_INTERNAL_LTLIBS) \
$(TALLOC_LIBS) \
libsss_test_common.la \
$(NULL)

EXTRA_ssh_srv_tests_DEPENDENCIES = \
$(ldblib_LTLIBRARIES) \
$(NULL)
Expand Down
4 changes: 4 additions & 0 deletions src/confdb/confdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@
#define CONFDB_PAM_PASSKEY_AUTH "pam_passkey_auth"
#define CONFDB_PAM_PASSKEY_CHILD_TIMEOUT "passkey_child_timeout"
#define CONFDB_PAM_PASSKEY_DEBUG_LIBFIDO2 "passkey_debug_libfido2"
#define CONFDB_PAM_JSON_SERVICES "pam_json_services"

/* SUDO */
#define CONFDB_SUDO_CONF_ENTRY "config/sudo"
Expand Down Expand Up @@ -324,6 +325,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_EIDP "eidp"
#define CONFDB_PC_EIDP_INIT_PROMPT "init_prompt"
#define CONFDB_PC_EIDP_LINK_PROMPT "link_prompt"

struct confdb_ctx;

Expand Down
1 change: 1 addition & 0 deletions src/config/SSSDConfig/sssdoptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ def __init__(self):
'pam_passkey_auth': _('Allow passkey device authentication.'),
'passkey_child_timeout': _('How many seconds will pam_sss wait for passkey_child to finish'),
'passkey_debug_libfido2': _('Enable debugging in the libfido2 library'),
'pam_json_services': _('Enable JSON protocol for authentication methods selection.'),

# [sudo]
'sudo_timed': _('Whether to evaluate the time-based attributes in sudo rules'),
Expand Down
8 changes: 8 additions & 0 deletions src/config/cfg_rules.ini
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ option = pam_gssapi_indicators_map
option = pam_passkey_auth
option = passkey_child_timeout
option = passkey_debug_libfido2
option = pam_json_services

[rule/allowed_sudo_options]
validator = ini_allowed_options
Expand Down Expand Up @@ -326,6 +327,13 @@ option = interactive_prompt
option = touch
option = touch_prompt

[rule/allowed_prompting_eidp_options]
validator = ini_allowed_options
section_re = ^prompting/eidp$

option = init_prompt
option = link_prompt

[rule/allowed_prompting_password_subsec_options]
validator = ini_allowed_options
section_re = ^prompting/password/[^/\@]\+$
Expand Down
1 change: 1 addition & 0 deletions src/config/etc/sssd.api.conf
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ pam_gssapi_indicators_map = str, None, false
pam_passkey_auth = bool, None, false
passkey_child_timeout = int, None, false
passkey_debug_libfido2 = bool, None, false
pam_json_services = str, None, false

[sudo]
# sudo service
Expand Down
7 changes: 7 additions & 0 deletions src/external/pam.m4
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,10 @@ AC_SUBST(GDM_PAM_EXTENSIONS_CFLAGS)
AS_IF([test x"$found_gdm_pam_extensions" = xyes],
[AC_DEFINE_UNQUOTED(HAVE_GDM_PAM_EXTENSIONS, 1,
[Build with gdm-pam-extensions support])])

AS_IF([test x"$found_gdm_pam_extensions" = xyes],
[AC_CHECK_HEADER([gdm/gdm-custom-json-pam-extension.h],
[AC_DEFINE_UNQUOTED(HAVE_GDM_CUSTOM_JSON_PAM_EXTENSION, 1,
[Build with gdm-custom-json-pam-extension support])])])
AM_CONDITIONAL([HAVE_GDM_CUSTOM_JSON_PAM_EXTENSION],
[test x"$found_gdm_pam_extensions" = xyes])
3 changes: 3 additions & 0 deletions src/man/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ SSSD_NON_ROOT_USER_CONDS = ;with_non_root_user_support
else
SSSD_NON_ROOT_USER_CONDS = ;without_non_root_user_support
endif
if HAVE_GDM_CUSTOM_JSON_PAM_EXTENSION
JSON_PAM_CONDS = ;build_json_pam
endif


CONDS = with_false$(SUDO_CONDS)$(AUTOFS_CONDS)$(SSH_CONDS)$(PAC_RESPONDER_CONDS)$(IFP_CONDS)$(GPO_CONDS)$(SYSTEMD_CONDS)$(KCM_CONDS)$(STAP_CONDS)$(KCM_RENEWAL_CONDS)$(LOCKFREE_CLIENT_CONDS)$(HAVE_INOTIFY_CONDS)$(PASSKEY_CONDS)$(FILES_PROVIDER_CONDS)$(SSSD_NON_ROOT_USER_CONDS)$(ENUM_CONDS)
Expand Down
49 changes: 49 additions & 0 deletions src/man/sssd.conf.5.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2062,6 +2062,29 @@ pam_gssapi_indicators_map = sudo:pkinit, sudo-i:pkinit
</para>
</listitem>
</varlistentry>
<varlistentry condition="build_json_pam">
<term>pam_json_services (string)</term>
<listitem>
<para>
Comma separated list of PAM services which can
handle the JSON protocol for selecting
authentication mechanisms
</para>
<para>
To disable JSON protocol, set this option
to <quote>-</quote> (dash).
</para>
<para>
Example:
<programlisting>
pam_json_services = gdm-switchable-auth
</programlisting>
</para>
<para>
Default: - (JSON protocol is disabled)
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect2>

Expand Down Expand Up @@ -4547,6 +4570,32 @@ ldap_user_extra_attrs = phone:telephoneNumber
</listitem>
</varlistentry>
</variablelist>
<variablelist>
<varlistentry>
<term>[prompting/eidp]</term>
<listitem>
<para>to configure External Identity Provider
authentication prompting, allowed options are:
<variablelist>
<varlistentry>
<term>init_prompt</term>
<listitem>
<para>to change the message of the initial prompt.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>link_prompt</term>
<listitem>
<para>to change the message of the link prompt.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
It is possible to add a subsection for specific PAM services,
Expand Down
54 changes: 52 additions & 2 deletions src/responder/pam/pam_prompting_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

#define DEFAULT_PASSKEY_PROMPT_INTERACTIVE _("Insert your Passkey device, then press ENTER.")
#define DEFAULT_PASSKEY_PROMPT_TOUCH _("Please touch the device.")
#define DEFAULT_EIDP_PROMPT_INIT _("Log In.")
#define DEFAULT_EIDP_PROMPT_LINK _("Log in online with another device.")

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

return ret;
}

static errno_t pam_set_eidp_prompting_options(TALLOC_CTX *tmp_ctx,
struct confdb_ctx *cdb,
const char *section,
struct prompt_config ***pc_list)
{
char *init_prompt = NULL;
char *link_prompt = NULL;
int ret;

ret = confdb_get_string(cdb, tmp_ctx, section, CONFDB_PC_EIDP_INIT_PROMPT,
DEFAULT_EIDP_PROMPT_INIT, &init_prompt);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "confdb_get_string failed, using defaults");
}

ret = confdb_get_string(cdb, tmp_ctx, section, CONFDB_PC_EIDP_LINK_PROMPT,
DEFAULT_EIDP_PROMPT_LINK, &link_prompt);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "confdb_get_string failed, using defaults");
}

ret = pc_list_add_eidp(pc_list, init_prompt, link_prompt);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "pc_list_add_eidp 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 @@ -212,7 +244,8 @@ static errno_t pam_set_prompting_options(struct confdb_ctx *cdb,
return ret;
}

errno_t pam_eval_prompting_config(struct pam_ctx *pctx, struct pam_data *pd)
errno_t pam_eval_prompting_config(struct pam_ctx *pctx, struct pam_data *pd,
struct prompt_config ***_pc_list)
{
int ret;
struct prompt_config **pc_list = NULL;
Expand Down Expand Up @@ -245,6 +278,20 @@ errno_t pam_eval_prompting_config(struct pam_ctx *pctx, struct pam_data *pd)
}
}

/* There's no option to enable/disable EIdP in PAM config, thus prompt
* options are always checked. */
ret = pam_set_prompting_options(pctx->rctx->cdb, pd->service,
pctx->prompting_config_sections,
pctx->num_prompting_config_sections,
CONFDB_PC_TYPE_EIDP,
pam_set_eidp_prompting_options,
&pc_list);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"pam_set_prompting_options failed.\n");
goto done;
}

if (types.cert_auth) {
/* If certificate based authentication is possilbe, i.e. a Smartcard
* or similar with the mapped certificate is available we currently
Expand Down Expand Up @@ -300,10 +347,13 @@ errno_t pam_eval_prompting_config(struct pam_ctx *pctx, struct pam_data *pd)
}
}

*_pc_list = pc_list;
ret = EOK;
done:
free(resp_data);
pc_list_free(pc_list);
if (ret != EOK) {
pc_list_free(pc_list);
}

return ret;
}
24 changes: 24 additions & 0 deletions src/responder/pam/pamsrv.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,30 @@ static int pam_process_init(TALLOC_CTX *mem_ctx,
}
}

/* Check if JSON authentication selection method is enabled for any PAM
* services
*/
ret = confdb_get_string(pctx->rctx->cdb, pctx, CONFDB_PAM_CONF_ENTRY,
CONFDB_PAM_JSON_SERVICES, "-", &tmpstr);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE,
"Failed to determine json services.\n");
goto done;
}
DEBUG(SSSDBG_TRACE_INTERNAL, "Found value [%s] for option [%s].\n", tmpstr,
CONFDB_PAM_JSON_SERVICES);

if (tmpstr != NULL) {
ret = split_on_separator(pctx, tmpstr, ',', true, true,
&pctx->json_services, NULL);
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE,
"split_on_separator() failed [%d]: [%s].\n", ret,
sss_strerror(ret));
goto done;
}
}

/* The responder is initialized. Now tell it to the monitor. */
ret = sss_monitor_register_service(rctx, rctx->sbus_conn,
SSS_PAM_SBUS_SERVICE_NAME,
Expand Down
Loading
Loading