diff --git a/configure.ac b/configure.ac index 55ca9fb5..aa4bffd0 100644 --- a/configure.ac +++ b/configure.ac @@ -95,18 +95,10 @@ AC_ARG_ENABLE(ipv6, AS_HELP_STRING([--enable-ipv6], AC_ARG_ENABLE(ipv6only, AS_HELP_STRING([--enable-ipv6only], [Build IPv6-only (default: no)]), [], [enable_ipv6only=no]) -AC_ARG_ENABLE(kerberos, AS_HELP_STRING([--enable-kerberos], - [Build kerberos support (prefer --enable-pam if available) (default: no)]), - [], [enable_kerberos=no]) -AM_CONDITIONAL(SESMAN_KERBEROS, [test x$enable_kerberos = xyes]) AC_ARG_ENABLE(bsd, AS_HELP_STRING([--enable-bsd], [Build BSD auth support (default: no)]), [], [enable_bsd=no]) AM_CONDITIONAL(SESMAN_BSD, [test x$enable_bsd = xyes]) -AC_ARG_ENABLE(pamuserpass, AS_HELP_STRING([--enable-pamuserpass], - [Build PAM userpass support (default: no)]), - [], [enable_pamuserpass=no]) -AM_CONDITIONAL(SESMAN_PAMUSERPASS, [test x$enable_pamuserpass = xyes]) AC_ARG_ENABLE(pam-config, AS_HELP_STRING([--enable-pam-config=CONF], [Select PAM config to install: arch, debian, redhat, suse, freebsd, macos, unix (default: autodetect)])) @@ -388,24 +380,10 @@ then AUTHMOD_OBJ=verify_user_bsd.lo AUTHMOD_LIB= fi -if test x$enable_kerberos = xyes -then - auth_cnt=`expr $auth_cnt + 1` - auth_mech="Kerberos" - AUTHMOD_OBJ=verify_user_kerberos.lo - AUTHMOD_LIB=-lkrb5 -fi -if test x$enable_pamuserpass = xyes -then - auth_cnt=`expr $auth_cnt + 1` - auth_mech="PAM userpass" - AUTHMOD_OBJ=verify_user_pam_userpass.lo - AUTHMOD_LIB="-lpam -lpam_userpass" -fi if test $auth_cnt -gt 1 then - AC_MSG_ERROR([--enable-pam, --enable-bsd, --enable-pamuserpass and --enable-kerberos are mutually exclusive]) + AC_MSG_ERROR([--enable-pam and --enable-bsd are mutually exclusive]) fi AC_SUBST([AUTHMOD_OBJ]) diff --git a/instfiles/pam.d/Makefile.am b/instfiles/pam.d/Makefile.am index feeaf7a2..bda67ed0 100644 --- a/instfiles/pam.d/Makefile.am +++ b/instfiles/pam.d/Makefile.am @@ -15,16 +15,8 @@ CLEANFILES = xrdp-sesman if SESMAN_NOPAM PAMFILE = else -if SESMAN_PAMUSERPASS -PAMFILE = -else -if SESMAN_KERBEROS -PAMFILE = -else PAMFILE = xrdp-sesman endif -endif -endif pamddir = $(pamconfdir) diff --git a/sesman/libsesman/Makefile.am b/sesman/libsesman/Makefile.am index 2beebd1e..fd2b1386 100644 --- a/sesman/libsesman/Makefile.am +++ b/sesman/libsesman/Makefile.am @@ -45,9 +45,7 @@ module_LTLIBRARIES = \ EXTRA_libsesman_la_SOURCES = \ verify_user.c \ verify_user_bsd.c \ - verify_user_kerberos.c \ - verify_user_pam.c \ - verify_user_pam_userpass.c + verify_user_pam.c # Make sure the right authentication module is pulled in libsesman_la_DEPENDENCIES = $(AUTHMOD_OBJ) diff --git a/sesman/libsesman/verify_user_kerberos.c b/sesman/libsesman/verify_user_kerberos.c deleted file mode 100644 index e822d72d..00000000 --- a/sesman/libsesman/verify_user_kerberos.c +++ /dev/null @@ -1,237 +0,0 @@ -/** - * xrdp: A Remote Desktop Protocol server. - * - * Copyright (C) Jay Sorg 2004-2013 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * - * @file verify_user_kerberos.c - * @brief Authenticate user using kerberos - * @author Jay Sorg - * - */ - -#if defined(HAVE_CONFIG_H) -#include -#endif - -#include "arch.h" -#include "sesman_auth.h" -#include "os_calls.h" -#include "string_calls.h" -#include "log.h" - -#include - -struct auth_info -{ - krb5_context ctx; - krb5_ccache cc; - krb5_principal me; -}; - -/******************************************************************************/ -/* Logs a kerberos error code */ -static void -log_kerberos_failure(krb5_context ctx, krb5_error_code code, const char *where) -{ - const char *errstr = krb5_get_error_message(ctx, code); - LOG(LOG_LEVEL_ERROR, "Kerberos call to %s failed [%s]", where, errstr); - krb5_free_error_message(ctx, errstr); -} - -/******************************************************************************/ -int -auth_end(struct auth_info *auth_info) -{ - if (auth_info != NULL) - { - if (auth_info->me) - { - krb5_free_principal(auth_info->ctx, auth_info->me); - } - - if (auth_info->cc) - { - krb5_cc_close(auth_info->ctx, auth_info->cc); - } - - if (auth_info->ctx) - { - krb5_free_context(auth_info->ctx); - } - - g_memset(auth_info, 0, sizeof(*auth_info)); - g_free(auth_info); - } - return 0; -} - -/******************************************************************************/ -/* Checks Kerberos can be used - * - * If all is well, an auth_info struct is returned */ -static struct auth_info * -k5_begin(const char *username) -{ - int ok = 0; - struct auth_info *auth_info = g_new0(struct auth_info, 1); - krb5_error_code code; - - if (auth_info == NULL) - { - LOG(LOG_LEVEL_ERROR, "Out of memory in k5_begin()"); - } - else if ((code = krb5_init_context(&auth_info->ctx)) != 0) - { - LOG(LOG_LEVEL_ERROR, "Can't init Kerberos context"); - } - /* Determine the credentials cache to use */ - else if ((code = krb5_cc_default(auth_info->ctx, &auth_info->cc)) != 0) - { - log_kerberos_failure(auth_info->ctx, code, "krb5_cc_default"); - } - /* Parse the username into a full principal */ - else if ((code = krb5_parse_name(auth_info->ctx, - username, &auth_info->me)) != 0) - { - log_kerberos_failure(auth_info->ctx, code, "krb5_parse_name"); - } - else - { - ok = 1; - } - - if (!ok) - { - auth_end(auth_info); - auth_info = NULL; - } - - return auth_info; -} - - -/******************************************************************************/ -/* returns boolean */ -static enum scp_login_status -k5_kinit(struct auth_info *auth_info, const char *password) -{ - enum scp_login_status status = E_SCP_LOGIN_GENERAL_ERROR; - krb5_creds my_creds; - krb5_error_code code = 0; - - code = krb5_get_init_creds_password(auth_info->ctx, - &my_creds, auth_info->me, - password, NULL, NULL, - 0, - NULL, - NULL); - if (code != 0) - { - log_kerberos_failure(auth_info->ctx, code, - "krb5_get_init_creds_password"); - status = E_SCP_LOGIN_NOT_AUTHENTICATED; - } - else - { - /* - * Try to store the creds in the credentials cache - */ - if ((code = krb5_cc_initialize(auth_info->ctx, auth_info->cc, - auth_info->me)) != 0) - { - log_kerberos_failure(auth_info->ctx, code, "krb5_cc_initialize"); - } - else if ((code = krb5_cc_store_cred(auth_info->ctx, auth_info->cc, - &my_creds)) != 0) - { - log_kerberos_failure(auth_info->ctx, code, "krb5_cc_store_cred"); - } - else - { - status = E_SCP_LOGIN_OK; - } - - /* Prevent double-free of the client principal */ - if (my_creds.client == auth_info->me) - { - my_creds.client = NULL; - } - - krb5_free_cred_contents(auth_info->ctx, &my_creds); - } - - return status; -} - -/******************************************************************************/ -/* returns non-NULL for success */ -struct auth_info * -auth_userpass(const char *user, const char *pass, - const char *client_ip, enum scp_login_status *errorcode) -{ - enum scp_login_status status = E_SCP_LOGIN_GENERAL_ERROR; - struct auth_info *auth_info = k5_begin(user); - - if (auth_info) - { - status = k5_kinit(auth_info, pass); - if (status != E_SCP_LOGIN_OK) - { - auth_end(auth_info); - auth_info = NULL; - } - } - - if (errorcode != NULL) - { - *errorcode = status; - } - - return auth_info; -} - -/******************************************************************************/ -/* returns non-NULL for success */ -struct auth_info * -auth_uds(const char *user, enum scp_login_status *errorcode) -{ - struct auth_info *auth_info = k5_begin(user); - - if (errorcode != NULL) - { - *errorcode = - (auth_info != NULL) ? E_SCP_LOGIN_OK : E_SCP_LOGIN_GENERAL_ERROR; - } - - return auth_info; -} - -/******************************************************************************/ -/* returns error */ -int -auth_start_session(struct auth_info *auth_info, const char *display) -{ - return 0; -} - -/******************************************************************************/ -int -auth_set_env(struct auth_info *auth_info) -{ - return 0; -} diff --git a/sesman/libsesman/verify_user_pam_userpass.c b/sesman/libsesman/verify_user_pam_userpass.c deleted file mode 100644 index 73c7d0da..00000000 --- a/sesman/libsesman/verify_user_pam_userpass.c +++ /dev/null @@ -1,365 +0,0 @@ -/** - * xrdp: A Remote Desktop Protocol server. - * - * Copyright (C) Jay Sorg 2004-2013 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * - * @file verify_user_pam.c - * @brief Authenticate user using pam - * @author Jay Sorg - * - */ - -#if defined(HAVE_CONFIG_H) -#include -#endif - -#include "arch.h" -#include "os_calls.h" -#include "log.h" -#include "string_calls.h" -#include "sesman_auth.h" - -#include - -#include -#include - -#define SERVICE "xrdp" - -struct auth_info -{ - pam_userpass_t userpass; - int session_opened; - int did_setcred; - struct pam_conv pamc; - pam_handle_t *ph; -}; - -/******************************************************************************/ - -/** Performs PAM operations common to login methods - * - * @param auth_info Module auth_info structure - * @param client_ip Client IP if known, or NULL - * @param need_pam_authenticate True if user must be authenticated as - * well as authorized - * @return Code describing the success of the operation - * - * The username is assumed to be supplied by the caller in - * auth_info->userpass.user - */ -static enum scp_login_status -common_pam_login(struct auth_info *auth_info, - const char *client_ip, - int need_pam_authenticate) -{ - int perror; - - perror = pam_start(SERVICE, auth_info->userpass.user, - &(auth_info->pamc), &(auth_info->ph)); - - if (perror != PAM_SUCCESS) - { - LOG(LOG_LEVEL_ERROR, "pam_start failed: %s", - pam_strerror(auth_info->ph, perror)); - pam_end(auth_info->ph, perror); - return E_SCP_LOGIN_GENERAL_ERROR; - } - - if (client_ip != NULL && client_ip[0] != '\0') - { - perror = pam_set_item(auth_info->ph, PAM_RHOST, client_ip); - if (perror != PAM_SUCCESS) - { - LOG(LOG_LEVEL_ERROR, "pam_set_item(PAM_RHOST) failed: %s", - pam_strerror(auth_info->ph, perror)); - } - } - - perror = pam_set_item(auth_info->ph, PAM_TTY, SERVICE); - if (perror != PAM_SUCCESS) - { - LOG(LOG_LEVEL_ERROR, "pam_set_item(PAM_TTY) failed: %s", - pam_strerror(auth_info->ph, perror)); - } - - if (need_pam_authenticate) - { - perror = pam_authenticate(auth_info->ph, 0); - - if (perror != PAM_SUCCESS) - { - LOG(LOG_LEVEL_ERROR, "pam_authenticate failed: %s", - pam_strerror(auth_info->ph, perror)); - pam_end(auth_info->ph, perror); - return E_SCP_LOGIN_NOT_AUTHENTICATED; - } - } - /* From man page: - The pam_acct_mgmt function is used to determine if the users account is - valid. It checks for authentication token and account expiration and - verifies access restrictions. It is typically called after the user has - been authenticated. - */ - perror = pam_acct_mgmt(auth_info->ph, 0); - - if (perror != PAM_SUCCESS) - { - LOG(LOG_LEVEL_ERROR, "pam_acct_mgmt failed: %s", - pam_strerror(auth_info->ph, perror)); - pam_end(auth_info->ph, perror); - return E_SCP_LOGIN_NOT_AUTHORIZED; - } - - return E_SCP_LOGIN_OK; -} - - -/******************************************************************************/ -/* returns non-NULL for success - * Detailed error code is in the errorcode variable */ - -struct auth_info * -auth_userpass(const char *user, const char *pass, - const char *client_ip, enum scp_login_status *errorcode) -{ - struct auth_info *auth_info; - enum scp_login_status status; - - auth_info = g_new0(struct auth_info, 1); - if (auth_info == NULL) - { - status = E_SCP_LOGIN_NO_MEMORY; - } - else - { - auth_info->userpass.user = user; - auth_info->userpass.pass = pass; - - auth_info->pamc.conv = &pam_userpass_conv; - auth_info->pamc.appdata_ptr = &(auth_info->userpass); - status = common_pam_login(auth_info, client_ip, 1); - - if (status != E_SCP_LOGIN_OK) - { - g_free(auth_info); - auth_info = NULL; - } - } - - if (errorcode != NULL) - { - *errorcode = status; - } - - return auth_info; -} - -/******************************************************************************/ - -struct auth_info * -auth_uds(const char *user, enum scp_login_status *errorcode) -{ - struct auth_info *auth_info; - enum scp_login_status status; - - auth_info = g_new0(struct auth_info, 1); - if (auth_info == NULL) - { - status = E_SCP_LOGIN_NO_MEMORY; - } - else - { - auth_info->userpass.user = user; - status = common_pam_login(auth_info, NULL, 0); - - if (status != E_SCP_LOGIN_OK) - { - g_free(auth_info); - auth_info = NULL; - } - } - - if (errorcode != NULL) - { - *errorcode = status; - } - - return auth_info; -} - -/******************************************************************************/ - -/* returns error */ -static int -auth_start_session_private(struct auth_info *auth_info, const char *display) -{ - // For Linux and maybe other systems, pam_systemd needs to know the - // session type in order to set the session up correctly - const char *session_type; - if (g_get_x11_display_from_display_string(display) >= 0) - { - session_type = "x11"; - } - else - { - session_type = "wayland"; - } - g_setenv_log("XDG_SESSION_TYPE", session_type, 1); - - int error = pam_set_item(auth_info->ph, PAM_TTY, display); - - if (error != PAM_SUCCESS) - { - LOG(LOG_LEVEL_ERROR, "pam_set_item(PAM_TTY) failed: %s", - pam_strerror(auth_info->ph, error)); - return 1; - } - - error = pam_setcred(auth_info->ph, PAM_ESTABLISH_CRED); - - if (error != PAM_SUCCESS) - { - LOG(LOG_LEVEL_ERROR, "pam_setcred failed: %s", - pam_strerror(auth_info->ph, error)); - return 1; - } - - auth_info->did_setcred = 1; - error = pam_open_session(auth_info->ph, 0); - - if (error != PAM_SUCCESS) - { - LOG(LOG_LEVEL_ERROR, "pam_open_session failed: %s", - pam_strerror(auth_info->ph, error)); - return 1; - } - - auth_info->session_opened = 1; - return 0; -} - -/******************************************************************************/ -/** - * Main routine to start a session - * - * Calls the private routine and logs an additional error if the private - * routine fails - */ -int -auth_start_session(struct auth_info *auth_info, const char *display) -{ - int result = auth_start_session_private(auth_info, display); - if (result != 0) - { - LOG(LOG_LEVEL_ERROR, - "Can't start PAM session. See PAM logging for more info"); - } - - return result; -} - -/******************************************************************************/ -/* returns error */ -static int -auth_stop_session(struct auth_info *auth_info) -{ - int rv = 0; - int error; - - if (auth_info->session_opened) - { - error = pam_close_session(auth_info->ph, 0); - if (error != PAM_SUCCESS) - { - LOG(LOG_LEVEL_ERROR, "pam_close_session failed: %s", - pam_strerror(auth_info->ph, error)); - rv = 1; - } - else - { - auth_info->session_opened = 0; - } - } - - if (auth_info->did_setcred) - { - pam_setcred(auth_info->ph, PAM_DELETE_CRED); - auth_info->did_setcred = 0; - } - - return rv; -} - -/******************************************************************************/ -/* returns error */ -/* cleanup */ -int -auth_end(struct auth_info *auth_info) -{ - if (auth_info != NULL) - { - if (auth_info->ph != 0) - { - auth_stop_session(auth_info); - - pam_end(auth_info->ph, PAM_SUCCESS); - auth_info->ph = 0; - } - } - - g_free(auth_info); - return 0; -} - -/******************************************************************************/ -/* returns error */ -/* set any pam env vars */ -int -auth_set_env(struct auth_info *auth_info) -{ - char **pam_envlist; - char **pam_env; - - if (auth_info != NULL) - { - /* export PAM environment */ - pam_envlist = pam_getenvlist(auth_info->ph); - - if (pam_envlist != NULL) - { - for (pam_env = pam_envlist; *pam_env != NULL; ++pam_env) - { - char *str = *pam_env; - char *eq_pos = strchr(str, '='); - - if (eq_pos != NULL) - { - *eq_pos = '\0'; - g_setenv_log(str, eq_pos + 1, 1); - } - - g_free(str); - } - - g_free(pam_envlist); - } - } - - return 0; -}