mirror of https://github.com/neutrinolabs/xrdp
Merge pull request #1741 from matt335672/sesrun-improvements
sesrun improvements and doc fixes
This commit is contained in:
commit
835536b406
11
common/log.c
11
common/log.c
|
@ -572,7 +572,7 @@ internal_log_location_overrides_level(const char *function_name,
|
|||
*/
|
||||
|
||||
struct log_config *
|
||||
log_config_init_for_console(enum logLevels lvl)
|
||||
log_config_init_for_console(enum logLevels lvl, const char *override_name)
|
||||
{
|
||||
struct log_config *config = internalInitAndAllocStruct();
|
||||
|
||||
|
@ -580,7 +580,14 @@ log_config_init_for_console(enum logLevels lvl)
|
|||
{
|
||||
config->program_name = "<null>";
|
||||
config->enable_console = 1;
|
||||
config->console_level = lvl;
|
||||
if (override_name != NULL && override_name[0] != '\0')
|
||||
{
|
||||
config->console_level = internal_log_text2level(override_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
config->console_level = lvl;
|
||||
}
|
||||
config->dump_on_start = 0; /* Don't need dump for console only */
|
||||
}
|
||||
return config;
|
||||
|
|
|
@ -275,9 +275,16 @@ log_start_from_param(const struct log_config *src_log_config);
|
|||
*
|
||||
* The config can be customised by the caller before calling
|
||||
* log_start_from_param()
|
||||
*
|
||||
* @param Default log level
|
||||
* @param Log level name, or NULL. This can be used to provide an
|
||||
* override to the default log level, by environment variable or
|
||||
* argument.
|
||||
*
|
||||
* @return pointer to struct log_config.
|
||||
*/
|
||||
struct log_config*
|
||||
log_config_init_for_console(enum logLevels lvl);
|
||||
log_config_init_for_console(enum logLevels lvl, const char *override_name);
|
||||
|
||||
/**
|
||||
* Read configuration from a file and store the values in the returned
|
||||
|
|
|
@ -1,42 +1,80 @@
|
|||
.TH "xrdp\-sesrun" "8" "@PACKAGE_VERSION@" "xrdp team" ""
|
||||
.SH "NAME"
|
||||
xrdp\-sesrun \- \fBxrdp-sesman\fR(8) session launcher
|
||||
\fBxrdp\-sesrun\fR \- \fBxrdp\-sesman\fR(8) session launcher
|
||||
|
||||
.SH "SYNTAX"
|
||||
.B xrdp\-sesrun
|
||||
.I [ -C /path/to/sesman.ini ] server username password width height bpp code
|
||||
.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 user logs in a new session and authenticates, thus starting a new session.
|
||||
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.
|
||||
|
||||
The utility prompts for a password if neither \fB-p\fR or \fB-F\fR is used.
|
||||
|
||||
.SH "OPTIONS"
|
||||
.TP
|
||||
.I \-\-config
|
||||
(Optional) Specify a path to a different \fIsesman.ini\fR file.
|
||||
.B -g <width>x<height>
|
||||
Set session geometry.
|
||||
.br
|
||||
Note that most configurations will resize the session on connection, so this
|
||||
option may not do what you expect.
|
||||
.TP
|
||||
.B -b <bits-per-pixel>
|
||||
Set session bits-per-pixel (colour depth). Some session types (i.e. Xorg)
|
||||
will ignore this setting.
|
||||
.TP
|
||||
.B -s <server>
|
||||
Server on which sesman is running (probably 'localhost').
|
||||
.br
|
||||
Use of this option is discouraged as it will be removed in the future.
|
||||
.TP
|
||||
.B -t <session-type>
|
||||
Session type - one of Xorg, Xvnc or X11rdp. Alternatively, for testing
|
||||
only, use the numeric session code.
|
||||
.TP
|
||||
.B -D <directory>
|
||||
Directory to run the new session in. Defaults to $HOME for the specified user.
|
||||
.TP
|
||||
.B -S <shell>
|
||||
Specify an alternate shell to run, instead of the default window manager.
|
||||
.TP
|
||||
.B -p <password>
|
||||
Password for user. USE FOR TESTING ONLY - the password will be visible
|
||||
in the output of the \fBps\fR command.
|
||||
.TP
|
||||
.B -F <file-descriptor>
|
||||
Specify a file descriptor (normally 0) to read the password in from. This
|
||||
is a secure way to pass the password in to the utility.
|
||||
.TP
|
||||
.B -c <sesman-ini>
|
||||
Specify a different sesman.ini file. This file is used to find out how to
|
||||
connect to \fBxrdp\-sesman\fR.
|
||||
|
||||
.SH "ENVIRONMENT"
|
||||
.TP
|
||||
.I server
|
||||
Server on which sesman is running
|
||||
.I SESRUN_LOG_LEVEL
|
||||
Override the default logging level. One of "error", "warn", "info",
|
||||
"debug", "trace" or a number 1-5.
|
||||
|
||||
.SH "EXAMPLES"
|
||||
.TP
|
||||
.I username
|
||||
user name of the session being started
|
||||
.B
|
||||
xrdp-sesrun -F 0 user1 <passwd.txt
|
||||
Create a default session for user \fBuser1\fR with a password from
|
||||
a file
|
||||
.TP
|
||||
.I password
|
||||
user password
|
||||
.TP
|
||||
.I width
|
||||
Screen width
|
||||
.TP
|
||||
.I height
|
||||
Screen height
|
||||
.TP
|
||||
.I bpp
|
||||
Session color depth
|
||||
.TP
|
||||
.I code
|
||||
Session type (0 for Xvnc, 10 for X11RDP, 20 for Xorg)
|
||||
.B
|
||||
xrdp-sesrun -t Xvnc -S /usr/bin/xterm user1
|
||||
Create an extremely minimal Xvnc session for user \fBuser1\fR. This
|
||||
could be useful for debugging why the standard session is not starting
|
||||
properly. Note you would need to install the \fBxterm\fR utility
|
||||
first. The \fBgnome\-terminal\fR utility probably won't work here.
|
||||
|
||||
.SH "FILES"
|
||||
@bindir@/xrdp\-sesman
|
||||
|
|
|
@ -471,7 +471,7 @@ config_read(const char *sesman_ini)
|
|||
if ((cfg->sesman_ini = g_strdup(sesman_ini)) != NULL)
|
||||
{
|
||||
int fd;
|
||||
if ((fd = g_file_open(cfg->sesman_ini)) != -1)
|
||||
if ((fd = g_file_open_ex(cfg->sesman_ini, 1, 0, 0, 0)) != -1)
|
||||
{
|
||||
struct list *sec;
|
||||
struct list *param_n;
|
||||
|
|
|
@ -62,7 +62,7 @@ int main(int argc, char **argv)
|
|||
serv[0] = '\0';
|
||||
port[0] = '\0';
|
||||
|
||||
logging = log_config_init_for_console(LOG_LEVEL_INFO);
|
||||
logging = log_config_init_for_console(LOG_LEVEL_INFO, NULL);
|
||||
log_start_from_param(logging);
|
||||
log_config_free(logging);
|
||||
|
||||
|
|
|
@ -28,139 +28,587 @@
|
|||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include "sesman.h"
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "parse.h"
|
||||
#include "os_calls.h"
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "tcp.h"
|
||||
|
||||
#if !defined(PACKAGE_VERSION)
|
||||
#define PACKAGE_VERSION "???"
|
||||
#endif
|
||||
|
||||
struct config_sesman *g_cfg; /* config.h */
|
||||
#ifndef MAX_PASSWORD_LEN
|
||||
# define MAX_PASSWORD_LEN 512
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_WIDTH
|
||||
# define DEFAULT_WIDTH 1280
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_HEIGHT
|
||||
# define DEFAULT_HEIGHT 1024
|
||||
#endif
|
||||
|
||||
/* Default setting used by Windows 10 mstsc.exe */
|
||||
#ifndef DEFAULT_BPP
|
||||
# define DEFAULT_BPP 32
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_SERVER
|
||||
# define DEFAULT_SERVER "localhost"
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_TYPE
|
||||
# define DEFAULT_TYPE "Xorg"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Maps session type strings to internal code numbers
|
||||
*/
|
||||
static struct
|
||||
{
|
||||
const char *name;
|
||||
int code;
|
||||
} type_map[] =
|
||||
{
|
||||
{ "Xvnc", 0},
|
||||
{ "X11rdp", 10},
|
||||
{ "Xorg", 20},
|
||||
{ NULL, -1}
|
||||
};
|
||||
|
||||
/**
|
||||
* Parameters needed for a session
|
||||
*/
|
||||
struct session_params
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
int bpp;
|
||||
int session_code;
|
||||
const char *server;
|
||||
|
||||
const char *domain; /* Currently unused by sesman */
|
||||
const char *directory;
|
||||
const char *shell;
|
||||
const char *client_ip;
|
||||
|
||||
const char *username;
|
||||
char password[MAX_PASSWORD_LEN + 1];
|
||||
};
|
||||
|
||||
/**************************************************************************//**
|
||||
* Maps a string to a session code
|
||||
*
|
||||
* @param t session type
|
||||
* @return session code, or -1 if not found
|
||||
*/
|
||||
static
|
||||
int get_session_type_code(const char *t)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0 ; type_map[i].name != NULL; ++i)
|
||||
{
|
||||
if (g_strcasecmp(type_map[i].name, t) == 0)
|
||||
{
|
||||
return type_map[i].code;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Returns a list of supported session types
|
||||
*
|
||||
* Caller supplies a buffer. Buffer handling and buffer overflow detection are
|
||||
* the same as snprint()
|
||||
*
|
||||
* @param buff area for result
|
||||
* @param bufflen Size of result
|
||||
* @return number of characters for the output string
|
||||
*/
|
||||
static
|
||||
unsigned int get_session_type_list(char *buff, unsigned int bufflen)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int ret = 0;
|
||||
const char *sep = "";
|
||||
|
||||
for (i = 0 ; type_map[i].name != NULL; ++i)
|
||||
{
|
||||
if (ret < bufflen)
|
||||
{
|
||||
ret += g_snprintf(buff + ret, bufflen - ret,
|
||||
"%s%s", sep, type_map[i].name);
|
||||
sep = ", ";
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Prints a brief summary of options and defaults
|
||||
*/
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
char sesstype_list[64];
|
||||
|
||||
(void)get_session_type_list(sesstype_list, sizeof(sesstype_list));
|
||||
|
||||
g_printf("xrdp session starter v" PACKAGE_VERSION "\n");
|
||||
g_printf("\nusage:\n");
|
||||
g_printf("sesrun [options] username\n\n");
|
||||
g_printf("options:\n");
|
||||
g_printf(" -g <geometry> Default:%dx%d\n",
|
||||
DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||||
g_printf(" -b <bits-per-pixel> Default:%d\n", DEFAULT_BPP);
|
||||
/* Don't encourage use of this one - we need to move to local sockets */
|
||||
g_printf(" -s <server> Default:%s (Deprecated)\n",
|
||||
DEFAULT_SERVER);
|
||||
g_printf(" -t <type> Default:%s\n", DEFAULT_TYPE);
|
||||
g_printf(" -D <directory> Default: $HOME\n"
|
||||
" -S <shell> Default: Defined window manager\n"
|
||||
" -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 or use int for internal code\n",
|
||||
sesstype_list);
|
||||
g_printf("Password is prompted if -p or -F are not specified\n");
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************//**
|
||||
* Parses a string <width>x<height>
|
||||
*
|
||||
* @param geom_str Input string
|
||||
* @param sp Session parameter structure for resulting width and height
|
||||
* @return !=0 for success
|
||||
*/
|
||||
static int
|
||||
parse_geometry_string(const char *geom_str, struct session_params *sp)
|
||||
{
|
||||
int result = 0;
|
||||
unsigned int sep_count = 0; /* Count of 'x' separators */
|
||||
unsigned int other_count = 0; /* Count of non-digits and non separators */
|
||||
const char *sepp = NULL; /* Pointer to the 'x' */
|
||||
const char *p = geom_str;
|
||||
|
||||
while (*p != '\0')
|
||||
{
|
||||
if (!isdigit(*p))
|
||||
{
|
||||
if (*p == 'x' || *p == 'X')
|
||||
{
|
||||
++sep_count;
|
||||
sepp = p;
|
||||
}
|
||||
else
|
||||
{
|
||||
++other_count;
|
||||
}
|
||||
}
|
||||
++p;
|
||||
}
|
||||
|
||||
if (sep_count != 1 || other_count > 0 ||
|
||||
sepp == geom_str || /* Separator at start of string */
|
||||
sepp == (p - 1) ) /* Separator at end of string */
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Invalid geometry string '%s'", geom_str);
|
||||
}
|
||||
else
|
||||
{
|
||||
sp->width = atoi(geom_str);
|
||||
sp->height = atoi(sepp + 1);
|
||||
result = 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************//**
|
||||
* Read a password from a file descriptor
|
||||
*
|
||||
* @param fd_str string representing file descriptor
|
||||
* @param sp Session parameter structure for resulting password
|
||||
* @return !=0 for success
|
||||
*/
|
||||
static int
|
||||
read_password_from_fd(const char *fd_str, struct session_params *sp)
|
||||
{
|
||||
int result = 0;
|
||||
int s = g_file_read(atoi(fd_str), sp->password, sizeof (sp->password) - 1);
|
||||
if (s < 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Can't read password from fd %s - %s",
|
||||
fd_str, g_get_strerror());
|
||||
sp->password[0] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
sp->password[s] = '\0';
|
||||
if (s > 0 && sp->password[s - 1] == '\n')
|
||||
{
|
||||
sp->password[s - 1] = '\0';
|
||||
}
|
||||
result = 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Parses the program args
|
||||
*
|
||||
* @param argc Passed to main
|
||||
* @param @argv Passed to main
|
||||
* @param sp Session parameter structure for resulting values
|
||||
* @param sesman_ini Pointer to an alternative config file if one is specified
|
||||
* @return !=0 for success
|
||||
*/
|
||||
static int
|
||||
parse_program_args(int argc, char *argv[], struct session_params *sp,
|
||||
const char **sesman_ini)
|
||||
{
|
||||
int params_ok = 1;
|
||||
int opt;
|
||||
bool_t password_set = 0;
|
||||
|
||||
sp->width = DEFAULT_WIDTH;
|
||||
sp->height = DEFAULT_HEIGHT;
|
||||
sp->bpp = DEFAULT_BPP;
|
||||
sp->session_code = get_session_type_code(DEFAULT_TYPE);
|
||||
sp->server = DEFAULT_SERVER;
|
||||
|
||||
sp->domain = "";
|
||||
sp->directory = "";
|
||||
sp->shell = "";
|
||||
sp->client_ip = "";
|
||||
|
||||
sp->username = NULL;
|
||||
sp->password[0] = '\0';
|
||||
|
||||
while ((opt = getopt(argc, argv, "g:b:s:t:D:S:p:F:c:")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'g':
|
||||
if (!parse_geometry_string(optarg, sp))
|
||||
{
|
||||
params_ok = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
sp->bpp = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
LOG(LOG_LEVEL_WARNING, "Using deprecated option '-s'");
|
||||
sp->server = optarg;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (isdigit(optarg[0]))
|
||||
{
|
||||
sp->session_code = atoi(optarg);
|
||||
}
|
||||
else
|
||||
{
|
||||
sp->session_code = get_session_type_code(optarg);
|
||||
if (sp->session_code < 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Unrecognised session type '%s'",
|
||||
optarg);
|
||||
params_ok = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
sp->directory = optarg;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
sp->shell = optarg;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
if (password_set)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Ignoring option '%c' - password already set ",
|
||||
(char)opt);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_strncpy(sp->password, optarg, sizeof(sp->password) - 1);
|
||||
password_set = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
if (password_set)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Ignoring option '%c' - password already set ",
|
||||
(char)opt);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (read_password_from_fd(optarg, sp))
|
||||
{
|
||||
password_set = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
params_ok = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
*sesman_ini = optarg;
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG(LOG_LEVEL_ERROR, "Unrecognised switch '%c'", (char)opt);
|
||||
params_ok = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc <= optind)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "No user name speciified");
|
||||
params_ok = 0;
|
||||
}
|
||||
else if ((argc - optind) > 1)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Unexpected arguments after username");
|
||||
params_ok = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sp->username = argv[optind];
|
||||
}
|
||||
|
||||
if (params_ok && !password_set)
|
||||
{
|
||||
const char *p = getpass("Password: ");
|
||||
if (p != NULL)
|
||||
{
|
||||
g_strcpy(sp->password, p);
|
||||
}
|
||||
}
|
||||
|
||||
return params_ok;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Helper function for send_scpv0_auth_request()
|
||||
*
|
||||
* @param s Output string
|
||||
* @param str String to write to s
|
||||
*/
|
||||
static void
|
||||
out_string16(struct stream *s, const char *str)
|
||||
{
|
||||
int i = g_strlen(str);
|
||||
out_uint16_be(s, i);
|
||||
out_uint8a(s, str, i);
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Sends an SCP V0 authorization request
|
||||
*
|
||||
* @param sck file descriptor to send request on
|
||||
* @param sp Data for request
|
||||
*
|
||||
* @todo This code duplicates functionality in the XRDP function
|
||||
* xrdp_mm_send_login(). When SCP is reworked, a common library
|
||||
* function should be used
|
||||
*/
|
||||
static void
|
||||
send_scpv0_auth_request(int sck, const struct session_params *sp)
|
||||
{
|
||||
struct stream *out_s;
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"width:%d height:%d bpp:%d code:%d\n"
|
||||
"server:\"%s\" domain:\"%s\" directory:\"%s\"\n"
|
||||
"shell:\"%s\" client_ip:\"%s\"",
|
||||
sp->width, sp->height, sp->bpp, sp->session_code,
|
||||
sp->server, sp->domain, sp->directory,
|
||||
sp->shell, sp->client_ip);
|
||||
/* Only log the password in development builds */
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "password:\"%s\"", sp->password);
|
||||
|
||||
make_stream(out_s);
|
||||
init_stream(out_s, 8192);
|
||||
|
||||
s_push_layer(out_s, channel_hdr, 8);
|
||||
out_uint16_be(out_s, sp->session_code);
|
||||
out_string16(out_s, sp->username);
|
||||
out_string16(out_s, sp->password);
|
||||
out_uint16_be(out_s, sp->width);
|
||||
out_uint16_be(out_s, sp->height);
|
||||
out_uint16_be(out_s, sp->bpp);
|
||||
out_string16(out_s, sp->domain);
|
||||
out_string16(out_s, sp->shell);
|
||||
out_string16(out_s, sp->directory);
|
||||
out_string16(out_s, sp->client_ip);
|
||||
s_mark_end(out_s);
|
||||
|
||||
s_pop_layer(out_s, channel_hdr);
|
||||
out_uint32_be(out_s, 0); /* version */
|
||||
out_uint32_be(out_s, out_s->end - out_s->data); /* size */
|
||||
tcp_force_send(sck, out_s->data, out_s->end - out_s->data);
|
||||
|
||||
free_stream(out_s);
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Receives an SCP V0 authorization reply
|
||||
*
|
||||
* @param sck file descriptor to receive reply on
|
||||
*
|
||||
* @todo This code duplicates functionality in the XRDP function
|
||||
* xrdp_mm_process_login_response(). When SCP is reworked, a
|
||||
* common library function should be used
|
||||
*/
|
||||
static int
|
||||
handle_scpv0_auth_reply(int sck)
|
||||
{
|
||||
int result = 1;
|
||||
int packet_ok = 0;
|
||||
|
||||
struct stream *in_s;
|
||||
|
||||
make_stream(in_s);
|
||||
init_stream(in_s, 8192);
|
||||
|
||||
if (tcp_force_recv(sck, in_s->data, 8) == 0)
|
||||
{
|
||||
int version;
|
||||
int size;
|
||||
int code;
|
||||
int data;
|
||||
int display;
|
||||
|
||||
in_uint32_be(in_s, version);
|
||||
in_uint32_be(in_s, size);
|
||||
if (version == 0 && size >= 14)
|
||||
{
|
||||
init_stream(in_s, 8192);
|
||||
if (tcp_force_recv(sck, in_s->data, size - 8) == 0)
|
||||
{
|
||||
in_s->end = in_s->data + (size - 8);
|
||||
|
||||
in_uint16_be(in_s, code);
|
||||
in_uint16_be(in_s, data);
|
||||
in_uint16_be(in_s, display);
|
||||
|
||||
if (code == 3)
|
||||
{
|
||||
packet_ok = 1;
|
||||
|
||||
if (data == 0)
|
||||
{
|
||||
g_printf("Connection denied (authentication error)\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
char guid[16];
|
||||
char guid_str[64];
|
||||
if (s_check_rem(in_s, 16) != 0)
|
||||
{
|
||||
in_uint8a(in_s, guid, 16);
|
||||
g_bytes_to_hexstr(guid, 16, guid_str, 64);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_strcpy(guid_str, "<none>");
|
||||
}
|
||||
|
||||
g_printf("ok data=%d display=:%d GUID=%s\n",
|
||||
(int)data, display, guid_str);
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!packet_ok)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Corrupt reply packet");
|
||||
}
|
||||
free_stream(in_s);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
const char *sesman_ini = XRDP_CFG_PATH "/sesman.ini";
|
||||
struct config_sesman *cfg = NULL;
|
||||
|
||||
int sck = -1;
|
||||
int code;
|
||||
int i;
|
||||
int size;
|
||||
int version;
|
||||
int width;
|
||||
int height;
|
||||
int bpp;
|
||||
int display;
|
||||
int session_code;
|
||||
struct stream *in_s;
|
||||
struct stream *out_s;
|
||||
char *username;
|
||||
char *password;
|
||||
long data;
|
||||
const char *sesman_ini;
|
||||
char default_sesman_ini[256];
|
||||
struct session_params sp;
|
||||
|
||||
struct log_config *logging;
|
||||
int status = 1;
|
||||
|
||||
/* User specified a different config file? */
|
||||
if (argc > 2 && (g_strcmp(argv[1], "-C") == 0))
|
||||
logging = log_config_init_for_console(LOG_LEVEL_WARNING,
|
||||
g_getenv("SESRUN_LOG_LEVEL"));
|
||||
log_start_from_param(logging);
|
||||
log_config_free(logging);
|
||||
|
||||
if (!parse_program_args(argc, argv, &sp, &sesman_ini))
|
||||
{
|
||||
sesman_ini = argv[2];
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
usage();
|
||||
}
|
||||
else if ((cfg = config_read(sesman_ini)) == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "error reading config file %s : %s",
|
||||
sesman_ini, g_get_strerror());
|
||||
}
|
||||
else
|
||||
{
|
||||
g_snprintf(default_sesman_ini, 255, "%s/sesman.ini", XRDP_CFG_PATH);
|
||||
sesman_ini = default_sesman_ini;
|
||||
}
|
||||
|
||||
if (argc != 8)
|
||||
{
|
||||
g_printf("xrdp session starter v" PACKAGE_VERSION "\n");
|
||||
g_printf("\nusage:\n");
|
||||
g_printf("xrdp-sesrun [-C /path/to/sesman.ini] <server> "
|
||||
"<username> <password> "
|
||||
"<width> <height> <bpp> <session_code>\n");
|
||||
g_printf("session code 0 for Xvnc, 10 for X11RDP, 20 for Xorg\n");
|
||||
}
|
||||
else if ((g_cfg = config_read(sesman_ini)) == NULL)
|
||||
{
|
||||
g_printf("xrdp-sesrun: error reading config %s. quitting.\n",
|
||||
sesman_ini);
|
||||
}
|
||||
else
|
||||
{
|
||||
username = argv[2];
|
||||
password = argv[3];
|
||||
width = g_atoi(argv[4]);
|
||||
height = g_atoi(argv[5]);
|
||||
bpp = g_atoi(argv[6]);
|
||||
session_code = g_atoi(argv[7]);
|
||||
make_stream(in_s);
|
||||
init_stream(in_s, 8192);
|
||||
make_stream(out_s);
|
||||
init_stream(out_s, 8192);
|
||||
|
||||
sck = g_tcp_socket();
|
||||
if (sck < 0)
|
||||
{
|
||||
g_printf("socket error\n");
|
||||
LOG(LOG_LEVEL_ERROR, "socket error - %s", g_get_strerror());
|
||||
}
|
||||
else if (g_tcp_connect(sck, argv[1], g_cfg->listen_port) != 0)
|
||||
else if (g_tcp_connect(sck, sp.server, cfg->listen_port) != 0)
|
||||
{
|
||||
g_printf("connect error\n");
|
||||
LOG(LOG_LEVEL_ERROR, "connect error - %s", g_get_strerror());
|
||||
}
|
||||
else
|
||||
{
|
||||
s_push_layer(out_s, channel_hdr, 8);
|
||||
out_uint16_be(out_s, session_code); /* code */
|
||||
i = g_strlen(username);
|
||||
out_uint16_be(out_s, i);
|
||||
out_uint8a(out_s, username, i);
|
||||
i = g_strlen(password);
|
||||
out_uint16_be(out_s, i);
|
||||
out_uint8a(out_s, password, i);
|
||||
out_uint16_be(out_s, width);
|
||||
out_uint16_be(out_s, height);
|
||||
out_uint16_be(out_s, bpp);
|
||||
s_mark_end(out_s);
|
||||
s_pop_layer(out_s, channel_hdr);
|
||||
out_uint32_be(out_s, 0); /* version */
|
||||
out_uint32_be(out_s, out_s->end - out_s->data); /* size */
|
||||
tcp_force_send(sck, out_s->data, out_s->end - out_s->data);
|
||||
|
||||
if (tcp_force_recv(sck, in_s->data, 8) == 0)
|
||||
{
|
||||
in_uint32_be(in_s, version);
|
||||
in_uint32_be(in_s, size);
|
||||
init_stream(in_s, 8192);
|
||||
|
||||
if (tcp_force_recv(sck, in_s->data, size - 8) == 0)
|
||||
{
|
||||
if (version == 0)
|
||||
{
|
||||
in_uint16_be(in_s, code);
|
||||
|
||||
if (code == 3)
|
||||
{
|
||||
in_uint16_be(in_s, data);
|
||||
in_uint16_be(in_s, display);
|
||||
g_printf("ok %d display %d\n", (int)data, display);
|
||||
status = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
send_scpv0_auth_request(sck, &sp);
|
||||
status = handle_scpv0_auth_reply(sck);
|
||||
}
|
||||
|
||||
if (sck >= 0)
|
||||
{
|
||||
g_tcp_close(sck);
|
||||
}
|
||||
free_stream(in_s);
|
||||
free_stream(out_s);
|
||||
}
|
||||
|
||||
config_free(g_cfg);
|
||||
if (sck >= 0)
|
||||
{
|
||||
g_tcp_close(sck);
|
||||
}
|
||||
|
||||
g_memset(sp.password, '\0', sizeof(sp.password));
|
||||
config_free(cfg);
|
||||
log_end();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -161,6 +161,9 @@ xrdp_mm_delete(struct xrdp_mm *self)
|
|||
|
||||
/*****************************************************************************/
|
||||
/* Send login information to sesman */
|
||||
/* FIXME : This code duplicates functionality in the sesman tools sesrun.c.
|
||||
* When SCP is reworked, a common library function should be used */
|
||||
|
||||
static int
|
||||
xrdp_mm_send_login(struct xrdp_mm *self)
|
||||
{
|
||||
|
@ -1553,6 +1556,8 @@ xrdp_mm_update_allowed_channels(struct xrdp_mm *self)
|
|||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* FIXME : This code duplicates functionality in the sesman tools sesrun.c.
|
||||
* When SCP is reworked, a common library function should be used */
|
||||
static int
|
||||
xrdp_mm_process_login_response(struct xrdp_mm *self, struct stream *s)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue