New files for sesexec
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
AM_CPPFLAGS = \
|
||||
-DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \
|
||||
-DXRDP_SBIN_PATH=\"${sbindir}\" \
|
||||
-DXRDP_LIBEXEC_PATH=\"${libexecdir}/xrdp\" \
|
||||
-DXRDP_SOCKET_PATH=\"${socketdir}\" \
|
||||
-I$(top_srcdir)/sesman/libsesman \
|
||||
-I$(top_srcdir)/libipm \
|
||||
-I$(top_srcdir)/common
|
||||
|
||||
SESEXEC_EXTRA_LIBS =
|
||||
|
||||
pkglibexec_PROGRAMS = \
|
||||
xrdp-sesexec
|
||||
|
||||
xrdp_sesexec_SOURCES = \
|
||||
sesexec.c \
|
||||
sesexec.h \
|
||||
session.c \
|
||||
session.h \
|
||||
eicp_server.c \
|
||||
eicp_server.h \
|
||||
ercp_server.c \
|
||||
ercp_server.h \
|
||||
env.c \
|
||||
env.h \
|
||||
login_info.c \
|
||||
login_info.h \
|
||||
xauth.c \
|
||||
xauth.h \
|
||||
xwait.c \
|
||||
xwait.h
|
||||
|
||||
xrdp_sesexec_LDFLAGS =
|
||||
|
||||
xrdp_sesexec_LDADD = \
|
||||
$(top_builddir)/sesman/libsesman/libsesman.la \
|
||||
$(top_builddir)/libipm/libipm.la \
|
||||
$(top_builddir)/common/libcommon.la \
|
||||
$(SESEXEC_EXTRA_LIBS)
|
||||
@@ -0,0 +1,201 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2023
|
||||
*
|
||||
* 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 eicp_server.c
|
||||
* @brief eicp (executive initialisation control protocol) server function
|
||||
* @author Matt Burt
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include "trans.h"
|
||||
|
||||
#include "eicp.h"
|
||||
#include "eicp_server.h"
|
||||
#include "login_info.h"
|
||||
#include "os_calls.h"
|
||||
#include "ercp.h"
|
||||
#include "scp.h"
|
||||
#include "sesexec.h"
|
||||
#include "session.h"
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
handle_sys_login_request(struct trans *self)
|
||||
{
|
||||
const char *username;
|
||||
const char *password;
|
||||
const char *ip_addr;
|
||||
int scp_fd;
|
||||
|
||||
int rv = eicp_get_sys_login_request(self, &username,
|
||||
&password, &ip_addr, &scp_fd);
|
||||
if (rv == 0)
|
||||
{
|
||||
struct trans *scp_trans;
|
||||
scp_trans = scp_init_trans_from_fd(scp_fd, TRANS_TYPE_SERVER,
|
||||
sesexec_is_term);
|
||||
if (scp_trans == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Can't create SCP trans");
|
||||
g_file_close(scp_fd);
|
||||
rv = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_login_info = login_info_sys_login_user(scp_trans, username,
|
||||
password, ip_addr);
|
||||
|
||||
if (g_login_info != NULL)
|
||||
{
|
||||
rv = eicp_send_sys_login_response(self, 1,
|
||||
g_login_info->uid, scp_fd);
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = eicp_send_sys_login_response(self, 0, (uid_t) -1, 0);
|
||||
}
|
||||
|
||||
trans_delete(scp_trans); // Closes scp_fd as well
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
handle_logout_request(struct trans *self)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "xrdp-sesexec pid %d is now logging out", g_pid);
|
||||
sesexec_terminate_main_loop(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
handle_create_session_request(struct trans *self)
|
||||
{
|
||||
int scp_fd;
|
||||
struct session_parameters sp = {0};
|
||||
int rv;
|
||||
|
||||
rv = eicp_get_create_session_request(self, &scp_fd, &sp.display,
|
||||
&sp.type, &sp.width, &sp.height,
|
||||
&sp.bpp, &sp.shell, &sp.directory);
|
||||
if (rv == 0)
|
||||
{
|
||||
// Need to talk to the SCP client
|
||||
struct trans *scp_trans;
|
||||
scp_trans = scp_init_trans_from_fd(scp_fd, TRANS_TYPE_SERVER,
|
||||
sesexec_is_term);
|
||||
if (scp_trans == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Can't create SCP trans");
|
||||
g_file_close(scp_fd);
|
||||
rv = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
enum scp_screate_status scp_status = E_SCP_SCREATE_OK;
|
||||
|
||||
// Use the UID from the SCP connection if the user hasn't
|
||||
// explicitly logged in
|
||||
if (g_login_info == NULL &&
|
||||
(g_login_info = login_info_uds_login_user(scp_trans)) == NULL)
|
||||
{
|
||||
scp_status = E_SCP_SCREATE_GENERAL_ERROR;
|
||||
}
|
||||
|
||||
if (scp_status == E_SCP_SCREATE_OK)
|
||||
{
|
||||
// Try to create the session
|
||||
sp.guid = guid_new();
|
||||
scp_status = session_start(g_login_info, &sp, &g_session_data);
|
||||
}
|
||||
|
||||
// Return the status to the SCP client
|
||||
rv = scp_send_create_session_response(scp_trans, scp_status,
|
||||
sp.display, &sp.guid);
|
||||
trans_delete(scp_trans);
|
||||
|
||||
// Further comms from sesexec is sent over the ERCP protocol
|
||||
ercp_trans_from_eicp_trans(self,
|
||||
sesexec_ercp_data_in,
|
||||
(void *)self);
|
||||
|
||||
if (scp_status == E_SCP_SCREATE_OK)
|
||||
{
|
||||
rv = ercp_send_session_announce_event(
|
||||
self,
|
||||
sp.display,
|
||||
g_login_info->uid,
|
||||
sp.type,
|
||||
sp.width,
|
||||
sp.height,
|
||||
sp.bpp,
|
||||
&sp.guid,
|
||||
g_login_info->ip_addr,
|
||||
session_get_start_time(g_session_data));
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = ercp_send_session_finished_event(self);
|
||||
sesexec_terminate_main_loop(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
eicp_server(struct trans *self)
|
||||
{
|
||||
int rv = 0;
|
||||
enum eicp_msg_code msgno;
|
||||
|
||||
switch ((msgno = eicp_msg_in_get_msgno(self)))
|
||||
{
|
||||
case E_EICP_SYS_LOGIN_REQUEST:
|
||||
rv = handle_sys_login_request(self);
|
||||
break;
|
||||
|
||||
case E_EICP_LOGOUT_REQUEST:
|
||||
rv = handle_logout_request(self);
|
||||
break;
|
||||
|
||||
case E_EICP_CREATE_SESSION_REQUEST:
|
||||
rv = handle_create_session_request(self);
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
char buff[64];
|
||||
eicp_msgno_to_str(msgno, buff, sizeof(buff));
|
||||
LOG(LOG_LEVEL_ERROR, "Ignored EICP message %s", buff);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2023
|
||||
*
|
||||
* 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 eicp_server.h
|
||||
* @brief eicp (executive initialisation control protocol) server function
|
||||
* @author Matt Burt
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EICP_SERVER_H
|
||||
#define EICP_SERVER_H
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Processes an EICP message
|
||||
* @param self The EICP transport the message is coming in on
|
||||
*
|
||||
*/
|
||||
int
|
||||
eicp_server(struct trans *self);
|
||||
|
||||
#endif // EICP_SERVER_H
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2023
|
||||
*
|
||||
* 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 ercp_server.c
|
||||
* @brief ercp (executive run-time control protocol) server function
|
||||
* @author Matt Burt
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include "arch.h"
|
||||
|
||||
#include "sesexec.h"
|
||||
#include "session.h"
|
||||
#include "trans.h"
|
||||
|
||||
#include "ercp.h"
|
||||
#include "ercp_server.h"
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
handle_session_reconnect_event(struct trans *self)
|
||||
{
|
||||
session_reconnect(g_login_info, g_session_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
ercp_server(struct trans *self)
|
||||
{
|
||||
int rv = 0;
|
||||
enum ercp_msg_code msgno;
|
||||
|
||||
switch ((msgno = ercp_msg_in_get_msgno(self)))
|
||||
{
|
||||
case E_ERCP_SESSION_RECONNECT_EVENT:
|
||||
rv = handle_session_reconnect_event(self);
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
char buff[64];
|
||||
ercp_msgno_to_str(msgno, buff, sizeof(buff));
|
||||
LOG(LOG_LEVEL_ERROR, "Ignored ERCP message %s", buff);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2023
|
||||
*
|
||||
* 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 ercp_server.h
|
||||
* @brief ercp (executive run-time control protocol) server function
|
||||
* @author Matt Burt
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ERCP_SERVER_H
|
||||
#define ERCP_SERVER_H
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Processes an ERCP message
|
||||
* @param self The ERCP transport the message is coming in on
|
||||
*
|
||||
*/
|
||||
int
|
||||
ercp_server(struct trans *self);
|
||||
|
||||
#endif // ERCP_SERVER_H
|
||||
@@ -0,0 +1,357 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2023
|
||||
*
|
||||
* 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 login_info.c
|
||||
* @brief Define functionality associated with user logins for sesexec
|
||||
* @author Matt Burt
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include "login_info.h"
|
||||
|
||||
#include "trans.h"
|
||||
|
||||
#include "sesman_auth.h"
|
||||
#include "sesman_access.h"
|
||||
#include "sesman_config.h"
|
||||
#include "login_info.h"
|
||||
#include "os_calls.h"
|
||||
#include "scp.h"
|
||||
#include "sesexec.h"
|
||||
#include "string_calls.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* Logs an authentication failure message
|
||||
*
|
||||
* @param username Username
|
||||
* @param ip_addr IP address, if known
|
||||
*
|
||||
* The message is intended for use by fail2ban. Make changes with care.
|
||||
*/
|
||||
static void
|
||||
log_authfail_message(const char *username, const char *ip_addr)
|
||||
{
|
||||
if (ip_addr == NULL || ip_addr[0] == '\0')
|
||||
{
|
||||
ip_addr = "unknown";
|
||||
}
|
||||
LOG(LOG_LEVEL_INFO, "AUTHFAIL: user=%s ip=%s time=%d",
|
||||
username, ip_addr, g_time1());
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* Authenticate and authorize the connection
|
||||
*
|
||||
* @param username Name for user
|
||||
* @param password Password
|
||||
* @param ip_addr Remote IP address
|
||||
* @param login_info Structure to fill in for a successful login
|
||||
* @return Status for the operation
|
||||
*
|
||||
* @post If E_SCP_LOGIN_OK is returned, g_login_info is filled in
|
||||
*
|
||||
*/
|
||||
static enum scp_login_status
|
||||
authenticate_and_authorize_connection(const char *supplied_username,
|
||||
const char *password,
|
||||
const char *ip_addr,
|
||||
struct login_info *login_info)
|
||||
{
|
||||
int uid;
|
||||
char *username; // From reverse-looking up the UID
|
||||
enum scp_login_status status;
|
||||
struct auth_info *auth_info;
|
||||
|
||||
if (g_getuser_info_by_name(supplied_username,
|
||||
&uid, NULL, NULL, NULL, NULL) != 0)
|
||||
{
|
||||
/* we can't get a UID for the user */
|
||||
LOG(LOG_LEVEL_ERROR, "Can't get UID for user %s",
|
||||
supplied_username);
|
||||
log_authfail_message(supplied_username, ip_addr);
|
||||
status = E_SCP_LOGIN_NOT_AUTHENTICATED;
|
||||
}
|
||||
else if (g_getuser_info_by_uid(uid,
|
||||
&username,
|
||||
NULL, NULL, NULL, NULL) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Can't reverse lookup UID %d", uid);
|
||||
status = E_SCP_LOGIN_NOT_AUTHENTICATED;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g_strcmp(username, supplied_username) != 0)
|
||||
{
|
||||
/*
|
||||
* If using a federated naming service (e.g. AD), the username
|
||||
* supplied may not match that name mapped to by the UID. We
|
||||
* will generate a warning in this instance so the user can see
|
||||
* what is being used
|
||||
*/
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Using username %s for the session (from UID %d)",
|
||||
username, uid);
|
||||
}
|
||||
|
||||
auth_info = auth_userpass(username, password, ip_addr, &status);
|
||||
|
||||
/* Sanity check on result of call */
|
||||
if ((auth_info != NULL && status != E_SCP_LOGIN_OK) ||
|
||||
(auth_info == NULL && status == E_SCP_LOGIN_OK))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Bugcheck; inconsistent auth result. "
|
||||
"info = %p, status = %d", (void *)auth_info, (int)status);
|
||||
status = E_SCP_LOGIN_GENERAL_ERROR;
|
||||
auth_end(auth_info);
|
||||
auth_info = NULL;
|
||||
}
|
||||
|
||||
/* Group access allowed? */
|
||||
if (status == E_SCP_LOGIN_OK &&
|
||||
!access_login_allowed(&g_cfg->sec, username))
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "Username okay but group problem for "
|
||||
"user: %s", username);
|
||||
status = E_SCP_LOGIN_NOT_AUTHORIZED;
|
||||
auth_end(auth_info);
|
||||
auth_info = NULL;
|
||||
}
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case E_SCP_LOGIN_OK:
|
||||
{
|
||||
char *dup_username = g_strdup(username);
|
||||
char *dup_ip_addr = g_strdup(ip_addr);
|
||||
|
||||
if (dup_username == NULL || dup_ip_addr == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s : Memory allocation failed",
|
||||
__func__);
|
||||
g_free(dup_username);
|
||||
g_free(dup_ip_addr);
|
||||
status = E_SCP_LOGIN_NO_MEMORY;
|
||||
auth_end(auth_info);
|
||||
auth_info = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "Access permitted for user: %s",
|
||||
username);
|
||||
login_info->uid = uid;
|
||||
login_info->username = dup_username;
|
||||
login_info->ip_addr = dup_ip_addr;
|
||||
login_info->auth_info = auth_info;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case E_SCP_LOGIN_NOT_AUTHENTICATED:
|
||||
log_authfail_message(username, ip_addr);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
g_free(username);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
get_scp_client_retry(struct trans *scp_trans,
|
||||
const char **username, const char **password,
|
||||
const char **ip_addr)
|
||||
{
|
||||
int got_message = 0;
|
||||
|
||||
// Wait for an SCP message
|
||||
enum scp_msg_code msgno;
|
||||
|
||||
scp_msg_in_reset(scp_trans);
|
||||
|
||||
if (scp_msg_in_wait_available(scp_trans) == 0)
|
||||
{
|
||||
msgno = scp_msg_in_get_msgno(scp_trans);
|
||||
switch (msgno)
|
||||
{
|
||||
case E_SCP_SYS_LOGIN_REQUEST:
|
||||
if (scp_get_sys_login_request(scp_trans, username,
|
||||
password, ip_addr) == 0)
|
||||
{
|
||||
got_message = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case E_SCP_CLOSE_CONNECTION_REQUEST:
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
char buff[64];
|
||||
scp_msgno_to_str(msgno, buff, sizeof(buff));
|
||||
LOG(LOG_LEVEL_ERROR, "unexpected message %s from SCP client",
|
||||
buff);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return got_message;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
struct login_info *
|
||||
login_info_sys_login_user(struct trans *scp_trans,
|
||||
const char *username,
|
||||
const char *password,
|
||||
const char *ip_addr)
|
||||
{
|
||||
struct login_info *result;
|
||||
enum scp_login_status status = E_SCP_LOGIN_GENERAL_ERROR;
|
||||
int server_closed = 0;
|
||||
|
||||
if ((result = g_new0(struct login_info, 1)) == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Allocation failure logging in user");
|
||||
}
|
||||
else
|
||||
{
|
||||
int first_time = 1;
|
||||
unsigned int retry_count = g_cfg->sec.login_retry;
|
||||
|
||||
result->uid = (uid_t) -1;
|
||||
|
||||
while (status != E_SCP_LOGIN_OK && !server_closed)
|
||||
{
|
||||
// First time round, we have credentials supplied by the
|
||||
// caller. On subsequent trips, we have to wait for the
|
||||
// SCP client to send us more.
|
||||
if (first_time)
|
||||
{
|
||||
first_time = 0;
|
||||
}
|
||||
else if (!get_scp_client_retry(scp_trans, &username,
|
||||
&password, &ip_addr))
|
||||
{
|
||||
status = E_SCP_LOGIN_GENERAL_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
status = authenticate_and_authorize_connection(username,
|
||||
password,
|
||||
ip_addr,
|
||||
result);
|
||||
|
||||
if (status != E_SCP_LOGIN_OK)
|
||||
{
|
||||
if (retry_count > 0)
|
||||
{
|
||||
--retry_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
server_closed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (scp_send_login_response(scp_trans, status, server_closed) != 0)
|
||||
{
|
||||
status = E_SCP_LOGIN_GENERAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (status != E_SCP_LOGIN_OK)
|
||||
{
|
||||
login_info_free(result);
|
||||
result = NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
struct login_info *
|
||||
login_info_uds_login_user(struct trans *scp_trans)
|
||||
{
|
||||
struct login_info *result;
|
||||
int uid; // Needed as g_sck_get_peer_cred() doesn't use uid_t
|
||||
|
||||
// Allocate a struct for the result, with the IP address set to ""
|
||||
if ((result = g_new0(struct login_info, 1)) == NULL ||
|
||||
(result->ip_addr = g_new0(char, 1)) == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Allocation failure logging in user");
|
||||
}
|
||||
else if (g_sck_get_peer_cred(scp_trans->sck, NULL, &uid, NULL) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Unable to get peer credentials for SCP socket");
|
||||
}
|
||||
else if (g_getuser_info_by_uid(uid, &result->username,
|
||||
NULL, NULL, NULL, NULL) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Can't reverse lookup UID %d", result->uid);
|
||||
}
|
||||
else if ((result->auth_info = auth_uds(result->username, NULL)) == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Can't authorize user %s over UDS",
|
||||
result->username);
|
||||
}
|
||||
else if (!access_login_allowed(&g_cfg->sec, result->username))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Access denied for user %s by your system admin",
|
||||
result->username);
|
||||
}
|
||||
else
|
||||
{
|
||||
result->uid = (uid_t)uid;
|
||||
return result;
|
||||
}
|
||||
|
||||
login_info_free(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
void
|
||||
login_info_free(struct login_info *self)
|
||||
{
|
||||
if (self != NULL)
|
||||
{
|
||||
g_free(self->username);
|
||||
g_free(self->ip_addr);
|
||||
if (self->auth_info != NULL)
|
||||
{
|
||||
auth_end(self->auth_info);
|
||||
}
|
||||
g_free(self);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2023
|
||||
*
|
||||
* 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 login_info.h
|
||||
* @brief Declare functionality associated with user logins for sesexec
|
||||
* @author Matt Burt
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LOGIN_INFO_H
|
||||
#define LOGIN_INFO_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
struct trans;
|
||||
|
||||
/**
|
||||
* Information associated with the logged-in user
|
||||
*/
|
||||
struct login_info
|
||||
{
|
||||
uid_t uid;
|
||||
char *username;
|
||||
char *ip_addr;
|
||||
struct auth_info *auth_info;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Attempt a system login using username/password
|
||||
* @param scp_trans SCP transport for talking to the client
|
||||
* @param username Username from xrdp
|
||||
* @param password Password from xrdp
|
||||
* @param ip_addr IP address for xrdp client
|
||||
*
|
||||
* @result Allocated login_info struct for a successful login
|
||||
*
|
||||
* This is a wrapper around the dialogue between sesexec and the SCP process
|
||||
* which is required to start a session.
|
||||
*
|
||||
* While this call is in operation, only the scp_trans transport will
|
||||
* be checked for messages. Incoming messages on other transports will be
|
||||
* ignored. The dialog can also be terminated by a SIGTERM if the SCP
|
||||
* transport is configured to allow this.
|
||||
*
|
||||
* The username in the returned structure may differ from the passed-in
|
||||
* username if multiple names map to the same UID. This can happen with
|
||||
* federated naming services (e.g. AD, LDAP)
|
||||
*/
|
||||
struct login_info *
|
||||
login_info_sys_login_user(struct trans *scp_trans,
|
||||
const char *username,
|
||||
const char *password,
|
||||
const char *ip_addr);
|
||||
|
||||
/**
|
||||
* @brief Create a login_info structure using UDS credentials
|
||||
*
|
||||
* This should be a formality, as by the time sesexec tries this, sesman
|
||||
* should already have done it.
|
||||
*
|
||||
* Errors are logged.
|
||||
*
|
||||
* @param scp_trans SCP transport for talking to the client
|
||||
* @param ip_addr IP address for xrdp client
|
||||
*
|
||||
* @result Allocated login_info struct for a successful login
|
||||
*/
|
||||
struct login_info *
|
||||
login_info_uds_login_user(struct trans *scp_trans);
|
||||
|
||||
/**
|
||||
* Free a struct login_info
|
||||
*/
|
||||
void
|
||||
login_info_free(struct login_info *self);
|
||||
|
||||
#endif // LOGIN_INFO_H
|
||||
@@ -0,0 +1,521 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Matt Burt 2023
|
||||
*
|
||||
* 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 sesexec.c
|
||||
* @brief Main program file for session executive process
|
||||
* @author Matt Burt
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "arch.h"
|
||||
#include "eicp.h"
|
||||
#include "eicp_server.h"
|
||||
#include "ercp.h"
|
||||
#include "ercp_server.h"
|
||||
#include "login_info.h"
|
||||
#include "sesexec.h"
|
||||
#include "sesman_config.h"
|
||||
#include "log.h"
|
||||
#include "os_calls.h"
|
||||
#include "session.h"
|
||||
#include "string_calls.h"
|
||||
#include "trans.h"
|
||||
#include "xrdp_sockets.h"
|
||||
|
||||
struct startup_params
|
||||
{
|
||||
const char *sesman_ini;
|
||||
};
|
||||
|
||||
/*
|
||||
* Program-scope globals
|
||||
*/
|
||||
struct config_sesman *g_cfg;
|
||||
unsigned char g_fixedkey[8] = { 23, 82, 107, 6, 35, 78, 88, 7 };
|
||||
struct login_info *g_login_info;
|
||||
struct session_data *g_session_data;
|
||||
|
||||
tintptr g_term_event = 0;
|
||||
tintptr g_sigchld_event = 0;
|
||||
pid_t g_pid;
|
||||
|
||||
/*
|
||||
* Module-scope globals
|
||||
*/
|
||||
static struct trans *g_ecp_trans;
|
||||
static int g_terminate_loop = 0;
|
||||
static int g_terminate_status = 0;
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Command line argument parser
|
||||
* @param[in] argc number of command line arguments
|
||||
* @param[in] argv pointer array of commandline arguments
|
||||
* @param[out] startup_params Returned startup parameters
|
||||
* @return 0 on success
|
||||
*/
|
||||
static int
|
||||
process_params(int argc, char **argv,
|
||||
struct startup_params *startup_params)
|
||||
{
|
||||
int index;
|
||||
const char *option;
|
||||
const char *value;
|
||||
|
||||
startup_params->sesman_ini = DEFAULT_SESMAN_INI;
|
||||
|
||||
index = 1;
|
||||
|
||||
while (index < argc)
|
||||
{
|
||||
option = argv[index];
|
||||
|
||||
if (index + 1 < argc)
|
||||
{
|
||||
value = argv[index + 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
|
||||
if (g_strcmp(option, "-c") == 0)
|
||||
{
|
||||
index++;
|
||||
startup_params->sesman_ini = value;
|
||||
}
|
||||
else /* unknown option */
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
#if 0
|
||||
static int
|
||||
sesexec_scp_data_in(struct trans *self)
|
||||
{
|
||||
int rv;
|
||||
int available;
|
||||
|
||||
rv = scp_msg_in_check_available(self, &available);
|
||||
|
||||
if (rv == 0 && available)
|
||||
{
|
||||
struct sesman_con *sc = (struct sesman_con *)self->callback_data;
|
||||
//if ((rv = scp_process(sc)) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s: scp_process failed", __func__);
|
||||
}
|
||||
scp_msg_in_reset(self);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
sesexec_eicp_data_in(struct trans *self)
|
||||
{
|
||||
int rv;
|
||||
int available;
|
||||
|
||||
rv = eicp_msg_in_check_available(self, &available);
|
||||
|
||||
if (rv == 0 && available)
|
||||
{
|
||||
if ((rv = eicp_server(self)) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s: eicp_server failed", __func__);
|
||||
}
|
||||
eicp_msg_in_reset(self);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
sesexec_ercp_data_in(struct trans *self)
|
||||
{
|
||||
int rv;
|
||||
int available;
|
||||
|
||||
rv = ercp_msg_in_check_available(self, &available);
|
||||
|
||||
if (rv == 0 && available)
|
||||
{
|
||||
if ((rv = ercp_server(self)) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s: ercp_server failed", __func__);
|
||||
}
|
||||
ercp_msg_in_reset(self);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* Informs the main loop a termination signal has been received
|
||||
*/
|
||||
static void
|
||||
set_term_event(int sig)
|
||||
{
|
||||
/* Don't try to use a wait obj in a child process */
|
||||
if (g_getpid() == g_pid)
|
||||
{
|
||||
g_set_wait_obj(g_term_event);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* No-op signal handler.
|
||||
*/
|
||||
static void
|
||||
sig_no_op(int sig)
|
||||
{
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* Informs the main loop a child exiting signal has been received
|
||||
*/
|
||||
static void
|
||||
set_sigchld_event(int sig)
|
||||
{
|
||||
/* Don't try to use a wait obj in a child process */
|
||||
if (g_getpid() == g_pid)
|
||||
{
|
||||
g_set_wait_obj(g_sigchld_event);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
sesexec_is_term(void)
|
||||
{
|
||||
return g_terminate_loop || g_is_wait_obj_set(g_term_event);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void
|
||||
sesexec_terminate_main_loop(int status)
|
||||
{
|
||||
g_terminate_loop = 1;
|
||||
g_terminate_status = status;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static void
|
||||
process_sigchld_event(void)
|
||||
{
|
||||
struct exit_status e;
|
||||
int pid;
|
||||
|
||||
// Check for any finished children
|
||||
while ((pid = g_waitchild(&e)) > 0)
|
||||
{
|
||||
session_process_child_exit(g_session_data, pid, &e);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
*
|
||||
* @brief Starts sesexec main loop
|
||||
*
|
||||
*/
|
||||
static int
|
||||
sesexec_main_loop(void)
|
||||
{
|
||||
int error = 0;
|
||||
int robjs_count;
|
||||
intptr_t robjs[32];
|
||||
|
||||
g_terminate_loop = 0;
|
||||
g_terminate_status = 0;
|
||||
g_login_info = NULL;
|
||||
|
||||
while (!g_terminate_loop)
|
||||
{
|
||||
robjs_count = 0;
|
||||
robjs[robjs_count++] = g_term_event;
|
||||
robjs[robjs_count++] = g_sigchld_event;
|
||||
|
||||
error = trans_get_wait_objs(g_ecp_trans, robjs, &robjs_count);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "sesexec_main_loop: "
|
||||
"trans_get_wait_objs(ECP) failed");
|
||||
sesexec_terminate_main_loop(error);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (g_obj_wait(robjs, robjs_count, NULL, 0, 0) != 0)
|
||||
{
|
||||
/* should not get here */
|
||||
LOG(LOG_LEVEL_WARNING, "sesexec_main_loop: "
|
||||
"Unexpected error from g_obj_wait()");
|
||||
g_sleep(100);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (g_is_wait_obj_set(g_term_event)) /* term */
|
||||
{
|
||||
g_reset_wait_obj(g_term_event);
|
||||
if (session_active(g_session_data))
|
||||
{
|
||||
// Ask the active session to terminate
|
||||
LOG(LOG_LEVEL_INFO, "sesexec_main_loop: "
|
||||
"sesexec asked to terminate. "
|
||||
"Terminating active session");
|
||||
session_send_term(g_session_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Terminate immediately
|
||||
LOG(LOG_LEVEL_INFO, "sesexec_main_loop: "
|
||||
"sesexec asked to terminate. "
|
||||
"No session is active");
|
||||
sesexec_terminate_main_loop(0);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_is_wait_obj_set(g_sigchld_event)) /* SIGCHLD */
|
||||
{
|
||||
g_reset_wait_obj(g_sigchld_event);
|
||||
|
||||
// See whether the session goes from active to inactive
|
||||
// after processing SIGCHLD
|
||||
int session_was_active = session_active(g_session_data);
|
||||
process_sigchld_event();
|
||||
if (session_was_active && !session_active(g_session_data))
|
||||
{
|
||||
// We've finished the session. Tell sesman and
|
||||
// finish up.
|
||||
(void)ercp_send_session_finished_event(g_ecp_trans);
|
||||
|
||||
session_data_free(g_session_data);
|
||||
g_session_data = NULL;
|
||||
sesexec_terminate_main_loop(0);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
error = trans_check_wait_objs(g_ecp_trans);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "sesexec_main_loop: "
|
||||
"trans_check_wait_objs failed for ECP transport");
|
||||
sesexec_terminate_main_loop(error);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
login_info_free(g_login_info);
|
||||
|
||||
return g_terminate_status;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static int start_logging(const char *sesman_ini)
|
||||
{
|
||||
char text[256];
|
||||
int rv = 1;
|
||||
if (!g_file_exist(sesman_ini))
|
||||
{
|
||||
g_printf("Config file %s does not exist\n", sesman_ini);
|
||||
}
|
||||
else
|
||||
{
|
||||
enum logReturns log_error;
|
||||
log_error = log_start(sesman_ini, "xrdp-sesexec", 0);
|
||||
|
||||
if (log_error != LOG_STARTUP_OK)
|
||||
{
|
||||
switch (log_error)
|
||||
{
|
||||
case LOG_ERROR_MALLOC:
|
||||
g_writeln("error on malloc. cannot start logging. quitting.");
|
||||
break;
|
||||
case LOG_ERROR_FILE_OPEN:
|
||||
g_writeln("error opening log file [%s]. quitting.",
|
||||
getLogFile(text, sizeof(text) - 1));
|
||||
break;
|
||||
default:
|
||||
// Assume sufficient messages have already been generated
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
get_eicp_fd(char errstr[], unsigned int errstr_size)
|
||||
{
|
||||
const char *s = g_getenv("EICP_FD");
|
||||
const char *p;
|
||||
int fd;
|
||||
|
||||
errstr[0] = '\0';
|
||||
|
||||
if (s == NULL || s[0] == '\0')
|
||||
{
|
||||
g_snprintf(errstr, errstr_size,
|
||||
"Can't read EICP_FD environment variable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (p = s ; isdigit(*p) ; ++p)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
if (*p != '\0')
|
||||
{
|
||||
g_snprintf(errstr, errstr_size, "EICP_FD has non-digit char '%c'", *p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((p - s) > 4)
|
||||
{
|
||||
g_snprintf(errstr, errstr_size, "EICP_FD has too many digits");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = g_atoi(s);
|
||||
if (!g_file_is_open(fd))
|
||||
{
|
||||
g_snprintf(errstr, errstr_size, "EICP_FD %d is not open", fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int error = 1;
|
||||
struct startup_params startup_params = {0};
|
||||
int errored_argc;
|
||||
int eicp_fd;
|
||||
char eicp_errstr[128];
|
||||
/*
|
||||
* Check the EICP transport file descriptor is provided and open
|
||||
* before opening any log files, config files, etc. We then open
|
||||
* log files, and log errors at that point */
|
||||
eicp_fd = get_eicp_fd(eicp_errstr, sizeof(eicp_errstr));
|
||||
|
||||
g_init("xrdp-sesexec");
|
||||
|
||||
//g_sleep(15 * 1000);
|
||||
errored_argc = process_params(argc, argv, &startup_params);
|
||||
if (errored_argc > 0)
|
||||
{
|
||||
g_writeln("Unknown option: %s", argv[errored_argc]);
|
||||
}
|
||||
/* starting logging subsystem
|
||||
*
|
||||
* For historic reasons, we share a log file with sesman */
|
||||
else if (start_logging(startup_params.sesman_ini) == 0)
|
||||
{
|
||||
/* reading config
|
||||
*
|
||||
* For historic reasons, we share a config with sesman */
|
||||
if ((g_cfg = config_read(startup_params.sesman_ini)) == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ALWAYS, "error reading config %s: %s",
|
||||
startup_params.sesman_ini, g_get_strerror());
|
||||
}
|
||||
else if (eicp_fd < 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s", eicp_errstr);
|
||||
}
|
||||
else
|
||||
{
|
||||
char text[128];
|
||||
|
||||
g_pid = g_getpid();
|
||||
|
||||
/* signal handling */
|
||||
g_snprintf(text, sizeof(text), "xrdp_sesexec_%8.8x_main_term",
|
||||
g_pid);
|
||||
g_term_event = g_create_wait_obj(text);
|
||||
g_snprintf(text, sizeof(text), "xrdp_sesexec_%8.8x_sigchld",
|
||||
g_pid);
|
||||
g_sigchld_event = g_create_wait_obj(text);
|
||||
|
||||
// No need to terminate on SIGINT for sesexec. This can
|
||||
// also make it hard to debug sessions.
|
||||
//g_signal_user_interrupt(set_term_event);
|
||||
g_signal_terminate(set_term_event); /* SIGTERM */
|
||||
g_signal_pipe(sig_no_op); /* SIGPIPE */
|
||||
g_signal_child_stop(set_sigchld_event);
|
||||
|
||||
/* Set up an EICP process handler
|
||||
* Errors are logged by this call if necessary */
|
||||
g_ecp_trans = eicp_init_trans_from_fd(eicp_fd,
|
||||
TRANS_TYPE_SERVER,
|
||||
sesexec_is_term);
|
||||
if (g_ecp_trans != NULL)
|
||||
{
|
||||
g_ecp_trans->trans_data_in = sesexec_eicp_data_in;
|
||||
g_ecp_trans->callback_data = NULL;
|
||||
|
||||
/* start program main loop */
|
||||
LOG(LOG_LEVEL_INFO, "starting xrdp-sesexec with pid %d", g_pid);
|
||||
error = sesexec_main_loop();
|
||||
trans_delete(g_ecp_trans);
|
||||
}
|
||||
|
||||
g_delete_wait_obj(g_term_event);
|
||||
}
|
||||
config_free(g_cfg);
|
||||
log_end();
|
||||
}
|
||||
|
||||
g_deinit();
|
||||
g_exit(error);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2023
|
||||
*
|
||||
* 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 sesexec.h
|
||||
* @brief Main include file
|
||||
* @author Jay Sorg
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SESEXEC_H
|
||||
#define SESEXEC_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
struct config_sesman;
|
||||
struct trans;
|
||||
struct login_info;
|
||||
struct session_data;
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
#define USE_BSD_SETLOGIN
|
||||
#endif
|
||||
|
||||
/* Globals */
|
||||
extern struct config_sesman *g_cfg;
|
||||
extern unsigned char g_fixedkey[8];
|
||||
extern struct login_info *g_login_info;
|
||||
extern struct session_data *g_session_data;
|
||||
|
||||
extern tintptr g_term_event;
|
||||
extern tintptr g_sigchld_event;
|
||||
extern pid_t g_pid;
|
||||
|
||||
|
||||
/**
|
||||
* Callback to process incoming ERCP data
|
||||
*/
|
||||
int
|
||||
sesexec_ercp_data_in(struct trans *self);
|
||||
|
||||
/*
|
||||
* Check for termination
|
||||
*/
|
||||
int
|
||||
sesexec_is_term(void);
|
||||
|
||||
/*
|
||||
* Terminate the sesexec main loop
|
||||
*/
|
||||
void
|
||||
sesexec_terminate_main_loop(int status);
|
||||
|
||||
#endif // SESEXEC_H
|
||||
Reference in New Issue
Block a user