Add authtest

Also, change the sesman Makefile generation to make it easy to pick the
correct authorization module for the authtest utility.
This commit is contained in:
matt335672 2022-12-02 17:02:46 +00:00
parent df83fbf9bf
commit 767d861df4
5 changed files with 348 additions and 26 deletions

View File

@ -325,25 +325,40 @@ AM_CONDITIONAL([USE_FREETYPE2], [test "x$use_freetype2" = xyes])
# Check only one auth mechanism is specified, and give it a name
auth_cnt=0
auth_mech="Builtin"
AUTHMOD_SRC=verify_user.c
AUTHMOD_OBJ=verify_user.${OBJEXT}
AUTHMOD_LIB=-lcrypt
if test x$enable_pam = xyes
then
auth_cnt=`expr $auth_cnt + 1`
auth_mech="PAM"
AUTHMOD_SRC=verify_user_pam.c
AUTHMOD_OBJ=verify_user_pam.${OBJEXT}
AUTHMOD_LIB=-lpam
fi
if test x$bsd = xtrue
then
auth_cnt=`expr $auth_cnt + 1`
auth_mech="BSD"
AUTHMOD_SRC=verify_user_bsd.c
AUTHMOD_OBJ=verify_user_bsd.${OBJEXT}
AUTHMOD_LIB=
fi
if test x$enable_kerberos = xyes
then
auth_cnt=`expr $auth_cnt + 1`
auth_mech="Kerberos"
AUTHMOD_SRC=verify_user_kerberos.c
AUTHMOD_OBJ=verify_user_kerberos.${OBJEXT}
AUTHMOD_LIB=-lkrb5
fi
if test x$enable_pamuserpass = xyes
then
auth_cnt=`expr $auth_cnt + 1`
auth_mech="PAM userpass"
AUTHMOD_SRC=verify_user_pam_userpass.c
AUTHMOD_OBJ=verify_user_pam_userpass.${OBJEXT}
AUTHMOD_LIB="-lpam -lpam_userpass"
fi
if test $auth_cnt -gt 1
@ -351,6 +366,10 @@ then
AC_MSG_ERROR([--enable-pam, --enable-bsd, --enable-pamuserpass and --enable-kerberos are mutually exclusive])
fi
AC_SUBST([AUTHMOD_SRC])
AC_SUBST([AUTHMOD_OBJ])
AC_SUBST([AUTHMOD_LIB])
# checking if pam should be autodetected.
if test "x$enable_pam" = "xyes"
then

View File

@ -12,29 +12,6 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/common \
-I$(top_srcdir)/libipm
if SESMAN_BSD
AUTH_C = verify_user_bsd.c
AUTH_LIB =
else
if SESMAN_PAMUSERPASS
AUTH_C = verify_user_pam_userpass.c
AUTH_LIB = -lpam -lpam_userpass
else
if SESMAN_KERBEROS
AUTH_C = verify_user_kerberos.c
AUTH_LIB = -lkrb5
else
if SESMAN_NOPAM
AUTH_C = verify_user.c
AUTH_LIB = -lcrypt
else
AUTH_C = verify_user_pam.c
AUTH_LIB = -lpam
endif
endif
endif
endif
sbin_PROGRAMS = \
xrdp-sesman
@ -57,13 +34,26 @@ xrdp_sesman_SOURCES = \
sig.c \
sig.h \
xauth.c \
xauth.h \
$(AUTH_C)
xauth.h
# Possible authentication modules
# See https://www.gnu.org/software/automake/manual/html_node/Conditional-Sources.html
EXTRA_xrdp_sesman_SOURCES = \
verify_user.c \
verify_user_bsd.c \
verify_user_kerberos.c \
verify_user_pam.c \
verify_user_pam_userpass.c
# Make sure the right authentication module is pulled in
xrdp_sesman_DEPENDENCIES = $(AUTHMOD_OBJ)
# Make sure the right authentication module is linked with
xrdp_sesman_LDADD = \
$(AUTHMOD_OBJ) \
$(top_builddir)/libipm/libipm.la \
$(top_builddir)/common/libcommon.la \
$(AUTH_LIB) \
$(AUTHMOD_LIB) \
-lpthread
sesmansysconfdir=$(sysconfdir)/xrdp

View File

@ -1,9 +1,11 @@
AM_CPPFLAGS = \
-DXRDP_SYSCONF_PATH=\"${sysconfdir}\" \
-DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \
-DXRDP_SBIN_PATH=\"${sbindir}\" \
-DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \
-DXRDP_PID_PATH=\"${localstatedir}/run\" \
-DXRDP_SOCKET_PATH=\"${socketdir}\" \
-DXRDP_AUTHMOD_SRC=\"../${AUTHMOD_SRC}\" \
-I$(top_srcdir)/common \
-I$(top_srcdir)/libipm \
-I$(top_srcdir)/sesman
@ -16,6 +18,7 @@ bin_PROGRAMS = \
xrdp-dis
noinst_PROGRAMS = \
xrdp-authtest \
xrdp-xcon
xrdp_sesrun_SOURCES = \
@ -38,6 +41,10 @@ xrdp_dis_LDADD = \
xrdp_xcon_SOURCES = \
xcon.c
xrdp_authtest_SOURCES = \
authmod.c \
authtest.c
xrdp_sesrun_LDADD = \
$(top_builddir)/common/libcommon.la \
$(top_builddir)/libipm/libipm.la
@ -51,3 +58,7 @@ xrdp_xcon_LDFLAGS = \
xrdp_xcon_LDADD = \
$(X_PRE_LIBS) -lX11 $(X_EXTRA_LIBS)
xrdp_authtest_LDADD = \
$(top_builddir)/common/libcommon.la \
$(AUTHMOD_LIB)

35
sesman/tools/authmod.c Normal file
View File

@ -0,0 +1,35 @@
/**
* 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 authmod.c
*
* @brief Pull in the configured authentication module
*
* Configured auth module is referenced by the macro define
* XRDP_AUTHMOD_SRC, defined by the configure system
*
* @author Matt Burt
*/
#if defined(HAVE_CONFIG_H)
#include <config_ac.h>
#endif
#include XRDP_AUTHMOD_SRC

267
sesman/tools/authtest.c Normal file
View File

@ -0,0 +1,267 @@
/**
* 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 authtest.c
* @brief An utility to test the compiled-in authentication module
* @author Matt Burt
*
*/
#if defined(HAVE_CONFIG_H)
#include <config_ac.h>
#endif
#include <unistd.h>
#include "log.h"
#include "auth.h"
#include "os_calls.h"
#include "string_calls.h"
#if !defined(PACKAGE_VERSION)
#define PACKAGE_VERSION "???"
#endif
#ifndef MAX_PASSWORD_LEN
# define MAX_PASSWORD_LEN 512
#endif
/**
* Parameters needed to call the auth module
*/
struct authmod_params
{
const char *username;
char password[MAX_PASSWORD_LEN + 1];
const char *command;
int start_session;
};
/**************************************************************************//**
* Prints a brief summary of options and defaults
*/
static void
usage(void)
{
g_printf("xrdp auth module tester v" PACKAGE_VERSION "\n");
g_printf("\n"
"Calls functions in the compiled-in auth module, so that the\n"
"module can be checked simply for functionality, memory leaks,\n"
"etc.\n\n"
"This is a DEVELOPER-ONLY tool\n");
g_printf("\nusage:\n");
g_printf("authtest [options] username\n\n");
g_printf("options:\n");
g_printf(" -p <password>\n"
" -F <file-descriptor> Read password from this file descriptor\n"
" -c <command> Start a session and run the\n"
" specified non-interactive command\n"
" in it\n");
g_printf("Password is prompted if -p or -F are not specified\n");
}
/**************************************************************************//**
* Read a password from a file descriptor
*
* @param fd_str string representing file descriptor
* @param sp Authmod parameter structure for resulting password
* @return !=0 for success
*/
static int
read_password_from_fd(const char *fd_str, struct authmod_params *amp)
{
int result = 0;
int s = g_file_read(atoi(fd_str), amp->password,
sizeof (amp->password) - 1);
if (s < 0)
{
LOG(LOG_LEVEL_ERROR, "Can't read password from fd %s - %s",
fd_str, g_get_strerror());
amp->password[0] = '\0';
}
else
{
amp->password[s] = '\0';
if (s > 0 && amp->password[s - 1] == '\n')
{
amp->password[s - 1] = '\0';
}
result = 1;
}
return result;
}
/**************************************************************************//**
* Parses the program args
*
* @param argc Passed to main
* @param @argv Passed to main
* @param amp Authmod parameter structure for resulting values
* @return !=0 for success
*/
static int
parse_program_args(int argc, char *argv[], struct authmod_params *amp)
{
int params_ok = 1;
int opt;
bool_t password_set = 0;
amp->username = NULL;
amp->password[0] = '\0';
amp->start_session = 0;
amp->command = NULL;
while ((opt = getopt(argc, argv, "c:p:F:")) != -1)
{
switch (opt)
{
case 'c':
if (amp->command)
{
LOG(LOG_LEVEL_WARNING, "Ignoring multiple '%c' options",
(char)opt);
}
else
{
amp->command = optarg;
}
break;
case 'p':
if (password_set)
{
LOG(LOG_LEVEL_WARNING,
"Ignoring option '%c' - password already set ",
(char)opt);
}
else
{
g_strncpy(amp->password, optarg, sizeof(amp->password) - 1);
password_set = 1;
}
break;
case 'F':
if (password_set)
{
LOG(LOG_LEVEL_WARNING,
"Ignoring option '%c' - password already set ",
(char)opt);
}
else
{
if (read_password_from_fd(optarg, amp))
{
password_set = 1;
}
else
{
params_ok = 0;
}
}
break;
default:
LOG(LOG_LEVEL_ERROR, "Unrecognised switch '%c'", (char)opt);
params_ok = 0;
}
}
if (argc <= optind)
{
LOG(LOG_LEVEL_ERROR, "No user name specified");
params_ok = 0;
}
else if ((argc - optind) > 1)
{
LOG(LOG_LEVEL_ERROR, "Unexpected arguments after username");
params_ok = 0;
}
else
{
amp->username = argv[optind];
}
if (params_ok && !password_set)
{
const char *p = getpass("Password: ");
if (p != NULL)
{
g_strcpy(amp->password, p);
}
}
return params_ok;
}
/******************************************************************************/
int
main(int argc, char **argv)
{
struct log_config *logging;
int rv = 1;
struct authmod_params amp;
logging = log_config_init_for_console(LOG_LEVEL_DEBUG,
g_getenv("AUTHTEST_LOG_LEVEL"));
log_start_from_param(logging);
log_config_free(logging);
if (!parse_program_args(argc, argv, &amp))
{
usage();
}
else
{
struct auth_info *auth_info;
auth_info = auth_userpass(amp.username, amp.password,
NULL, &rv);
LOG(LOG_LEVEL_INFO, "auth_userpass() returned %s, errorcode=%d",
(auth_info == NULL) ? "NULL" : "non-NULL",
rv);
if (auth_info && rv == 0 && amp.command != NULL)
{
int display = 10;
rv = auth_start_session(auth_info, display);
LOG(LOG_LEVEL_INFO, "auth_start_session(,%d) returned %d",
display, rv);
if (rv == 0)
{
rv = g_system(amp.command);
LOG(LOG_LEVEL_INFO, "command \"%s\" returned %d",
amp.command, rv);
auth_stop_session(auth_info);
}
}
if (auth_info != NULL)
{
int rv2 = auth_end(auth_info);
LOG(LOG_LEVEL_INFO, "auth_end() returned %d", rv2);
rv = (rv == 0) ? rv2 : rv;
}
}
log_end();
return rv;
}