Merge pull request #2011 from matt335672/unify_scpv0_code
Unify scpv0 code #2011
This commit is contained in:
commit
ab0e141fa9
Makefile.am
common
neutrinordp
sesman
libscp
libscp_connection.clibscp_connection.hlibscp_session.clibscp_session.hlibscp_types.hlibscp_v0.clibscp_v0.h
scp_v0.csession.csession.htools
vnc
xrdp
@ -48,8 +48,8 @@ SUBDIRS = \
|
||||
libxrdp \
|
||||
$(PAINTERDIR) \
|
||||
$(RFXCODECDIR) \
|
||||
xrdp \
|
||||
sesman \
|
||||
xrdp \
|
||||
keygen \
|
||||
docs \
|
||||
instfiles \
|
||||
|
@ -47,6 +47,8 @@ libcommon_la_SOURCES = \
|
||||
fifo.h \
|
||||
file.c \
|
||||
file.h \
|
||||
guid.c \
|
||||
guid.h \
|
||||
list.c \
|
||||
list.h \
|
||||
list16.c \
|
||||
|
72
common/guid.c
Normal file
72
common/guid.c
Normal file
@ -0,0 +1,72 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) 2021 Matt Burt, 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 common/guid.c
|
||||
* @brief GUID manipulation definitions
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include "guid.h"
|
||||
#include "os_calls.h"
|
||||
#include "string_calls.h"
|
||||
|
||||
struct guid
|
||||
guid_new(void)
|
||||
{
|
||||
struct guid guid = {0};
|
||||
g_random(guid.g, sizeof(guid.g));
|
||||
return guid;
|
||||
}
|
||||
|
||||
void
|
||||
guid_clear(struct guid *guid)
|
||||
{
|
||||
g_memset(&guid->g, '\x00', GUID_SIZE);
|
||||
}
|
||||
|
||||
int
|
||||
guid_is_set(const struct guid *guid)
|
||||
{
|
||||
unsigned int i;
|
||||
int rv = 0;
|
||||
if (guid != NULL)
|
||||
{
|
||||
for (i = 0 ; i < GUID_SIZE; ++i)
|
||||
{
|
||||
if (guid->g[i] != '\x00')
|
||||
{
|
||||
rv = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
||||
}
|
||||
|
||||
const char *guid_to_str(const struct guid *guid, char *str)
|
||||
{
|
||||
g_bytes_to_hexstr(guid->g, GUID_SIZE, str, GUID_STR_SIZE);
|
||||
return str;
|
||||
}
|
75
common/guid.h
Normal file
75
common/guid.h
Normal file
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2021
|
||||
*
|
||||
* 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 common/guid.h
|
||||
* @brief GUID manipulation declarations
|
||||
*/
|
||||
|
||||
#ifndef GUID_H
|
||||
#define GUID_H
|
||||
|
||||
#include "arch.h"
|
||||
|
||||
#define GUID_SIZE 16 /* bytes */
|
||||
#define GUID_STR_SIZE (GUID_SIZE * 2 + 1) /* Size for string representation */
|
||||
|
||||
/**
|
||||
* Use a struct for the guid so we can easily copy by assignment
|
||||
*/
|
||||
struct guid
|
||||
{
|
||||
char g[GUID_SIZE];
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an initialised GUID
|
||||
*
|
||||
* @return new GUID
|
||||
*/
|
||||
struct guid guid_new(void);
|
||||
|
||||
/**
|
||||
* Clears an initialised GUID, so guid_is_set() returns true
|
||||
*
|
||||
* @param guid GUID to clear
|
||||
*/
|
||||
void
|
||||
guid_clear(struct guid *guid);
|
||||
|
||||
/**
|
||||
* Checks if a GUID is initialised
|
||||
*
|
||||
* @param guid GUID to check (can be NULL)
|
||||
* @return non-zero if GUID is set
|
||||
*/
|
||||
int
|
||||
guid_is_set(const struct guid *guid);
|
||||
|
||||
/**
|
||||
* Converts a GUID to a string representation
|
||||
*
|
||||
* @param guid GUID to represent
|
||||
* @param str pointer to at least GUID_STR_SIZE bytes to store the
|
||||
* representation
|
||||
* @return str is returned for convenience
|
||||
*/
|
||||
const char *guid_to_str(const struct guid *guid, char *str);
|
||||
|
||||
#endif
|
@ -257,7 +257,15 @@ lxrdp_connect(struct mod *mod)
|
||||
LOG(LOG_LEVEL_INFO, buf);
|
||||
mod->server_msg(mod, buf, 0);
|
||||
}
|
||||
|
||||
#else
|
||||
{
|
||||
/* This version of freerdp returns no useful information at
|
||||
* all */
|
||||
mod->server_msg(mod, "Neutrinordp connect failed.", 0);
|
||||
mod->server_msg(mod, "No more information is available", 0);
|
||||
mod->server_msg(mod, "Check host is up"
|
||||
" and credentials are correct", 0);
|
||||
}
|
||||
#endif
|
||||
LOG(LOG_LEVEL_ERROR, "NeutrinoRDP proxy connection: status [Failed],"
|
||||
" RDP client [%s:%s], RDP server [%s:%d], RDP server username [%s],"
|
||||
|
@ -108,7 +108,7 @@ struct mod
|
||||
char *data, int width, int height, int srcx, int srcy);
|
||||
int (*server_set_pointer)(struct mod *v, int x, int y, char *data, char *mask);
|
||||
int (*server_palette)(struct mod *v, int *palette);
|
||||
int (*server_msg)(struct mod *v, char *msg, int code);
|
||||
int (*server_msg)(struct mod *v, const char *msg, int code);
|
||||
int (*server_is_term)(struct mod *v);
|
||||
int (*server_set_clip)(struct mod *v, int x, int y, int cx, int cy);
|
||||
int (*server_reset_clip)(struct mod *v);
|
||||
|
@ -29,16 +29,109 @@
|
||||
#endif
|
||||
|
||||
#include "libscp_connection.h"
|
||||
#include "string_calls.h"
|
||||
#include "trans.h"
|
||||
|
||||
//extern struct log_config* s_log;
|
||||
|
||||
/*****************************************************************************/
|
||||
struct trans *
|
||||
scp_trans_create(int sck)
|
||||
scp_connect(const char *host, const char *port,
|
||||
tis_term term_func,
|
||||
ttrans_data_in data_in_func,
|
||||
void *callback_data)
|
||||
{
|
||||
struct trans *result = trans_create(TRANS_MODE_TCP, 8192, 8192);
|
||||
if (result != NULL)
|
||||
struct trans *t = trans_create(TRANS_MODE_TCP, 8192, 8192);
|
||||
int index;
|
||||
|
||||
if (host == NULL)
|
||||
{
|
||||
result->sck = sck;
|
||||
host = "localhost";
|
||||
}
|
||||
|
||||
if (port == NULL)
|
||||
{
|
||||
port = "3350";
|
||||
}
|
||||
|
||||
t->is_term = term_func;
|
||||
|
||||
t->trans_data_in = data_in_func;
|
||||
t->header_size = 8;
|
||||
t->no_stream_init_on_data_in = 1;
|
||||
t->callback_data = callback_data;
|
||||
|
||||
/* try to connect up to 4 times
|
||||
*
|
||||
* term_func can be NULL, so check before calling it */
|
||||
index = 4;
|
||||
while (trans_connect(t, host, port, 3000) != 0 &&
|
||||
!(term_func && term_func()) &&
|
||||
--index > 0)
|
||||
{
|
||||
g_sleep(1000);
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "Connect failed. Trying again...");
|
||||
}
|
||||
|
||||
if (t->status != TRANS_STATUS_UP)
|
||||
{
|
||||
trans_delete(t);
|
||||
t = NULL;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const char *
|
||||
scp_client_state_to_str(enum SCP_CLIENT_STATES_E e)
|
||||
{
|
||||
const char *result = "SCP_CLIENT_STATE_????";
|
||||
|
||||
/* Some compilers will warn if this switch is missing states */
|
||||
switch (e)
|
||||
{
|
||||
case SCP_CLIENT_STATE_OK:
|
||||
result = "SCP_CLIENT_STATE_OK";
|
||||
break;
|
||||
case SCP_CLIENT_STATE_NETWORK_ERR:
|
||||
result = "SCP_CLIENT_STATE_NETWORK_ERR";
|
||||
break;
|
||||
case SCP_CLIENT_STATE_VERSION_ERR:
|
||||
result = "SCP_CLIENT_STATE_VERSION_ERR";
|
||||
break;
|
||||
case SCP_CLIENT_STATE_SEQUENCE_ERR:
|
||||
result = "SCP_CLIENT_STATE_SEQUENCE_ERR";
|
||||
break;
|
||||
case SCP_CLIENT_STATE_SIZE_ERR:
|
||||
result = "SCP_CLIENT_STATE_SIZE_ERR";
|
||||
break;
|
||||
case SCP_CLIENT_STATE_INTERNAL_ERR:
|
||||
result = "SCP_CLIENT_STATE_INTERNAL_ERR";
|
||||
break;
|
||||
case SCP_CLIENT_STATE_SESSION_LIST:
|
||||
result = "SCP_CLIENT_STATE_SESSION_LIST";
|
||||
break;
|
||||
case SCP_CLIENT_STATE_LIST_OK:
|
||||
result = "SCP_CLIENT_STATE_LIST_OK";
|
||||
break;
|
||||
case SCP_CLIENT_STATE_RESEND_CREDENTIALS:
|
||||
result = "SCP_CLIENT_STATE_RESEND_CREDENTIALS";
|
||||
break;
|
||||
case SCP_CLIENT_STATE_CONNECTION_DENIED:
|
||||
result = "SCP_CLIENT_STATE_CONNECTION_DENIED";
|
||||
break;
|
||||
case SCP_CLIENT_STATE_PWD_CHANGE_REQ:
|
||||
result = "SCP_CLIENT_STATE_PWD_CHANGE_REQ";
|
||||
break;
|
||||
case SCP_CLIENT_STATE_RECONNECT_SINGLE:
|
||||
result = "SCP_CLIENT_STATE_RECONNECT_SINGLE";
|
||||
break;
|
||||
case SCP_CLIENT_STATE_SELECTION_CANCEL:
|
||||
result = "SCP_CLIENT_STATE_SELECTION_CANCEL";
|
||||
break;
|
||||
case SCP_CLIENT_STATE_END:
|
||||
result = "SCP_CLIENT_STATE_END";
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -31,11 +31,12 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief creates a new SCP transport object
|
||||
* @param sck the connection socket
|
||||
*
|
||||
* This is a convenience function which calls trans_create() with the
|
||||
* correct parameters.
|
||||
* @brief creates a new SCP connection
|
||||
* @param host Hostname to connect to (NULL for default)
|
||||
* @param port Port to connect to (NULL for default)
|
||||
* @param term_func Transport termination function (or NULL)
|
||||
* @param data_in_func Transport 'data in' function
|
||||
* @param callback_data Closure data for data in function
|
||||
*
|
||||
* Returned object can be freed with trans_delete()
|
||||
*
|
||||
@ -43,6 +44,18 @@
|
||||
*
|
||||
*/
|
||||
struct trans *
|
||||
scp_trans_create(int sck);
|
||||
scp_connect(const char *host, const char *port,
|
||||
tis_term term_func,
|
||||
ttrans_data_in data_in_func,
|
||||
void *callback_data);
|
||||
|
||||
/**
|
||||
* @brief Maps SCP_CLIENT_TYPES_E to a string
|
||||
* @param e
|
||||
*
|
||||
* @return Pointer to a string
|
||||
*
|
||||
*/
|
||||
const char *scp_client_state_to_str(enum SCP_CLIENT_STATES_E e);
|
||||
|
||||
#endif
|
||||
|
@ -414,7 +414,7 @@ scp_session_set_addr(struct SCP_SESSION *s, int type, const void *addr)
|
||||
|
||||
/*******************************************************************/
|
||||
int
|
||||
scp_session_set_guid(struct SCP_SESSION *s, const tui8 *guid)
|
||||
scp_session_set_guid(struct SCP_SESSION *s, const struct guid *guid)
|
||||
{
|
||||
if (0 == guid)
|
||||
{
|
||||
@ -422,7 +422,7 @@ scp_session_set_guid(struct SCP_SESSION *s, const tui8 *guid)
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_memcpy(s->guid, guid, 16);
|
||||
s->guid = *guid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ int
|
||||
scp_session_set_errstr(struct SCP_SESSION *s, const char *str);
|
||||
|
||||
int
|
||||
scp_session_set_guid(struct SCP_SESSION *s, const tui8 *guid);
|
||||
scp_session_set_guid(struct SCP_SESSION *s, const struct guid *guid);
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "os_calls.h"
|
||||
#include "parse.h"
|
||||
#include "arch.h"
|
||||
#include "guid.h"
|
||||
#include "log.h"
|
||||
#include "trans.h"
|
||||
|
||||
@ -85,7 +86,7 @@ struct SCP_SESSION
|
||||
char *program;
|
||||
char *directory;
|
||||
char *connection_description;
|
||||
tui8 guid[16];
|
||||
struct guid guid;
|
||||
/* added for state */
|
||||
int current_cmd;
|
||||
int return_sid;
|
||||
|
@ -47,177 +47,290 @@ extern struct log_config *s_log;
|
||||
* Buffer is null-terminated on success
|
||||
*
|
||||
* @param s Input stream
|
||||
* @param [out] Output buffer (must be >= (STRING16_MAX_LEN+1) chars)
|
||||
* @param param Parameter we're reading
|
||||
* @param [out] str Output buffer (must be >= (STRING16_MAX_LEN+1) chars)
|
||||
* @param prefix Logging prefix for errors
|
||||
* @return != 0 if string read OK
|
||||
*/
|
||||
static
|
||||
int in_string16(struct stream *s, char str[], const char *param)
|
||||
int in_string16(struct stream *s, char str[], const char *prefix)
|
||||
{
|
||||
int result;
|
||||
unsigned int sz;
|
||||
|
||||
if (!s_check_rem(s, 2))
|
||||
if ((result = s_check_rem_and_log(s, 2, prefix)) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "connection aborted: %s len missing", param);
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int sz;
|
||||
|
||||
in_uint16_be(s, sz);
|
||||
if (sz > STRING16_MAX_LEN)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"connection aborted: %s too long (%u chars)", param, sz);
|
||||
LOG(LOG_LEVEL_ERROR, "%s input string too long (%u chars)",
|
||||
prefix, sz);
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
else if ((result = s_check_rem_and_log(s, sz, prefix)) != 0)
|
||||
{
|
||||
result = s_check_rem(s, sz);
|
||||
if (!result)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "connection aborted: %s data missing", param);
|
||||
}
|
||||
else
|
||||
{
|
||||
in_uint8a(s, str, sz);
|
||||
str[sz] = '\0';
|
||||
}
|
||||
in_uint8a(s, str, sz);
|
||||
str[sz] = '\0';
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/* client API */
|
||||
#if 0
|
||||
/******************************************************************************/
|
||||
static enum SCP_CLIENT_STATES_E
|
||||
scp_v0c_connect(struct SCP_CONNECTION *c, struct SCP_SESSION *s)
|
||||
|
||||
/**
|
||||
* Writes a big-endian uint16 followed by a string into a buffer
|
||||
*
|
||||
* @param s Output stream
|
||||
* @param[in] str output string (must be <= (STRING16_MAX_LEN+1) chars)
|
||||
* @param param Parameter we're sending
|
||||
* @return != 0 if string written OK
|
||||
*/
|
||||
static
|
||||
int out_string16(struct stream *out_s, const char *str, const char *prefix)
|
||||
{
|
||||
tui32 version;
|
||||
int size;
|
||||
tui16 sz;
|
||||
int result;
|
||||
|
||||
init_stream(c->in_s, c->in_s->size);
|
||||
init_stream(c->out_s, c->in_s->size);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "starting connection");
|
||||
g_tcp_set_non_blocking(c->in_sck);
|
||||
g_tcp_set_no_delay(c->in_sck);
|
||||
s_push_layer(c->out_s, channel_hdr, 8);
|
||||
|
||||
/* code */
|
||||
if (s->type == SCP_SESSION_TYPE_XVNC)
|
||||
unsigned int sz = g_strlen(str);
|
||||
if (sz > STRING16_MAX_LEN)
|
||||
{
|
||||
out_uint16_be(c->out_s, 0);
|
||||
LOG(LOG_LEVEL_WARNING, "%s String too long (%u chars)", prefix, sz);
|
||||
result = 0;
|
||||
}
|
||||
else if (s->type == SCP_SESSION_TYPE_XRDP)
|
||||
else if ((result = s_check_rem_out_and_log(out_s, 2 + sz, prefix)) != 0)
|
||||
{
|
||||
out_uint16_be(c->out_s, 10);
|
||||
out_uint16_be(out_s, sz);
|
||||
out_uint8a(out_s, str, sz);
|
||||
}
|
||||
else if (s->type == SCP_SESSION_TYPE_XORG)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/***
|
||||
* Terminates a V0 request, adds the header and sends it.
|
||||
*
|
||||
* On entry, channel_hdr on the transport output stream is expected to
|
||||
* contain the location for the SCP header
|
||||
*
|
||||
* @param atrans Transport for the message
|
||||
* @return error code
|
||||
*/
|
||||
static enum SCP_CLIENT_STATES_E
|
||||
terminate_and_send_v0_request(struct trans *atrans)
|
||||
{
|
||||
enum SCP_CLIENT_STATES_E e;
|
||||
|
||||
struct stream *s = atrans->out_s;
|
||||
s_mark_end(s);
|
||||
s_pop_layer(s, channel_hdr);
|
||||
|
||||
/* version */
|
||||
out_uint32_be(s, 0);
|
||||
/* size */
|
||||
out_uint32_be(s, s->end - s->data);
|
||||
|
||||
if (trans_force_write_s(atrans, s) == 0)
|
||||
{
|
||||
out_uint16_be(c->out_s, 20);
|
||||
e = SCP_CLIENT_STATE_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "connection aborted: network error");
|
||||
return SCP_CLIENT_STATE_INTERNAL_ERR;
|
||||
LOG(LOG_LEVEL_ERROR, "connection aborted: network error");
|
||||
e = SCP_CLIENT_STATE_NETWORK_ERR;
|
||||
}
|
||||
|
||||
sz = g_strlen(s->username);
|
||||
if (sz > STRING16_MAX_LEN)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "connection aborted: username too long");
|
||||
return SCP_CLIENT_STATE_SIZE_ERR;
|
||||
}
|
||||
out_uint16_be(c->out_s, sz);
|
||||
out_uint8a(c->out_s, s->username, sz);
|
||||
|
||||
sz = g_strlen(s->password);
|
||||
if (sz > STRING16_MAX_LEN)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "connection aborted: password too long");
|
||||
return SCP_CLIENT_STATE_SIZE_ERR;
|
||||
}
|
||||
out_uint16_be(c->out_s, sz);
|
||||
out_uint8a(c->out_s, s->password, sz);
|
||||
out_uint16_be(c->out_s, s->width);
|
||||
out_uint16_be(c->out_s, s->height);
|
||||
out_uint16_be(c->out_s, s->bpp);
|
||||
|
||||
s_mark_end(c->out_s);
|
||||
s_pop_layer(c->out_s, channel_hdr);
|
||||
|
||||
/* version */
|
||||
out_uint32_be(c->out_s, 0);
|
||||
/* size */
|
||||
out_uint32_be(c->out_s, c->out_s->end - c->out_s->data);
|
||||
|
||||
if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, c->out_s->end - c->out_s->data))
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "connection aborted: network error");
|
||||
return SCP_CLIENT_STATE_NETWORK_ERR;
|
||||
}
|
||||
|
||||
if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, 8))
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "connection aborted: network error");
|
||||
return SCP_CLIENT_STATE_NETWORK_ERR;
|
||||
}
|
||||
|
||||
in_uint32_be(c->in_s, version);
|
||||
|
||||
if (0 != version)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "connection aborted: version error");
|
||||
return SCP_CLIENT_STATE_VERSION_ERR;
|
||||
}
|
||||
|
||||
in_uint32_be(c->in_s, size);
|
||||
|
||||
if (size < (8 + 2 + 2 + 2) || size > SCP_MAX_MESSAGE_SIZE)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "connection aborted: msg size = %d", size);
|
||||
return SCP_CLIENT_STATE_SIZE_ERR;
|
||||
}
|
||||
|
||||
/* getting payload */
|
||||
init_stream(c->in_s, size - 8);
|
||||
|
||||
if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, size - 8))
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "connection aborted: network error");
|
||||
return SCP_CLIENT_STATE_NETWORK_ERR;
|
||||
}
|
||||
|
||||
c->in_s->end = c->in_s->data + (size - 8);
|
||||
|
||||
/* check code */
|
||||
in_uint16_be(c->in_s, sz);
|
||||
|
||||
if (3 != sz)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "connection aborted: sequence error");
|
||||
return SCP_CLIENT_STATE_SEQUENCE_ERR;
|
||||
}
|
||||
|
||||
/* message payload */
|
||||
in_uint16_be(c->in_s, sz);
|
||||
|
||||
if (1 != sz)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "connection aborted: connection denied");
|
||||
return SCP_CLIENT_STATE_CONNECTION_DENIED;
|
||||
}
|
||||
|
||||
in_uint16_be(c->in_s, sz);
|
||||
s->display = sz;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "connection terminated");
|
||||
return SCP_CLIENT_STATE_END;
|
||||
return e;
|
||||
}
|
||||
|
||||
/* client API */
|
||||
/******************************************************************************/
|
||||
enum SCP_CLIENT_STATES_E
|
||||
scp_v0c_create_session_request(struct trans *atrans,
|
||||
const char *username,
|
||||
const char *password,
|
||||
unsigned short code,
|
||||
unsigned short width,
|
||||
unsigned short height,
|
||||
unsigned short bpp,
|
||||
const char *domain,
|
||||
const char *shell,
|
||||
const char *directory,
|
||||
const char *client_ip)
|
||||
{
|
||||
enum SCP_CLIENT_STATES_E e;
|
||||
|
||||
struct stream *s = trans_get_out_s(atrans, 8192);
|
||||
s_push_layer(s, channel_hdr, 8);
|
||||
|
||||
out_uint16_be(s, code);
|
||||
if (!out_string16(s, username, "Session username") ||
|
||||
!out_string16(s, password, "Session passwd"))
|
||||
{
|
||||
e = SCP_CLIENT_STATE_SIZE_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_uint16_be(s, width);
|
||||
out_uint16_be(s, height);
|
||||
out_uint16_be(s, bpp);
|
||||
if (!out_string16(s, domain, "Session domain") ||
|
||||
!out_string16(s, shell, "Session shell") ||
|
||||
!out_string16(s, directory, "Session directory") ||
|
||||
!out_string16(s, client_ip, "Session client IP"))
|
||||
{
|
||||
e = SCP_CLIENT_STATE_SIZE_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
e = terminate_and_send_v0_request(atrans);
|
||||
}
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
enum SCP_CLIENT_STATES_E
|
||||
scp_v0c_gateway_request(struct trans *atrans,
|
||||
const char *username,
|
||||
const char *password)
|
||||
{
|
||||
enum SCP_CLIENT_STATES_E e;
|
||||
|
||||
struct stream *s = trans_get_out_s(atrans, 500);
|
||||
s_push_layer(s, channel_hdr, 8);
|
||||
|
||||
out_uint16_be(s, SCP_GW_AUTHENTICATION);
|
||||
if (!out_string16(s, username, "Gateway username") ||
|
||||
!out_string16(s, password, "Gateway passwd"))
|
||||
{
|
||||
e = SCP_CLIENT_STATE_SIZE_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
e = terminate_and_send_v0_request(atrans);
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Is a reply available from the other end?
|
||||
*
|
||||
* Returns true if it is, or if an error has occurred which needs handling.
|
||||
*
|
||||
* @param trans Transport to be polled
|
||||
* @return True if scp_v0c_get_reply() should be called
|
||||
*/
|
||||
int
|
||||
scp_v0c_reply_available(struct trans *trans)
|
||||
{
|
||||
int result = 1;
|
||||
if (trans != NULL && trans->status == TRANS_STATUS_UP)
|
||||
{
|
||||
/* Have we read enough data from the stream? */
|
||||
if ((trans->in_s->end - trans->in_s->data) < trans->header_size)
|
||||
{
|
||||
result = 0;
|
||||
}
|
||||
else if (trans->extra_flags == 0)
|
||||
{
|
||||
int version;
|
||||
int size;
|
||||
|
||||
/* We've read the header only */
|
||||
in_uint32_be(trans->in_s, version);
|
||||
in_uint32_be(trans->in_s, size);
|
||||
|
||||
if (version != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Unexpected version number %d from SCP",
|
||||
version);
|
||||
trans->status = TRANS_STATUS_DOWN;
|
||||
}
|
||||
else if (size <= 8 || size > trans->in_s->size)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Invalid V0 message length %d from SCP",
|
||||
size);
|
||||
trans->status = TRANS_STATUS_DOWN;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read the rest of the message */
|
||||
trans->header_size = size;
|
||||
trans->extra_flags = 1;
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
/**************************************************************************//**
|
||||
* Get a reply from the V0 transport
|
||||
*
|
||||
* Only call this once scp_v0c_reply_available() has returned true
|
||||
*
|
||||
* After a successful call, the transport is ready to be used for the
|
||||
* next incoming message
|
||||
*
|
||||
* @param trans Transport containing the reply
|
||||
* @param[out] reply, provided result is SCP_CLIENT_STATE_OK
|
||||
* @return SCP client state
|
||||
*/
|
||||
enum SCP_CLIENT_STATES_E
|
||||
scp_v0c_get_reply(struct trans *trans, struct scp_v0_reply_type *reply)
|
||||
{
|
||||
enum SCP_CLIENT_STATES_E e;
|
||||
|
||||
if (trans == NULL || trans->status != TRANS_STATUS_UP)
|
||||
{
|
||||
e = SCP_CLIENT_STATE_NETWORK_ERR;
|
||||
}
|
||||
else if (!s_check_rem_and_log(trans->in_s, 6, "SCPV0 reply"))
|
||||
{
|
||||
trans->status = TRANS_STATUS_DOWN;
|
||||
e = SCP_CLIENT_STATE_NETWORK_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
int word1;
|
||||
int word2;
|
||||
int word3;
|
||||
in_uint16_be(trans->in_s, word1);
|
||||
in_uint16_be(trans->in_s, word2);
|
||||
in_uint16_be(trans->in_s, word3);
|
||||
|
||||
if (word1 == SCP_GW_AUTHENTICATION)
|
||||
{
|
||||
reply->is_gw_auth_response = 1;
|
||||
reply->auth_result = word2;
|
||||
reply->display = 0;
|
||||
guid_clear(&reply->guid);
|
||||
}
|
||||
else
|
||||
{
|
||||
reply->is_gw_auth_response = 0;
|
||||
reply->auth_result = word2;
|
||||
reply->display = word3;
|
||||
if (s_check_rem(trans->in_s, GUID_SIZE))
|
||||
{
|
||||
in_uint8a(trans->in_s, reply->guid.g, GUID_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
guid_clear(&reply->guid);
|
||||
}
|
||||
}
|
||||
|
||||
e = SCP_CLIENT_STATE_OK;
|
||||
|
||||
/* Reset the input stream for the next message */
|
||||
trans->header_size = 8;
|
||||
trans->extra_flags = 0;
|
||||
init_stream(trans->in_s, 0);
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* server API */
|
||||
|
||||
@ -265,7 +378,7 @@ scp_v0s_accept(struct trans *atrans, struct SCP_SESSION *session)
|
||||
scp_session_set_type(session, session_type);
|
||||
|
||||
/* reading username */
|
||||
if (!in_string16(in_s, buf, "username"))
|
||||
if (!in_string16(in_s, buf, "Session username"))
|
||||
{
|
||||
return SCP_SERVER_STATE_SIZE_ERR;
|
||||
}
|
||||
@ -276,7 +389,7 @@ scp_v0s_accept(struct trans *atrans, struct SCP_SESSION *session)
|
||||
}
|
||||
|
||||
/* reading password */
|
||||
if (!in_string16(in_s, buf, "passwd"))
|
||||
if (!in_string16(in_s, buf, "Session passwd"))
|
||||
{
|
||||
return SCP_SERVER_STATE_SIZE_ERR;
|
||||
}
|
||||
@ -297,10 +410,9 @@ scp_v0s_accept(struct trans *atrans, struct SCP_SESSION *session)
|
||||
in_uint16_be(in_s, height);
|
||||
scp_session_set_height(session, height);
|
||||
in_uint16_be(in_s, bpp);
|
||||
if (session_type == SCP_SESSION_TYPE_XORG && bpp != 24)
|
||||
if (session_type == SCP_SESSION_TYPE_XORG)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Setting bpp to 24 from %d for Xorg session", bpp);
|
||||
/* Client value is ignored */
|
||||
bpp = 24;
|
||||
}
|
||||
if (0 != scp_session_set_bpp(session, (tui8)bpp))
|
||||
@ -313,7 +425,7 @@ scp_v0s_accept(struct trans *atrans, struct SCP_SESSION *session)
|
||||
if (s_check_rem(in_s, 2))
|
||||
{
|
||||
/* reading domain */
|
||||
if (!in_string16(in_s, buf, "domain"))
|
||||
if (!in_string16(in_s, buf, "Session domain"))
|
||||
{
|
||||
return SCP_SERVER_STATE_SIZE_ERR;
|
||||
}
|
||||
@ -327,7 +439,7 @@ scp_v0s_accept(struct trans *atrans, struct SCP_SESSION *session)
|
||||
if (s_check_rem(in_s, 2))
|
||||
{
|
||||
/* reading program */
|
||||
if (!in_string16(in_s, buf, "program"))
|
||||
if (!in_string16(in_s, buf, "Session program"))
|
||||
{
|
||||
return SCP_SERVER_STATE_SIZE_ERR;
|
||||
}
|
||||
@ -341,7 +453,7 @@ scp_v0s_accept(struct trans *atrans, struct SCP_SESSION *session)
|
||||
if (s_check_rem(in_s, 2))
|
||||
{
|
||||
/* reading directory */
|
||||
if (!in_string16(in_s, buf, "directory"))
|
||||
if (!in_string16(in_s, buf, "Session directory"))
|
||||
{
|
||||
return SCP_SERVER_STATE_SIZE_ERR;
|
||||
}
|
||||
@ -369,7 +481,7 @@ scp_v0s_accept(struct trans *atrans, struct SCP_SESSION *session)
|
||||
{
|
||||
scp_session_set_type(session, SCP_GW_AUTHENTICATION);
|
||||
/* reading username */
|
||||
if (!in_string16(in_s, buf, "username"))
|
||||
if (!in_string16(in_s, buf, "Session username"))
|
||||
{
|
||||
return SCP_SERVER_STATE_SIZE_ERR;
|
||||
}
|
||||
@ -381,7 +493,7 @@ scp_v0s_accept(struct trans *atrans, struct SCP_SESSION *session)
|
||||
}
|
||||
|
||||
/* reading password */
|
||||
if (!in_string16(in_s, buf, "passwd"))
|
||||
if (!in_string16(in_s, buf, "Session passwd"))
|
||||
{
|
||||
return SCP_SERVER_STATE_SIZE_ERR;
|
||||
}
|
||||
@ -403,13 +515,14 @@ scp_v0s_accept(struct trans *atrans, struct SCP_SESSION *session)
|
||||
|
||||
/******************************************************************************/
|
||||
enum SCP_SERVER_STATES_E
|
||||
scp_v0s_allow_connection(struct trans *atrans, SCP_DISPLAY d, const tui8 *guid)
|
||||
scp_v0s_allow_connection(struct trans *atrans, SCP_DISPLAY d,
|
||||
const struct guid *guid)
|
||||
{
|
||||
int msg_size;
|
||||
struct stream *out_s;
|
||||
|
||||
out_s = trans_get_out_s(atrans, 0);
|
||||
msg_size = guid == 0 ? 14 : 14 + 16;
|
||||
msg_size = guid_is_set(guid) ? 14 + GUID_SIZE : 14;
|
||||
out_uint32_be(out_s, 0); /* version */
|
||||
out_uint32_be(out_s, msg_size); /* size */
|
||||
out_uint16_be(out_s, 3); /* cmd */
|
||||
@ -417,7 +530,7 @@ scp_v0s_allow_connection(struct trans *atrans, SCP_DISPLAY d, const tui8 *guid)
|
||||
out_uint16_be(out_s, d); /* data */
|
||||
if (msg_size > 14)
|
||||
{
|
||||
out_uint8a(out_s, guid, 16);
|
||||
out_uint8a(out_s, guid->g, GUID_SIZE);
|
||||
}
|
||||
s_mark_end(out_s);
|
||||
if (0 != trans_write_copy(atrans))
|
||||
|
@ -28,22 +28,59 @@
|
||||
#define LIBSCP_V0_H
|
||||
|
||||
#include "libscp.h"
|
||||
#include "guid.h"
|
||||
|
||||
/*TODO : Replace this (unused) function with something that can be used
|
||||
* by xrdp_mm.c and sesrun.c */
|
||||
#if 0
|
||||
/* client API */
|
||||
/**
|
||||
*
|
||||
* @brief connects to sesman using scp v0
|
||||
* @param c connection descriptor
|
||||
* @param s session descriptor
|
||||
* @param d display
|
||||
*
|
||||
|
||||
struct scp_v0_reply_type
|
||||
{
|
||||
/**
|
||||
* True if this is a reply to a gateway authentication request
|
||||
*/
|
||||
int is_gw_auth_response;
|
||||
|
||||
/**
|
||||
* Authentication result. PAM code for gateway request, boolean otherwise
|
||||
*/
|
||||
int auth_result;
|
||||
|
||||
/**
|
||||
* Display number for successful non-gateway requests
|
||||
*/
|
||||
int display;
|
||||
|
||||
/**
|
||||
* GUID for successful non-gateway requests
|
||||
*/
|
||||
struct guid guid;
|
||||
};
|
||||
|
||||
enum SCP_CLIENT_STATES_E
|
||||
scp_v0c_gateway_request(struct trans *atrans,
|
||||
const char *username,
|
||||
const char *password);
|
||||
|
||||
/*
|
||||
* Note client bpp is ignored by the sesman for Xorg sessions
|
||||
*/
|
||||
enum SCP_CLIENT_STATES_E
|
||||
scp_v0c_connect(struct SCP_CONNECTION *c, struct SCP_SESSION *s);
|
||||
#endif
|
||||
scp_v0c_create_session_request(struct trans *atrans,
|
||||
const char *username,
|
||||
const char *password,
|
||||
unsigned short code,
|
||||
unsigned short width,
|
||||
unsigned short height,
|
||||
unsigned short bpp,
|
||||
const char *domain,
|
||||
const char *shell,
|
||||
const char *directory,
|
||||
const char *client_ip);
|
||||
|
||||
int
|
||||
scp_v0c_reply_available(struct trans *atrans);
|
||||
|
||||
enum SCP_CLIENT_STATES_E
|
||||
scp_v0c_get_reply(struct trans *atrans, struct scp_v0_reply_type *reply);
|
||||
|
||||
/* server API */
|
||||
/**
|
||||
@ -63,7 +100,8 @@ scp_v0s_accept(struct trans *atrans, struct SCP_SESSION *s);
|
||||
*
|
||||
*/
|
||||
enum SCP_SERVER_STATES_E
|
||||
scp_v0s_allow_connection(struct trans *atrans, SCP_DISPLAY d, const tui8 *guid);
|
||||
scp_v0s_allow_connection(struct trans *atrans, SCP_DISPLAY d,
|
||||
const struct guid *guid);
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -82,7 +82,7 @@ scp_v0_process(struct trans *t, struct SCP_SESSION *s)
|
||||
if (s_item != 0)
|
||||
{
|
||||
display = s_item->display;
|
||||
g_memcpy(s->guid, s_item->guid, 16);
|
||||
s->guid = s_item->guid;
|
||||
if (0 != s->connection_description)
|
||||
{
|
||||
LOG( LOG_LEVEL_INFO, "++ reconnected session: username %s, "
|
||||
@ -105,10 +105,9 @@ scp_v0_process(struct trans *t, struct SCP_SESSION *s)
|
||||
|
||||
if (1 == access_login_allowed(s->username))
|
||||
{
|
||||
tui8 guid[16];
|
||||
struct guid guid = guid_new();
|
||||
|
||||
g_random((char *)guid, 16);
|
||||
scp_session_set_guid(s, guid);
|
||||
scp_session_set_guid(s, &guid);
|
||||
|
||||
if (0 != s->connection_description)
|
||||
{
|
||||
@ -153,7 +152,7 @@ scp_v0_process(struct trans *t, struct SCP_SESSION *s)
|
||||
}
|
||||
else
|
||||
{
|
||||
scp_v0s_allow_connection(t, display, s->guid);
|
||||
scp_v0s_allow_connection(t, display, &s->guid);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -779,8 +779,8 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
|
||||
}
|
||||
else if (type == SESMAN_SESSION_TYPE_XVNC)
|
||||
{
|
||||
char guid_str[64];
|
||||
g_bytes_to_hexstr(s->guid, 16, guid_str, 64);
|
||||
char guid_str[GUID_STR_SIZE];
|
||||
guid_to_str(&s->guid, guid_str);
|
||||
env_check_password_file(passwd_file, guid_str);
|
||||
xserver_params = list_create();
|
||||
xserver_params->auto_free = 1;
|
||||
@ -957,7 +957,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
|
||||
temp->item->data = data;
|
||||
g_strncpy(temp->item->connection_description, s->connection_description, 255); /* store client ip data */
|
||||
g_strncpy(temp->item->name, s->username, 255);
|
||||
g_memcpy(temp->item->guid, s->guid, 16);
|
||||
temp->item->guid = s->guid;
|
||||
|
||||
ltime = g_time1();
|
||||
localtime_r(<ime, &stime);
|
||||
|
@ -29,6 +29,7 @@
|
||||
#define SESSION_H
|
||||
|
||||
#include "libscp_types.h"
|
||||
#include "guid.h"
|
||||
|
||||
#define SESMAN_SESSION_TYPE_XRDP 1
|
||||
#define SESMAN_SESSION_TYPE_XVNC 2
|
||||
@ -76,7 +77,7 @@ struct session_item
|
||||
struct session_date disconnect_time;
|
||||
struct session_date idle_time;
|
||||
char connection_description[256];
|
||||
tui8 guid[16];
|
||||
struct guid guid;
|
||||
};
|
||||
|
||||
struct session_chain
|
||||
|
@ -41,7 +41,8 @@ xrdp_xcon_SOURCES = \
|
||||
xcon.c
|
||||
|
||||
xrdp_sesrun_LDADD = \
|
||||
$(top_builddir)/common/libcommon.la
|
||||
$(top_builddir)/common/libcommon.la \
|
||||
$(top_builddir)/sesman/libscp/libscp.la
|
||||
|
||||
xrdp_sestest_LDADD = \
|
||||
$(top_builddir)/common/libcommon.la \
|
||||
|
@ -53,7 +53,6 @@ int main(int argc, char **argv)
|
||||
//int end;
|
||||
int idx;
|
||||
//int sel;
|
||||
int sock;
|
||||
char *pwd;
|
||||
struct log_config *logging;
|
||||
|
||||
@ -128,21 +127,14 @@ int main(int argc, char **argv)
|
||||
|
||||
scp_init();
|
||||
|
||||
sock = g_tcp_socket();
|
||||
if (sock < 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "Socket open error, g_tcp_socket() failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
s = scp_session_create();
|
||||
t = scp_trans_create(sock);
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "Connecting to %s:%s)", serv, port);
|
||||
t = scp_connect(serv, port, NULL, NULL, NULL);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "Connecting to %s:%s with user %s (%s)", serv, port, user, pass);
|
||||
|
||||
if (0 != trans_connect(t, serv, port, 3000))
|
||||
if (t == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "trans_connect() error");
|
||||
LOG(LOG_LEVEL_ERROR, "scp_connect() error");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,9 @@
|
||||
#include "log.h"
|
||||
#include "tcp.h"
|
||||
#include "string_calls.h"
|
||||
#include "guid.h"
|
||||
|
||||
#include "libscp_connection.h"
|
||||
|
||||
#if !defined(PACKAGE_VERSION)
|
||||
#define PACKAGE_VERSION "???"
|
||||
@ -413,20 +416,6 @@ parse_program_args(int argc, char *argv[], struct session_params *sp,
|
||||
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
|
||||
*
|
||||
@ -437,11 +426,9 @@ out_string16(struct stream *s, const char *str)
|
||||
* 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)
|
||||
static enum SCP_CLIENT_STATES_E
|
||||
send_scpv0_auth_request(struct trans *t, 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"
|
||||
@ -452,110 +439,72 @@ send_scpv0_auth_request(int sck, const struct session_params *sp)
|
||||
/* 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);
|
||||
return scp_v0c_create_session_request(
|
||||
t, sp->username, sp->password, sp->session_code, sp->width, sp->height,
|
||||
sp->bpp, sp->domain, sp->shell, sp->directory, sp->client_ip);
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* 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
|
||||
* @param t SCP transport to receive reply on
|
||||
* @return 0 for success
|
||||
*/
|
||||
static int
|
||||
handle_scpv0_auth_reply(int sck)
|
||||
handle_scpv0_auth_reply(struct trans *t)
|
||||
{
|
||||
int result = 1;
|
||||
int packet_ok = 0;
|
||||
tbus wobj[1];
|
||||
int ocnt = 0;
|
||||
|
||||
struct stream *in_s;
|
||||
int rv = 1;
|
||||
|
||||
make_stream(in_s);
|
||||
init_stream(in_s, 8192);
|
||||
|
||||
if (tcp_force_recv(sck, in_s->data, 8) == 0)
|
||||
if (trans_get_wait_objs(t, wobj, &ocnt) != 0)
|
||||
{
|
||||
int version;
|
||||
int size;
|
||||
int code;
|
||||
int data;
|
||||
int display;
|
||||
|
||||
in_s->end = in_s->data + 8;
|
||||
in_uint32_be(in_s, version);
|
||||
in_uint32_be(in_s, size);
|
||||
if (version == 0 && size >= 14)
|
||||
LOG(LOG_LEVEL_ERROR, "Can't get wait object for sesman transport");
|
||||
}
|
||||
else
|
||||
{
|
||||
while (t->status == TRANS_STATUS_UP)
|
||||
{
|
||||
init_stream(in_s, 8192);
|
||||
if (tcp_force_recv(sck, in_s->data, size - 8) == 0)
|
||||
g_obj_wait(wobj, ocnt, NULL, 0, -1);
|
||||
if (trans_check_wait_objs(t) != 0)
|
||||
{
|
||||
in_s->end = in_s->data + (size - 8);
|
||||
LOG(LOG_LEVEL_ERROR, "sesman transport down");
|
||||
break;
|
||||
}
|
||||
|
||||
in_uint16_be(in_s, code);
|
||||
in_uint16_be(in_s, data);
|
||||
in_uint16_be(in_s, display);
|
||||
|
||||
if (code == 3)
|
||||
if (scp_v0c_reply_available(t))
|
||||
{
|
||||
struct scp_v0_reply_type msg;
|
||||
enum SCP_CLIENT_STATES_E e = scp_v0c_get_reply(t, &msg);
|
||||
if (e != SCP_CLIENT_STATE_OK)
|
||||
{
|
||||
packet_ok = 1;
|
||||
|
||||
if (data == 0)
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Error reading response from sesman [%s]",
|
||||
scp_client_state_to_str(e));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (msg.auth_result == 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>");
|
||||
}
|
||||
|
||||
char guid_str[GUID_STR_SIZE];
|
||||
g_printf("ok data=%d display=:%d GUID=%s\n",
|
||||
(int)data, display, guid_str);
|
||||
result = 0;
|
||||
msg.auth_result,
|
||||
msg.display,
|
||||
guid_to_str(&msg.guid, guid_str));
|
||||
}
|
||||
rv = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!packet_ok)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Corrupt reply packet");
|
||||
}
|
||||
free_stream(in_s);
|
||||
|
||||
return result;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@ -565,11 +514,12 @@ main(int argc, char **argv)
|
||||
const char *sesman_ini = XRDP_CFG_PATH "/sesman.ini";
|
||||
struct config_sesman *cfg = NULL;
|
||||
|
||||
int sck = -1;
|
||||
struct trans *t = NULL;
|
||||
enum SCP_CLIENT_STATES_E e;
|
||||
struct session_params sp;
|
||||
|
||||
struct log_config *logging;
|
||||
int status = 1;
|
||||
int rv = 1;
|
||||
|
||||
logging = log_config_init_for_console(LOG_LEVEL_WARNING,
|
||||
g_getenv("SESRUN_LOG_LEVEL"));
|
||||
@ -585,32 +535,30 @@ 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(sp.server, cfg->listen_port, NULL, NULL, NULL)))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "connect error - %s", g_get_strerror());
|
||||
}
|
||||
else
|
||||
{
|
||||
sck = g_tcp_socket();
|
||||
if (sck < 0)
|
||||
e = send_scpv0_auth_request(t, &sp);
|
||||
if (e != SCP_CLIENT_STATE_OK)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "socket error - %s", g_get_strerror());
|
||||
}
|
||||
else if (g_tcp_connect(sck, sp.server, cfg->listen_port) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "connect error - %s", g_get_strerror());
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Error sending create session to sesman [%s]",
|
||||
scp_client_state_to_str(e));
|
||||
rv = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
send_scpv0_auth_request(sck, &sp);
|
||||
status = handle_scpv0_auth_reply(sck);
|
||||
rv = handle_scpv0_auth_reply(t);
|
||||
}
|
||||
}
|
||||
|
||||
if (sck >= 0)
|
||||
{
|
||||
g_tcp_close(sck);
|
||||
trans_delete(t);
|
||||
}
|
||||
|
||||
g_memset(sp.password, '\0', sizeof(sp.password));
|
||||
config_free(cfg);
|
||||
log_end();
|
||||
|
||||
return status;
|
||||
return rv;
|
||||
}
|
||||
|
@ -46,7 +46,6 @@ int main(int argc, char **argv)
|
||||
int scnt;
|
||||
int idx;
|
||||
int sel;
|
||||
int sock;
|
||||
|
||||
logging = log_config_init_for_console(LOG_LEVEL_INFO, NULL);
|
||||
log_start_from_param(logging);
|
||||
@ -54,16 +53,9 @@ int main(int argc, char **argv)
|
||||
|
||||
scp_init();
|
||||
|
||||
sock = g_tcp_socket();
|
||||
if (sock < 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
s = scp_session_create();
|
||||
t = scp_trans_create(sock);
|
||||
|
||||
if (0 != trans_connect(t, "localhost", "3350", 3000))
|
||||
t = scp_connect("localhost", "3350", NULL, NULL, NULL);
|
||||
if (t == NULL)
|
||||
{
|
||||
g_printf("error connecting");
|
||||
return 1;
|
||||
|
@ -1717,10 +1717,10 @@ lib_mod_connect(struct vnc *v)
|
||||
if (error == 0)
|
||||
{
|
||||
init_stream(s, 8192);
|
||||
if (v->got_guid)
|
||||
if (guid_is_set(&v->guid))
|
||||
{
|
||||
char guid_str[64];
|
||||
g_bytes_to_hexstr(v->guid, 16, guid_str, 64);
|
||||
char guid_str[GUID_STR_SIZE];
|
||||
guid_to_str(&v->guid, guid_str);
|
||||
rfbHashEncryptBytes(s->data, guid_str);
|
||||
}
|
||||
else
|
||||
@ -2091,8 +2091,7 @@ lib_mod_set_param(struct vnc *v, const char *name, const char *value)
|
||||
}
|
||||
else if (g_strcasecmp(name, "guid") == 0)
|
||||
{
|
||||
v->got_guid = 1;
|
||||
g_memcpy(v->guid, value, 16);
|
||||
v->guid = *(struct guid *)value;
|
||||
}
|
||||
else if (g_strcasecmp(name, "disabled_encodings_mask") == 0)
|
||||
{
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "parse.h"
|
||||
#include "os_calls.h"
|
||||
#include "defines.h"
|
||||
#include "guid.h"
|
||||
|
||||
#define CURRENT_MOD_VER 4
|
||||
|
||||
@ -159,8 +160,7 @@ struct vnc
|
||||
struct vnc_clipboard_data *vc;
|
||||
int delay_ms;
|
||||
struct trans *trans;
|
||||
int got_guid;
|
||||
tui8 guid[16];
|
||||
struct guid guid;
|
||||
int suppress_output;
|
||||
unsigned int enabled_encodings_mask;
|
||||
/* Resizeable support */
|
||||
|
@ -12,6 +12,7 @@ AM_CPPFLAGS = \
|
||||
-DXRDP_SOCKET_PATH=\"${socketdir}\" \
|
||||
-I$(top_builddir) \
|
||||
-I$(top_srcdir)/common \
|
||||
-I$(top_srcdir)/sesman/libscp \
|
||||
-I$(top_srcdir)/libxrdp \
|
||||
$(IMLIB2_CFLAGS)
|
||||
|
||||
@ -61,6 +62,7 @@ xrdp_SOURCES = \
|
||||
|
||||
xrdp_LDADD = \
|
||||
$(top_builddir)/common/libcommon.la \
|
||||
$(top_builddir)/sesman/libscp/libscp.la \
|
||||
$(top_builddir)/libxrdp/libxrdp.la \
|
||||
$(IMLIB2_LIBS) \
|
||||
$(XRDP_EXTRA_LIBS)
|
||||
|
@ -149,6 +149,8 @@ int
|
||||
xrdp_wm_check_wait_objs(struct xrdp_wm *self);
|
||||
int
|
||||
xrdp_wm_set_login_state(struct xrdp_wm *self, enum wm_login_state login_state);
|
||||
void
|
||||
xrdp_wm_mod_connect_done(struct xrdp_wm *self, int status);
|
||||
|
||||
/* xrdp_process.c */
|
||||
struct xrdp_process *
|
||||
@ -418,7 +420,7 @@ struct xrdp_mm *
|
||||
xrdp_mm_create(struct xrdp_wm *owner);
|
||||
void
|
||||
xrdp_mm_delete(struct xrdp_mm *self);
|
||||
int
|
||||
void
|
||||
xrdp_mm_connect(struct xrdp_mm *self);
|
||||
int
|
||||
xrdp_mm_process_channel_data(struct xrdp_mm *self, tbus param1, tbus param2,
|
||||
@ -473,7 +475,7 @@ server_set_pointer_ex(struct xrdp_mod *mod, int x, int y,
|
||||
int
|
||||
server_palette(struct xrdp_mod *mod, int *palette);
|
||||
int
|
||||
server_msg(struct xrdp_mod *mod, char *msg, int code);
|
||||
server_msg(struct xrdp_mod *mod, const char *msg, int code);
|
||||
int
|
||||
server_is_term(struct xrdp_mod *mod);
|
||||
int
|
||||
|
1390
xrdp/xrdp_mm.c
1390
xrdp/xrdp_mm.c
File diff suppressed because it is too large
Load Diff
@ -27,6 +27,7 @@
|
||||
#include "xrdp_rail.h"
|
||||
#include "xrdp_constants.h"
|
||||
#include "fifo.h"
|
||||
#include "guid.h"
|
||||
|
||||
#define MAX_NR_CHANNELS 16
|
||||
#define MAX_CHANNEL_NAME 16
|
||||
@ -72,7 +73,7 @@ struct xrdp_mod
|
||||
int (*server_set_pointer)(struct xrdp_mod *v, int x, int y,
|
||||
char *data, char *mask);
|
||||
int (*server_palette)(struct xrdp_mod *v, int *palette);
|
||||
int (*server_msg)(struct xrdp_mod *v, char *msg, int code);
|
||||
int (*server_msg)(struct xrdp_mod *v, const char *msg, int code);
|
||||
int (*server_is_term)(struct xrdp_mod *v);
|
||||
int (*server_set_clip)(struct xrdp_mod *v, int x, int y, int cx, int cy);
|
||||
int (*server_reset_clip)(struct xrdp_mod *v);
|
||||
@ -295,13 +296,40 @@ struct xrdp_cache
|
||||
/* defined later */
|
||||
struct xrdp_enc_data;
|
||||
|
||||
/**
|
||||
* Stages we go through connecting to the session
|
||||
*/
|
||||
enum mm_connect_state
|
||||
{
|
||||
MMCS_CONNECT_TO_SESMAN,
|
||||
MMCS_PAM_AUTH,
|
||||
MMCS_SESSION_AUTH,
|
||||
MMCS_CONNECT_TO_SESSION,
|
||||
MMCS_CONNECT_TO_CHANSRV,
|
||||
MMCS_DONE
|
||||
};
|
||||
|
||||
struct xrdp_mm
|
||||
{
|
||||
struct xrdp_wm *wm; /* owner */
|
||||
int connected_state; /* true if connected to sesman else false */
|
||||
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_chansrv; /* true if chansrvport is set in xrdp.ini or using sesman */
|
||||
struct trans *sesman_trans; /* connection to sesman */
|
||||
int sesman_trans_up; /* true once connected to sesman */
|
||||
int delete_sesman_trans; /* boolean set when done with sesman connection */
|
||||
struct trans *pam_auth_trans; /* connection to pam authenticator */
|
||||
struct trans *chan_trans; /* connection to chansrv */
|
||||
|
||||
/* We can't delete transports while we're in a callback for that
|
||||
* transport, as this causes trans.c to reference undefined memory.
|
||||
* These flags mark transports as needing to be deleted when
|
||||
* we are definitely not in a transport callback */
|
||||
int delete_sesman_trans;
|
||||
int delete_pam_auth_trans;
|
||||
|
||||
struct list *login_names;
|
||||
struct list *login_values;
|
||||
/* mod vars */
|
||||
@ -310,12 +338,8 @@ struct xrdp_mm
|
||||
int (*mod_exit)(struct xrdp_mod *);
|
||||
struct xrdp_mod *mod; /* module interface */
|
||||
int display; /* 10 for :10.0, 11 for :11.0, etc */
|
||||
struct guid guid; /* GUID for the session, or all zeros */
|
||||
int code; /* 0=Xvnc session, 10=X11rdp session, 20=xorg driver mode */
|
||||
int sesman_controlled; /* true if this is a sesman session */
|
||||
struct trans *chan_trans; /* connection to chansrv */
|
||||
int chan_trans_up; /* true once connected to chansrv */
|
||||
int delete_chan_trans; /* boolean set when done with channel connection */
|
||||
int usechansrv; /* true if chansrvport is set in xrdp.ini or using sesman */
|
||||
struct xrdp_encoder *encoder;
|
||||
int cs2xr_cid_map[256];
|
||||
int xr2cr_cid_map[256];
|
||||
|
@ -1845,7 +1845,7 @@ xrdp_wm_process_channel_data(struct xrdp_wm *self,
|
||||
|
||||
if (self->mm->mod != 0)
|
||||
{
|
||||
if (self->mm->usechansrv)
|
||||
if (self->mm->use_chansrv)
|
||||
{
|
||||
rv = xrdp_mm_process_channel_data(self->mm, param1, param2,
|
||||
param3, param4);
|
||||
@ -1956,16 +1956,13 @@ xrdp_wm_login_state_changed(struct xrdp_wm *self)
|
||||
}
|
||||
else if (self->login_state == WMLS_START_CONNECT)
|
||||
{
|
||||
if (xrdp_mm_connect(self->mm) == 0)
|
||||
{
|
||||
xrdp_wm_set_login_state(self, WMLS_CONNECT_IN_PROGRESS);
|
||||
xrdp_wm_delete_all_children(self);
|
||||
self->dragging = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* we do nothing on connect error so far */
|
||||
}
|
||||
xrdp_wm_delete_all_children(self);
|
||||
self->dragging = 0;
|
||||
xrdp_wm_set_login_state(self, WMLS_CONNECT_IN_PROGRESS);
|
||||
|
||||
/* This calls back to xrdp_wm_mod_connect_done() when the
|
||||
* connect is finished*/
|
||||
xrdp_mm_connect(self->mm);
|
||||
}
|
||||
else if (self->login_state == WMLS_CLEANUP)
|
||||
{
|
||||
@ -1977,6 +1974,26 @@ xrdp_wm_login_state_changed(struct xrdp_wm *self)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* this gets called when the module manager finishes a connect
|
||||
* which was initiated by xrdp_mm_connect()
|
||||
*/
|
||||
void
|
||||
xrdp_wm_mod_connect_done(struct xrdp_wm *self, int status)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "status from xrdp_mm_connect() : %d", status);
|
||||
if (status == 0)
|
||||
{
|
||||
xrdp_wm_set_login_state(self, WMLS_CLEANUP);
|
||||
self->dragging = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
xrdp_wm_set_login_state(self, WMLS_INACTIVE);
|
||||
xrdp_wm_show_log(self);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* this is the log windows notify function */
|
||||
static int
|
||||
|
Loading…
x
Reference in New Issue
Block a user