mirror of https://github.com/neutrinolabs/xrdp
Merge pull request #2472 from matt335672/implement-uds-auth
Implement uds authentication
This commit is contained in:
commit
bef2e3b1e4
|
@ -36,6 +36,7 @@ NEWS
|
|||
README
|
||||
sesman/chansrv/xrdp-chansrv
|
||||
sesman/sessvc/xrdp-sessvc
|
||||
sesman/tools/xrdp-authtest
|
||||
sesman/tools/xrdp-dis
|
||||
sesman/tools/xrdp-sesadmin
|
||||
sesman/tools/xrdp-sesrun
|
||||
|
|
|
@ -671,7 +671,7 @@ g_sck_get_peer_cred(int sck, int *pid, int *uid, int *gid)
|
|||
unsigned int xucred_length;
|
||||
xucred_length = sizeof(xucred);
|
||||
|
||||
if (getsockopt(sck, SOL_SOCKET, LOCAL_PEERCRED, &xucred, &xucred_length))
|
||||
if (getsockopt(sck, SOL_LOCAL, LOCAL_PEERCRED, &xucred, &xucred_length))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
@ -2797,7 +2797,7 @@ g_initgroups(const char *username)
|
|||
return 0;
|
||||
#else
|
||||
int gid;
|
||||
int error = g_getuser_info(username, &gid, NULL, NULL, NULL, NULL);
|
||||
int error = g_getuser_info_by_name(username, NULL, &gid, NULL, NULL, NULL);
|
||||
if (error == 0)
|
||||
{
|
||||
error = initgroups(username, gid);
|
||||
|
@ -3060,26 +3060,85 @@ g_sighup(int pid)
|
|||
/* the caller is responsible to free the buffs */
|
||||
/* does not work in win32 */
|
||||
int
|
||||
g_getuser_info(const char *username, int *gid, int *uid, char **shell,
|
||||
char **dir, char **gecos)
|
||||
g_getuser_info_by_name(const char *username, int *uid, int *gid,
|
||||
char **shell, char **dir, char **gecos)
|
||||
{
|
||||
int rv = 1;
|
||||
#if !defined(_WIN32)
|
||||
|
||||
if (username == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "g_getuser_info_by_name() called for NULL user");
|
||||
}
|
||||
else
|
||||
{
|
||||
struct passwd *pwd_1 = getpwnam(username);
|
||||
|
||||
if (pwd_1 != 0)
|
||||
{
|
||||
rv = 0;
|
||||
|
||||
if (uid != 0)
|
||||
{
|
||||
*uid = pwd_1->pw_uid;
|
||||
}
|
||||
|
||||
if (gid != 0)
|
||||
{
|
||||
*gid = pwd_1->pw_gid;
|
||||
}
|
||||
|
||||
if (shell != 0)
|
||||
{
|
||||
*shell = g_strdup(pwd_1->pw_shell);
|
||||
}
|
||||
|
||||
if (dir != 0)
|
||||
{
|
||||
*dir = g_strdup(pwd_1->pw_dir);
|
||||
}
|
||||
|
||||
if (gecos != 0)
|
||||
{
|
||||
*gecos = g_strdup(pwd_1->pw_gecos);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns 0 if ok */
|
||||
/* the caller is responsible to free the buffs */
|
||||
/* does not work in win32 */
|
||||
int
|
||||
g_getuser_info_by_uid(int uid, char **username, int *gid,
|
||||
char **shell, char **dir, char **gecos)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return 1;
|
||||
#else
|
||||
struct passwd *pwd_1;
|
||||
|
||||
pwd_1 = getpwnam(username);
|
||||
pwd_1 = getpwuid(uid);
|
||||
|
||||
if (pwd_1 != 0)
|
||||
{
|
||||
if (username != NULL)
|
||||
{
|
||||
*username = g_strdup(pwd_1->pw_name);
|
||||
}
|
||||
|
||||
if (gid != 0)
|
||||
{
|
||||
*gid = pwd_1->pw_gid;
|
||||
}
|
||||
|
||||
if (uid != 0)
|
||||
if (shell != 0)
|
||||
{
|
||||
*uid = pwd_1->pw_uid;
|
||||
*shell = g_strdup(pwd_1->pw_shell);
|
||||
}
|
||||
|
||||
if (dir != 0)
|
||||
|
@ -3087,11 +3146,6 @@ g_getuser_info(const char *username, int *gid, int *uid, char **shell,
|
|||
*dir = g_strdup(pwd_1->pw_dir);
|
||||
}
|
||||
|
||||
if (shell != 0)
|
||||
{
|
||||
*shell = g_strdup(pwd_1->pw_shell);
|
||||
}
|
||||
|
||||
if (gecos != 0)
|
||||
{
|
||||
*gecos = g_strdup(pwd_1->pw_gecos);
|
||||
|
|
|
@ -193,8 +193,10 @@ int g_exit(int exit_code);
|
|||
int g_getpid(void);
|
||||
int g_sigterm(int pid);
|
||||
int g_sighup(int pid);
|
||||
int g_getuser_info(const char *username, int *gid, int *uid, char **shell,
|
||||
char **dir, char **gecos);
|
||||
int g_getuser_info_by_name(const char *username, int *uid, int *gid,
|
||||
char **shell, char **dir, char **gecos);
|
||||
int g_getuser_info_by_uid(int uid, char **username, int *gid,
|
||||
char **shell, char **dir, char **gecos);
|
||||
int g_getgroup_info(const char *groupname, int *gid);
|
||||
int g_check_user_in_group(const char *username, int gid, int *ok);
|
||||
int g_time1(void);
|
||||
|
|
|
@ -424,11 +424,6 @@ then
|
|||
AC_DEFINE([XRDP_ENABLE_IPV6],1,[Enable IPv6])
|
||||
fi
|
||||
|
||||
if test "x$enable_pam" = "xyes"
|
||||
then
|
||||
AC_DEFINE([USE_PAM],1,[Enable PAM])
|
||||
fi
|
||||
|
||||
AS_IF( [test "x$enable_neutrinordp" = "xyes"] , [PKG_CHECK_MODULES(FREERDP, freerdp >= 1.0.0)] )
|
||||
|
||||
# checking for libjpeg
|
||||
|
|
|
@ -18,13 +18,11 @@ command.
|
|||
A summary of options is included below.
|
||||
.TP
|
||||
.BI \-u= username
|
||||
\fIUsername\fP for authentication on the server.
|
||||
Defaults to \fBroot\fP.
|
||||
Retained for compatibility, but ignored.
|
||||
|
||||
.TP
|
||||
.BI \-p= password
|
||||
The \fIpassword\fP to authenticate with.
|
||||
The default is to ask for the password interactively.
|
||||
Retained for compatibility, but ignored.
|
||||
|
||||
.TP
|
||||
.BI \-i= port
|
||||
|
@ -39,7 +37,7 @@ Valid commands are:
|
|||
.RS 4
|
||||
.TP
|
||||
.B list
|
||||
List currently active sessions.
|
||||
List active sessions for the current user.
|
||||
.TP
|
||||
.BI kill: sid
|
||||
Kills the session specified the given \fIsession id\fP.
|
||||
|
|
|
@ -4,18 +4,28 @@
|
|||
|
||||
.SH "SYNTAX"
|
||||
.B xrdp\-sesrun
|
||||
.I [ options ] username
|
||||
.I --help
|
||||
.br
|
||||
|
||||
.B xrdp\-sesrun
|
||||
.I [ options ] [ username ]
|
||||
|
||||
.SH "DESCRIPTION"
|
||||
\fBxrdp\-sesrun\fR starts a session using \fBxrdp\-sesman\fR(8).
|
||||
.br
|
||||
This is a tool useful for testing, it simply behaves like xrdp when some
|
||||
This is a tool useful for testing. It simply behaves like xrdp when some
|
||||
user logs in a new session and authenticates, thus starting a new session.
|
||||
|
||||
Default values for the options are set at compile-time. Run the utility without
|
||||
a username to see what the defaults are for your installation.
|
||||
Default values for the options are set at compile-time. Run the utility with
|
||||
the '--help' option to see what the defaults are for your installation.
|
||||
|
||||
The utility prompts for a password if neither \fB-p\fR or \fB-F\fR is used.
|
||||
If no username is used, the current username is used, and no password
|
||||
needs to be provided. In this instance, it is important that any necessary
|
||||
authentication tokens for a GUI session (e.g. a Kerberos ticket) have
|
||||
already been acquired.
|
||||
|
||||
If a username is provided, a password must also be provided. In this instance
|
||||
the utility prompts for a password if neither \fB-p\fR or \fB-F\fR is used.
|
||||
|
||||
.SH "OPTIONS"
|
||||
.TP
|
||||
|
@ -60,6 +70,10 @@ Override the default logging level. One of "error", "warn", "info",
|
|||
.SH "EXAMPLES"
|
||||
.TP
|
||||
.B
|
||||
xrdp-sesrun
|
||||
Create a default session for the current user.
|
||||
.TP
|
||||
.B
|
||||
xrdp-sesrun -F 0 user1 <passwd.txt
|
||||
Create a default session for user \fBuser1\fR with a password from
|
||||
a file
|
||||
|
|
|
@ -107,7 +107,9 @@ If not specified or set to \fB0\fP, unlimited.
|
|||
|
||||
.TP
|
||||
\fBpamerrortxt\fP=\fIerror_text\fP
|
||||
Specify text passed to PAM when authentication failed. The maximum length is \fB256\fP.
|
||||
Specify additional text displayed to user if authentication fails. The maximum length is \fB256\fP.
|
||||
|
||||
The use of 'pam' in the name of this option is historic
|
||||
|
||||
.TP
|
||||
\fBport\fP=\fIport\fP
|
||||
|
|
|
@ -15,7 +15,8 @@ libipm_la_SOURCES = \
|
|||
libipm_private.h \
|
||||
scp.h \
|
||||
scp.c \
|
||||
scp_application_types.h
|
||||
scp_application_types.h \
|
||||
scp_application_types.c
|
||||
|
||||
libipm_la_LIBADD = \
|
||||
$(top_builddir)/common/libcommon.la
|
||||
|
|
237
libipm/scp.c
237
libipm/scp.c
|
@ -40,12 +40,21 @@ static const char *
|
|||
msgno_to_str(unsigned short n)
|
||||
{
|
||||
return
|
||||
(n == E_SCP_GATEWAY_REQUEST) ? "SCP_GATEWAY_REQUEST" :
|
||||
(n == E_SCP_GATEWAY_RESPONSE) ? "SCP_GATEWAY_RESPONSE" :
|
||||
(n == E_SCP_SET_PEERNAME_REQUEST) ? "SCP_SET_PEERNAME_REQUEST" :
|
||||
|
||||
(n == E_SCP_SYS_LOGIN_REQUEST) ? "SCP_SYS_LOGIN_REQUEST" :
|
||||
(n == E_SCP_UDS_LOGIN_REQUEST) ? "SCP_UDS_LOGIN_REQUEST" :
|
||||
(n == E_SCP_LOGIN_RESPONSE) ? "SCP_LOGIN_RESPONSE" :
|
||||
|
||||
(n == E_SCP_LOGOUT_REQUEST) ? "SCP_LOGOUT_REQUEST" :
|
||||
|
||||
(n == E_SCP_CREATE_SESSION_REQUEST) ? "SCP_CREATE_SESSION_REQUEST" :
|
||||
(n == E_SCP_CREATE_SESSION_RESPONSE) ? "SCP_CREATE_SESSION_RESPONSE" :
|
||||
|
||||
(n == E_SCP_LIST_SESSIONS_REQUEST) ? "SCP_LIST_SESSIONS_REQUEST" :
|
||||
(n == E_SCP_LIST_SESSIONS_RESPONSE) ? "SCP_LIST_SESSIONS_RESPONSE" :
|
||||
|
||||
(n == E_SCP_CLOSE_CONNECTION_REQUEST) ? "SCP_CLOSE_CONNECTION_REQUEST" :
|
||||
NULL;
|
||||
}
|
||||
|
||||
|
@ -147,6 +156,7 @@ scp_port_to_display_string(const char *port, char *buff, unsigned int bufflen)
|
|||
/*****************************************************************************/
|
||||
struct trans *
|
||||
scp_connect(const char *port,
|
||||
const char *peername,
|
||||
int (*term_func)(void))
|
||||
{
|
||||
char sock_path[256];
|
||||
|
@ -162,8 +172,12 @@ scp_connect(const char *port,
|
|||
trans_delete(t);
|
||||
t = NULL;
|
||||
}
|
||||
else if (libipm_init_trans(t, LIBIPM_FAC_SCP, msgno_to_str) !=
|
||||
E_LI_SUCCESS)
|
||||
else if (scp_init_trans(t) != 0)
|
||||
{
|
||||
trans_delete(t);
|
||||
t = NULL;
|
||||
}
|
||||
else if (scp_send_set_peername_request(t, peername) != 0)
|
||||
{
|
||||
trans_delete(t);
|
||||
t = NULL;
|
||||
|
@ -214,16 +228,48 @@ scp_msg_in_start(struct trans *trans)
|
|||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
scp_send_gateway_request(struct trans *trans,
|
||||
const char *username,
|
||||
const char *password,
|
||||
const char *ip_addr)
|
||||
scp_send_set_peername_request(struct trans *trans,
|
||||
const char *peername)
|
||||
{
|
||||
return libipm_msg_out_simple_send(
|
||||
trans,
|
||||
(int)E_SCP_SET_PEERNAME_REQUEST,
|
||||
"s",
|
||||
peername);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
scp_get_set_peername_request(struct trans *trans,
|
||||
const char **peername)
|
||||
{
|
||||
return libipm_msg_in_parse( trans, "s", peername);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
scp_send_uds_login_request(struct trans *trans)
|
||||
{
|
||||
return libipm_msg_out_simple_send(trans,
|
||||
(int)E_SCP_UDS_LOGIN_REQUEST,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
scp_send_sys_login_request(struct trans *trans,
|
||||
const char *username,
|
||||
const char *password,
|
||||
const char *ip_addr)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = libipm_msg_out_simple_send(
|
||||
trans,
|
||||
(int)E_SCP_GATEWAY_REQUEST,
|
||||
(int)E_SCP_SYS_LOGIN_REQUEST,
|
||||
"sss",
|
||||
username,
|
||||
password,
|
||||
|
@ -238,93 +284,99 @@ scp_send_gateway_request(struct trans *trans,
|
|||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
scp_get_gateway_request(struct trans *trans,
|
||||
const char **username,
|
||||
const char **password,
|
||||
const char **ip_addr)
|
||||
scp_get_sys_login_request(struct trans *trans,
|
||||
const char **username,
|
||||
const char **password,
|
||||
const char **ip_addr)
|
||||
{
|
||||
/* Make sure the buffer is cleared after processing this message */
|
||||
libipm_set_flags(trans, LIBIPM_E_MSG_IN_ERASE_AFTER_USE);
|
||||
|
||||
return libipm_msg_in_parse(trans, "sss", username, password,
|
||||
ip_addr);
|
||||
return libipm_msg_in_parse( trans, "sss",
|
||||
username, password, ip_addr);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
scp_send_gateway_response(struct trans *trans,
|
||||
int auth_result)
|
||||
scp_send_login_response(struct trans *trans,
|
||||
enum scp_login_status login_result,
|
||||
int server_closed)
|
||||
{
|
||||
return libipm_msg_out_simple_send(
|
||||
trans,
|
||||
(int)E_SCP_GATEWAY_RESPONSE,
|
||||
"i",
|
||||
auth_result);
|
||||
(int)E_SCP_LOGIN_RESPONSE,
|
||||
"ib",
|
||||
login_result,
|
||||
(server_closed != 0)); /* Convert to 0/1 */
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
scp_get_gateway_response(struct trans *trans,
|
||||
int *auth_result)
|
||||
scp_get_login_response(struct trans *trans,
|
||||
enum scp_login_status *login_result,
|
||||
int *server_closed)
|
||||
{
|
||||
int32_t i_auth_result = 0;
|
||||
int rv = libipm_msg_in_parse(trans, "i", &i_auth_result);
|
||||
int32_t i_login_result = 0;
|
||||
int dummy;
|
||||
/* User can pass in NULL for server_closed if they're trying an
|
||||
* login method like UDS for which all fails are fatal */
|
||||
if (server_closed == NULL)
|
||||
{
|
||||
server_closed = &dummy;
|
||||
}
|
||||
|
||||
int rv = libipm_msg_in_parse(trans, "ib", &i_login_result, server_closed);
|
||||
if (rv == 0)
|
||||
{
|
||||
*auth_result = i_auth_result;
|
||||
*login_result = (enum scp_login_status)i_login_result;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
scp_send_logout_request(struct trans *trans)
|
||||
{
|
||||
return libipm_msg_out_simple_send( trans, (int)E_SCP_LOGOUT_REQUEST, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
scp_send_create_session_request(struct trans *trans,
|
||||
const char *username,
|
||||
const char *password,
|
||||
enum scp_session_type type,
|
||||
unsigned short width,
|
||||
unsigned short height,
|
||||
unsigned char bpp,
|
||||
const char *shell,
|
||||
const char *directory,
|
||||
const char *ip_addr)
|
||||
const char *directory)
|
||||
{
|
||||
int rv = libipm_msg_out_simple_send(
|
||||
trans,
|
||||
(int)E_SCP_CREATE_SESSION_REQUEST,
|
||||
"ssyqqysss",
|
||||
username,
|
||||
password,
|
||||
type,
|
||||
width,
|
||||
height,
|
||||
bpp,
|
||||
shell,
|
||||
directory,
|
||||
ip_addr);
|
||||
|
||||
/* Wipe the output buffer to remove the password */
|
||||
libipm_msg_out_erase(trans);
|
||||
|
||||
return rv;
|
||||
return libipm_msg_out_simple_send(
|
||||
trans,
|
||||
(int)E_SCP_CREATE_SESSION_REQUEST,
|
||||
"yqqyss",
|
||||
type,
|
||||
width,
|
||||
height,
|
||||
bpp,
|
||||
shell,
|
||||
directory);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
scp_get_create_session_request(struct trans *trans,
|
||||
const char **username,
|
||||
const char **password,
|
||||
enum scp_session_type *type,
|
||||
unsigned short *width,
|
||||
unsigned short *height,
|
||||
unsigned char *bpp,
|
||||
const char **shell,
|
||||
const char **directory,
|
||||
const char **ip_addr)
|
||||
const char **directory)
|
||||
{
|
||||
/* Intermediate values */
|
||||
uint8_t i_type;
|
||||
|
@ -332,21 +384,15 @@ scp_get_create_session_request(struct trans *trans,
|
|||
uint16_t i_height;
|
||||
uint8_t i_bpp;
|
||||
|
||||
/* Make sure the buffer is cleared after processing this message */
|
||||
libipm_set_flags(trans, LIBIPM_E_MSG_IN_ERASE_AFTER_USE);
|
||||
|
||||
int rv = libipm_msg_in_parse(
|
||||
trans,
|
||||
"ssyqqysss",
|
||||
username,
|
||||
password,
|
||||
"yqqyss",
|
||||
&i_type,
|
||||
&i_width,
|
||||
&i_height,
|
||||
&i_bpp,
|
||||
shell,
|
||||
directory,
|
||||
ip_addr);
|
||||
directory);
|
||||
|
||||
if (rv == 0)
|
||||
{
|
||||
|
@ -364,7 +410,7 @@ scp_get_create_session_request(struct trans *trans,
|
|||
|
||||
int
|
||||
scp_send_create_session_response(struct trans *trans,
|
||||
int auth_result,
|
||||
enum scp_screate_status status,
|
||||
int display,
|
||||
const struct guid *guid)
|
||||
{
|
||||
|
@ -374,7 +420,7 @@ scp_send_create_session_response(struct trans *trans,
|
|||
trans,
|
||||
(int)E_SCP_CREATE_SESSION_RESPONSE,
|
||||
"iiB",
|
||||
auth_result,
|
||||
status,
|
||||
display,
|
||||
&guid_descriptor);
|
||||
}
|
||||
|
@ -383,12 +429,12 @@ scp_send_create_session_response(struct trans *trans,
|
|||
|
||||
int
|
||||
scp_get_create_session_response(struct trans *trans,
|
||||
int *auth_result,
|
||||
enum scp_screate_status *status,
|
||||
int *display,
|
||||
struct guid *guid)
|
||||
{
|
||||
/* Intermediate values */
|
||||
int32_t i_auth_result;
|
||||
int32_t i_status;
|
||||
int32_t i_display;
|
||||
|
||||
const struct libipm_fsb guid_descriptor = { (void *)guid, sizeof(*guid) };
|
||||
|
@ -396,12 +442,12 @@ scp_get_create_session_response(struct trans *trans,
|
|||
int rv = libipm_msg_in_parse(
|
||||
trans,
|
||||
"iiB",
|
||||
&i_auth_result,
|
||||
&i_status,
|
||||
&i_display,
|
||||
&guid_descriptor);
|
||||
if (rv == 0)
|
||||
{
|
||||
*auth_result = i_auth_result;
|
||||
*status = (enum scp_screate_status)i_status;
|
||||
*display = i_display;
|
||||
}
|
||||
|
||||
|
@ -411,36 +457,12 @@ scp_get_create_session_response(struct trans *trans,
|
|||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
scp_send_list_sessions_request(struct trans *trans,
|
||||
const char *username,
|
||||
const char *password)
|
||||
scp_send_list_sessions_request(struct trans *trans)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = libipm_msg_out_simple_send(
|
||||
trans,
|
||||
(int)E_SCP_LIST_SESSIONS_REQUEST,
|
||||
"ss",
|
||||
username,
|
||||
password);
|
||||
|
||||
/* Wipe the output buffer to remove the password */
|
||||
libipm_msg_out_erase(trans);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
scp_get_list_sessions_request(struct trans *trans,
|
||||
const char **username,
|
||||
const char **password)
|
||||
{
|
||||
/* Make sure the buffer is cleared after processing this message */
|
||||
libipm_set_flags(trans, LIBIPM_E_MSG_IN_ERASE_AFTER_USE);
|
||||
|
||||
return libipm_msg_in_parse(trans, "ss", username, password);
|
||||
return libipm_msg_out_simple_send(
|
||||
trans,
|
||||
(int)E_SCP_LIST_SESSIONS_REQUEST,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -465,7 +487,7 @@ scp_send_list_sessions_response(
|
|||
rv = libipm_msg_out_simple_send(
|
||||
trans,
|
||||
(int)E_SCP_LIST_SESSIONS_RESPONSE,
|
||||
"iiuyqqyxss",
|
||||
"iiuyqqyxis",
|
||||
status,
|
||||
info->sid,
|
||||
info->display,
|
||||
|
@ -474,7 +496,7 @@ scp_send_list_sessions_response(
|
|||
info->height,
|
||||
info->bpp,
|
||||
info->start_time,
|
||||
info->username,
|
||||
info->uid,
|
||||
info->start_ip_addr);
|
||||
}
|
||||
|
||||
|
@ -511,12 +533,12 @@ scp_get_list_sessions_response(
|
|||
uint16_t i_height;
|
||||
uint8_t i_bpp;
|
||||
int64_t i_start_time;
|
||||
char *i_username;
|
||||
int32_t i_uid;
|
||||
char *i_start_ip_addr;
|
||||
|
||||
rv = libipm_msg_in_parse(
|
||||
trans,
|
||||
"iuyqqyxss",
|
||||
"iuyqqyxis",
|
||||
&i_sid,
|
||||
&i_display,
|
||||
&i_type,
|
||||
|
@ -524,7 +546,7 @@ scp_get_list_sessions_response(
|
|||
&i_height,
|
||||
&i_bpp,
|
||||
&i_start_time,
|
||||
&i_username,
|
||||
&i_uid,
|
||||
&i_start_ip_addr);
|
||||
|
||||
if (rv == 0)
|
||||
|
@ -532,7 +554,6 @@ scp_get_list_sessions_response(
|
|||
/* Allocate a block of memory large enough for the
|
||||
* structure result, and the strings it contains */
|
||||
unsigned int len = sizeof(struct scp_session_info) +
|
||||
g_strlen(i_username) + 1 +
|
||||
g_strlen(i_start_ip_addr) + 1;
|
||||
if ((p = (struct scp_session_info *)g_malloc(len, 1)) == NULL)
|
||||
{
|
||||
|
@ -542,9 +563,8 @@ scp_get_list_sessions_response(
|
|||
{
|
||||
/* Set up the string pointers in the block to point
|
||||
* into the memory allocated after the block */
|
||||
p->username = (char *)p + sizeof(struct scp_session_info);
|
||||
p->start_ip_addr =
|
||||
p->username + g_strlen(i_username) + 1;
|
||||
(char *)p + sizeof(struct scp_session_info);
|
||||
|
||||
/* Copy the data over */
|
||||
p->sid = i_sid;
|
||||
|
@ -554,7 +574,7 @@ scp_get_list_sessions_response(
|
|||
p->height = i_height;
|
||||
p->bpp = i_bpp;
|
||||
p->start_time = i_start_time;
|
||||
g_strcpy(p->username, i_username);
|
||||
p->uid = i_uid;
|
||||
g_strcpy(p->start_ip_addr, i_start_ip_addr);
|
||||
}
|
||||
}
|
||||
|
@ -563,3 +583,14 @@ scp_get_list_sessions_response(
|
|||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
scp_send_close_connection_request(struct trans *trans)
|
||||
{
|
||||
return libipm_msg_out_simple_send(
|
||||
trans,
|
||||
(int)E_SCP_CLOSE_CONNECTION_REQUEST,
|
||||
NULL);
|
||||
}
|
||||
|
|
222
libipm/scp.h
222
libipm/scp.h
|
@ -43,12 +43,24 @@ struct trans;
|
|||
/* Message codes */
|
||||
enum scp_msg_code
|
||||
{
|
||||
E_SCP_GATEWAY_REQUEST = 1,
|
||||
E_SCP_GATEWAY_RESPONSE,
|
||||
E_SCP_SET_PEERNAME_REQUEST = 1,
|
||||
// No E_SCP_SET_PEERNAME_RESPONSE
|
||||
|
||||
E_SCP_SYS_LOGIN_REQUEST,
|
||||
E_SCP_UDS_LOGIN_REQUEST,
|
||||
E_SCP_LOGIN_RESPONSE, /* Shared between login request types */
|
||||
|
||||
E_SCP_LOGOUT_REQUEST,
|
||||
// No S_SCP_LOGOUT_RESPONSE
|
||||
|
||||
E_SCP_CREATE_SESSION_REQUEST,
|
||||
E_SCP_CREATE_SESSION_RESPONSE,
|
||||
|
||||
E_SCP_LIST_SESSIONS_REQUEST,
|
||||
E_SCP_LIST_SESSIONS_RESPONSE
|
||||
E_SCP_LIST_SESSIONS_RESPONSE,
|
||||
|
||||
E_SCP_CLOSE_CONNECTION_REQUEST
|
||||
// No E_SCP_CLOSE_CONNECTION_RESPONSE
|
||||
};
|
||||
|
||||
/* Common facilities */
|
||||
|
@ -97,6 +109,7 @@ scp_port_to_display_string(const char *port, char *buff, unsigned int bufflen);
|
|||
* Connect to an SCP server
|
||||
*
|
||||
* @param port Port definition (e.g. from sesman.ini)
|
||||
* @param peername Name of this program or object (e.g. "xrdp-sesadmin")
|
||||
* @param term_func Function to poll during connection for program
|
||||
* termination, or NULL for none.
|
||||
* @return Initialised SCP transport
|
||||
|
@ -104,16 +117,19 @@ scp_port_to_display_string(const char *port, char *buff, unsigned int bufflen);
|
|||
* The returned transport has the is_term member set to term_func.
|
||||
*/
|
||||
struct trans *
|
||||
scp_connect(const char *port,
|
||||
scp_connect(const char *port,
|
||||
const char *peername,
|
||||
int (*term_func)(void));
|
||||
|
||||
/**
|
||||
* Converts a standard trans connected to an SCP endpoint to an SCP transport
|
||||
*
|
||||
* If you are running on a client, you may wish to use
|
||||
* scp_send_set_peername_request() after the commnect to inform the
|
||||
* server who you are.
|
||||
*
|
||||
* @param trans connected endpoint
|
||||
* @return != 0 for error
|
||||
*
|
||||
* The returned transport has the is_term member set to term_func.
|
||||
*/
|
||||
int
|
||||
scp_init_trans(struct trans *trans);
|
||||
|
@ -170,9 +186,54 @@ scp_msg_in_start(struct trans *trans);
|
|||
void
|
||||
scp_msg_in_reset(struct trans *trans);
|
||||
|
||||
/* -------------------- Setup messages-------------------- */
|
||||
|
||||
/**
|
||||
* Send an E_SCP_GATEWAY_REQUEST (SCP client)
|
||||
* Send an E_SCP_SET_PEERNAME_REQUEST (SCP client)
|
||||
*
|
||||
* @param trans SCP transport
|
||||
* @param peername Peername
|
||||
* @return != 0 for error
|
||||
*
|
||||
* Server does not send a response
|
||||
*
|
||||
* This message is sent automatically by scp_connect(), but it can
|
||||
* be sent at any time.
|
||||
*/
|
||||
int
|
||||
scp_send_set_peername_request(struct trans *trans,
|
||||
const char *peername);
|
||||
|
||||
/**
|
||||
* Parse an incoming E_SCP_SET_PEERNAME_REQUEST message (SCP server)
|
||||
*
|
||||
* @param trans SCP transport
|
||||
* @param[out] peername peername
|
||||
* @return != 0 for error
|
||||
*/
|
||||
int
|
||||
scp_get_set_peername_request(struct trans *trans,
|
||||
const char **peername);
|
||||
|
||||
/* -------------------- Login messages-------------------- */
|
||||
|
||||
/**
|
||||
* Send an E_SCP_UDS_LOGIN_REQUEST (SCP client)
|
||||
*
|
||||
* User is logged in using their socket details
|
||||
*
|
||||
* @param trans SCP transport
|
||||
* @return != 0 for error
|
||||
*
|
||||
* Server replies with E_SCP_LOGIN_RESPONSE
|
||||
*/
|
||||
int
|
||||
scp_send_uds_login_request(struct trans *trans);
|
||||
|
||||
/**
|
||||
* Send an E_SCP_SYS_LOGIN_REQUEST (SCP client)
|
||||
*
|
||||
* User is logged in using explicit credentials
|
||||
*
|
||||
* @param trans SCP transport
|
||||
* @param username Username
|
||||
|
@ -180,16 +241,16 @@ scp_msg_in_reset(struct trans *trans);
|
|||
* @param ip_addr IP address for the client (or "" if not known)
|
||||
* @return != 0 for error
|
||||
*
|
||||
* Server replies with E_SCP_GATEWAY_RESPONSE
|
||||
* Server replies with E_SCP_LOGIN_RESPONSE
|
||||
*/
|
||||
int
|
||||
scp_send_gateway_request(struct trans *trans,
|
||||
const char *username,
|
||||
const char *password,
|
||||
const char *ip_addr);
|
||||
scp_send_sys_login_request(struct trans *trans,
|
||||
const char *username,
|
||||
const char *password,
|
||||
const char *ip_addr);
|
||||
|
||||
/**
|
||||
* Parse an incoming E_SCP_GATEWAY_REQUEST message (SCP server)
|
||||
* Parse an incoming E_SCP_SYS_LOGIN_REQUEST message (SCP server)
|
||||
*
|
||||
* @param trans SCP transport
|
||||
* @param[out] username Username
|
||||
|
@ -198,78 +259,89 @@ scp_send_gateway_request(struct trans *trans,
|
|||
* @return != 0 for error
|
||||
*/
|
||||
int
|
||||
scp_get_gateway_request(struct trans *trans,
|
||||
const char **username,
|
||||
const char **password,
|
||||
const char **ip_addr);
|
||||
scp_get_sys_login_request(struct trans *trans,
|
||||
const char **username,
|
||||
const char **password,
|
||||
const char **ip_addr);
|
||||
|
||||
/**
|
||||
* Send an E_SCP_GATEWAY_RESPONSE (SCP server)
|
||||
* Send an E_SCP_LOGIN_RESPONSE (SCP server)
|
||||
*
|
||||
* @param trans SCP transport
|
||||
* @param auth_result 0 for success, PAM error code otherwise
|
||||
* @param login_result What happened to the login
|
||||
* @param server_closed. If login fails, whether server has closed connection.
|
||||
* If not, a retry can be made.
|
||||
* @return != 0 for error
|
||||
*/
|
||||
int
|
||||
scp_send_gateway_response(struct trans *trans,
|
||||
int auth_result);
|
||||
scp_send_login_response(struct trans *trans,
|
||||
enum scp_login_status login_result,
|
||||
int server_closed);
|
||||
|
||||
/**
|
||||
* Parses an incoming E_SCP_GATEWAY_RESPONSE (SCP client)
|
||||
* Parses an incoming E_SCP_LOGIN_RESPONSE (SCP client)
|
||||
*
|
||||
* @param trans SCP transport
|
||||
* @param[out] auth_result 0 for success, PAM error code otherwise
|
||||
* @param[out] login_result 0 for success, PAM error code otherwise
|
||||
* @param[out] server_closed. If login fails, whether server has closed
|
||||
* connection. If not a retry can be made.
|
||||
* @return != 0 for error
|
||||
*/
|
||||
int
|
||||
scp_get_gateway_response(struct trans *trans,
|
||||
int *auth_result);
|
||||
scp_get_login_response(struct trans *trans,
|
||||
enum scp_login_status *login_result,
|
||||
int *server_closed);
|
||||
|
||||
/* Session messages */
|
||||
/**
|
||||
* Send an E_SCP_LOGOUT_REQUEST (SCP client)
|
||||
*
|
||||
* @param trans SCP transport
|
||||
* @return != 0 for error
|
||||
*
|
||||
* Logs the user out (if they are logged in), so that another
|
||||
* login request can be sent, maybe with a different user.
|
||||
*
|
||||
* A reply is not sent
|
||||
*/
|
||||
int
|
||||
scp_send_logout_request(struct trans *trans);
|
||||
|
||||
/* -------------------- Session messages-------------------- */
|
||||
|
||||
/**
|
||||
* Send an E_SCP_CREATE_SESSION_REQUEST (SCP client)
|
||||
*
|
||||
* @param trans SCP transport
|
||||
* @param username Username of session to create or re-connect to
|
||||
* @param password Password for user
|
||||
* @param type Session type
|
||||
* @param width Initial session width
|
||||
* @param height Initial session height
|
||||
* @param bpp Session bits-per-pixel (ignored for Xorg sessions)
|
||||
* @param shell User program to run. May be ""
|
||||
* @param directory Directory to run the program in. May be ""
|
||||
* @param ip_addr IP address for the client (or "" if not known)
|
||||
* @return != 0 for error
|
||||
*
|
||||
* Server replies with E_SCP_CREATE_SESSION_RESPONSE
|
||||
*/
|
||||
int
|
||||
scp_send_create_session_request(struct trans *trans,
|
||||
const char *username,
|
||||
const char *password,
|
||||
enum scp_session_type type,
|
||||
unsigned short width,
|
||||
unsigned short height,
|
||||
unsigned char bpp,
|
||||
const char *shell,
|
||||
const char *directory,
|
||||
const char *ip_addr);
|
||||
const char *directory);
|
||||
|
||||
|
||||
/**
|
||||
* Parse an incoming E_SCP_CREATE_SESSION_REQUEST (SCP server)
|
||||
*
|
||||
* @param trans SCP transport
|
||||
* @param[out] username Username of session to create or re-connect to
|
||||
* @param[out] password Password for user
|
||||
* @param[out] type Session type
|
||||
* @param[out] width Initial session width
|
||||
* @param[out] height Initial session height
|
||||
* @param[out] bpp Session bits-per-pixel (ignored for Xorg sessions)
|
||||
* @param[out] shell User program to run. May be ""
|
||||
* @param[out] directory Directory to run the program in. May be ""
|
||||
* @param[out] ip_addr IP address for the client. May be ""
|
||||
* @return != 0 for error
|
||||
*
|
||||
* Returned string pointers are valid until scp_msg_in_reset() is
|
||||
|
@ -277,29 +349,26 @@ scp_send_create_session_request(struct trans *trans,
|
|||
*/
|
||||
int
|
||||
scp_get_create_session_request(struct trans *trans,
|
||||
const char **username,
|
||||
const char **password,
|
||||
enum scp_session_type *type,
|
||||
unsigned short *width,
|
||||
unsigned short *height,
|
||||
unsigned char *bpp,
|
||||
const char **shell,
|
||||
const char **directory,
|
||||
const char **ip_addr);
|
||||
const char **directory);
|
||||
|
||||
/**
|
||||
* Send an E_SCP_CREATE_SESSION_RESPONSE (SCP server)
|
||||
*
|
||||
* @param trans SCP transport
|
||||
* @param auth_result 0 for success, PAM error code otherwise
|
||||
* @param display Should be zero if authentication failed.
|
||||
* @param guid Guid for session. Should be all zeros if authentication failed
|
||||
* @param status Status of creation request
|
||||
* @param display Should be zero if create session failed.
|
||||
* @param guid Guid for session. Should be all zeros if create session failed
|
||||
*
|
||||
* @return != 0 for error
|
||||
*/
|
||||
int
|
||||
scp_send_create_session_response(struct trans *trans,
|
||||
int auth_result,
|
||||
enum scp_screate_status status,
|
||||
int display,
|
||||
const struct guid *guid);
|
||||
|
||||
|
@ -308,73 +377,29 @@ scp_send_create_session_response(struct trans *trans,
|
|||
* Parse an incoming E_SCP_CREATE_SESSION_RESPONSE (SCP client)
|
||||
*
|
||||
* @param trans SCP transport
|
||||
* @param[out] auth_result 0 for success, PAM error code otherwise
|
||||
* @param[out] display Should be zero if authentication failed.
|
||||
* @param[out] guid Guid for session. Should be all zeros if authentication
|
||||
* @param[out] status Status of creation request
|
||||
* @param[out] display Should be zero if create session failed.
|
||||
* @param[out] guid Guid for session. Should be all zeros if create session
|
||||
* failed
|
||||
*
|
||||
* @return != 0 for error
|
||||
*/
|
||||
int
|
||||
scp_get_create_session_response(struct trans *trans,
|
||||
int *auth_result,
|
||||
enum scp_screate_status *status,
|
||||
int *display,
|
||||
struct guid *guid);
|
||||
|
||||
/**
|
||||
* Status of an E_SCP_LIST_SESSIONS_RESPONSE message
|
||||
*/
|
||||
enum scp_list_sessions_status
|
||||
{
|
||||
/**
|
||||
* This message contains a valid session, and other messages
|
||||
* will be sent
|
||||
*/
|
||||
E_SCP_LS_SESSION_INFO = 0,
|
||||
|
||||
/**
|
||||
* This message indicates the end of a list of sessions. No session
|
||||
* is contained in the message */
|
||||
E_SCP_LS_END_OF_LIST,
|
||||
|
||||
/**
|
||||
* Authentication failed for the user
|
||||
*/
|
||||
E_SCP_LS_AUTHENTICATION_FAIL = 100,
|
||||
|
||||
/**
|
||||
* A client-side error occurred allocating memory for the session
|
||||
*/
|
||||
E_SCP_LS_NO_MEMORY
|
||||
};
|
||||
|
||||
/**
|
||||
* Send an E_LIST_SESSIONS_REQUEST (SCP client)
|
||||
*
|
||||
* @param trans SCP transport
|
||||
* @param username Username
|
||||
* @param password Password
|
||||
* @return != 0 for error
|
||||
*
|
||||
* Server replies with one or more E_SCP_LIST_SESSIONS_RESPONSE
|
||||
*/
|
||||
int
|
||||
scp_send_list_sessions_request(struct trans *trans,
|
||||
const char *username,
|
||||
const char *password);
|
||||
|
||||
/**
|
||||
* Parse an incoming E_LIST_SESSIONS_REQUEST (SCP server)
|
||||
*
|
||||
* @param trans SCP transport
|
||||
* @param[out] username Username
|
||||
* @param[out] password Password
|
||||
* @return != 0 for error
|
||||
*/
|
||||
int
|
||||
scp_get_list_sessions_request(struct trans *trans,
|
||||
const char **username,
|
||||
const char **password);
|
||||
scp_send_list_sessions_request(struct trans *trans);
|
||||
|
||||
/**
|
||||
* Send an E_LIST_SESSIONS_RESPONSE (SCP server)
|
||||
|
@ -411,5 +436,16 @@ scp_get_list_sessions_response(
|
|||
enum scp_list_sessions_status *status,
|
||||
struct scp_session_info **info);
|
||||
|
||||
/**
|
||||
* Send an E_CLOSE_CONNECTION_REQUEST (SCP client)
|
||||
*
|
||||
* @param trans SCP transport
|
||||
* @return != 0 for error
|
||||
*
|
||||
* Server closes the connection quietly.
|
||||
*/
|
||||
int
|
||||
scp_send_close_connection_request(struct trans *trans);
|
||||
|
||||
|
||||
#endif /* SCP_H */
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2022, all xrdp contributors
|
||||
*
|
||||
* 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 libipm/scp_application_types.c
|
||||
* @brief Support routines for types in scp_application_types.h
|
||||
* @author Matt Burt
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include "scp_application_types.h"
|
||||
#include "os_calls.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
const char *
|
||||
scp_login_status_to_str(enum scp_login_status n,
|
||||
char *buff, unsigned int buff_size)
|
||||
{
|
||||
const char *str =
|
||||
(n == E_SCP_LOGIN_OK) ? "OK" :
|
||||
(n == E_SCP_LOGIN_ALREADY_LOGGED_IN) ? "A user is already logged in" :
|
||||
(n == E_SCP_LOGIN_NO_MEMORY) ? "No memory for login" :
|
||||
(n == E_SCP_LOGIN_NOT_AUTHENTICATED) ? "User does not exist, or could not be authenticated" :
|
||||
(n == E_SCP_LOGIN_NOT_AUTHORIZED) ? "User is not authorized" :
|
||||
(n == E_SCP_LOGIN_GENERAL_ERROR) ? "General login error" :
|
||||
/* Default */ NULL;
|
||||
|
||||
if (str == NULL)
|
||||
{
|
||||
g_snprintf(buff, buff_size, "[login error code #%d]", (int)n);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_snprintf(buff, buff_size, "%s", str);
|
||||
}
|
||||
|
||||
return buff;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
const char *
|
||||
scp_screate_status_to_str(enum scp_screate_status n,
|
||||
char *buff, unsigned int buff_size)
|
||||
{
|
||||
const char *str =
|
||||
(n == E_SCP_SCREATE_OK) ? "OK" :
|
||||
(n == E_SCP_SCREATE_NO_MEMORY) ? "No memory for session" :
|
||||
(n == E_SCP_SCREATE_NOT_LOGGED_IN) ? "Connection is not logged in" :
|
||||
(n == E_SCP_SCREATE_MAX_REACHED) ? "Max session limit reached" :
|
||||
(n == E_SCP_SCREATE_NO_DISPLAY) ? "No X displays are avaiable" :
|
||||
(n == E_SCP_SCREATE_GENERAL_ERROR) ? "General session creation error" :
|
||||
/* Default */ NULL;
|
||||
|
||||
if (str == NULL)
|
||||
{
|
||||
g_snprintf(buff, buff_size, "[session creation error code #%d]",
|
||||
(int)n);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_snprintf(buff, buff_size, "%s", str);
|
||||
}
|
||||
|
||||
return buff;
|
||||
}
|
|
@ -26,7 +26,7 @@
|
|||
#ifndef SCP_APPLICATION_TYPES_H
|
||||
#define SCP_APPLICATION_TYPES_H
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/**
|
||||
* Select the desktop application session type
|
||||
|
@ -57,9 +57,85 @@ struct scp_session_info
|
|||
unsigned short height; ///< Initial session height
|
||||
unsigned char bpp; ///< Session bits-per-pixel
|
||||
time_t start_time; ///< When session was created
|
||||
char *username; ///< Username for session
|
||||
uid_t uid; ///< Username for session
|
||||
char *start_ip_addr; ///< IP address of starting client
|
||||
};
|
||||
|
||||
/**
|
||||
* Status of a login request
|
||||
*/
|
||||
enum scp_login_status
|
||||
{
|
||||
E_SCP_LOGIN_OK = 0, ///< The connection is now loggned in
|
||||
E_SCP_LOGIN_ALREADY_LOGGED_IN, //< A user is currently logged in
|
||||
E_SCP_LOGIN_NO_MEMORY, ///< Memory allocation failure
|
||||
/**
|
||||
* User couldn't be authenticated, or user doesn't exist */
|
||||
E_SCP_LOGIN_NOT_AUTHENTICATED,
|
||||
E_SCP_LOGIN_NOT_AUTHORIZED, ///< User is authenticated, but not authorized
|
||||
E_SCP_LOGIN_GENERAL_ERROR ///< An unspecific error has occurred
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert an scp_login_status code to a readable string for output
|
||||
* @param n Message code
|
||||
* @param buff to contain string
|
||||
* @param buff_size length of buff
|
||||
* @return buff is returned for convenience.
|
||||
*/
|
||||
const char *
|
||||
scp_login_status_to_str(enum scp_login_status n,
|
||||
char *buff, unsigned int buff_size);
|
||||
|
||||
/**
|
||||
* Status of a session creation request
|
||||
*/
|
||||
enum scp_screate_status
|
||||
{
|
||||
E_SCP_SCREATE_OK = 0, ///< Session created
|
||||
E_SCP_SCREATE_NO_MEMORY, ///< Memory allocation failure
|
||||
E_SCP_SCREATE_NOT_LOGGED_IN, ///< Connection is not logged in
|
||||
E_SCP_SCREATE_MAX_REACHED, ///< Max number of sessions already reached
|
||||
E_SCP_SCREATE_NO_DISPLAY, ///< No X server display number is available
|
||||
E_SCP_SCREATE_GENERAL_ERROR ///< An unspecific error has occurred
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert an scp_session creation code to a readable string for output
|
||||
* @param n Message code
|
||||
* @param buff to contain string
|
||||
* @param buff_size length of buff
|
||||
* @return buff is returned for convenience.
|
||||
*/
|
||||
const char *
|
||||
scp_screate_status_to_str(enum scp_screate_status n,
|
||||
char *buff, unsigned int buff_size);
|
||||
|
||||
/**
|
||||
* Status of an list sessions message
|
||||
*/
|
||||
enum scp_list_sessions_status
|
||||
{
|
||||
/**
|
||||
* This message contains a valid session, and other messages
|
||||
* will be sent
|
||||
*/
|
||||
E_SCP_LS_SESSION_INFO = 0,
|
||||
|
||||
/**
|
||||
* This message indicates the end of a list of sessions. No session
|
||||
* is contained in the message */
|
||||
E_SCP_LS_END_OF_LIST,
|
||||
|
||||
/**
|
||||
* Client hasn't logged in yet
|
||||
*/
|
||||
E_SCP_LS_NOT_LOGGED_IN = 100,
|
||||
/**
|
||||
* A client-side error occurred allocating memory for the session
|
||||
*/
|
||||
E_SCP_LS_NO_MEMORY
|
||||
};
|
||||
|
||||
|
||||
#endif /* SCP_APPLICATION_TYPES_H */
|
||||
|
|
|
@ -28,7 +28,13 @@
|
|||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include "arch.h"
|
||||
|
||||
#include "access.h"
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "sesman.h"
|
||||
#include "os_calls.h"
|
||||
#include "string_calls.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -51,7 +57,7 @@ access_login_allowed(const char *user)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (0 != g_getuser_info(user, &gid, 0, 0, 0, 0))
|
||||
if (0 != g_getuser_info_by_name(user, 0, &gid, 0, 0, 0))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Cannot read user info! - login denied");
|
||||
return 0;
|
||||
|
@ -100,7 +106,7 @@ access_login_mng_allowed(const char *user)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (0 != g_getuser_info(user, &gid, 0, 0, 0, 0))
|
||||
if (0 != g_getuser_info_by_name(user, 0, &gid, 0, 0, 0))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "[MNG] Cannot read user info! - login denied");
|
||||
return 0;
|
||||
|
|
|
@ -27,11 +27,11 @@
|
|||
#ifndef AUTH_H
|
||||
#define AUTH_H
|
||||
|
||||
|
||||
/**
|
||||
* Opaque type used to represent an authentication handle
|
||||
*/
|
||||
struct auth_info;
|
||||
#include "scp_application_types.h"
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -39,13 +39,25 @@ struct auth_info;
|
|||
* @param user user's login name
|
||||
* @param pass user's password
|
||||
* @param client_ip IP address of connecting client (or ""/NULL if not known)
|
||||
* @param[out] errorcode from result
|
||||
* @param[out] Error code for the operation. E_SCP_LOGIN_OK on success.
|
||||
* @return auth handle on success, NULL on failure
|
||||
*
|
||||
*/
|
||||
struct auth_info *
|
||||
auth_userpass(const char *user, const char *pass,
|
||||
const char *client_ip, int *errorcode);
|
||||
const char *client_ip, enum scp_login_status *errorcode);
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Gets an auth handle for a UDS login
|
||||
*
|
||||
* @param uid User ID
|
||||
* @param[out] Error code for the operation. E_SCP_LOGIN_OK on success.
|
||||
* @return auth handle on success, NULL on failure
|
||||
*
|
||||
*/
|
||||
struct auth_info *
|
||||
auth_uds(const char *user, enum scp_login_status *errorcode);
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -29,9 +29,10 @@
|
|||
#endif
|
||||
|
||||
#include "arch.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "list.h"
|
||||
#include "file.h"
|
||||
#include "sesman.h"
|
||||
#include "log.h"
|
||||
#include "string_calls.h"
|
||||
#include "chansrv/chansrv_common.h"
|
||||
|
|
36
sesman/env.c
36
sesman/env.c
|
@ -30,11 +30,15 @@
|
|||
|
||||
#include <grp.h>
|
||||
|
||||
#include "xrdp_sockets.h"
|
||||
#include "env.h"
|
||||
#include "config.h"
|
||||
#include "list.h"
|
||||
#include "log.h"
|
||||
#include "os_calls.h"
|
||||
#include "sesman.h"
|
||||
#include "ssl_calls.h"
|
||||
#include "string_calls.h"
|
||||
#include "xrdp_sockets.h"
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
|
@ -88,26 +92,27 @@ env_check_password_file(const char *filename, const char *passwd)
|
|||
/******************************************************************************/
|
||||
/* its the responsibility of the caller to free passwd_file */
|
||||
int
|
||||
env_set_user(const char *username, char **passwd_file, int display,
|
||||
env_set_user(int uid, char **passwd_file, int display,
|
||||
const struct list *env_names, const struct list *env_values)
|
||||
{
|
||||
int error;
|
||||
int pw_uid;
|
||||
int pw_gid;
|
||||
int uid;
|
||||
int index;
|
||||
int len;
|
||||
char *name;
|
||||
char *value;
|
||||
char *pw_username;
|
||||
char *pw_shell;
|
||||
char *pw_dir;
|
||||
char text[256];
|
||||
char hostname[256];
|
||||
|
||||
pw_username = 0;
|
||||
pw_shell = 0;
|
||||
pw_dir = 0;
|
||||
|
||||
error = g_getuser_info(username, &pw_gid, &pw_uid, &pw_shell, &pw_dir, 0);
|
||||
error = g_getuser_info_by_uid(uid, &pw_username, &pw_gid, &pw_shell,
|
||||
&pw_dir, 0);
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
|
@ -119,7 +124,6 @@ env_set_user(const char *username, char **passwd_file, int display,
|
|||
|
||||
if (error == 0)
|
||||
{
|
||||
uid = pw_uid;
|
||||
error = g_setuid(uid);
|
||||
}
|
||||
|
||||
|
@ -130,8 +134,8 @@ env_set_user(const char *username, char **passwd_file, int display,
|
|||
g_clearenv();
|
||||
g_setenv("SHELL", pw_shell, 1);
|
||||
g_setenv("PATH", "/sbin:/bin:/usr/bin:/usr/local/bin", 1);
|
||||
g_setenv("USER", username, 1);
|
||||
g_setenv("LOGNAME", username, 1);
|
||||
g_setenv("USER", pw_username, 1);
|
||||
g_setenv("LOGNAME", pw_username, 1);
|
||||
g_sprintf(text, "%d", uid);
|
||||
g_setenv("UID", text, 1);
|
||||
g_setenv("HOME", pw_dir, 1);
|
||||
|
@ -177,14 +181,14 @@ env_set_user(const char *username, char **passwd_file, int display,
|
|||
}
|
||||
|
||||
len = g_snprintf(NULL, 0, "%s/.vnc/sesman_passwd-%s@%s:%d",
|
||||
pw_dir, username, hostname, display);
|
||||
pw_dir, pw_username, hostname, display);
|
||||
|
||||
*passwd_file = (char *) g_malloc(len + 1, 1);
|
||||
if (*passwd_file != NULL)
|
||||
{
|
||||
/* Try legacy names first, remove if found */
|
||||
g_sprintf(*passwd_file, "%s/.vnc/sesman_%s_passwd:%d",
|
||||
pw_dir, username, display);
|
||||
pw_dir, pw_username, display);
|
||||
if (g_file_exist(*passwd_file))
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "Removing old "
|
||||
|
@ -192,7 +196,7 @@ env_set_user(const char *username, char **passwd_file, int display,
|
|||
g_file_delete(*passwd_file);
|
||||
}
|
||||
g_sprintf(*passwd_file, "%s/.vnc/sesman_%s_passwd",
|
||||
pw_dir, username);
|
||||
pw_dir, pw_username);
|
||||
if (g_file_exist(*passwd_file))
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "Removing insecure "
|
||||
|
@ -200,18 +204,18 @@ env_set_user(const char *username, char **passwd_file, int display,
|
|||
g_file_delete(*passwd_file);
|
||||
}
|
||||
g_sprintf(*passwd_file, "%s/.vnc/sesman_passwd-%s@%s:%d",
|
||||
pw_dir, username, hostname, display);
|
||||
pw_dir, pw_username, hostname, display);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* we use auth_file_path as requested */
|
||||
len = g_snprintf(NULL, 0, g_cfg->auth_file_path, username);
|
||||
len = g_snprintf(NULL, 0, g_cfg->auth_file_path, pw_username);
|
||||
|
||||
*passwd_file = (char *) g_malloc(len + 1, 1);
|
||||
if (*passwd_file != NULL)
|
||||
{
|
||||
g_sprintf(*passwd_file, g_cfg->auth_file_path, username);
|
||||
g_sprintf(*passwd_file, g_cfg->auth_file_path, pw_username);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -221,6 +225,7 @@ env_set_user(const char *username, char **passwd_file, int display,
|
|||
}
|
||||
}
|
||||
|
||||
g_free(pw_username);
|
||||
g_free(pw_dir);
|
||||
g_free(pw_shell);
|
||||
}
|
||||
|
@ -228,8 +233,7 @@ env_set_user(const char *username, char **passwd_file, int display,
|
|||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"error getting user info for user %s",
|
||||
username);
|
||||
"error getting user info for uid %d", uid);
|
||||
}
|
||||
|
||||
return error;
|
||||
|
|
|
@ -43,14 +43,14 @@ env_check_password_file(const char *filename, const char *password);
|
|||
/**
|
||||
*
|
||||
* @brief Sets user environment ($PATH, $HOME, $UID, and others)
|
||||
* @param username Username
|
||||
* @param uid user ID
|
||||
* @param passwd_file VNC password file
|
||||
* @param display The session display
|
||||
* @return 0 on success, g_getuser_info() error codes on error
|
||||
*
|
||||
*/
|
||||
int
|
||||
env_set_user(const char *username, char **passwd_file, int display,
|
||||
env_set_user(int uid, char **passwd_file, int display,
|
||||
const struct list *env_names, const struct list *env_values);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -35,7 +35,10 @@
|
|||
#include "scp_process.h"
|
||||
#include "access.h"
|
||||
#include "auth.h"
|
||||
#include "os_calls.h"
|
||||
#include "session.h"
|
||||
#include "sesman.h"
|
||||
#include "string_calls.h"
|
||||
|
||||
/**************************************************************************//**
|
||||
* Logs an authentication failure message
|
||||
|
@ -58,142 +61,408 @@ log_authfail_message(const char *username, const char *ip_addr)
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
static int
|
||||
process_gateway_request(struct trans *trans)
|
||||
/**
|
||||
* Mode parameter for authenticate_and_authorize_connection()
|
||||
*/
|
||||
enum login_mode
|
||||
{
|
||||
int rv;
|
||||
const char *username;
|
||||
const char *password;
|
||||
const char *ip_addr;
|
||||
AM_SYSTEM,
|
||||
AM_UDS
|
||||
};
|
||||
|
||||
rv = scp_get_gateway_request(trans, &username, &password, &ip_addr);
|
||||
if (rv == 0)
|
||||
/**
|
||||
* Authenticate and authorize the connection
|
||||
*
|
||||
* @param sc Connection to sesman
|
||||
* @param login_mode Describes the type of login in use
|
||||
* @param uid UID for user
|
||||
* @param username Name for user
|
||||
* @param password Password (AM_SYSTEM) or NULL.
|
||||
* @param ip_addr Remote IP address (AM_SYSTEM) or NULL.
|
||||
* @return Status for the operation
|
||||
*
|
||||
* @pre sc->auth_info, sc->username and sc->ip_addr must be NULL
|
||||
*
|
||||
* @post If E_SCP_LOGIN_OK is returned, sc->auth_info is non-NULL
|
||||
* @post If E_SCP_LOGIN_OK is returned, sc->username is non-NULL
|
||||
* @post If E_SCP_LOGIN_OK is returned, sc->ip_addr is non-NULL
|
||||
*
|
||||
*/
|
||||
static enum scp_login_status
|
||||
authenticate_and_authorize_connection(struct sesman_con *sc,
|
||||
enum login_mode login_mode,
|
||||
int uid,
|
||||
const char *username,
|
||||
const char *password,
|
||||
const char *ip_addr)
|
||||
{
|
||||
enum scp_login_status status = E_SCP_LOGIN_GENERAL_ERROR;
|
||||
struct auth_info *auth_info = NULL;
|
||||
|
||||
/* Check preconditions */
|
||||
if (sc->auth_info != NULL || sc->username != NULL || sc->ip_addr != NULL)
|
||||
{
|
||||
int errorcode = 0;
|
||||
struct auth_info *auth_info;
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Internal error - connection already logged in");
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (login_mode)
|
||||
{
|
||||
case AM_SYSTEM:
|
||||
auth_info = auth_userpass(username, password, ip_addr, &status);
|
||||
break;
|
||||
case AM_UDS:
|
||||
auth_info = auth_uds(username, &status);
|
||||
break;
|
||||
default:
|
||||
LOG(LOG_LEVEL_ERROR, "%s called with invalid mode %d",
|
||||
__func__, (int)login_mode);
|
||||
}
|
||||
|
||||
LOG(LOG_LEVEL_INFO, "Received authentication request for user: %s",
|
||||
username);
|
||||
|
||||
auth_info = auth_userpass(username, password, ip_addr, &errorcode);
|
||||
if (auth_info != NULL)
|
||||
{
|
||||
if (1 == access_login_allowed(username))
|
||||
if (status != E_SCP_LOGIN_OK)
|
||||
{
|
||||
/* the user is member of the correct groups. */
|
||||
LOG(LOG_LEVEL_INFO, "Access permitted for user: %s",
|
||||
username);
|
||||
/* This shouldn't happen */
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Unexpected status return %d from auth call",
|
||||
(int)status);
|
||||
}
|
||||
else
|
||||
else if (!access_login_allowed(username))
|
||||
{
|
||||
/* all first 32 are reserved for PAM errors */
|
||||
errorcode = 32 + 3;
|
||||
status = E_SCP_LOGIN_NOT_AUTHORIZED;
|
||||
LOG(LOG_LEVEL_INFO, "Username okay but group problem for "
|
||||
"user: %s", username);
|
||||
}
|
||||
|
||||
/* If all is well, put the auth_info in the sesman connection
|
||||
* for later use. If not, remove the auth_info */
|
||||
if (status == E_SCP_LOGIN_OK)
|
||||
{
|
||||
char *dup_username = g_strdup(username);
|
||||
char *dup_ip_addr =
|
||||
(ip_addr == NULL) ? g_strdup("") : 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;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "Access permitted for user: %s",
|
||||
username);
|
||||
sc->auth_info = auth_info;
|
||||
sc->uid = uid;
|
||||
sc->username = dup_username;
|
||||
sc->ip_addr = dup_ip_addr;
|
||||
}
|
||||
}
|
||||
|
||||
if (status != E_SCP_LOGIN_OK)
|
||||
{
|
||||
auth_end(auth_info);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log_authfail_message(username, ip_addr);
|
||||
}
|
||||
rv = scp_send_gateway_response(trans, errorcode);
|
||||
auth_end(auth_info);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static int
|
||||
process_set_peername_request(struct sesman_con *sc)
|
||||
{
|
||||
int rv;
|
||||
const char *peername;
|
||||
|
||||
rv = scp_get_set_peername_request(sc->t, &peername);
|
||||
if (rv == 0)
|
||||
{
|
||||
if (sesman_set_connection_peername(sc, peername) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Failed to set connection peername from %s to %s",
|
||||
sc->peername, peername);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static int
|
||||
process_create_session_request(struct trans *trans)
|
||||
process_sys_login_request(struct sesman_con *sc)
|
||||
{
|
||||
int rv;
|
||||
const char *supplied_username;
|
||||
const char *password;
|
||||
const char *ip_addr;
|
||||
|
||||
rv = scp_get_sys_login_request(sc->t, &supplied_username,
|
||||
&password, &ip_addr);
|
||||
if (rv == 0)
|
||||
{
|
||||
enum scp_login_status errorcode;
|
||||
int server_closed = 1;
|
||||
int uid;
|
||||
char *username = NULL;
|
||||
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Received system login request from %s for user: %s IP: %s",
|
||||
sc->peername, supplied_username, ip_addr);
|
||||
|
||||
if (sc->auth_info != NULL)
|
||||
{
|
||||
errorcode = E_SCP_LOGIN_ALREADY_LOGGED_IN;
|
||||
LOG(LOG_LEVEL_ERROR, "Connection is already logged in for %s",
|
||||
sc->username);
|
||||
}
|
||||
else if (g_getuser_info_by_name(supplied_username,
|
||||
&uid, NULL, NULL, NULL, NULL) != 0)
|
||||
{
|
||||
/* we can't get a UID for the user */
|
||||
errorcode = E_SCP_LOGIN_NOT_AUTHENTICATED;
|
||||
LOG(LOG_LEVEL_ERROR, "Can't get UID for user %s",
|
||||
supplied_username);
|
||||
log_authfail_message(username, ip_addr);
|
||||
}
|
||||
else if (g_getuser_info_by_uid(uid,
|
||||
&username, NULL, NULL, NULL, NULL) != 0)
|
||||
{
|
||||
errorcode = E_SCP_LOGIN_GENERAL_ERROR;
|
||||
LOG(LOG_LEVEL_ERROR, "Can't reverse lookup UID %d", uid);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g_strcmp(supplied_username, 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 within sesman
|
||||
*/
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Using username %s for the session (from UID %d)",
|
||||
username, uid);
|
||||
}
|
||||
|
||||
errorcode = authenticate_and_authorize_connection(
|
||||
sc, AM_SYSTEM,
|
||||
uid, username,
|
||||
password, ip_addr);
|
||||
if (errorcode == E_SCP_LOGIN_OK)
|
||||
{
|
||||
server_closed = 0;
|
||||
}
|
||||
else if (errorcode == E_SCP_LOGIN_NOT_AUTHENTICATED)
|
||||
{
|
||||
log_authfail_message(username, ip_addr);
|
||||
if (sc->auth_retry_count > 0)
|
||||
{
|
||||
/* Password problem? Invite the user to retry */
|
||||
server_closed = 0;
|
||||
--sc->auth_retry_count;
|
||||
}
|
||||
}
|
||||
|
||||
g_free(username);
|
||||
}
|
||||
|
||||
if (server_closed)
|
||||
{
|
||||
/* Expecting no more client messages. Close the connection
|
||||
* after returning from this callback */
|
||||
sc->close_requested = 1;
|
||||
}
|
||||
|
||||
rv = scp_send_login_response(sc->t, errorcode, server_closed);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static int
|
||||
process_uds_login_request(struct sesman_con *sc)
|
||||
{
|
||||
enum scp_login_status errorcode;
|
||||
int rv;
|
||||
int uid;
|
||||
int pid;
|
||||
char *username = NULL;
|
||||
int server_closed = 1;
|
||||
|
||||
rv = g_sck_get_peer_cred(sc->t->sck, &pid, &uid, NULL);
|
||||
if (rv != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Unable to get peer credentials for socket %d",
|
||||
(int)sc->t->sck);
|
||||
errorcode = E_SCP_LOGIN_GENERAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Received UDS login request from %s for UID: %d from PID: %d",
|
||||
sc->peername, uid, pid);
|
||||
|
||||
if (sc->auth_info != NULL)
|
||||
{
|
||||
errorcode = E_SCP_LOGIN_ALREADY_LOGGED_IN;
|
||||
LOG(LOG_LEVEL_ERROR, "Connection is already logged in for %s",
|
||||
sc->username);
|
||||
}
|
||||
else if (g_getuser_info_by_uid(uid, &username,
|
||||
NULL, NULL, NULL, NULL) != 0)
|
||||
{
|
||||
errorcode = E_SCP_LOGIN_GENERAL_ERROR;
|
||||
LOG(LOG_LEVEL_ERROR, "Can't reverse lookup UID %d", uid);
|
||||
}
|
||||
else
|
||||
{
|
||||
errorcode = authenticate_and_authorize_connection(
|
||||
sc, AM_UDS,
|
||||
uid, username,
|
||||
NULL, NULL);
|
||||
g_free(username);
|
||||
|
||||
if (errorcode == E_SCP_LOGIN_OK)
|
||||
{
|
||||
server_closed = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (server_closed)
|
||||
{
|
||||
/* Close the connection after returning from this callback */
|
||||
sc->close_requested = 1;
|
||||
}
|
||||
|
||||
return scp_send_login_response(sc->t, errorcode, server_closed);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static int
|
||||
process_logout_request(struct sesman_con *sc)
|
||||
{
|
||||
if (sc->auth_info != NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "Logging out %s from sesman", sc->username);
|
||||
auth_end(sc->auth_info);
|
||||
sc->auth_info = NULL;
|
||||
sc->uid = -1;
|
||||
g_free(sc->username);
|
||||
sc->username = NULL;
|
||||
g_free(sc->ip_addr);
|
||||
sc->ip_addr = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static int
|
||||
process_create_session_request(struct sesman_con *sc)
|
||||
{
|
||||
int rv;
|
||||
struct session_parameters sp;
|
||||
const char *password;
|
||||
struct guid guid;
|
||||
int display = 0;
|
||||
enum scp_screate_status status = E_SCP_SCREATE_OK;
|
||||
|
||||
guid_clear(&guid);
|
||||
int display = 0;
|
||||
|
||||
rv = scp_get_create_session_request(
|
||||
trans,
|
||||
&sp.username, &password,
|
||||
&sp.type, &sp.width, &sp.height, &sp.bpp,
|
||||
&sp.shell, &sp.directory, &sp.ip_addr);
|
||||
rv = scp_get_create_session_request(sc->t,
|
||||
&sp.type, &sp.width, &sp.height,
|
||||
&sp.bpp, &sp.shell, &sp.directory);
|
||||
|
||||
if (rv == 0)
|
||||
{
|
||||
struct auth_info *auth_info;
|
||||
struct session_item *s_item;
|
||||
int errorcode = 0;
|
||||
bool_t do_auth_end = 1;
|
||||
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Received request to create %s session for user: %s",
|
||||
SCP_SESSION_TYPE_TO_STR(sp.type),
|
||||
sp.username);
|
||||
|
||||
auth_info = auth_userpass(sp.username, password, sp.ip_addr, &errorcode);
|
||||
if (auth_info != NULL)
|
||||
if (sc->auth_info == NULL)
|
||||
{
|
||||
s_item = session_get_bydata(&sp);
|
||||
status = E_SCP_SCREATE_NOT_LOGGED_IN;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Received request from %s to create a session for user %s",
|
||||
sc->peername, sc->username);
|
||||
|
||||
// Copy over the items we got from the login request,
|
||||
// but which we need to describe the session
|
||||
sp.uid = sc->uid;
|
||||
sp.ip_addr = sc->ip_addr; // Guaranteed to be non-NULL
|
||||
|
||||
struct session_item *s_item = session_get_bydata(&sp);
|
||||
if (s_item != 0)
|
||||
{
|
||||
// Found an existing session
|
||||
display = s_item->display;
|
||||
guid = s_item->guid;
|
||||
if (sp.ip_addr[0] != '\0')
|
||||
{
|
||||
LOG( LOG_LEVEL_INFO, "++ reconnected session: username %s, "
|
||||
"display :%d.0, session_pid %d, ip %s",
|
||||
sp.username, display, s_item->pid, sp.ip_addr);
|
||||
sc->username, display, s_item->pid, sp.ip_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "++ reconnected session: username %s, "
|
||||
"display :%d.0, session_pid %d", sp.username, display,
|
||||
s_item->pid);
|
||||
"display :%d.0, session_pid %d",
|
||||
sc->username, display, s_item->pid);
|
||||
}
|
||||
|
||||
session_reconnect(display, sp.username, auth_info);
|
||||
session_reconnect(display, sc->uid, sc->auth_info);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "pre auth");
|
||||
|
||||
if (1 == access_login_allowed(sp.username))
|
||||
// Need to create a new session
|
||||
if (sp.ip_addr[0] != '\0')
|
||||
{
|
||||
if (sp.ip_addr[0] != '\0')
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"++ created session (access granted): "
|
||||
"username %s, ip %s", sp.username, sp.ip_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"++ created session (access granted): "
|
||||
"username %s", sp.username);
|
||||
}
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"++ created session: username %s, ip %s",
|
||||
sc->username, sp.ip_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"++ created session: username %s", sc->username);
|
||||
}
|
||||
|
||||
display = session_start(auth_info, &sp, &guid);
|
||||
|
||||
/* if the session started up ok, auth_end will be called on
|
||||
sig child */
|
||||
do_auth_end = display == 0;
|
||||
// The new session will have a lifetime longer than
|
||||
// the sesman connection, and so needs to own
|
||||
// the auth_info struct.
|
||||
//
|
||||
// Copy the auth_info struct out of the connection and pass
|
||||
// it to the session
|
||||
struct auth_info *auth_info = sc->auth_info;
|
||||
sc->auth_info = NULL;
|
||||
status = session_start(auth_info, &sp, &display, &guid);
|
||||
if (status != E_SCP_SCREATE_OK)
|
||||
{
|
||||
// Close the auth session down as it can't be re-used.
|
||||
auth_end(auth_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log_authfail_message(sp.username, sp.ip_addr);
|
||||
}
|
||||
|
||||
if (do_auth_end)
|
||||
{
|
||||
auth_end(auth_info);
|
||||
}
|
||||
/* Currently a create session request is the last thing on a
|
||||
* connection, and results in automatic closure */
|
||||
sc->close_requested = 1;
|
||||
|
||||
rv = scp_send_create_session_response(trans, errorcode, display, &guid);
|
||||
rv = scp_send_create_session_response(sc->t, status, display, &guid);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -202,75 +471,99 @@ process_create_session_request(struct trans *trans)
|
|||
/******************************************************************************/
|
||||
|
||||
static int
|
||||
process_list_sessions_request(struct trans *trans)
|
||||
process_list_sessions_request(struct sesman_con *sc)
|
||||
{
|
||||
int rv;
|
||||
int rv = 0;
|
||||
|
||||
const char *username;
|
||||
const char *password;
|
||||
struct scp_session_info *info = NULL;
|
||||
unsigned int cnt = 0;
|
||||
unsigned int i;
|
||||
|
||||
rv = scp_get_list_sessions_request(trans, &username, &password);
|
||||
if (rv == 0)
|
||||
if (sc->auth_info == NULL)
|
||||
{
|
||||
rv = scp_send_list_sessions_response(sc->t,
|
||||
E_SCP_LS_NOT_LOGGED_IN,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
enum scp_list_sessions_status status;
|
||||
int errorcode = 0;
|
||||
struct auth_info *auth_info;
|
||||
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Received request to list sessions for user %s", username);
|
||||
"Received request from %s to list sessions for user %s",
|
||||
sc->peername, sc->username);
|
||||
|
||||
auth_info = auth_userpass(username, password, NULL, &errorcode);
|
||||
if (auth_info != NULL)
|
||||
{
|
||||
struct scp_session_info *info = NULL;
|
||||
unsigned int cnt = 0;
|
||||
unsigned int i;
|
||||
info = session_get_byuser(username, &cnt,
|
||||
SESMAN_SESSION_STATUS_ALL);
|
||||
info = session_get_byuid(sc->uid, &cnt,
|
||||
SESMAN_SESSION_STATUS_ALL);
|
||||
|
||||
for (i = 0; rv == 0 && i < cnt; ++i)
|
||||
{
|
||||
rv = scp_send_list_sessions_response(trans,
|
||||
E_SCP_LS_SESSION_INFO,
|
||||
&info[i]);
|
||||
}
|
||||
free_session_info_list(info, cnt);
|
||||
status = E_SCP_LS_END_OF_LIST;
|
||||
}
|
||||
else
|
||||
for (i = 0; rv == 0 && i < cnt; ++i)
|
||||
{
|
||||
status = E_SCP_LS_AUTHENTICATION_FAIL;
|
||||
rv = scp_send_list_sessions_response(sc->t,
|
||||
E_SCP_LS_SESSION_INFO,
|
||||
&info[i]);
|
||||
}
|
||||
auth_end(auth_info);
|
||||
free_session_info_list(info, cnt);
|
||||
|
||||
if (rv == 0)
|
||||
{
|
||||
rv = scp_send_list_sessions_response(trans, status, NULL);
|
||||
rv = scp_send_list_sessions_response(sc->t,
|
||||
E_SCP_LS_END_OF_LIST,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static int
|
||||
process_close_connection_request(struct sesman_con *sc)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
LOG(LOG_LEVEL_INFO, "Received request to close connection from %s",
|
||||
sc->peername);
|
||||
|
||||
/* Expecting no more client messages. Close the connection
|
||||
* after returning from this callback */
|
||||
sc->close_requested = 1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
scp_process(struct trans *t)
|
||||
scp_process(struct sesman_con *sc)
|
||||
{
|
||||
enum scp_msg_code msgno;
|
||||
int rv = 0;
|
||||
|
||||
switch ((msgno = scp_msg_in_start(t)))
|
||||
switch ((msgno = scp_msg_in_start(sc->t)))
|
||||
{
|
||||
case E_SCP_GATEWAY_REQUEST:
|
||||
rv = process_gateway_request(t);
|
||||
case E_SCP_SET_PEERNAME_REQUEST:
|
||||
rv = process_set_peername_request(sc);
|
||||
break;
|
||||
|
||||
case E_SCP_SYS_LOGIN_REQUEST:
|
||||
rv = process_sys_login_request(sc);
|
||||
break;
|
||||
|
||||
case E_SCP_UDS_LOGIN_REQUEST:
|
||||
rv = process_uds_login_request(sc);
|
||||
break;
|
||||
|
||||
case E_SCP_LOGOUT_REQUEST:
|
||||
rv = process_logout_request(sc);
|
||||
break;
|
||||
|
||||
case E_SCP_CREATE_SESSION_REQUEST:
|
||||
rv = process_create_session_request(t);
|
||||
rv = process_create_session_request(sc);
|
||||
break;
|
||||
|
||||
case E_SCP_LIST_SESSIONS_REQUEST:
|
||||
rv = process_list_sessions_request(t);
|
||||
rv = process_list_sessions_request(sc);
|
||||
break;
|
||||
|
||||
case E_SCP_CLOSE_CONNECTION_REQUEST:
|
||||
rv = process_close_connection_request(sc);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -27,15 +27,15 @@
|
|||
#ifndef SCP_PROCESS_H
|
||||
#define SCP_PROCESS_H
|
||||
|
||||
struct trans;
|
||||
struct sesman_con;
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Processes an SCP message
|
||||
* @param t the connection trans
|
||||
* @param sc the sesman connection
|
||||
*
|
||||
*/
|
||||
int
|
||||
scp_process(struct trans *t);
|
||||
scp_process(struct sesman_con *sc);
|
||||
|
||||
#endif
|
||||
|
|
109
sesman/sesman.c
109
sesman/sesman.c
|
@ -30,13 +30,19 @@
|
|||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "arch.h"
|
||||
#include "sesman.h"
|
||||
#include "xrdp_configure_options.h"
|
||||
|
||||
#include "auth.h"
|
||||
#include "config.h"
|
||||
#include "lock_uds.h"
|
||||
#include "os_calls.h"
|
||||
#include "scp.h"
|
||||
#include "scp_process.h"
|
||||
#include "sig.h"
|
||||
#include "string_calls.h"
|
||||
#include "trans.h"
|
||||
|
||||
#include "scp_process.h"
|
||||
#include "lock_uds.h"
|
||||
#include "xrdp_configure_options.h"
|
||||
|
||||
/**
|
||||
* Maximum number of short-lived connections to sesman
|
||||
|
@ -72,14 +78,6 @@ tintptr g_term_event = 0;
|
|||
tintptr g_sigchld_event = 0;
|
||||
tintptr g_reload_event = 0;
|
||||
|
||||
/**
|
||||
* Items stored on the g_con_list
|
||||
*/
|
||||
struct sesman_con
|
||||
{
|
||||
struct trans *t;
|
||||
};
|
||||
|
||||
static struct trans *g_list_trans;
|
||||
|
||||
/* Variables used to lock g_list_trans */
|
||||
|
@ -126,9 +124,11 @@ alloc_connection(struct trans *t)
|
|||
{
|
||||
struct sesman_con *result;
|
||||
|
||||
if ((result = g_new(struct sesman_con, 1)) != NULL)
|
||||
if ((result = g_new0(struct sesman_con, 1)) != NULL)
|
||||
{
|
||||
g_snprintf(result->peername, sizeof(result->peername), "%s", "unknown");
|
||||
result->t = t;
|
||||
result->auth_retry_count = g_cfg->sec.login_retry;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -140,15 +140,40 @@ alloc_connection(struct trans *t)
|
|||
* After this call, the passed-in pointer is invalid and must not be
|
||||
* referenced.
|
||||
*
|
||||
* Any auth_info struct found in the sesman_con is also deallocated.
|
||||
*
|
||||
* @param sc struct to de-allocate
|
||||
*/
|
||||
static void
|
||||
delete_connection(struct sesman_con *sc)
|
||||
{
|
||||
trans_delete(sc->t);
|
||||
g_free(sc);
|
||||
if (sc != NULL)
|
||||
{
|
||||
trans_delete(sc->t);
|
||||
if (sc->auth_info != NULL)
|
||||
{
|
||||
auth_end(sc->auth_info);
|
||||
}
|
||||
g_free(sc->username);
|
||||
g_free(sc->ip_addr);
|
||||
g_free(sc);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
sesman_set_connection_peername(struct sesman_con *sc, const char *name)
|
||||
{
|
||||
int rv = 1;
|
||||
|
||||
if (sc != NULL && name != NULL)
|
||||
{
|
||||
g_snprintf(sc->peername, sizeof(sc->peername), "%s", name);
|
||||
rv = 0;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
|
@ -275,16 +300,23 @@ static int sesman_listen_test(struct config_sesman *cfg)
|
|||
|
||||
/******************************************************************************/
|
||||
int
|
||||
sesman_close_all(void)
|
||||
sesman_close_all(unsigned int flags)
|
||||
{
|
||||
int index;
|
||||
struct sesman_con *sc;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "sesman_close_all:");
|
||||
|
||||
|
||||
sesman_delete_listening_transport();
|
||||
for (index = 0; index < g_con_list->count; index++)
|
||||
{
|
||||
sc = (struct sesman_con *) list_get_item(g_con_list, index);
|
||||
if (sc != NULL && (flags & SCA_CLOSE_AUTH_INFO) == 0)
|
||||
{
|
||||
// Prevent delete_connection() closing the auth_info down
|
||||
sc->auth_info = NULL;
|
||||
}
|
||||
delete_connection(sc);
|
||||
}
|
||||
return 0;
|
||||
|
@ -301,7 +333,8 @@ sesman_data_in(struct trans *self)
|
|||
|
||||
if (rv == 0 && available)
|
||||
{
|
||||
if ((rv = scp_process(self)) != 0)
|
||||
struct sesman_con *sc = (struct sesman_con *)self->callback_data;
|
||||
if ((rv = scp_process(sc)) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "sesman_data_in: scp_process_msg failed");
|
||||
}
|
||||
|
@ -327,7 +360,7 @@ sesman_listen_conn_in(struct trans *self, struct trans *new_self)
|
|||
{
|
||||
LOG(LOG_LEVEL_ERROR, "sesman_data_in: No memory to allocate "
|
||||
"new connection");
|
||||
trans_delete(new_self);
|
||||
delete_connection(sc);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -549,20 +582,30 @@ sesman_main_loop(void)
|
|||
sig_sesman_reload_cfg();
|
||||
}
|
||||
|
||||
for (index = 0; index < g_con_list->count; index++)
|
||||
index = 0;
|
||||
while (index < g_con_list->count)
|
||||
{
|
||||
int remove_con = 0;
|
||||
scon = (struct sesman_con *)list_get_item(g_con_list, index);
|
||||
if (scon != NULL)
|
||||
if (trans_check_wait_objs(scon->t) != 0)
|
||||
{
|
||||
if (trans_check_wait_objs(scon->t) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "sesman_main_loop: "
|
||||
"trans_check_wait_objs failed, removing trans");
|
||||
delete_connection(scon);
|
||||
list_remove_item(g_con_list, index);
|
||||
index--;
|
||||
continue;
|
||||
}
|
||||
LOG(LOG_LEVEL_ERROR, "sesman_main_loop: "
|
||||
"trans_check_wait_objs failed, removing trans");
|
||||
remove_con = 1;
|
||||
}
|
||||
else if (scon->close_requested)
|
||||
{
|
||||
remove_con = 1;
|
||||
}
|
||||
|
||||
if (remove_con)
|
||||
{
|
||||
delete_connection(scon);
|
||||
list_remove_item(g_con_list, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -577,13 +620,9 @@ sesman_main_loop(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
for (index = 0; index < g_con_list->count; index++)
|
||||
{
|
||||
scon = (struct sesman_con *) list_get_item(g_con_list, index);
|
||||
delete_connection(scon);
|
||||
}
|
||||
|
||||
sesman_close_all(SCA_CLOSE_AUTH_INFO);
|
||||
list_delete(g_con_list);
|
||||
sesman_delete_listening_transport();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,17 +27,20 @@
|
|||
#ifndef SESMAN_H
|
||||
#define SESMAN_H
|
||||
|
||||
#include "arch.h"
|
||||
#include "parse.h"
|
||||
#include "os_calls.h"
|
||||
#include "log.h"
|
||||
#include "env.h"
|
||||
#include "auth.h"
|
||||
#include "config.h"
|
||||
#include "sig.h"
|
||||
#include "session.h"
|
||||
#include "access.h"
|
||||
#include "scp.h"
|
||||
/**
|
||||
* Type for managing sesman connections from xrdp (etc)
|
||||
*/
|
||||
struct sesman_con
|
||||
{
|
||||
struct trans *t;
|
||||
char peername[15 + 1]; /* Name of peer, if known, for logging */
|
||||
int close_requested; /* Set to close the connection normally */
|
||||
unsigned int auth_retry_count;
|
||||
struct auth_info *auth_info; /* non-NULL for an authenticated connection */
|
||||
int uid; /* User */
|
||||
char *username; /* Username from UID (at time of logon) */
|
||||
char *ip_addr; /* Connecting IP address */
|
||||
};
|
||||
|
||||
/* Globals */
|
||||
extern struct config_sesman *g_cfg;
|
||||
|
@ -46,6 +49,15 @@ extern tintptr g_term_event;
|
|||
extern tintptr g_sigchld_event;
|
||||
extern tintptr g_reload_event;
|
||||
|
||||
/**
|
||||
* Set the peername of a connection
|
||||
*
|
||||
* @param name Name to set
|
||||
* @result 0 for success
|
||||
*/
|
||||
int
|
||||
sesman_set_connection_peername(struct sesman_con *sc, const char *name);
|
||||
|
||||
/*
|
||||
* Close all file descriptors used by sesman.
|
||||
*
|
||||
|
@ -54,9 +66,14 @@ extern tintptr g_reload_event;
|
|||
*
|
||||
* This call will also release all trans and SCP_SESSION objects
|
||||
* held by sesman
|
||||
*
|
||||
* @param flags Set SCA_CLOSE_AUTH_INFO to close any open auth_info
|
||||
* objects. By default these are not cleared, and should
|
||||
* only be done so when exiting sesman.
|
||||
*/
|
||||
#define SCA_CLOSE_AUTH_INFO (1<<0)
|
||||
int
|
||||
sesman_close_all(void);
|
||||
sesman_close_all(unsigned int flags);
|
||||
|
||||
/*
|
||||
* Remove the listening transport
|
||||
|
|
161
sesman/session.c
161
sesman/session.c
|
@ -37,10 +37,19 @@
|
|||
#include <sys/prctl.h>
|
||||
#endif
|
||||
|
||||
#include "arch.h"
|
||||
#include "session.h"
|
||||
|
||||
#include "auth.h"
|
||||
#include "config.h"
|
||||
#include "env.h"
|
||||
#include "list.h"
|
||||
#include "log.h"
|
||||
#include "os_calls.h"
|
||||
#include "sesman.h"
|
||||
#include "string_calls.h"
|
||||
#include "xauth.h"
|
||||
#include "xrdp_sockets.h"
|
||||
#include "string_calls.h"
|
||||
|
||||
#ifndef PR_SET_NO_NEW_PRIVS
|
||||
#define PR_SET_NO_NEW_PRIVS 38
|
||||
|
@ -103,10 +112,10 @@ session_get_bydata(const struct session_parameters *sp)
|
|||
config_output_policy_string(policy, policy_str, sizeof(policy_str));
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"%s: search policy=%s type=%s U=%s B=%d D=(%dx%d) I=%s",
|
||||
"%s: search policy=%s type=%s U=%d B=%d D=(%dx%d) I=%s",
|
||||
__func__,
|
||||
policy_str, SCP_SESSION_TYPE_TO_STR(sp->type),
|
||||
sp->username, sp->bpp, sp->width, sp->height,
|
||||
sp->uid, sp->bpp, sp->width, sp->height,
|
||||
sp->ip_addr);
|
||||
|
||||
/* 'Separate' policy never matches */
|
||||
|
@ -121,11 +130,11 @@ session_get_bydata(const struct session_parameters *sp)
|
|||
struct session_item *item = tmp->item;
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"%s: try %p type=%s U=%s B=%d D=(%dx%d) I=%s",
|
||||
"%s: try %p type=%s U=%d B=%d D=(%dx%d) I=%s",
|
||||
__func__,
|
||||
item,
|
||||
SCP_SESSION_TYPE_TO_STR(item->type),
|
||||
item->name,
|
||||
item->uid,
|
||||
item->bpp,
|
||||
item->width, item->height,
|
||||
item->start_ip_addr);
|
||||
|
@ -136,11 +145,10 @@ session_get_bydata(const struct session_parameters *sp)
|
|||
continue;
|
||||
}
|
||||
|
||||
if ((policy & SESMAN_CFG_SESS_POLICY_U) &&
|
||||
g_strncmp(sp->username, item->name, sizeof(item->name) - 1) != 0)
|
||||
if ((policy & SESMAN_CFG_SESS_POLICY_U) && sp->uid != item->uid)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"%s: Username doesn't match for 'U' policy", __func__);
|
||||
"%s: UID doesn't match for 'U' policy", __func__);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -399,7 +407,7 @@ wait_for_xserver(int display)
|
|||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
session_start_chansrv(const char *username, int display)
|
||||
session_start_chansrv(int uid, int display)
|
||||
{
|
||||
struct list *chansrv_params;
|
||||
char exe_path[262];
|
||||
|
@ -421,7 +429,7 @@ session_start_chansrv(const char *username, int display)
|
|||
list_add_item(chansrv_params, (intptr_t) g_strdup(exe_path));
|
||||
list_add_item(chansrv_params, 0); /* mandatory */
|
||||
|
||||
env_set_user(username, 0, display,
|
||||
env_set_user(uid, 0, display,
|
||||
g_cfg->env_names,
|
||||
g_cfg->env_values);
|
||||
|
||||
|
@ -436,10 +444,38 @@ session_start_chansrv(const char *username, int display)
|
|||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* Convert a UID to a username
|
||||
*
|
||||
* @param uid UID
|
||||
* @param uname pointer to output buffer
|
||||
* @param uname_len Length of output buffer
|
||||
* @return 0 for success.
|
||||
*/
|
||||
static int
|
||||
username_from_uid(int uid, char *uname, int uname_len)
|
||||
{
|
||||
char *ustr;
|
||||
int rv = g_getuser_info_by_uid(uid, &ustr, NULL, NULL, NULL, NULL);
|
||||
|
||||
int
|
||||
if (rv == 0)
|
||||
{
|
||||
g_snprintf(uname, uname_len, "%s", ustr);
|
||||
g_free(ustr);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_snprintf(uname, uname_len, "<unknown>");
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
enum scp_screate_status
|
||||
session_start(struct auth_info *auth_info,
|
||||
const struct session_parameters *s,
|
||||
int *returned_display,
|
||||
struct guid *guid)
|
||||
{
|
||||
int display = 0;
|
||||
|
@ -448,6 +484,7 @@ session_start(struct auth_info *auth_info,
|
|||
char depth[32];
|
||||
char screen[32]; /* display number */
|
||||
char text[256];
|
||||
char username[256];
|
||||
char execvpparams[2048];
|
||||
char *xserver = NULL; /* absolute/relative path to Xorg/X11rdp/Xvnc */
|
||||
char *passwd_file;
|
||||
|
@ -467,12 +504,15 @@ session_start(struct auth_info *auth_info,
|
|||
|
||||
passwd_file = 0;
|
||||
|
||||
/* Get the username for display purposes */
|
||||
username_from_uid(s->uid, username, sizeof(username));
|
||||
|
||||
/* check to limit concurrent sessions */
|
||||
if (g_session_count >= g_cfg->sess.max_sessions)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "max concurrent session limit "
|
||||
"exceeded. login for user %s denied", s->username);
|
||||
return 0;
|
||||
"exceeded. login for user %s denied", username);
|
||||
return E_SCP_SCREATE_MAX_REACHED;
|
||||
}
|
||||
|
||||
temp = (struct session_chain *)g_malloc(sizeof(struct session_chain), 0);
|
||||
|
@ -480,8 +520,8 @@ session_start(struct auth_info *auth_info,
|
|||
if (temp == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Out of memory error: cannot create new session "
|
||||
"chain element - user %s", s->username);
|
||||
return 0;
|
||||
"chain element - user %s", username);
|
||||
return E_SCP_SCREATE_NO_MEMORY;
|
||||
}
|
||||
|
||||
temp->item = (struct session_item *)g_malloc(sizeof(struct session_item), 0);
|
||||
|
@ -490,8 +530,8 @@ session_start(struct auth_info *auth_info,
|
|||
{
|
||||
g_free(temp);
|
||||
LOG(LOG_LEVEL_ERROR, "Out of memory error: cannot create new session "
|
||||
"item - user %s", s->username);
|
||||
return 0;
|
||||
"item - user %s", username);
|
||||
return E_SCP_SCREATE_NO_MEMORY;
|
||||
}
|
||||
|
||||
display = session_get_avail_display_from_chain();
|
||||
|
@ -500,11 +540,12 @@ session_start(struct auth_info *auth_info,
|
|||
{
|
||||
g_free(temp->item);
|
||||
g_free(temp);
|
||||
return 0;
|
||||
return E_SCP_SCREATE_NO_DISPLAY;
|
||||
}
|
||||
|
||||
/* Create a GUID for the new session before we work */
|
||||
/* Create a GUID for the new session before we fork */
|
||||
*guid = guid_new();
|
||||
*returned_display = display;
|
||||
|
||||
pid = g_fork(); /* parent is fork from tcp accept,
|
||||
child forks X and wm, then becomes scp */
|
||||
|
@ -515,8 +556,12 @@ session_start(struct auth_info *auth_info,
|
|||
"[session start] (display %d): Failed to fork for scp with "
|
||||
"errno: %d, description: %s",
|
||||
display, g_get_errno(), g_get_strerror());
|
||||
g_free(temp->item);
|
||||
g_free(temp);
|
||||
return E_SCP_SCREATE_GENERAL_ERROR;
|
||||
}
|
||||
else if (pid == 0)
|
||||
|
||||
if (pid == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"[session start] (display %d): calling auth_start_session from pid %d",
|
||||
|
@ -538,16 +583,16 @@ session_start(struct auth_info *auth_info,
|
|||
|
||||
/* Set the secondary groups before starting the session to prevent
|
||||
* problems on PAM-based systems (see pam_setcred(3)) */
|
||||
if (g_initgroups(s->username) != 0)
|
||||
if (g_initgroups(username) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Failed to initialise secondary groups for %s: %s",
|
||||
s->username, g_get_strerror());
|
||||
username, g_get_strerror());
|
||||
g_exit(1);
|
||||
}
|
||||
|
||||
sesman_close_all(0);
|
||||
auth_start_session(auth_info, display);
|
||||
sesman_close_all();
|
||||
g_sprintf(geometry, "%dx%d", s->width, s->height);
|
||||
g_sprintf(depth, "%d", s->bpp);
|
||||
g_sprintf(screen, ":%d", display);
|
||||
|
@ -579,11 +624,11 @@ session_start(struct auth_info *auth_info,
|
|||
display, g_getpid());
|
||||
}
|
||||
|
||||
if (g_setlogin(s->username) < 0)
|
||||
if (g_setlogin(username) < 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"[session start] (display %d): setlogin failed for user %s - pid %d",
|
||||
display, s->username, g_getpid());
|
||||
display, username, g_getpid());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -608,7 +653,7 @@ session_start(struct auth_info *auth_info,
|
|||
else if (window_manager_pid == 0)
|
||||
{
|
||||
wait_for_xserver(display);
|
||||
env_set_user(s->username,
|
||||
env_set_user(s->uid,
|
||||
0,
|
||||
display,
|
||||
g_cfg->env_names,
|
||||
|
@ -706,7 +751,7 @@ session_start(struct auth_info *auth_info,
|
|||
{
|
||||
if (s->type == SCP_SESSION_TYPE_XVNC)
|
||||
{
|
||||
env_set_user(s->username,
|
||||
env_set_user(s->uid,
|
||||
&passwd_file,
|
||||
display,
|
||||
g_cfg->env_names,
|
||||
|
@ -714,7 +759,7 @@ session_start(struct auth_info *auth_info,
|
|||
}
|
||||
else
|
||||
{
|
||||
env_set_user(s->username,
|
||||
env_set_user(s->uid,
|
||||
0,
|
||||
display,
|
||||
g_cfg->env_names,
|
||||
|
@ -892,11 +937,11 @@ session_start(struct auth_info *auth_info,
|
|||
struct exit_status chansrv_exit_status;
|
||||
|
||||
wait_for_xserver(display);
|
||||
chansrv_pid = session_start_chansrv(s->username, display);
|
||||
chansrv_pid = session_start_chansrv(s->uid, display);
|
||||
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Session started successfully for user %s on display %d",
|
||||
s->username, display);
|
||||
username, display);
|
||||
|
||||
/* Monitor the amount of time we wait for the
|
||||
* window manager. This is approximately how long the window
|
||||
|
@ -930,10 +975,12 @@ session_start(struct auth_info *auth_info,
|
|||
window_manager_pid, display, wm_wait_time);
|
||||
}
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Calling auth_stop_session and auth_end from pid %d",
|
||||
"Calling auth_stop_session from pid %d",
|
||||
g_getpid());
|
||||
auth_stop_session(auth_info);
|
||||
auth_end(auth_info);
|
||||
// auth_end() is called from the main process currently,
|
||||
// as this called auth_start()
|
||||
//auth_end(auth_info);
|
||||
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Terminating X server (pid %d) on display %d",
|
||||
|
@ -969,8 +1016,8 @@ session_start(struct auth_info *auth_info,
|
|||
{
|
||||
LOG(LOG_LEVEL_INFO, "Starting session: session_pid %d, "
|
||||
"display :%d.0, width %d, height %d, bpp %d, client ip %s, "
|
||||
"user name %s",
|
||||
pid, display, s->width, s->height, s->bpp, s->ip_addr, s->username);
|
||||
"UID %d",
|
||||
pid, display, s->width, s->height, s->bpp, s->ip_addr, s->uid);
|
||||
temp->item->pid = pid;
|
||||
temp->item->display = display;
|
||||
temp->item->width = s->width;
|
||||
|
@ -979,7 +1026,7 @@ session_start(struct auth_info *auth_info,
|
|||
temp->item->auth_info = auth_info;
|
||||
g_strncpy(temp->item->start_ip_addr, s->ip_addr,
|
||||
sizeof(temp->item->start_ip_addr) - 1);
|
||||
g_strncpy(temp->item->name, s->username, 255);
|
||||
temp->item->uid = s->uid;
|
||||
temp->item->guid = *guid;
|
||||
|
||||
temp->item->start_time = g_time1();
|
||||
|
@ -991,17 +1038,18 @@ session_start(struct auth_info *auth_info,
|
|||
g_sessions = temp;
|
||||
g_session_count++;
|
||||
|
||||
return display;
|
||||
return E_SCP_SCREATE_OK;
|
||||
}
|
||||
|
||||
/* Shouldn't get here */
|
||||
g_free(temp->item);
|
||||
g_free(temp);
|
||||
return display;
|
||||
return E_SCP_SCREATE_GENERAL_ERROR;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
session_reconnect(int display, const char *username,
|
||||
session_reconnect(int display, int uid,
|
||||
struct auth_info *auth_info)
|
||||
{
|
||||
int pid;
|
||||
|
@ -1014,7 +1062,7 @@ session_reconnect(int display, const char *username,
|
|||
}
|
||||
else if (pid == 0)
|
||||
{
|
||||
env_set_user(username,
|
||||
env_set_user(uid,
|
||||
0,
|
||||
display,
|
||||
g_cfg->env_names,
|
||||
|
@ -1081,10 +1129,23 @@ session_kill(int pid)
|
|||
|
||||
if (tmp->item->pid == pid)
|
||||
{
|
||||
char username[256];
|
||||
username_from_uid(tmp->item->uid, username, sizeof(username));
|
||||
|
||||
/* deleting the session */
|
||||
if (tmp->item->auth_info != NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Calling auth_end for pid %d from pid %d",
|
||||
pid, g_getpid());
|
||||
auth_end(tmp->item->auth_info);
|
||||
tmp->item->auth_info = NULL;
|
||||
}
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"++ terminated session: username %s, display :%d.0, session_pid %d, ip %s",
|
||||
tmp->item->name, tmp->item->display, tmp->item->pid, tmp->item->start_ip_addr);
|
||||
"++ terminated session: UID %d (%s), display :%d.0, "
|
||||
"session_pid %d, ip %s",
|
||||
tmp->item->uid, username, tmp->item->display,
|
||||
tmp->item->pid, tmp->item->start_ip_addr);
|
||||
g_free(tmp->item);
|
||||
|
||||
if (prev == 0)
|
||||
|
@ -1177,7 +1238,7 @@ session_get_bypid(int pid)
|
|||
|
||||
/******************************************************************************/
|
||||
struct scp_session_info *
|
||||
session_get_byuser(const char *user, unsigned int *cnt, unsigned char flags)
|
||||
session_get_byuid(int uid, unsigned int *cnt, unsigned char flags)
|
||||
{
|
||||
struct session_chain *tmp;
|
||||
struct scp_session_info *sess;
|
||||
|
@ -1188,10 +1249,10 @@ session_get_byuser(const char *user, unsigned int *cnt, unsigned char flags)
|
|||
|
||||
tmp = g_sessions;
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG, "searching for session by user: %s", user);
|
||||
LOG(LOG_LEVEL_DEBUG, "searching for session by UID: %d", uid);
|
||||
while (tmp != 0)
|
||||
{
|
||||
if ((NULL == user) || (!g_strncasecmp(user, tmp->item->name, 256)))
|
||||
if (uid == tmp->item->uid)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "session_get_byuser: status=%d, flags=%d, "
|
||||
"result=%d", (tmp->item->status), flags,
|
||||
|
@ -1227,8 +1288,7 @@ session_get_byuser(const char *user, unsigned int *cnt, unsigned char flags)
|
|||
|
||||
while (tmp != 0 && index < count)
|
||||
{
|
||||
/* #warning FIXME: we should get only disconnected sessions! */
|
||||
if ((NULL == user) || (!g_strncasecmp(user, tmp->item->name, 256)))
|
||||
if (uid == tmp->item->uid)
|
||||
{
|
||||
if ((tmp->item->status) & flags)
|
||||
{
|
||||
|
@ -1239,11 +1299,11 @@ session_get_byuser(const char *user, unsigned int *cnt, unsigned char flags)
|
|||
(sess[index]).width = tmp->item->width;
|
||||
(sess[index]).bpp = tmp->item->bpp;
|
||||
(sess[index]).start_time = tmp->item->start_time;
|
||||
(sess[index]).username = g_strdup(tmp->item->name);
|
||||
(sess[index]).uid = tmp->item->uid;
|
||||
(sess[index]).start_ip_addr = g_strdup(tmp->item->start_ip_addr);
|
||||
|
||||
if ((sess[index]).username == NULL ||
|
||||
(sess[index]).start_ip_addr == NULL)
|
||||
/* Check for string allocation failures */
|
||||
if ((sess[index]).start_ip_addr == NULL)
|
||||
{
|
||||
free_session_info_list(sess, *cnt);
|
||||
(*cnt) = 0;
|
||||
|
@ -1270,7 +1330,6 @@ free_session_info_list(struct scp_session_info *sesslist, unsigned int cnt)
|
|||
unsigned int i;
|
||||
for (i = 0 ; i < cnt ; ++i)
|
||||
{
|
||||
g_free(sesslist[i].username);
|
||||
g_free(sesslist[i].start_ip_addr);
|
||||
}
|
||||
}
|
||||
|
@ -1383,7 +1442,6 @@ clone_session_params(const struct session_parameters *sp)
|
|||
/* Allocate a single block of memory big enough for the structure and
|
||||
* all the strings it points to */
|
||||
unsigned int len = sizeof(*result);
|
||||
len += g_strlen(sp->username) + 1;
|
||||
len += g_strlen(sp->shell) + 1;
|
||||
len += g_strlen(sp->directory) + 1;
|
||||
len += g_strlen(sp->ip_addr) + 1;
|
||||
|
@ -1403,7 +1461,6 @@ clone_session_params(const struct session_parameters *sp)
|
|||
strptr += len;\
|
||||
}
|
||||
|
||||
COPY_STRING_MEMBER(sp->username, result->username);
|
||||
COPY_STRING_MEMBER(sp->shell, result->shell);
|
||||
COPY_STRING_MEMBER(sp->directory, result->directory);
|
||||
COPY_STRING_MEMBER(sp->ip_addr, result->ip_addr);
|
||||
|
|
|
@ -53,7 +53,7 @@ struct scp_session_info;
|
|||
|
||||
struct session_item
|
||||
{
|
||||
char name[256];
|
||||
int uid; /* UID of session */
|
||||
int pid; /* pid of sesman waiting for wm to end */
|
||||
int display;
|
||||
int width;
|
||||
|
@ -85,11 +85,11 @@ struct session_chain
|
|||
*/
|
||||
struct session_parameters
|
||||
{
|
||||
int uid;
|
||||
enum scp_session_type type;
|
||||
unsigned short height;
|
||||
unsigned short width;
|
||||
unsigned char bpp;
|
||||
const char *username;
|
||||
const char *shell;
|
||||
const char *directory;
|
||||
const char *ip_addr;
|
||||
|
@ -110,16 +110,17 @@ session_get_bydata(const struct session_parameters *params);
|
|||
/**
|
||||
*
|
||||
* @brief starts a session
|
||||
* @return 0 on error, display number if success
|
||||
*
|
||||
* @return Connection status.
|
||||
*/
|
||||
int
|
||||
enum scp_screate_status
|
||||
session_start(struct auth_info *auth_info,
|
||||
const struct session_parameters *params,
|
||||
int *display,
|
||||
struct guid *guid);
|
||||
|
||||
int
|
||||
session_reconnect(int display, const char *username,
|
||||
session_reconnect(int display, int uid,
|
||||
struct auth_info *auth_info);
|
||||
|
||||
/**
|
||||
|
@ -154,14 +155,14 @@ session_get_bypid(int pid);
|
|||
/**
|
||||
*
|
||||
* @brief retrieves session descriptions
|
||||
* @param user the user for the sessions
|
||||
* @param UID the UID for the descriptions
|
||||
* @return A block of session descriptions
|
||||
*
|
||||
* Pass the return result to free_session_info_list() after use
|
||||
*
|
||||
*/
|
||||
struct scp_session_info *
|
||||
session_get_byuser(const char *user, unsigned int *cnt, unsigned char flags);
|
||||
session_get_byuid(int uid, unsigned int *cnt, unsigned char flags);
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -28,8 +28,15 @@
|
|||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include "string_calls.h"
|
||||
#include "arch.h"
|
||||
#include "sig.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "os_calls.h"
|
||||
#include "sesman.h"
|
||||
#include "session.h"
|
||||
#include "string_calls.h"
|
||||
|
||||
/******************************************************************************/
|
||||
void
|
||||
|
|
|
@ -61,4 +61,5 @@ xrdp_xcon_LDADD = \
|
|||
|
||||
xrdp_authtest_LDADD = \
|
||||
$(top_builddir)/common/libcommon.la \
|
||||
$(top_builddir)/libipm/libipm.la \
|
||||
$(AUTHMOD_LIB)
|
||||
|
|
|
@ -68,14 +68,17 @@ usage(void)
|
|||
"etc.\n\n"
|
||||
"This is a DEVELOPER-ONLY tool\n");
|
||||
g_printf("\nusage:\n");
|
||||
g_printf("authtest [options] username\n\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");
|
||||
g_printf("\nIf username is omitted, the current user is used, and.\n"
|
||||
"a UDS login is attempted\n"
|
||||
"If username is provided, password is needed.\n"
|
||||
" Password is prompted for if -p or -F are not specified\n");
|
||||
}
|
||||
|
||||
|
||||
|
@ -186,10 +189,15 @@ parse_program_args(int argc, char *argv[], struct authmod_params *amp)
|
|||
}
|
||||
}
|
||||
|
||||
if (argc <= optind)
|
||||
if (argc == optind)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "No user name specified");
|
||||
params_ok = 0;
|
||||
// No username was specified
|
||||
if (password_set)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "No username - ignoring specified password");
|
||||
amp->password[0] = '\0';
|
||||
}
|
||||
amp->username = NULL;
|
||||
}
|
||||
else if ((argc - optind) > 1)
|
||||
{
|
||||
|
@ -199,26 +207,58 @@ parse_program_args(int argc, char *argv[], struct authmod_params *amp)
|
|||
else
|
||||
{
|
||||
amp->username = argv[optind];
|
||||
}
|
||||
|
||||
if (params_ok && !password_set)
|
||||
{
|
||||
const char *p = getpass("Password: ");
|
||||
if (p != NULL)
|
||||
if (!password_set)
|
||||
{
|
||||
g_strcpy(amp->password, p);
|
||||
const char *p = getpass("Password: ");
|
||||
if (p == NULL)
|
||||
{
|
||||
params_ok = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_snprintf(amp->password, sizeof(amp->password), "%s", p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return params_ok;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* Gets the current username for a UDS login
|
||||
*
|
||||
* Result must be freed after use.
|
||||
*/
|
||||
static char *
|
||||
get_username()
|
||||
{
|
||||
int uid = g_getuid();
|
||||
char *this_user;
|
||||
int status;
|
||||
|
||||
status = g_getuser_info_by_uid(uid, &this_user, NULL, NULL, NULL, NULL);
|
||||
if (status != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Can't map UID %d to a username", uid);
|
||||
this_user = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "Mapped current UID %d to \"%s\"",
|
||||
uid, this_user);
|
||||
}
|
||||
|
||||
return this_user;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct log_config *logging;
|
||||
int rv = 1;
|
||||
int rv = 0;
|
||||
char *this_user = NULL;
|
||||
struct authmod_params amp;
|
||||
|
||||
logging = log_config_init_for_console(LOG_LEVEL_DEBUG,
|
||||
|
@ -229,16 +269,34 @@ main(int argc, char **argv)
|
|||
if (!parse_program_args(argc, argv, &))
|
||||
{
|
||||
usage();
|
||||
rv = 1;
|
||||
}
|
||||
else if (amp.username == NULL && (this_user = get_username()) == NULL)
|
||||
{
|
||||
rv = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct auth_info *auth_info;
|
||||
auth_info = auth_userpass(amp.username, amp.password,
|
||||
NULL, &rv);
|
||||
enum scp_login_status errorcode;
|
||||
char errstr[64];
|
||||
|
||||
LOG(LOG_LEVEL_INFO, "auth_userpass() returned %s, errorcode=%d",
|
||||
if (amp.username == NULL)
|
||||
{
|
||||
auth_info = auth_uds(this_user, &errorcode);
|
||||
}
|
||||
else
|
||||
{
|
||||
auth_info = auth_userpass(amp.username, amp.password,
|
||||
NULL, &errorcode);
|
||||
}
|
||||
scp_login_status_to_str(errorcode, errstr, sizeof(errstr));
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"auth_userpass() returned %s, errorcode=%d [%s]",
|
||||
(auth_info == NULL) ? "NULL" : "non-NULL",
|
||||
rv);
|
||||
(int)errorcode, errstr);
|
||||
|
||||
rv = (int)errorcode;
|
||||
if (auth_info && rv == 0 && amp.command != NULL)
|
||||
{
|
||||
int display = 10;
|
||||
|
@ -261,6 +319,7 @@ main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
g_free(this_user);
|
||||
log_end();
|
||||
|
||||
return rv;
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
char user[257];
|
||||
char pass[257];
|
||||
char cmnd[257];
|
||||
char port[257];
|
||||
|
||||
|
@ -47,12 +45,9 @@ int main(int argc, char **argv)
|
|||
//int end;
|
||||
int idx;
|
||||
//int sel;
|
||||
char *pwd;
|
||||
struct log_config *logging;
|
||||
int rv = 1;
|
||||
|
||||
user[0] = '\0';
|
||||
pass[0] = '\0';
|
||||
cmnd[0] = '\0';
|
||||
port[0] = '\0';
|
||||
|
||||
|
@ -64,11 +59,11 @@ int main(int argc, char **argv)
|
|||
{
|
||||
if (0 == g_strncmp(argv[idx], "-u=", 3))
|
||||
{
|
||||
g_strncpy(user, (argv[idx]) + 3, 256);
|
||||
g_printf("** Ignoring unused argument '-u'");
|
||||
}
|
||||
else if (0 == g_strncmp(argv[idx], "-p=", 3))
|
||||
{
|
||||
g_strncpy(pass, (argv[idx]) + 3, 256);
|
||||
g_printf("** Ignoring unused argument '-p'");
|
||||
}
|
||||
else if (0 == g_strncmp(argv[idx], "-i=", 3))
|
||||
{
|
||||
|
@ -80,48 +75,57 @@ int main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
if (0 == g_strncmp(port, "", 1))
|
||||
{
|
||||
g_strncpy(port, "3350", 256);
|
||||
}
|
||||
|
||||
if (0 == g_strncmp(user, "", 1))
|
||||
{
|
||||
cmndHelp();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (0 == g_strncmp(cmnd, "", 1))
|
||||
{
|
||||
cmndHelp();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (0 == g_strncmp(pass, "", 1))
|
||||
{
|
||||
pwd = getpass("password:");
|
||||
g_strncpy(pass, pwd, 256);
|
||||
|
||||
}
|
||||
|
||||
t = scp_connect(port, NULL);
|
||||
|
||||
t = scp_connect(port, "xrdp-sesadmin", NULL);
|
||||
|
||||
if (t == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "scp_connect() error");
|
||||
}
|
||||
else if (0 == g_strncmp(cmnd, "list", 5))
|
||||
else
|
||||
{
|
||||
rv = cmndList(t);
|
||||
}
|
||||
else if (0 == g_strncmp(cmnd, "kill:", 5))
|
||||
{
|
||||
rv = cmndKill(t);
|
||||
enum scp_login_status login_result;
|
||||
|
||||
/* Log in as the current user */
|
||||
if ((rv = scp_send_uds_login_request(t)) == 0 &&
|
||||
(rv = wait_for_sesman_reply(t, E_SCP_LOGIN_RESPONSE)) == 0)
|
||||
{
|
||||
rv = scp_get_login_response(t, &login_result, NULL);
|
||||
if (rv == 0)
|
||||
{
|
||||
if (login_result != E_SCP_LOGIN_OK)
|
||||
{
|
||||
char msg[256];
|
||||
scp_login_status_to_str(login_result, msg, sizeof(msg));
|
||||
g_printf("Login failed; %s\n", msg);
|
||||
rv = 1;
|
||||
}
|
||||
}
|
||||
scp_msg_in_reset(t); // Done with this message
|
||||
}
|
||||
}
|
||||
|
||||
g_memset(pass, '\0', sizeof(pass));
|
||||
if (rv == 0)
|
||||
{
|
||||
if (0 == g_strncmp(cmnd, "list", 5))
|
||||
{
|
||||
rv = cmndList(t);
|
||||
}
|
||||
else if (0 == g_strncmp(cmnd, "kill:", 5))
|
||||
{
|
||||
rv = cmndKill(t);
|
||||
}
|
||||
}
|
||||
|
||||
if (rv == 0)
|
||||
{
|
||||
rv = scp_send_close_connection_request(t);
|
||||
}
|
||||
trans_delete(t);
|
||||
log_end();
|
||||
|
||||
|
@ -133,10 +137,7 @@ cmndHelp(void)
|
|||
{
|
||||
fprintf(stderr, "sesadmin - a console sesman administration tool\n");
|
||||
fprintf(stderr, "syntax: sesadmin [] COMMAND [OPTIONS]\n\n");
|
||||
fprintf(stderr, "-u=<username>: username to connect to sesman [MANDATORY]\n");
|
||||
fprintf(stderr, "-p=<password>: password to connect to sesman (asked if not given)\n");
|
||||
fprintf(stderr, "-s=<hostname>: sesman host (default is localhost)\n");
|
||||
fprintf(stderr, "-i=<port> : sesman port (default 3350)\n");
|
||||
fprintf(stderr, "-i=<port> : sesman port (can be defaulted)\n");
|
||||
fprintf(stderr, "-c=<command> : command to execute on the server [MANDATORY]\n");
|
||||
fprintf(stderr, " it can be one of those:\n");
|
||||
fprintf(stderr, " list\n");
|
||||
|
@ -146,9 +147,14 @@ cmndHelp(void)
|
|||
static void
|
||||
print_session(const struct scp_session_info *s)
|
||||
{
|
||||
char *username;
|
||||
const char *uptr;
|
||||
g_getuser_info_by_uid(s->uid, &username, NULL, NULL, NULL, NULL);
|
||||
uptr = (username == NULL) ? "<unknown>" : username;
|
||||
|
||||
printf("Session ID: %d\n", s->sid);
|
||||
printf("\tDisplay: :%u\n", s->display);
|
||||
printf("\tUser: %s\n", s->username);
|
||||
printf("\tUser: %s\n", uptr);
|
||||
printf("\tSession type: %s\n", SCP_SESSION_TYPE_TO_STR(s->type));
|
||||
printf("\tScreen size: %dx%d, color depth %d\n",
|
||||
s->width, s->height, s->bpp);
|
||||
|
@ -157,6 +163,7 @@ print_session(const struct scp_session_info *s)
|
|||
{
|
||||
printf("\tStart IP address: %s\n", s->start_ip_addr);
|
||||
}
|
||||
g_free(username);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -168,7 +175,7 @@ cmndList(struct trans *t)
|
|||
enum scp_list_sessions_status status;
|
||||
struct scp_session_info *p;
|
||||
|
||||
int rv = scp_send_list_sessions_request(t, user, pass);
|
||||
int rv = scp_send_list_sessions_request(t);
|
||||
|
||||
sessions->auto_free = 1;
|
||||
|
||||
|
@ -188,11 +195,6 @@ cmndList(struct trans *t)
|
|||
|
||||
switch (status)
|
||||
{
|
||||
case E_SCP_LS_AUTHENTICATION_FAIL:
|
||||
printf("Connection denied (authentication error)\n");
|
||||
rv = 1;
|
||||
break;
|
||||
|
||||
case E_SCP_LS_SESSION_INFO:
|
||||
list_add_item(sessions, (tintptr)p);
|
||||
break;
|
||||
|
|
|
@ -94,7 +94,7 @@ struct session_params
|
|||
|
||||
const char *directory;
|
||||
const char *shell;
|
||||
const char *connection_description;
|
||||
const char *ip_addr;
|
||||
|
||||
const char *username;
|
||||
char password[MAX_PASSWORD_LEN + 1];
|
||||
|
@ -165,7 +165,9 @@ usage(void)
|
|||
|
||||
g_printf("xrdp session starter v" PACKAGE_VERSION "\n");
|
||||
g_printf("\nusage:\n");
|
||||
g_printf("sesrun [options] username\n\n");
|
||||
g_printf("sesrun --help\n"
|
||||
"\nor\n"
|
||||
"sesrun [options] [username]\n\n");
|
||||
g_printf("options:\n");
|
||||
g_printf(" -g <geometry> Default:%dx%d\n",
|
||||
DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||||
|
@ -176,9 +178,11 @@ usage(void)
|
|||
" -p <password> TESTING ONLY - DO NOT USE IN PRODUCTION\n"
|
||||
" -F <file-descriptor> Read password from this file descriptor\n"
|
||||
" -c <sesman_ini> Alternative sesman.ini file\n");
|
||||
g_printf("Supported types are %s\n",
|
||||
g_printf("\nSupported types are %s\n",
|
||||
sesstype_list);
|
||||
g_printf("Password is prompted if -p or -F are not specified\n");
|
||||
g_printf("\nIf username is omitted, the current user is used.\n"
|
||||
"If username is provided, password is needed.\n"
|
||||
" Password is prompted for if -p or -F are not specified\n");
|
||||
}
|
||||
|
||||
|
||||
|
@ -286,7 +290,7 @@ parse_program_args(int argc, char *argv[], struct session_params *sp,
|
|||
|
||||
sp->directory = "";
|
||||
sp->shell = "";
|
||||
sp->connection_description = "";
|
||||
sp->ip_addr = "";
|
||||
|
||||
sp->username = NULL;
|
||||
sp->password[0] = '\0';
|
||||
|
@ -367,33 +371,109 @@ parse_program_args(int argc, char *argv[], struct session_params *sp,
|
|||
}
|
||||
}
|
||||
|
||||
if (argc <= optind)
|
||||
if (argc == optind)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "No user name specified");
|
||||
params_ok = 0;
|
||||
// No username was specified
|
||||
if (password_set)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "No username - ignoring specified password");
|
||||
sp->password[0] = '\0';
|
||||
}
|
||||
sp->username = NULL;
|
||||
}
|
||||
else if ((argc - optind) > 1)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Unexpected arguments after username");
|
||||
params_ok = 0;
|
||||
}
|
||||
else
|
||||
else if (params_ok)
|
||||
{
|
||||
// A username is specified
|
||||
sp->username = argv[optind];
|
||||
}
|
||||
|
||||
if (params_ok && !password_set)
|
||||
{
|
||||
const char *p = getpass("Password: ");
|
||||
if (p != NULL)
|
||||
if (!password_set)
|
||||
{
|
||||
g_strcpy(sp->password, p);
|
||||
const char *p = getpass("Password: ");
|
||||
if (p == NULL)
|
||||
{
|
||||
params_ok = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_snprintf(sp->password, sizeof(sp->password), "%s", p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return params_ok;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Sends an SCP login request
|
||||
*
|
||||
* A sys login request (i.e. username / password) is used if a username
|
||||
* is specified. Otherwise we use a uds login request for the current user.
|
||||
*
|
||||
* @param t SCP connection
|
||||
* @param sp Data for request
|
||||
*/
|
||||
static int
|
||||
send_login_request(struct trans *t, const struct session_params *sp)
|
||||
{
|
||||
int rv;
|
||||
LOG(LOG_LEVEL_DEBUG, "ip_addr:\"%s\"", sp->ip_addr);
|
||||
if (sp->username != NULL)
|
||||
{
|
||||
/* Only log the password in development builds */
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "password:\"%s\"", sp->password);
|
||||
|
||||
rv = scp_send_sys_login_request(t, sp->username,
|
||||
sp->password, sp->ip_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = scp_send_uds_login_request(t);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Receives an SCP login response
|
||||
*
|
||||
* @param t SCP transport to receive reply on
|
||||
* @param[out] server_closed != 0 if server has gone away
|
||||
* @return 0 for successful authentication
|
||||
*/
|
||||
static int
|
||||
handle_login_response(struct trans *t, int *server_closed)
|
||||
{
|
||||
enum scp_login_status login_result;
|
||||
|
||||
int rv = wait_for_sesman_reply(t, E_SCP_LOGIN_RESPONSE);
|
||||
if (rv != 0)
|
||||
{
|
||||
*server_closed = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = scp_get_login_response(t, &login_result, server_closed);
|
||||
if (rv == 0)
|
||||
{
|
||||
if (login_result != E_SCP_LOGIN_OK)
|
||||
{
|
||||
char msg[256];
|
||||
scp_login_status_to_str(login_result, msg, sizeof(msg));
|
||||
g_printf("Login failed; %s\n", msg);
|
||||
rv = 1;
|
||||
}
|
||||
}
|
||||
scp_msg_in_reset(t); // Done with this message
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************//**
|
||||
* Sends an SCP create session request
|
||||
*
|
||||
|
@ -405,18 +485,13 @@ send_create_session_request(struct trans *t, const struct session_params *sp)
|
|||
{
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"width:%d height:%d bpp:%d code:%d\n"
|
||||
"directory:\"%s\"\n"
|
||||
"shell:\"%s\" connection_description:\"%s\"",
|
||||
"directory:\"%s\" shell:\"%s\"",
|
||||
sp->width, sp->height, sp->bpp, sp->session_type,
|
||||
sp->directory,
|
||||
sp->shell, sp->connection_description);
|
||||
/* Only log the password in development builds */
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "password:\"%s\"", sp->password);
|
||||
sp->directory, sp->shell);
|
||||
|
||||
return scp_send_create_session_request(
|
||||
t, sp->username, sp->password, sp->session_type,
|
||||
sp->width, sp->height, sp->bpp, sp->shell, sp->directory,
|
||||
sp->connection_description);
|
||||
t, sp->session_type,
|
||||
sp->width, sp->height, sp->bpp, sp->shell, sp->directory);
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
|
@ -428,21 +503,24 @@ send_create_session_request(struct trans *t, const struct session_params *sp)
|
|||
static int
|
||||
handle_create_session_response(struct trans *t)
|
||||
{
|
||||
int auth_result;
|
||||
enum scp_screate_status status;
|
||||
int display;
|
||||
struct guid guid;
|
||||
|
||||
int rv = wait_for_sesman_reply(t, E_SCP_CREATE_SESSION_RESPONSE);
|
||||
if (rv == 0)
|
||||
{
|
||||
rv = scp_get_create_session_response(t, &auth_result,
|
||||
rv = scp_get_create_session_response(t, &status,
|
||||
&display, &guid);
|
||||
|
||||
if (rv == 0)
|
||||
{
|
||||
if (auth_result != 0)
|
||||
if (status != E_SCP_SCREATE_OK)
|
||||
{
|
||||
g_printf("Connection denied (authentication error)\n");
|
||||
char msg[256];
|
||||
scp_screate_status_to_str(status, msg, sizeof(msg));
|
||||
g_printf("Connection failed; %s\n", msg);
|
||||
rv = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -452,6 +530,7 @@ handle_create_session_response(struct trans *t)
|
|||
guid_to_str(&guid, guid_str));
|
||||
}
|
||||
}
|
||||
scp_msg_in_reset(t); // Done with this message
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -475,7 +554,12 @@ main(int argc, char **argv)
|
|||
log_start_from_param(logging);
|
||||
log_config_free(logging);
|
||||
|
||||
if (!parse_program_args(argc, argv, &sp, &sesman_ini))
|
||||
if (argc == 2 && g_strcmp(argv[1], "--help") == 0)
|
||||
{
|
||||
usage();
|
||||
rv = 0;
|
||||
}
|
||||
else if (!parse_program_args(argc, argv, &sp, &sesman_ini))
|
||||
{
|
||||
usage();
|
||||
}
|
||||
|
@ -484,20 +568,44 @@ main(int argc, char **argv)
|
|||
LOG(LOG_LEVEL_ERROR, "error reading config file %s : %s",
|
||||
sesman_ini, g_get_strerror());
|
||||
}
|
||||
else if (!(t = scp_connect(cfg->listen_port, NULL)))
|
||||
else if (!(t = scp_connect(cfg->listen_port, "xrdp-sesrun", NULL)))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "connect error - %s", g_get_strerror());
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = send_create_session_request(t, &sp);
|
||||
if (rv != 0)
|
||||
int server_closed = 0;
|
||||
while (!server_closed)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Error sending create session to sesman");
|
||||
rv = send_login_request(t, &sp);
|
||||
if (rv != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Error sending login request to sesman");
|
||||
break;
|
||||
}
|
||||
|
||||
rv = handle_login_response(t, &server_closed);
|
||||
if (rv == 0)
|
||||
{
|
||||
break; /* Successful authentication */
|
||||
}
|
||||
if (!server_closed)
|
||||
{
|
||||
const char *p = getpass("Password: ");
|
||||
if (p == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
g_snprintf(sp.password, sizeof(sp.password), "%s", p);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (rv == 0)
|
||||
{
|
||||
rv = handle_create_session_response(t);
|
||||
if ((rv = send_create_session_request(t, &sp)) == 0)
|
||||
{
|
||||
rv = handle_create_session_response(t);
|
||||
}
|
||||
}
|
||||
trans_delete(t);
|
||||
}
|
||||
|
|
|
@ -63,53 +63,115 @@ struct auth_info
|
|||
/* returns non-NULL for success */
|
||||
struct auth_info *
|
||||
auth_userpass(const char *user, const char *pass,
|
||||
const char *client_ip, int *errorcode)
|
||||
const char *client_ip, enum scp_login_status *errorcode)
|
||||
{
|
||||
const char *encr;
|
||||
const char *epass;
|
||||
const char *encr = NULL;
|
||||
struct passwd *spw;
|
||||
struct spwd *stp;
|
||||
|
||||
/* Need a non-NULL pointer to return to indicate success */
|
||||
static struct auth_info success = {0};
|
||||
|
||||
spw = getpwnam(user);
|
||||
/* Most likely codepath return from here is 'not authenticated' */
|
||||
enum scp_login_status status = E_SCP_LOGIN_NOT_AUTHENTICATED;
|
||||
|
||||
if (spw == 0)
|
||||
/* Find the encrypted password */
|
||||
if ((spw = getpwnam(user)) != NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (g_strncmp(spw->pw_passwd, "x", 3) == 0)
|
||||
{
|
||||
/* the system is using shadow */
|
||||
stp = getspnam(user);
|
||||
|
||||
if (stp == 0)
|
||||
if (g_strncmp(spw->pw_passwd, "x", 3) == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
struct spwd *stp;
|
||||
|
||||
if (1 == auth_account_disabled(stp))
|
||||
/* the system is using shadow */
|
||||
if ((stp = getspnam(user)) == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Can't get shadow entry for account %s",
|
||||
user);
|
||||
status = E_SCP_LOGIN_GENERAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (1 == auth_account_disabled(stp))
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "account %s is disabled", user);
|
||||
status = E_SCP_LOGIN_NOT_AUTHORIZED;
|
||||
}
|
||||
else
|
||||
{
|
||||
encr = stp->sp_pwdp;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "account %s is disabled", user);
|
||||
return NULL;
|
||||
/* old system with only passwd */
|
||||
encr = spw->pw_passwd;
|
||||
}
|
||||
}
|
||||
|
||||
encr = stp->sp_pwdp;
|
||||
}
|
||||
else
|
||||
if (encr != NULL)
|
||||
{
|
||||
/* old system with only passwd */
|
||||
encr = spw->pw_passwd;
|
||||
const char *epass;
|
||||
if ((epass = crypt(pass, encr)) != NULL &&
|
||||
g_strcmp(encr, epass) == 0)
|
||||
{
|
||||
status = E_SCP_LOGIN_OK;
|
||||
}
|
||||
}
|
||||
epass = crypt(pass, encr);
|
||||
if (epass == 0)
|
||||
|
||||
if (errorcode != NULL)
|
||||
{
|
||||
return NULL;
|
||||
*errorcode = status;
|
||||
}
|
||||
return (strcmp(encr, epass) == 0) ? &success : NULL;
|
||||
|
||||
return (status == E_SCP_LOGIN_OK) ? &success : NULL;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
struct auth_info *
|
||||
auth_uds(const char *user, enum scp_login_status *errorcode)
|
||||
{
|
||||
struct passwd *spw;
|
||||
|
||||
/* Need a non-NULL pointer to return to indicate success */
|
||||
static struct auth_info success = {0};
|
||||
|
||||
enum scp_login_status status = E_SCP_LOGIN_OK;
|
||||
|
||||
/* Try to check for a disabled account */
|
||||
if ((spw = getpwnam(user)) != NULL)
|
||||
{
|
||||
if (g_strncmp(spw->pw_passwd, "x", 3) == 0)
|
||||
{
|
||||
struct spwd *stp;
|
||||
|
||||
/* the system is using shadow */
|
||||
if ((stp = getspnam(user)) == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Can't get shadow entry for account %s",
|
||||
user);
|
||||
status = E_SCP_LOGIN_GENERAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (1 == auth_account_disabled(stp))
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "account %s is disabled", user);
|
||||
status = E_SCP_LOGIN_NOT_AUTHORIZED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (errorcode != NULL)
|
||||
{
|
||||
*errorcode = status;
|
||||
}
|
||||
|
||||
return (status == E_SCP_LOGIN_OK) ? &success : NULL;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* returns error */
|
||||
int
|
||||
|
|
|
@ -37,13 +37,26 @@
|
|||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include <sys/param.h>
|
||||
#if defined(OpenBSD)
|
||||
#include <login_cap.h>
|
||||
#include <bsd_auth.h>
|
||||
|
||||
#ifndef SECS_PER_DAY
|
||||
#define SECS_PER_DAY (24L*3600L)
|
||||
#else
|
||||
/*
|
||||
* If OpenBSD isn't defined, add static definitions of OpenBSD-specific
|
||||
* functions. This won't work, but will let the compiler on other
|
||||
* systems check that all is correctly defined */
|
||||
static int
|
||||
auth_userokay(char *name, char *style, char *type, char *password)
|
||||
{
|
||||
fprintf(stderr, "auth_userokay() not implmented on this platform!\n");
|
||||
abort();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Need a complete type for struct auth_info, even though we're
|
||||
* not really using it if this module (BSD authentication) is selected */
|
||||
|
@ -55,18 +68,53 @@ struct auth_info
|
|||
/******************************************************************************/
|
||||
/* returns non-NULL for success */
|
||||
struct auth_info *
|
||||
auth_userpass(const char *user, const char *pass,
|
||||
const char *client_ip, int *errorcode)
|
||||
auth_userpass(const char *const_user, const char *const_pass,
|
||||
const char *client_ip, enum scp_login_status *errorcode)
|
||||
{
|
||||
/* Need a non-NULL pointer to return to indicate success */
|
||||
static struct auth_info success = {0};
|
||||
struct auth_info *ret = NULL;
|
||||
enum scp_login_status status;
|
||||
|
||||
if (auth_userokay(user, NULL, "auth-xrdp", pass))
|
||||
// auth_userokay is not const-correct. See usr.sbin/smtpd/smtpd.c in
|
||||
// the OpenBSD source tree for this workaround
|
||||
char user[LOGIN_NAME_MAX];
|
||||
char pass[LINE_MAX];
|
||||
char type[] = "auth-xrdp";
|
||||
|
||||
snprintf(user, sizeof(user), "%s", const_user);
|
||||
snprintf(pass, sizeof(pass), "%s", const_pass);
|
||||
|
||||
if (auth_userokay(user, NULL, type, pass))
|
||||
{
|
||||
ret = &success;
|
||||
status = E_SCP_LOGIN_OK;
|
||||
}
|
||||
return ret;
|
||||
else
|
||||
{
|
||||
status = E_SCP_LOGIN_NOT_AUTHENTICATED;
|
||||
}
|
||||
|
||||
if (errorcode != NULL)
|
||||
{
|
||||
*errorcode = status;
|
||||
}
|
||||
|
||||
return (status == E_SCP_LOGIN_OK) ? &success : NULL;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* returns non-NULL for success */
|
||||
struct auth_info *
|
||||
auth_uds(const char *user, enum scp_login_status *errorcode)
|
||||
{
|
||||
/* Need a non-NULL pointer to return to indicate success */
|
||||
static struct auth_info success = {0};
|
||||
|
||||
if (errorcode != NULL)
|
||||
{
|
||||
*errorcode = E_SCP_LOGIN_OK;
|
||||
}
|
||||
|
||||
return &success;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
@ -127,12 +127,12 @@ k5_begin(const char *username)
|
|||
|
||||
/******************************************************************************/
|
||||
/* returns boolean */
|
||||
static int
|
||||
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;
|
||||
int rv = 0;
|
||||
|
||||
code = krb5_get_init_creds_password(auth_info->ctx,
|
||||
&my_creds, auth_info->me,
|
||||
|
@ -144,6 +144,7 @@ k5_kinit(struct auth_info *auth_info, const char *password)
|
|||
{
|
||||
log_kerberos_failure(auth_info->ctx, code,
|
||||
"krb5_get_init_creds_password");
|
||||
status = E_SCP_LOGIN_NOT_AUTHENTICATED;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -162,7 +163,7 @@ k5_kinit(struct auth_info *auth_info, const char *password)
|
|||
}
|
||||
else
|
||||
{
|
||||
rv = 1;
|
||||
status = E_SCP_LOGIN_OK;
|
||||
}
|
||||
|
||||
/* Prevent double-free of the client principal */
|
||||
|
@ -174,20 +175,22 @@ k5_kinit(struct auth_info *auth_info, const char *password)
|
|||
krb5_free_cred_contents(auth_info->ctx, &my_creds);
|
||||
}
|
||||
|
||||
return rv;
|
||||
return status;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* returns non-NULL for success */
|
||||
struct auth_info *
|
||||
auth_userpass(const char *user, const char *pass,
|
||||
const char *client_ip, int *errorcode)
|
||||
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)
|
||||
{
|
||||
if (!k5_kinit(auth_info, pass))
|
||||
status = k5_kinit(auth_info, pass);
|
||||
if (status != E_SCP_LOGIN_OK)
|
||||
{
|
||||
auth_end(auth_info);
|
||||
auth_info = NULL;
|
||||
|
@ -196,7 +199,23 @@ auth_userpass(const char *user, const char *pass,
|
|||
|
||||
if (errorcode != NULL)
|
||||
{
|
||||
*errorcode = (auth_info == 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;
|
||||
|
|
|
@ -37,10 +37,9 @@
|
|||
#include <stdio.h>
|
||||
#include <security/pam_appl.h>
|
||||
|
||||
/* Allows the conversation function to find the username and password */
|
||||
struct t_user_pass
|
||||
/* Allows the conversation function to find required items */
|
||||
struct conv_func_data
|
||||
{
|
||||
const char *user;
|
||||
const char *pass;
|
||||
};
|
||||
|
||||
|
@ -100,7 +99,7 @@ msg_style_to_str(int msg_style, char *buff, unsigned int bufflen)
|
|||
* @param[in] num_msg Count of messages in the msg array
|
||||
* @param[in] msg Messages from the PAM stack to the application
|
||||
* @param[out] resp Message replies from the application to the PAM stack
|
||||
* @param[in] appdata_ptr Used to pass in a struct t_user_pass pointer
|
||||
* @param[in] appdata_ptr Used to pass in a struct conv_func_data pointer
|
||||
*
|
||||
* @result PAM_SUCCESS if the messages were all processed successfully.
|
||||
*
|
||||
|
@ -120,7 +119,7 @@ verify_pam_conv(int num_msg, const struct pam_message **msg,
|
|||
{
|
||||
int i;
|
||||
struct pam_response *reply = NULL;
|
||||
struct t_user_pass *user_pass;
|
||||
struct conv_func_data *conv_func_data;
|
||||
char sb[64];
|
||||
int rv = PAM_SUCCESS;
|
||||
|
||||
|
@ -144,10 +143,10 @@ verify_pam_conv(int num_msg, const struct pam_message **msg,
|
|||
switch (msg[i]->msg_style)
|
||||
{
|
||||
case PAM_PROMPT_ECHO_OFF: /* password */
|
||||
user_pass = (struct t_user_pass *) appdata_ptr;
|
||||
conv_func_data = (struct conv_func_data *) appdata_ptr;
|
||||
/* Check this function isn't being called
|
||||
* later than we expected */
|
||||
if (user_pass == NULL)
|
||||
if (conv_func_data == NULL || conv_func_data->pass == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"verify_pam_conv: Password unavailable");
|
||||
|
@ -155,7 +154,7 @@ verify_pam_conv(int num_msg, const struct pam_message **msg,
|
|||
}
|
||||
else
|
||||
{
|
||||
reply[i].resp = g_strdup(user_pass->pass);
|
||||
reply[i].resp = g_strdup(conv_func_data->pass);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -216,73 +215,79 @@ get_service_name(char *service_name)
|
|||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* 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, int *errorcode)
|
||||
/** Performs PAM operations common to login methods
|
||||
*
|
||||
* @param auth_info Module auth_info structure
|
||||
* @param user User name
|
||||
* @param pass Password, if needed for authentication.
|
||||
* @param client_ip Client IP if known, or NULL
|
||||
* @param authentication_required True if user must be authenticated
|
||||
*
|
||||
* For a UDS connection, the user can be assumed to be authenticated,
|
||||
* so in this instance authentication_required can be false.
|
||||
*
|
||||
* @return Code describing the success of the operation
|
||||
*/
|
||||
static enum scp_login_status
|
||||
common_pam_login(struct auth_info *auth_info,
|
||||
const char *user,
|
||||
const char *pass,
|
||||
const char *client_ip,
|
||||
int authentication_required)
|
||||
{
|
||||
int error;
|
||||
struct auth_info *auth_info;
|
||||
int perror;
|
||||
char service_name[256];
|
||||
struct t_user_pass user_pass = {user, pass};
|
||||
struct pam_conv pamc = {verify_pam_conv, (void *) &user_pass};
|
||||
struct conv_func_data conv_func_data;
|
||||
struct pam_conv pamc;
|
||||
|
||||
auth_info = g_new0(struct auth_info, 1);
|
||||
if (auth_info == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "auth_userpass: No memory");
|
||||
error = PAM_BUF_ERR;
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
* Set up the data required by the conversation function, and the
|
||||
* structure which allows us to pass this to pam_start()
|
||||
*/
|
||||
conv_func_data.pass = (authentication_required) ? pass : NULL;
|
||||
pamc.conv = verify_pam_conv;
|
||||
pamc.appdata_ptr = (void *) &conv_func_data;
|
||||
|
||||
get_service_name(service_name);
|
||||
error = pam_start(service_name, user, &pamc, &(auth_info->ph));
|
||||
perror = pam_start(service_name, user, &pamc, &(auth_info->ph));
|
||||
|
||||
if (error != PAM_SUCCESS)
|
||||
if (perror != PAM_SUCCESS)
|
||||
{
|
||||
if (errorcode != NULL)
|
||||
{
|
||||
*errorcode = error;
|
||||
}
|
||||
LOG(LOG_LEVEL_ERROR, "pam_start failed: %s",
|
||||
pam_strerror(auth_info->ph, error));
|
||||
pam_end(auth_info->ph, error);
|
||||
g_free(auth_info);
|
||||
return NULL;
|
||||
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')
|
||||
{
|
||||
error = pam_set_item(auth_info->ph, PAM_RHOST, client_ip);
|
||||
if (error != PAM_SUCCESS)
|
||||
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, error));
|
||||
pam_strerror(auth_info->ph, perror));
|
||||
}
|
||||
}
|
||||
|
||||
error = pam_set_item(auth_info->ph, PAM_TTY, service_name);
|
||||
if (error != PAM_SUCCESS)
|
||||
perror = pam_set_item(auth_info->ph, PAM_TTY, service_name);
|
||||
if (perror != PAM_SUCCESS)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "pam_set_item(PAM_TTY) failed: %s",
|
||||
pam_strerror(auth_info->ph, error));
|
||||
pam_strerror(auth_info->ph, perror));
|
||||
}
|
||||
|
||||
error = pam_authenticate(auth_info->ph, 0);
|
||||
|
||||
if (error != PAM_SUCCESS)
|
||||
if (authentication_required)
|
||||
{
|
||||
if (errorcode != NULL)
|
||||
perror = pam_authenticate(auth_info->ph, 0);
|
||||
|
||||
if (perror != PAM_SUCCESS)
|
||||
{
|
||||
*errorcode = error;
|
||||
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;
|
||||
}
|
||||
LOG(LOG_LEVEL_ERROR, "pam_authenticate failed: %s",
|
||||
pam_strerror(auth_info->ph, error));
|
||||
pam_end(auth_info->ph, error);
|
||||
g_free(auth_info);
|
||||
return NULL;
|
||||
}
|
||||
/* From man page:
|
||||
The pam_acct_mgmt function is used to determine if the users account is
|
||||
|
@ -290,35 +295,99 @@ auth_userpass(const char *user, const char *pass,
|
|||
verifies access restrictions. It is typically called after the user has
|
||||
been authenticated.
|
||||
*/
|
||||
error = pam_acct_mgmt(auth_info->ph, 0);
|
||||
perror = pam_acct_mgmt(auth_info->ph, 0);
|
||||
|
||||
if (error != PAM_SUCCESS)
|
||||
if (perror != PAM_SUCCESS)
|
||||
{
|
||||
if (errorcode != NULL)
|
||||
{
|
||||
*errorcode = error;
|
||||
}
|
||||
LOG(LOG_LEVEL_ERROR, "pam_acct_mgmt failed: %s",
|
||||
pam_strerror(auth_info->ph, error));
|
||||
pam_end(auth_info->ph, error);
|
||||
g_free(auth_info);
|
||||
return NULL;
|
||||
pam_strerror(auth_info->ph, perror));
|
||||
pam_end(auth_info->ph, perror);
|
||||
return E_SCP_LOGIN_NOT_AUTHORIZED;
|
||||
}
|
||||
|
||||
/* Set the appdata_ptr passed to the conversation function to
|
||||
* NULL, as the existing value is going out of scope */
|
||||
pamc.appdata_ptr = NULL;
|
||||
error = pam_set_item(auth_info->ph, PAM_CONV, &pamc);
|
||||
if (error != PAM_SUCCESS)
|
||||
perror = pam_set_item(auth_info->ph, PAM_CONV, &pamc);
|
||||
if (perror != PAM_SUCCESS)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "pam_set_item(PAM_CONV) failed: %s",
|
||||
pam_strerror(auth_info->ph, error));
|
||||
pam_strerror(auth_info->ph, perror));
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
status = common_pam_login(auth_info, user, pass, 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
|
||||
{
|
||||
status = common_pam_login(auth_info, user, NULL, 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 */
|
||||
int
|
||||
auth_start_session(struct auth_info *auth_info, int display_num)
|
||||
|
@ -364,17 +433,31 @@ auth_start_session(struct auth_info *auth_info, int display_num)
|
|||
int
|
||||
auth_stop_session(struct auth_info *auth_info)
|
||||
{
|
||||
int rv = 0;
|
||||
int error;
|
||||
|
||||
error = pam_close_session(auth_info->ph, 0);
|
||||
if (error != PAM_SUCCESS)
|
||||
if (auth_info->session_opened)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "pam_close_session failed: %s",
|
||||
pam_strerror(auth_info->ph, error));
|
||||
return 1;
|
||||
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;
|
||||
}
|
||||
}
|
||||
auth_info->session_opened = 0;
|
||||
return 0;
|
||||
|
||||
if (auth_info->did_setcred)
|
||||
{
|
||||
pam_setcred(auth_info->ph, PAM_DELETE_CRED);
|
||||
auth_info->did_setcred = 0;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -387,15 +470,7 @@ auth_end(struct auth_info *auth_info)
|
|||
{
|
||||
if (auth_info->ph != 0)
|
||||
{
|
||||
if (auth_info->session_opened)
|
||||
{
|
||||
pam_close_session(auth_info->ph, 0);
|
||||
}
|
||||
|
||||
if (auth_info->did_setcred)
|
||||
{
|
||||
pam_setcred(auth_info->ph, PAM_DELETE_CRED);
|
||||
}
|
||||
auth_stop_session(auth_info);
|
||||
|
||||
pam_end(auth_info->ph, PAM_SUCCESS);
|
||||
auth_info->ph = 0;
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
|
||||
/**
|
||||
*
|
||||
* @file verify_user_pam_userpass.c
|
||||
* @brief Authenticate user using pam_userpass module
|
||||
* @file verify_user_pam.c
|
||||
* @brief Authenticate user using pam
|
||||
* @author Jay Sorg
|
||||
*
|
||||
*/
|
||||
|
@ -29,81 +29,220 @@
|
|||
#endif
|
||||
|
||||
#include "arch.h"
|
||||
#include "auth.h"
|
||||
#include "os_calls.h"
|
||||
#include "log.h"
|
||||
#include "string_calls.h"
|
||||
#include "auth.h"
|
||||
|
||||
#include <security/pam_userpass.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <security/pam_appl.h>
|
||||
|
||||
#define SERVICE "xrdp"
|
||||
|
||||
/*
|
||||
* Need a complete type for struct auth_info, even though we're
|
||||
* not really using it if this module (PAM userpass) is selected */
|
||||
struct auth_info
|
||||
{
|
||||
char dummy;
|
||||
pam_userpass_t userpass;
|
||||
int session_opened;
|
||||
int did_setcred;
|
||||
struct pam_conv pamc;
|
||||
pam_handle_t *ph;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/* returns non-NULL for success */
|
||||
|
||||
/** 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;
|
||||
char service_name[256];
|
||||
|
||||
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_name);
|
||||
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, int *errorcode)
|
||||
const char *client_ip, enum scp_login_status *errorcode)
|
||||
{
|
||||
pam_handle_t *pamh;
|
||||
pam_userpass_t userpass;
|
||||
struct pam_conv conv = {pam_userpass_conv, &userpass};
|
||||
const void *template1;
|
||||
int status;
|
||||
/* Need a non-NULL pointer to return to indicate success */
|
||||
static struct auth_info success = {0};
|
||||
struct auth_info *auth_info;
|
||||
enum scp_login_status status;
|
||||
|
||||
userpass.user = user;
|
||||
userpass.pass = pass;
|
||||
|
||||
if (pam_start(SERVICE, user, &conv, &pamh) != PAM_SUCCESS)
|
||||
auth_info = g_new0(struct auth_info, 1);
|
||||
if (auth_info == NULL)
|
||||
{
|
||||
return 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;
|
||||
}
|
||||
}
|
||||
|
||||
status = pam_authenticate(pamh, 0);
|
||||
|
||||
if (status != PAM_SUCCESS)
|
||||
if (errorcode != NULL)
|
||||
{
|
||||
pam_end(pamh, status);
|
||||
return NULL;
|
||||
*errorcode = status;
|
||||
}
|
||||
|
||||
status = pam_acct_mgmt(pamh, 0);
|
||||
|
||||
if (status != PAM_SUCCESS)
|
||||
{
|
||||
pam_end(pamh, status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = pam_get_item(pamh, PAM_USER, &template1);
|
||||
|
||||
if (status != PAM_SUCCESS)
|
||||
{
|
||||
pam_end(pamh, status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pam_end(pamh, PAM_SUCCESS) != PAM_SUCCESS)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &success;
|
||||
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 */
|
||||
int
|
||||
auth_start_session(struct auth_info *auth_info, int display_num)
|
||||
{
|
||||
int error;
|
||||
char display[256];
|
||||
|
||||
g_sprintf(display, ":%d", display_num);
|
||||
error = pam_set_item(auth_info->ph, PAM_TTY, display);
|
||||
|
||||
if (error != PAM_SUCCESS)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "pam_set_item 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;
|
||||
}
|
||||
|
||||
|
@ -112,19 +251,90 @@ auth_start_session(struct auth_info *auth_info, int display_num)
|
|||
int
|
||||
auth_stop_session(struct auth_info *auth_info)
|
||||
{
|
||||
return 0;
|
||||
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;
|
||||
char item[256];
|
||||
char value[256];
|
||||
int eq_pos;
|
||||
|
||||
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)
|
||||
{
|
||||
eq_pos = g_pos(*pam_env, "=");
|
||||
|
||||
if (eq_pos >= 0 && eq_pos < 250)
|
||||
{
|
||||
g_strncpy(item, *pam_env, eq_pos);
|
||||
g_strncpy(value, (*pam_env) + eq_pos + 1, 255);
|
||||
g_setenv(item, value, 1);
|
||||
}
|
||||
|
||||
g_free(*pam_env);
|
||||
}
|
||||
|
||||
g_free(pam_envlist);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
596
xrdp/xrdp_mm.c
596
xrdp/xrdp_mm.c
|
@ -30,15 +30,6 @@
|
|||
|
||||
#include "scp.h"
|
||||
|
||||
#ifdef USE_PAM
|
||||
#if defined(HAVE__PAM_TYPES_H)
|
||||
#define LINUXPAM 1
|
||||
#include <security/_pam_types.h>
|
||||
#elif defined(HAVE_PAM_CONSTANTS_H)
|
||||
#define OPENPAM 1
|
||||
#include <security/pam_constants.h>
|
||||
#endif
|
||||
#endif /* USE_PAM */
|
||||
#include <ctype.h>
|
||||
|
||||
#include "xrdp_encoder.h"
|
||||
|
@ -47,10 +38,6 @@
|
|||
|
||||
|
||||
/* Forward declarations */
|
||||
static const char *
|
||||
getPAMError(const int pamError, char *text, int text_bytes);
|
||||
static const char *
|
||||
getPAMAdditionalErrorInfo(const int pamError, struct xrdp_mm *self);
|
||||
static int
|
||||
xrdp_mm_chansrv_connect(struct xrdp_mm *self, const char *port);
|
||||
static void
|
||||
|
@ -233,85 +220,63 @@ xrdp_mm_get_value_int(struct xrdp_mm *self, const char *aname, int def)
|
|||
/*****************************************************************************/
|
||||
/* Send gateway login information to sesman */
|
||||
static int
|
||||
xrdp_mm_send_gateway_login(struct xrdp_mm *self, const char *username,
|
||||
const char *password)
|
||||
xrdp_mm_send_sys_login_request(struct xrdp_mm *self, const char *username,
|
||||
const char *password)
|
||||
{
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_DEBUG,
|
||||
"sending login info to session manager, please wait...");
|
||||
|
||||
return scp_send_gateway_request(
|
||||
return scp_send_sys_login_request(
|
||||
self->sesman_trans, username, password,
|
||||
self->wm->client_info->client_ip);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Send login information to sesman */
|
||||
/* Send a create session request to sesman */
|
||||
static int
|
||||
xrdp_mm_send_login(struct xrdp_mm *self)
|
||||
xrdp_mm_create_session(struct xrdp_mm *self)
|
||||
{
|
||||
int rv = 0;
|
||||
int xserverbpp;
|
||||
const char *username;
|
||||
const char *password;
|
||||
enum scp_session_type type;
|
||||
|
||||
username = xrdp_mm_get_value(self, "username");
|
||||
password = xrdp_mm_get_value(self, "password");
|
||||
if (username == NULL || username[0] == '\0')
|
||||
/* Map the session code to an SCP session type */
|
||||
switch (self->code)
|
||||
{
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_ERROR, "No username is available");
|
||||
rv = 1;
|
||||
case XVNC_SESSION_CODE:
|
||||
type = SCP_SESSION_TYPE_XVNC;
|
||||
break;
|
||||
|
||||
case XRDP_SESSION_CODE:
|
||||
type = SCP_SESSION_TYPE_XRDP;
|
||||
break;
|
||||
|
||||
case XORG_SESSION_CODE:
|
||||
type = SCP_SESSION_TYPE_XORG;
|
||||
break;
|
||||
|
||||
default:
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_ERROR,
|
||||
"Unrecognised session code %d", self->code);
|
||||
rv = 1;
|
||||
}
|
||||
else if (password == NULL)
|
||||
|
||||
if (rv == 0)
|
||||
{
|
||||
/* Can't find a password definition at all - even an empty one */
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_ERROR,
|
||||
"No password field is available");
|
||||
rv = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
enum scp_session_type type;
|
||||
/* Map the session code to an SCP session type */
|
||||
switch (self->code)
|
||||
{
|
||||
case XVNC_SESSION_CODE:
|
||||
type = SCP_SESSION_TYPE_XVNC;
|
||||
break;
|
||||
xserverbpp = xrdp_mm_get_value_int(self, "xserverbpp",
|
||||
self->wm->screen->bpp);
|
||||
|
||||
case XRDP_SESSION_CODE:
|
||||
type = SCP_SESSION_TYPE_XRDP;
|
||||
break;
|
||||
|
||||
case XORG_SESSION_CODE:
|
||||
type = SCP_SESSION_TYPE_XORG;
|
||||
break;
|
||||
|
||||
default:
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_ERROR,
|
||||
"Unrecognised session code %d", self->code);
|
||||
rv = 1;
|
||||
}
|
||||
|
||||
if (rv == 0)
|
||||
{
|
||||
xserverbpp = xrdp_mm_get_value_int(self, "xserverbpp",
|
||||
self->wm->screen->bpp);
|
||||
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_DEBUG,
|
||||
"sending login info to session manager. "
|
||||
"Please wait...");
|
||||
rv = scp_send_create_session_request(
|
||||
self->sesman_trans,
|
||||
username,
|
||||
password,
|
||||
type,
|
||||
self->wm->screen->width,
|
||||
self->wm->screen->height,
|
||||
xserverbpp,
|
||||
self->wm->client_info->program,
|
||||
self->wm->client_info->directory,
|
||||
self->wm->client_info->client_ip);
|
||||
}
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_DEBUG,
|
||||
"sending create session request to session"
|
||||
" manager. Please wait...");
|
||||
rv = scp_send_create_session_request(
|
||||
self->sesman_trans,
|
||||
type,
|
||||
self->wm->screen->width,
|
||||
self->wm->screen->height,
|
||||
xserverbpp,
|
||||
self->wm->client_info->program,
|
||||
self->wm->client_info->directory);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -1920,21 +1885,6 @@ xrdp_mm_chan_data_in(struct trans *trans)
|
|||
return error;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void cleanup_sesman_connection(struct xrdp_mm *self)
|
||||
{
|
||||
/* Don't delete any transports here - we may be in
|
||||
* an auth callback from one of them */
|
||||
self->delete_sesman_trans = 1;
|
||||
|
||||
if (self->wm->login_state != WMLS_CLEANUP)
|
||||
{
|
||||
xrdp_wm_set_login_state(self->wm, WMLS_INACTIVE);
|
||||
xrdp_mm_module_cleanup(self);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* does the section in xrdp.ini has any channel.*=true | false */
|
||||
static int
|
||||
|
@ -2088,38 +2038,49 @@ xrdp_mm_process_channel_data(struct xrdp_mm *self, tbus param1, tbus param2,
|
|||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
xrdp_mm_process_gateway_response(struct xrdp_mm *self)
|
||||
xrdp_mm_process_login_response(struct xrdp_mm *self)
|
||||
{
|
||||
int auth_result;
|
||||
enum scp_login_status login_result;
|
||||
int rv;
|
||||
int server_closed;
|
||||
|
||||
rv = scp_get_gateway_response(self->sesman_trans, &auth_result);
|
||||
rv = scp_get_login_response(self->sesman_trans, &login_result, &server_closed);
|
||||
if (rv == 0)
|
||||
{
|
||||
const char *additionalError;
|
||||
char pam_error[128];
|
||||
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO,
|
||||
"Reply from access control: %s",
|
||||
getPAMError(auth_result,
|
||||
pam_error, sizeof(pam_error)));
|
||||
|
||||
if (auth_result != 0)
|
||||
if (login_result != E_SCP_LOGIN_OK)
|
||||
{
|
||||
additionalError = getPAMAdditionalErrorInfo(auth_result, self);
|
||||
if (additionalError && additionalError[0])
|
||||
char buff[128];
|
||||
scp_login_status_to_str(login_result, buff, sizeof(buff));
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "%s", buff);
|
||||
|
||||
if (login_result == E_SCP_LOGIN_NOT_AUTHENTICATED &&
|
||||
self->wm->pamerrortxt[0] != '\0')
|
||||
{
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "%s",
|
||||
additionalError);
|
||||
self->wm->pamerrortxt);
|
||||
}
|
||||
|
||||
/* TODO : Check this is displayed */
|
||||
cleanup_sesman_connection(self);
|
||||
if (server_closed)
|
||||
{
|
||||
if (login_result == E_SCP_LOGIN_NOT_AUTHENTICATED)
|
||||
{
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "%s",
|
||||
"Login retry limit reached");
|
||||
}
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "%s",
|
||||
"Close the log window to exit.");
|
||||
self->wm->fatal_error_in_log_window = 1;
|
||||
/* Transport can be deleted now */
|
||||
self->delete_sesman_trans = 1;
|
||||
}
|
||||
/* If the server hasn't closed, inform the window manager
|
||||
* of the fail, but leave the sesman connection open for
|
||||
* further login attempts */
|
||||
xrdp_wm_mod_connect_done(self->wm, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Authentication successful */
|
||||
/* login successful */
|
||||
xrdp_mm_connect_sm(self);
|
||||
}
|
||||
}
|
||||
|
@ -2131,18 +2092,17 @@ xrdp_mm_process_gateway_response(struct xrdp_mm *self)
|
|||
static int
|
||||
xrdp_mm_process_create_session_response(struct xrdp_mm *self)
|
||||
{
|
||||
int auth_result;
|
||||
enum scp_screate_status status;
|
||||
int display;
|
||||
struct guid guid;
|
||||
|
||||
int rv;
|
||||
|
||||
rv = scp_get_create_session_response(self->sesman_trans, &auth_result,
|
||||
rv = scp_get_create_session_response(self->sesman_trans, &status,
|
||||
&display, &guid);
|
||||
if (rv == 0)
|
||||
{
|
||||
const char *username;
|
||||
char displayinfo[64];
|
||||
|
||||
/* Sort out some logging information */
|
||||
if ((username = xrdp_mm_get_value(self, "username")) == NULL)
|
||||
|
@ -2150,38 +2110,27 @@ xrdp_mm_process_create_session_response(struct xrdp_mm *self)
|
|||
username = "???";
|
||||
}
|
||||
|
||||
if (display == 0)
|
||||
if (status == E_SCP_SCREATE_OK)
|
||||
{
|
||||
/* A returned display of zero doesn't mean anything useful, and
|
||||
* can confuse the user. It's most likely authentication has
|
||||
* failed and no display was allocated */
|
||||
displayinfo[0] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
g_snprintf(displayinfo, sizeof(displayinfo),
|
||||
" on display %d", display);
|
||||
}
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO,
|
||||
"session is available on display %d for user %s",
|
||||
display, username);
|
||||
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO,
|
||||
"login %s for user %s%s",
|
||||
((auth_result == 0) ? "successful" : "failed"),
|
||||
username, displayinfo);
|
||||
|
||||
if (auth_result != 0)
|
||||
{
|
||||
/* Authentication failure */
|
||||
cleanup_sesman_connection(self);
|
||||
xrdp_wm_mod_connect_done(self->wm, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Authentication successful - carry on with the connect
|
||||
* state machine */
|
||||
/* Carry on with the connect state machine */
|
||||
self->display = display;
|
||||
self->guid = guid;
|
||||
xrdp_mm_connect_sm(self);
|
||||
}
|
||||
else
|
||||
{
|
||||
char buff[128];
|
||||
scp_screate_status_to_str(status, buff, sizeof(buff));
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO,
|
||||
"Can't create session for user %s - %s",
|
||||
username, buff);
|
||||
/* Leave the sesman connection open for further login attenpts */
|
||||
xrdp_wm_mod_connect_done(self->wm, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -2203,8 +2152,8 @@ xrdp_mm_scp_data_in(struct trans *trans)
|
|||
|
||||
switch ((msgno = scp_msg_in_start(trans)))
|
||||
{
|
||||
case E_SCP_GATEWAY_RESPONSE:
|
||||
rv = xrdp_mm_process_gateway_response(self);
|
||||
case E_SCP_LOGIN_RESPONSE:
|
||||
rv = xrdp_mm_process_login_response(self);
|
||||
break;
|
||||
|
||||
case E_SCP_CREATE_SESSION_RESPONSE:
|
||||
|
@ -2229,7 +2178,10 @@ xrdp_mm_scp_data_in(struct trans *trans)
|
|||
/*****************************************************************************/
|
||||
/* This routine clears all states to make sure that our next login will be
|
||||
* as expected. If the user does not press ok on the log window and try to
|
||||
* connect again we must make sure that no previous information is stored.*/
|
||||
* connect again we must make sure that no previous information is stored.
|
||||
*
|
||||
* This routine does not clear a sesman_trans if it is allocated, as this
|
||||
* would break the password retry limit mechanism */
|
||||
static void
|
||||
cleanup_states(struct xrdp_mm *self)
|
||||
{
|
||||
|
@ -2238,8 +2190,8 @@ cleanup_states(struct xrdp_mm *self)
|
|||
self->connect_state = MMCS_CONNECT_TO_SESMAN;
|
||||
self->use_sesman = 0; /* true if this is a sesman session */
|
||||
self->use_chansrv = 0; /* true if chansrvport is set in xrdp.ini or using sesman */
|
||||
self->use_pam_auth = 0; /* true if we're to use the PAM authentication facility */
|
||||
self->sesman_trans = NULL; /* connection to sesman */
|
||||
self->use_gw_login = 0; /* true if we're to use the gateway login facility */
|
||||
//self->sesman_trans = NULL; /* connection to sesman */
|
||||
self->chan_trans = NULL; /* connection to chansrv */
|
||||
self->delete_sesman_trans = 0;
|
||||
self->display = 0; /* 10 for :10.0, 11 for :11.0, etc */
|
||||
|
@ -2248,235 +2200,6 @@ cleanup_states(struct xrdp_mm *self)
|
|||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
getPAMError(const int pamError, char *text, int text_bytes)
|
||||
{
|
||||
switch (pamError)
|
||||
{
|
||||
#if defined(LINUXPAM)
|
||||
case PAM_SUCCESS:
|
||||
return "Success";
|
||||
case PAM_OPEN_ERR:
|
||||
return "dlopen() failure";
|
||||
case PAM_SYMBOL_ERR:
|
||||
return "Symbol not found";
|
||||
case PAM_SERVICE_ERR:
|
||||
return "Error in service module";
|
||||
case PAM_SYSTEM_ERR:
|
||||
return "System error";
|
||||
case PAM_BUF_ERR:
|
||||
return "Memory buffer error";
|
||||
case PAM_PERM_DENIED:
|
||||
return "Permission denied";
|
||||
case PAM_AUTH_ERR:
|
||||
return "Authentication failure";
|
||||
case PAM_CRED_INSUFFICIENT:
|
||||
return "Insufficient credentials to access authentication data";
|
||||
case PAM_AUTHINFO_UNAVAIL:
|
||||
return "Authentication service cannot retrieve authentication info.";
|
||||
case PAM_USER_UNKNOWN:
|
||||
return "User not known to the underlying authentication module";
|
||||
case PAM_MAXTRIES:
|
||||
return "Have exhausted maximum number of retries for service.";
|
||||
case PAM_NEW_AUTHTOK_REQD:
|
||||
return "Authentication token is no longer valid; new one required.";
|
||||
case PAM_ACCT_EXPIRED:
|
||||
return "User account has expired";
|
||||
case PAM_CRED_UNAVAIL:
|
||||
return "Authentication service cannot retrieve user credentials";
|
||||
case PAM_CRED_EXPIRED:
|
||||
return "User credentials expired";
|
||||
case PAM_CRED_ERR:
|
||||
return "Failure setting user credentials";
|
||||
case PAM_NO_MODULE_DATA:
|
||||
return "No module specific data is present";
|
||||
case PAM_BAD_ITEM:
|
||||
return "Bad item passed to pam_*_item()";
|
||||
case PAM_CONV_ERR:
|
||||
return "Conversation error";
|
||||
case PAM_AUTHTOK_ERR:
|
||||
return "Authentication token manipulation error";
|
||||
case PAM_AUTHTOK_LOCK_BUSY:
|
||||
return "Authentication token lock busy";
|
||||
case PAM_AUTHTOK_DISABLE_AGING:
|
||||
return "Authentication token aging disabled";
|
||||
case PAM_TRY_AGAIN:
|
||||
return "Failed preliminary check by password service";
|
||||
case PAM_IGNORE:
|
||||
return "Please ignore underlying account module";
|
||||
case PAM_MODULE_UNKNOWN:
|
||||
return "Module is unknown";
|
||||
case PAM_AUTHTOK_EXPIRED:
|
||||
return "Authentication token expired";
|
||||
case PAM_CONV_AGAIN:
|
||||
return "Conversation is waiting for event";
|
||||
case PAM_INCOMPLETE:
|
||||
return "Application needs to call libpam again";
|
||||
case 32 + 1:
|
||||
return "Error connecting to PAM";
|
||||
case 32 + 3:
|
||||
return "Username okey but group problem";
|
||||
#elif defined(OPENPAM)
|
||||
case PAM_SUCCESS: /* 0 */
|
||||
return "Success";
|
||||
case PAM_OPEN_ERR:
|
||||
return "dlopen() failure";
|
||||
case PAM_SYMBOL_ERR:
|
||||
return "Symbol not found";
|
||||
case PAM_SERVICE_ERR:
|
||||
return "Error in service module";
|
||||
case PAM_SYSTEM_ERR:
|
||||
return "System error";
|
||||
case PAM_BUF_ERR:
|
||||
return "Memory buffer error";
|
||||
case PAM_CONV_ERR:
|
||||
return "Conversation error";
|
||||
case PAM_PERM_DENIED:
|
||||
return "Permission denied";
|
||||
case PAM_MAXTRIES:
|
||||
return "Have exhausted maximum number of retries for service.";
|
||||
case PAM_AUTH_ERR:
|
||||
return "Authentication failure";
|
||||
case PAM_NEW_AUTHTOK_REQD: /* 10 */
|
||||
return "Authentication token is no longer valid; new one required.";
|
||||
case PAM_CRED_INSUFFICIENT:
|
||||
return "Insufficient credentials to access authentication data";
|
||||
case PAM_AUTHINFO_UNAVAIL:
|
||||
return "Authentication service cannot retrieve authentication info.";
|
||||
case PAM_USER_UNKNOWN:
|
||||
return "User not known to the underlying authentication module";
|
||||
case PAM_CRED_UNAVAIL:
|
||||
return "Authentication service cannot retrieve user credentials";
|
||||
case PAM_CRED_EXPIRED:
|
||||
return "User credentials expired";
|
||||
case PAM_CRED_ERR:
|
||||
return "Failure setting user credentials";
|
||||
case PAM_ACCT_EXPIRED:
|
||||
return "User account has expired";
|
||||
case PAM_AUTHTOK_EXPIRED:
|
||||
return "Authentication token expired";
|
||||
case PAM_SESSION_ERR:
|
||||
return "Session failure";
|
||||
case PAM_AUTHTOK_ERR: /* 20 */
|
||||
return "Authentication token manipulation error";
|
||||
case PAM_AUTHTOK_RECOVERY_ERR:
|
||||
return "Failed to recover old authentication token";
|
||||
case PAM_AUTHTOK_LOCK_BUSY:
|
||||
return "Authentication token lock busy";
|
||||
case PAM_AUTHTOK_DISABLE_AGING:
|
||||
return "Authentication token aging disabled";
|
||||
case PAM_NO_MODULE_DATA:
|
||||
return "No module specific data is present";
|
||||
case PAM_IGNORE:
|
||||
return "Please ignore underlying account module";
|
||||
case PAM_ABORT:
|
||||
return "General failure";
|
||||
case PAM_TRY_AGAIN:
|
||||
return "Failed preliminary check by password service";
|
||||
case PAM_MODULE_UNKNOWN:
|
||||
return "Module is unknown";
|
||||
case PAM_DOMAIN_UNKNOWN: /* 29 */
|
||||
return "Unknown authentication domain";
|
||||
#endif
|
||||
default:
|
||||
g_snprintf(text, text_bytes, "Not defined PAM error:%d", pamError);
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
getPAMAdditionalErrorInfo(const int pamError, struct xrdp_mm *self)
|
||||
{
|
||||
switch (pamError)
|
||||
{
|
||||
#if defined(LINUXPAM)
|
||||
case PAM_SUCCESS:
|
||||
return NULL;
|
||||
case PAM_OPEN_ERR:
|
||||
case PAM_SYMBOL_ERR:
|
||||
case PAM_SERVICE_ERR:
|
||||
case PAM_SYSTEM_ERR:
|
||||
case PAM_BUF_ERR:
|
||||
case PAM_PERM_DENIED:
|
||||
case PAM_AUTH_ERR:
|
||||
case PAM_CRED_INSUFFICIENT:
|
||||
case PAM_AUTHINFO_UNAVAIL:
|
||||
case PAM_USER_UNKNOWN:
|
||||
case PAM_CRED_UNAVAIL:
|
||||
case PAM_CRED_ERR:
|
||||
case PAM_NO_MODULE_DATA:
|
||||
case PAM_BAD_ITEM:
|
||||
case PAM_CONV_ERR:
|
||||
case PAM_AUTHTOK_ERR:
|
||||
case PAM_AUTHTOK_LOCK_BUSY:
|
||||
case PAM_AUTHTOK_DISABLE_AGING:
|
||||
case PAM_TRY_AGAIN:
|
||||
case PAM_IGNORE:
|
||||
case PAM_MODULE_UNKNOWN:
|
||||
case PAM_CONV_AGAIN:
|
||||
case PAM_INCOMPLETE:
|
||||
case _PAM_RETURN_VALUES + 1:
|
||||
case _PAM_RETURN_VALUES + 3:
|
||||
return NULL;
|
||||
case PAM_MAXTRIES:
|
||||
case PAM_NEW_AUTHTOK_REQD:
|
||||
case PAM_ACCT_EXPIRED:
|
||||
case PAM_CRED_EXPIRED:
|
||||
case PAM_AUTHTOK_EXPIRED:
|
||||
if (self->wm->pamerrortxt[0])
|
||||
{
|
||||
return self->wm->pamerrortxt;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Authentication error - Verify that user/password is valid";
|
||||
}
|
||||
#elif defined(OPENPAM)
|
||||
case PAM_SUCCESS: /* 0 */
|
||||
return NULL;
|
||||
case PAM_OPEN_ERR:
|
||||
case PAM_SYMBOL_ERR:
|
||||
case PAM_SERVICE_ERR:
|
||||
case PAM_SYSTEM_ERR:
|
||||
case PAM_BUF_ERR:
|
||||
case PAM_CONV_ERR:
|
||||
case PAM_PERM_DENIED:
|
||||
case PAM_MAXTRIES:
|
||||
case PAM_AUTH_ERR:
|
||||
case PAM_NEW_AUTHTOK_REQD: /* 10 */
|
||||
case PAM_CRED_INSUFFICIENT:
|
||||
case PAM_AUTHINFO_UNAVAIL:
|
||||
case PAM_USER_UNKNOWN:
|
||||
case PAM_CRED_UNAVAIL:
|
||||
case PAM_CRED_EXPIRED:
|
||||
case PAM_CRED_ERR:
|
||||
case PAM_ACCT_EXPIRED:
|
||||
case PAM_AUTHTOK_EXPIRED:
|
||||
case PAM_SESSION_ERR:
|
||||
case PAM_AUTHTOK_ERR: /* 20 */
|
||||
case PAM_AUTHTOK_RECOVERY_ERR:
|
||||
case PAM_AUTHTOK_LOCK_BUSY:
|
||||
case PAM_AUTHTOK_DISABLE_AGING:
|
||||
case PAM_NO_MODULE_DATA:
|
||||
case PAM_IGNORE:
|
||||
case PAM_ABORT:
|
||||
case PAM_TRY_AGAIN:
|
||||
case PAM_MODULE_UNKNOWN:
|
||||
case PAM_DOMAIN_UNKNOWN: /* 29 */
|
||||
if (self->wm->pamerrortxt[0])
|
||||
{
|
||||
return self->wm->pamerrortxt;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Authentication error - Verify that user/password is valid";
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
return "No expected error";
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************//**
|
||||
* Parses a chansrvport string
|
||||
*
|
||||
|
@ -2539,7 +2262,7 @@ xrdp_mm_scp_connect(struct xrdp_mm *self)
|
|||
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_DEBUG,
|
||||
"connecting to sesman on %s", port_description);
|
||||
t = scp_connect(port, g_is_term);
|
||||
t = scp_connect(port, "xrdp", g_is_term);
|
||||
if (t != NULL)
|
||||
{
|
||||
/* fully connected */
|
||||
|
@ -2650,7 +2373,7 @@ void
|
|||
xrdp_mm_connect(struct xrdp_mm *self)
|
||||
{
|
||||
const char *port = xrdp_mm_get_value(self, "port");
|
||||
const char *gateway_username = xrdp_mm_get_value(self, "pamusername");
|
||||
const char *gw_username = xrdp_mm_get_value(self, "pamusername");
|
||||
|
||||
/* make sure we start in correct state */
|
||||
cleanup_states(self);
|
||||
|
@ -2680,7 +2403,7 @@ xrdp_mm_connect(struct xrdp_mm *self)
|
|||
}
|
||||
}
|
||||
|
||||
if (gateway_username != NULL)
|
||||
if (gw_username != NULL)
|
||||
{
|
||||
/* Connecting to a remote sesman is no longer supported */
|
||||
if (xrdp_mm_get_value(self, "pamsessionmng") != NULL)
|
||||
|
@ -2690,13 +2413,7 @@ xrdp_mm_connect(struct xrdp_mm *self)
|
|||
"Parameter 'pamsessionmng' is obsolete."
|
||||
" Please remove from config");
|
||||
}
|
||||
#ifdef USE_PAM
|
||||
self->use_pam_auth = 1;
|
||||
#else
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_WARNING,
|
||||
"pamusername parameter ignored - "
|
||||
"xrdp is compiled without PAM support");
|
||||
#endif
|
||||
self->use_gw_login = 1;
|
||||
}
|
||||
|
||||
/* Will we need chansrv ? We use it unconditionally for a
|
||||
|
@ -2731,7 +2448,8 @@ xrdp_mm_connect_sm(struct xrdp_mm *self)
|
|||
{
|
||||
case MMCS_CONNECT_TO_SESMAN:
|
||||
{
|
||||
if (self->use_sesman || self->use_pam_auth)
|
||||
if (self->sesman_trans == NULL &&
|
||||
(self->use_sesman || self->use_gw_login))
|
||||
{
|
||||
/* Synchronous call */
|
||||
status = xrdp_mm_sesman_connect(self);
|
||||
|
@ -2739,45 +2457,46 @@ xrdp_mm_connect_sm(struct xrdp_mm *self)
|
|||
}
|
||||
break;
|
||||
|
||||
case MMCS_PAM_AUTH:
|
||||
case MMCS_GATEWAY_LOGIN:
|
||||
{
|
||||
if (self->use_pam_auth)
|
||||
if (self->use_gw_login)
|
||||
{
|
||||
const char *gateway_username;
|
||||
const char *gateway_password;
|
||||
const char *gw_username;
|
||||
const char *gw_password;
|
||||
|
||||
gateway_username = xrdp_mm_get_value(self, "pamusername");
|
||||
gateway_password = xrdp_mm_get_value(self, "pampassword");
|
||||
if (!g_strcmp(gateway_username, "same"))
|
||||
gw_username = xrdp_mm_get_value(self, "pamusername");
|
||||
gw_password = xrdp_mm_get_value(self, "pampassword");
|
||||
if (!g_strcmp(gw_username, "same"))
|
||||
{
|
||||
gateway_username = xrdp_mm_get_value(self, "username");
|
||||
gw_username = xrdp_mm_get_value(self, "username");
|
||||
}
|
||||
|
||||
if (gateway_password == NULL ||
|
||||
!g_strcmp(gateway_password, "same"))
|
||||
if (gw_password == NULL ||
|
||||
!g_strcmp(gw_password, "same"))
|
||||
{
|
||||
gateway_password = xrdp_mm_get_value(self, "password");
|
||||
gw_password = xrdp_mm_get_value(self, "password");
|
||||
}
|
||||
|
||||
if (gateway_username == NULL || gateway_password == NULL)
|
||||
if (gw_username == NULL || gw_password == NULL)
|
||||
{
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_ERROR,
|
||||
"Can't determine username and/or "
|
||||
"password for gateway authorization");
|
||||
"password for gateway login");
|
||||
status = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO,
|
||||
"Performing access control for %s",
|
||||
gateway_username);
|
||||
gw_username);
|
||||
|
||||
status = xrdp_mm_send_gateway_login(self,
|
||||
gateway_username,
|
||||
gateway_password);
|
||||
status = xrdp_mm_send_sys_login_request(self,
|
||||
gw_username,
|
||||
gw_password);
|
||||
if (status == 0)
|
||||
{
|
||||
/* Now waiting for a reply from sesman */
|
||||
/* Now waiting for a reply from sesman - see
|
||||
xrdp_mm_process_login_response() */
|
||||
waiting_for_msg = 1;
|
||||
}
|
||||
}
|
||||
|
@ -2785,21 +2504,77 @@ xrdp_mm_connect_sm(struct xrdp_mm *self)
|
|||
}
|
||||
break;
|
||||
|
||||
case MMCS_SESSION_AUTH:
|
||||
case MMCS_SESSION_LOGIN:
|
||||
{
|
||||
if (self->use_sesman)
|
||||
// Finished with the gateway login
|
||||
if (self->use_gw_login)
|
||||
{
|
||||
if ((status = xrdp_mm_send_login(self)) == 0)
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO,
|
||||
"access control check was successful");
|
||||
// No reply needed for this one
|
||||
status = scp_send_logout_request(self->sesman_trans);
|
||||
}
|
||||
|
||||
if (status == 0 && self->use_sesman)
|
||||
{
|
||||
const char *username;
|
||||
const char *password;
|
||||
|
||||
username = xrdp_mm_get_value(self, "username");
|
||||
password = xrdp_mm_get_value(self, "password");
|
||||
if (username == NULL || username[0] == '\0')
|
||||
{
|
||||
/* Now waiting for a reply from sesman */
|
||||
waiting_for_msg = 1;
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_ERROR,
|
||||
"No username is available");
|
||||
status = 1;
|
||||
}
|
||||
else if (password == NULL)
|
||||
{
|
||||
/* Can't find a password definition at all - even
|
||||
* an empty one */
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_ERROR,
|
||||
"No password field is available");
|
||||
status = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO,
|
||||
"Performing login request for %s",
|
||||
username);
|
||||
status = xrdp_mm_send_sys_login_request(self,
|
||||
username,
|
||||
password);
|
||||
if (status == 0)
|
||||
{
|
||||
/* Now waiting for a reply from sesman - see
|
||||
xrdp_mm_process_create_session_response() */
|
||||
waiting_for_msg = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MMCS_CREATE_SESSION:
|
||||
if (self->use_sesman)
|
||||
{
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO,
|
||||
"login was successful - creating session");
|
||||
if ((status = xrdp_mm_create_session(self)) == 0)
|
||||
{
|
||||
/* Now waiting for a reply from sesman. Note that
|
||||
* at this point sesman is expecting us to
|
||||
* close the connection - we can do nothing else
|
||||
* with it */
|
||||
waiting_for_msg = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MMCS_CONNECT_TO_SESSION:
|
||||
{
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO,
|
||||
"Connecting to session");
|
||||
/* This is synchronous - no reply message expected */
|
||||
status = xrdp_mm_user_session_connect(self);
|
||||
}
|
||||
|
@ -2811,6 +2586,8 @@ xrdp_mm_connect_sm(struct xrdp_mm *self)
|
|||
{
|
||||
char portbuff[256];
|
||||
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO,
|
||||
"Connecting to chansrv");
|
||||
if (self->use_sesman)
|
||||
{
|
||||
g_snprintf(portbuff, sizeof(portbuff),
|
||||
|
@ -2848,8 +2625,17 @@ xrdp_mm_connect_sm(struct xrdp_mm *self)
|
|||
|
||||
if (!waiting_for_msg)
|
||||
{
|
||||
/* We don't need the sesman transport anymore */
|
||||
if (self->sesman_trans != NULL)
|
||||
{
|
||||
self->delete_sesman_trans = 1;
|
||||
}
|
||||
xrdp_wm_mod_connect_done(self->wm, status);
|
||||
cleanup_sesman_connection(self);
|
||||
/* Make sure the module is cleaned up if we weren't successful */
|
||||
if (status != 0)
|
||||
{
|
||||
xrdp_mm_module_cleanup(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -312,8 +312,9 @@ struct xrdp_enc_data;
|
|||
enum mm_connect_state
|
||||
{
|
||||
MMCS_CONNECT_TO_SESMAN,
|
||||
MMCS_PAM_AUTH,
|
||||
MMCS_SESSION_AUTH,
|
||||
MMCS_GATEWAY_LOGIN,
|
||||
MMCS_SESSION_LOGIN,
|
||||
MMCS_CREATE_SESSION,
|
||||
MMCS_CONNECT_TO_SESSION,
|
||||
MMCS_CONNECT_TO_CHANSRV,
|
||||
MMCS_DONE
|
||||
|
@ -348,10 +349,8 @@ struct xrdp_mm
|
|||
struct xrdp_wm *wm; /* owner */
|
||||
enum mm_connect_state connect_state; /* State of connection */
|
||||
/* Other processes we connect to */
|
||||
/* NB : When we move to UDS, the sesman and pam_auth
|
||||
* connection be merged */
|
||||
int use_sesman; /* true if this is a sesman session */
|
||||
int use_pam_auth; /* True if we're to authenticate using PAM */
|
||||
int use_gw_login; /* True if we're to login using a gateway */
|
||||
int use_chansrv; /* true if chansrvport is set in xrdp.ini or using sesman */
|
||||
struct trans *sesman_trans; /* connection to sesman */
|
||||
struct trans *chan_trans; /* connection to chansrv */
|
||||
|
@ -495,6 +494,7 @@ struct xrdp_wm
|
|||
struct xrdp_font *default_font;
|
||||
struct xrdp_keymap keymap;
|
||||
int hide_log_window;
|
||||
int fatal_error_in_log_window;
|
||||
struct xrdp_bitmap *target_surface; /* either screen or os surface */
|
||||
int current_surface_index;
|
||||
int hints;
|
||||
|
|
|
@ -2034,12 +2034,22 @@ xrdp_wm_login_state_changed(struct xrdp_wm *self)
|
|||
LOG(LOG_LEVEL_DEBUG, "xrdp_wm_login_mode_changed: login_mode is %d", self->login_state);
|
||||
if (self->login_state == WMLS_RESET)
|
||||
{
|
||||
/* this is the initial state of the login window */
|
||||
xrdp_wm_set_login_state(self, WMLS_USER_PROMPT);
|
||||
list_clear(self->log);
|
||||
xrdp_wm_delete_all_children(self);
|
||||
self->dragging = 0;
|
||||
xrdp_wm_init(self);
|
||||
|
||||
if (self->fatal_error_in_log_window)
|
||||
{
|
||||
/* We've got here after OK is pressed in the log
|
||||
* window, so the user has read the message(s) in it */
|
||||
g_set_wait_obj(self->pro_layer->self_term_event);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* this is the initial state of the login window */
|
||||
xrdp_wm_set_login_state(self, WMLS_USER_PROMPT);
|
||||
xrdp_wm_init(self);
|
||||
}
|
||||
}
|
||||
else if (self->login_state == WMLS_START_CONNECT)
|
||||
{
|
||||
|
@ -2160,7 +2170,6 @@ add_string_to_logwindow(const char *msg, struct list *log)
|
|||
do
|
||||
{
|
||||
new_part_message = g_strndup(current_pointer, LOG_WINDOW_CHAR_PER_LINE);
|
||||
LOG(LOG_LEVEL_INFO, "%s", new_part_message);
|
||||
list_add_item(log, (tintptr) new_part_message);
|
||||
len_done += g_strlen(new_part_message);
|
||||
current_pointer += g_strlen(new_part_message);
|
||||
|
|
Loading…
Reference in New Issue