Merge pull request #2251 from matt335672/refactor_ip_addr_handling

Refactor ip address handling
This commit is contained in:
matt335672 2022-05-19 10:59:26 +01:00 committed by GitHub
commit 6c4bdf7d5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 1036 additions and 578 deletions

View File

@ -78,6 +78,7 @@
#include "os_calls.h"
#include "string_calls.h"
#include "log.h"
#include "xrdp_constants.h"
/* for clearenv() */
#if defined(_WIN32)
@ -103,6 +104,22 @@ extern char **environ;
#define INADDR_NONE ((unsigned long)-1)
#endif
/**
* Type big enough to hold socket address information for any connecting type
*/
union sock_info
{
struct sockaddr sa;
struct sockaddr_in sa_in;
#if defined(XRDP_ENABLE_IPV6)
struct sockaddr_in6 sa_in6;
#endif
struct sockaddr_un sa_un;
#if defined(XRDP_ENABLE_VSOCK)
struct sockaddr_vm sa_vm;
#endif
};
/*****************************************************************************/
int
g_rm_temp_dir(void)
@ -669,6 +686,83 @@ g_sck_get_peer_cred(int sck, int *pid, int *uid, int *gid)
#endif
}
/*****************************************************************************/
static const char *
get_peer_description(const union sock_info *sock_info,
char *desc, unsigned int bytes)
{
if (bytes > 0)
{
int family = sock_info->sa.sa_family;
switch (family)
{
case AF_INET:
{
char ip[INET_ADDRSTRLEN];
const struct sockaddr_in *sa_in = &sock_info->sa_in;
if (inet_ntop(family, &sa_in->sin_addr,
ip, sizeof(ip)) != NULL)
{
g_snprintf(desc, bytes, "%s:%d", ip,
ntohs(sa_in->sin_port));
}
else
{
g_snprintf(desc, bytes, "<unknown AF_INET>:%d",
ntohs(sa_in->sin_port));
}
break;
}
#if defined(XRDP_ENABLE_IPV6)
case AF_INET6:
{
char ip[INET6_ADDRSTRLEN];
const struct sockaddr_in6 *sa_in6 = &sock_info->sa_in6;
if (inet_ntop(family, &sa_in6->sin6_addr,
ip, sizeof(ip)) != NULL)
{
g_snprintf(desc, bytes, "[%s]:%d", ip,
ntohs(sa_in6->sin6_port));
}
else
{
g_snprintf(desc, bytes, "[<unknown AF_INET6>]:%d",
ntohs(sa_in6->sin6_port));
}
break;
}
#endif
case AF_UNIX:
{
g_snprintf(desc, bytes, "AF_UNIX");
break;
}
#if defined(XRDP_ENABLE_VSOCK)
case AF_VSOCK:
{
const struct sockaddr_vm *sa_vm = &sock_info->sa_vm;
g_snprintf(desc, bytes, "AF_VSOCK:cid=%u/port=%u",
sa_vm->svm_cid, sa_vm->svm_port);
break;
}
#endif
default:
g_snprintf(desc, bytes, "Unknown address family %d", family);
break;
}
}
return desc;
}
/*****************************************************************************/
void
g_sck_close(int sck)
@ -676,77 +770,15 @@ g_sck_close(int sck)
#if defined(_WIN32)
closesocket(sck);
#else
char sockname[128];
union
{
struct sockaddr sock_addr;
struct sockaddr_in sock_addr_in;
#if defined(XRDP_ENABLE_IPV6)
struct sockaddr_in6 sock_addr_in6;
#endif
#if defined(XRDP_ENABLE_VSOCK)
struct sockaddr_vm sock_addr_vm;
#endif
} sock_info;
socklen_t sock_len = sizeof(sock_info);
char sockname[MAX_PEER_DESCSTRLEN];
union sock_info sock_info;
socklen_t sock_len = sizeof(sock_info);
memset(&sock_info, 0, sizeof(sock_info));
if (getsockname(sck, &sock_info.sock_addr, &sock_len) == 0)
if (getsockname(sck, &sock_info.sa, &sock_len) == 0)
{
switch (sock_info.sock_addr.sa_family)
{
case AF_INET:
{
struct sockaddr_in *sock_addr_in = &sock_info.sock_addr_in;
g_snprintf(sockname, sizeof(sockname), "AF_INET %s:%d",
inet_ntoa(sock_addr_in->sin_addr),
ntohs(sock_addr_in->sin_port));
break;
}
#if defined(XRDP_ENABLE_IPV6)
case AF_INET6:
{
char addr[48];
struct sockaddr_in6 *sock_addr_in6 = &sock_info.sock_addr_in6;
g_snprintf(sockname, sizeof(sockname), "AF_INET6 %s port %d",
inet_ntop(sock_addr_in6->sin6_family,
&sock_addr_in6->sin6_addr, addr, sizeof(addr)),
ntohs(sock_addr_in6->sin6_port));
break;
}
#endif
case AF_UNIX:
g_snprintf(sockname, sizeof(sockname), "AF_UNIX");
break;
#if defined(XRDP_ENABLE_VSOCK)
case AF_VSOCK:
{
struct sockaddr_vm *sock_addr_vm = &sock_info.sock_addr_vm;
g_snprintf(sockname,
sizeof(sockname),
"AF_VSOCK cid %d port %d",
sock_addr_vm->svm_cid,
sock_addr_vm->svm_port);
break;
}
#endif
default:
g_snprintf(sockname, sizeof(sockname), "unknown family %d",
sock_info.sock_addr.sa_family);
break;
}
get_peer_description(&sock_info, sockname, sizeof(sockname));
}
else
{
@ -1238,19 +1270,10 @@ g_sck_listen(int sck)
/*****************************************************************************/
int
g_tcp_accept(int sck)
g_sck_accept(int sck)
{
int ret;
char msg[256];
union
{
struct sockaddr sock_addr;
struct sockaddr_in sock_addr_in;
#if defined(XRDP_ENABLE_IPV6)
struct sockaddr_in6 sock_addr_in6;
#endif
} sock_info;
union sock_info sock_info;
socklen_t sock_len = sizeof(sock_info);
memset(&sock_info, 0, sock_len);
@ -1258,141 +1281,10 @@ g_tcp_accept(int sck)
if (ret > 0)
{
switch (sock_info.sock_addr.sa_family)
{
case AF_INET:
{
struct sockaddr_in *sock_addr_in = &sock_info.sock_addr_in;
g_snprintf(msg, sizeof(msg), "A connection received from %s port %d",
inet_ntoa(sock_addr_in->sin_addr),
ntohs(sock_addr_in->sin_port));
LOG(LOG_LEVEL_INFO, "%s", msg);
break;
}
#if defined(XRDP_ENABLE_IPV6)
case AF_INET6:
{
struct sockaddr_in6 *sock_addr_in6 = &sock_info.sock_addr_in6;
char addr[256];
inet_ntop(sock_addr_in6->sin6_family,
&sock_addr_in6->sin6_addr, addr, sizeof(addr));
g_snprintf(msg, sizeof(msg), "A connection received from %s port %d",
addr, ntohs(sock_addr_in6->sin6_port));
LOG(LOG_LEVEL_INFO, "%s", msg);
break;
}
#endif
}
}
return ret;
}
/*****************************************************************************/
int
g_sck_accept(int sck, char *addr, int addr_bytes, char *port, int port_bytes)
{
int ret;
char msg[256];
union
{
struct sockaddr sock_addr;
struct sockaddr_in sock_addr_in;
#if defined(XRDP_ENABLE_IPV6)
struct sockaddr_in6 sock_addr_in6;
#endif
struct sockaddr_un sock_addr_un;
#if defined(XRDP_ENABLE_VSOCK)
struct sockaddr_vm sock_addr_vm;
#endif
} sock_info;
socklen_t sock_len = sizeof(sock_info);
memset(&sock_info, 0, sock_len);
ret = accept(sck, (struct sockaddr *)&sock_info, &sock_len);
if (ret > 0)
{
switch (sock_info.sock_addr.sa_family)
{
case AF_INET:
{
struct sockaddr_in *sock_addr_in = &sock_info.sock_addr_in;
g_snprintf(addr, addr_bytes, "%s", inet_ntoa(sock_addr_in->sin_addr));
g_snprintf(port, port_bytes, "%d", ntohs(sock_addr_in->sin_port));
g_snprintf(msg, sizeof(msg),
"AF_INET connection received from %s port %s",
addr, port);
break;
}
#if defined(XRDP_ENABLE_IPV6)
case AF_INET6:
{
struct sockaddr_in6 *sock_addr_in6 = &sock_info.sock_addr_in6;
inet_ntop(sock_addr_in6->sin6_family,
&sock_addr_in6->sin6_addr, addr, addr_bytes);
g_snprintf(port, port_bytes, "%d", ntohs(sock_addr_in6->sin6_port));
g_snprintf(msg, sizeof(msg),
"AF_INET6 connection received from %s port %s",
addr, port);
break;
}
#endif
case AF_UNIX:
{
g_strncpy(addr, "", addr_bytes - 1);
g_strncpy(port, "", port_bytes - 1);
g_snprintf(msg, sizeof(msg), "AF_UNIX connection received");
break;
}
#if defined(XRDP_ENABLE_VSOCK)
case AF_VSOCK:
{
struct sockaddr_vm *sock_addr_vm = &sock_info.sock_addr_vm;
g_snprintf(addr, addr_bytes - 1, "%d", sock_addr_vm->svm_cid);
g_snprintf(port, addr_bytes - 1, "%d", sock_addr_vm->svm_port);
g_snprintf(msg,
sizeof(msg),
"AF_VSOCK connection received from cid: %s port: %s",
addr,
port);
break;
}
#endif
default:
{
g_strncpy(addr, "", addr_bytes - 1);
g_strncpy(port, "", port_bytes - 1);
g_snprintf(msg, sizeof(msg),
"connection received, unknown socket family %d",
sock_info.sock_addr.sa_family);
break;
}
}
LOG(LOG_LEVEL_INFO, "Socket %d: %s", ret, msg);
char description[MAX_PEER_DESCSTRLEN];
get_peer_description(&sock_info, description, sizeof(description));
LOG(LOG_LEVEL_INFO, "Socket %d: connection accepted from %s",
ret, description);
}
@ -1401,119 +1293,87 @@ g_sck_accept(int sck, char *addr, int addr_bytes, char *port, int port_bytes)
/*****************************************************************************/
void
g_write_connection_description(int rcv_sck, char *description, int bytes)
{
char *addr;
int port;
int ok;
union
{
struct sockaddr sock_addr;
struct sockaddr_in sock_addr_in;
#if defined(XRDP_ENABLE_IPV6)
struct sockaddr_in6 sock_addr_in6;
#endif
struct sockaddr_un sock_addr_un;
} sock_info;
ok = 0;
socklen_t sock_len = sizeof(sock_info);
memset(&sock_info, 0, sock_len);
#if defined(XRDP_ENABLE_IPV6)
addr = (char *)g_malloc(INET6_ADDRSTRLEN, 1);
#else
addr = (char *)g_malloc(INET_ADDRSTRLEN, 1);
#endif
if (getpeername(rcv_sck, (struct sockaddr *)&sock_info, &sock_len) == 0)
{
switch (sock_info.sock_addr.sa_family)
{
case AF_INET:
{
struct sockaddr_in *sock_addr_in = &sock_info.sock_addr_in;
g_snprintf(addr, INET_ADDRSTRLEN, "%s", inet_ntoa(sock_addr_in->sin_addr));
port = ntohs(sock_addr_in->sin_port);
ok = 1;
break;
}
#if defined(XRDP_ENABLE_IPV6)
case AF_INET6:
{
struct sockaddr_in6 *sock_addr_in6 = &sock_info.sock_addr_in6;
inet_ntop(sock_addr_in6->sin6_family,
&sock_addr_in6->sin6_addr, addr, INET6_ADDRSTRLEN);
port = ntohs(sock_addr_in6->sin6_port);
ok = 1;
break;
}
#endif
default:
{
break;
}
}
if (ok)
{
g_snprintf(description, bytes, "%s:%d - socket: %d", addr, port, rcv_sck);
}
}
if (!ok)
{
g_snprintf(description, bytes, "NULL:NULL - socket: %d", rcv_sck);
}
g_free(addr);
}
/*****************************************************************************/
const char *g_get_ip_from_description(const char *description,
char *ip, int bytes)
const char *
g_sck_get_peer_ip_address(int sck,
char *ip, unsigned int bytes,
unsigned short *port)
{
if (bytes > 0)
{
/* Look for the space after ip:port */
const char *end = g_strchr(description, ' ');
if (end == NULL)
int ok = 0;
union sock_info sock_info;
socklen_t sock_len = sizeof(sock_info);
memset(&sock_info, 0, sock_len);
if (getpeername(sck, (struct sockaddr *)&sock_info, &sock_len) == 0)
{
end = description; /* Means we've failed */
}
else
{
/* Look back for the last ':' */
while (end > description && *end != ':')
int family = sock_info.sa.sa_family;
switch (family)
{
--end;
case AF_INET:
{
struct sockaddr_in *sa_in = &sock_info.sa_in;
if (inet_ntop(family, &sa_in->sin_addr, ip, bytes) != NULL)
{
ok = 1;
if (port != NULL)
{
*port = ntohs(sa_in->sin_port);
}
}
break;
}
#if defined(XRDP_ENABLE_IPV6)
case AF_INET6:
{
struct sockaddr_in6 *sa_in6 = &sock_info.sa_in6;
if (inet_ntop(family, &sa_in6->sin6_addr, ip, bytes) != NULL)
{
ok = 1;
if (port != NULL)
{
*port = ntohs(sa_in6->sin6_port);
}
}
break;
}
#endif
default:
break;
}
}
if (end == description)
if (!ok)
{
g_snprintf(ip, bytes, "<unknown>");
}
else if ((end - description) < (bytes - 1))
{
g_strncpy(ip, description, end - description);
}
else
{
g_strncpy(ip, description, bytes - 1);
ip[0] = '\0';
}
}
return ip;
}
/*****************************************************************************/
const char *
g_sck_get_peer_description(int sck,
char *desc, unsigned int bytes)
{
union sock_info sock_info;
socklen_t sock_len = sizeof(sock_info);
memset(&sock_info, 0, sock_len);
if (getpeername(sck, (struct sockaddr *)&sock_info, &sock_len) == 0)
{
get_peer_description(&sock_info, desc, bytes);
}
return desc;
}
/*****************************************************************************/
void
g_sleep(int msecs)

View File

@ -84,9 +84,7 @@ int g_sck_vsock_bind(int sck, const char *port);
int g_sck_vsock_bind_address(int sck, const char *port, const char *address);
int g_tcp_bind_address(int sck, const char *port, const char *address);
int g_sck_listen(int sck);
int g_tcp_accept(int sck);
int g_sck_accept(int sck, char *addr, int addr_bytes,
char *port, int port_bytes);
int g_sck_accept(int sck);
int g_sck_recv(int sck, void *ptr, int len, int flags);
int g_sck_send(int sck, const void *ptr, int len, int flags);
int g_sck_last_error_would_block(int sck);
@ -94,18 +92,35 @@ int g_sck_socket_ok(int sck);
int g_sck_can_send(int sck, int millis);
int g_sck_can_recv(int sck, int millis);
int g_sck_select(int sck1, int sck2);
void g_write_connection_description(int rcv_sck,
char *description, int bytes);
/**
* Extracts the IP address from the connection description
* @param description Connection description (from
* g_write_connection_description())
* Gets the IP address of a connected peer, if it has one
* @param sck File descriptor for peer
* @param ip buffer to write IP address to
* @param bytes Size of ip buffer
* @param bytes Size of ip buffer. Should be at least MAX_IP_ADDRSTRLEN
* @param[out] portptr Optional variable to receive the port number
* @return Pointer to IP for convenience
*
* If the peer has no IP address (for example, it is a Unix Domain Socket),
* or the specified buffer is too small, the returned string is ""
*/
const char *g_get_ip_from_description(const char *description,
char *ip, int bytes);
const char *
g_sck_get_peer_ip_address(int sck,
char *ip, unsigned int bytes,
unsigned short *port);
/**
* Gets a description for a connected peer
* @param sck File descriptor for peer
* @param desc buffer to write description to
* @param bytes Size of description buffer. Should be at least
* MAX_PEER_DESCSTRLEN
* @return Pointer to desc for convenience
*
* Unlike g_sck_get_peer_ip_address(), this will return a
* description of some sort for any socket type.
*/
const char *
g_sck_get_peer_description(int sck,
char *desc, unsigned int bytes);
void g_sleep(int msecs);
tintptr g_create_wait_obj(const char *name);
tintptr g_create_wait_obj_from_socket(tintptr socket, int write);

View File

@ -921,6 +921,7 @@ g_strnjoin(char *dest, int dest_len, const char *joiner, const char *src[], int
return dest;
}
/*****************************************************************************/
int
g_bitmask_to_str(int bitmask, const struct bitmask_string bitdefs[],
char delim, char *buff, int bufflen)
@ -987,6 +988,7 @@ g_bitmask_to_str(int bitmask, const struct bitmask_string bitdefs[],
return rlen;
}
/*****************************************************************************/
int
g_str_to_bitmask(const char *str, const struct bitmask_string bitdefs[],
const char *delim, char *unrecognised, int unrecognised_len)
@ -1055,3 +1057,88 @@ g_str_to_bitmask(const char *str, const struct bitmask_string bitdefs[],
return mask;
}
/*****************************************************************************/
int
g_bitmask_to_charstr(int bitmask, const struct bitmask_char bitdefs[],
char *buff, int bufflen, int *rest)
{
int rlen = 0; /* Returned length */
if (bufflen <= 0) /* Caller error */
{
rlen = -1;
}
else
{
char *p = buff;
/* Find the last writeable character in the buffer */
const char *last = buff + (bufflen - 1);
const struct bitmask_char *b;
for (b = &bitdefs[0] ; b->c != '\0'; ++b)
{
if ((bitmask & b->mask) != 0)
{
if (p < last)
{
*p++ = b->c;
}
++rlen;
/* Remove the bit so we don't report it back */
bitmask &= ~b->mask;
}
}
*p = '\0';
if (rest != NULL)
{
*rest = bitmask;
}
}
return rlen;
}
/*****************************************************************************/
int
g_charstr_to_bitmask(const char *str, const struct bitmask_char bitdefs[],
char *unrecognised, int unrecognised_len)
{
int bitmask = 0;
const char *cp;
int j = 0;
if (str != NULL && bitdefs != NULL)
{
for (cp = str ; *cp != '\0' ; ++cp)
{
const struct bitmask_char *b;
char c = toupper(*cp);
for (b = &bitdefs[0] ; b->c != '\0'; ++b)
{
if (toupper(b->c) == c)
{
bitmask |= b->mask;
break;
}
}
if (b->c == '\0')
{
if (unrecognised != NULL && j < (unrecognised_len - 1))
{
unrecognised[j++] = *cp;
}
}
}
}
if (unrecognised != NULL && j < unrecognised_len)
{
unrecognised[j] = '\0';
}
return bitmask;
}

View File

@ -52,6 +52,21 @@ struct bitmask_string
#define BITMASK_STRING_END_OF_LIST { 0, NULL }
/**
* Map a bitmask to a char value
*
*
* This structure is used by g_bitmask_to_charstr() to specify the
* char for each bit in the bitmask
*/
struct bitmask_char
{
int mask;
char c;
};
#define BITMASK_CHAR_END_OF_LIST { 0, '\0' }
/**
* Processes a format string for general info
*
@ -158,6 +173,9 @@ g_get_display_num_from_display(const char *display_text);
/**
* Converts a bitmask into a string for output purposes
*
* Similar to g_bitmask_to_charstr(), but tokens are strings, separated
* by delimiters.
*
* @param bitmask Bitmask to convert
* @param bitdefs Definitions for strings for bits
* @param delim Delimiter to use between strings
@ -171,23 +189,67 @@ g_get_display_num_from_display(const char *display_text);
* a hexadecimal constant.
*/
int
g_bitmask_to_str(int bitmask, const struct bitmask_string[],
g_bitmask_to_str(int bitmask, const struct bitmask_string bitdefs[],
char delim, char *buff, int bufflen);
/***
* Converts a string containing a series of tokens to a bitmask.
*
* Similar to g_charstr_to_bitmask(), but tokens are strings, separated
* by delimiters.
*
* @param str Input string
* @param bitmask_string Array mapping tokens to bitmask values
* @param bitdefs Array mapping tokens to bitmask values
* @param delim Delimiter for tokens in str
* @param[out] unrecognised Buffer for any unrecognised tokens
* @param unrecognised_len Length of unrecognised including '\0';
* @return bitmask value for recognised tokens
*/
int
g_str_to_bitmask(const char *str, const struct bitmask_string[],
g_str_to_bitmask(const char *str, const struct bitmask_string bitdefs[],
const char *delim, char *unrecognised,
int unrecognised_len);
/**
* Converts a bitmask into a string for output purposes
*
* Similar to g_bitmask_to_str(), but tokens are individual characters, and
* there are no delimiters.
*
* @param bitmask Bitmask to convert
* @param bitdefs Definitions for strings for bits
* @param buff Output buff
* @param bufflen Length of buff, including terminator '`\0'
* @param[out] rest Any unused bits which weren't covered by bitdefs.
* May be NULL.
*
* @return Total length excluding terminator which would be written, as
* in snprintf(). Can be used to check for overflow
*
* @note Any undefined bits in the bitmask are appended to the output as
* a hexadecimal constant.
*/
int
g_bitmask_to_charstr(int bitmask, const struct bitmask_char bitdefs[],
char *buff, int bufflen, int *rest);
/***
* Converts a string containing a series of characters to a bitmask.
*
* Similar to g_str_to_bitmask(), but tokens are individual characters, and
* there are no delimiters.
*
* @param str Input string
* @param bitdefs Array mapping tokens to bitmask values
* @param delim Delimiter for tokens in str
* @param[out] unrecognised Buffer for any unrecognised tokens
* @param unrecognised_len Length of unrecognised including '\0';
* @return bitmask value for recognised tokens
*/
int
g_charstr_to_bitmask(const char *str, const struct bitmask_char bitdefs[],
char *unrecognised, int unrecognised_len);
int g_strlen(const char *text);
char *g_strchr(const char *text, int c);
char *g_strrchr(const char *text, int c);

View File

@ -330,9 +330,7 @@ trans_check_wait_objs(struct trans *self)
{
if (g_sck_can_recv(self->sck, 0))
{
in_sck = g_sck_accept(self->sck, self->addr, sizeof(self->addr),
self->port, sizeof(self->port));
in_sck = g_sck_accept(self->sck);
if (in_sck == -1)
{
if (g_tcp_last_error_would_block(self->sck))
@ -357,10 +355,6 @@ trans_check_wait_objs(struct trans *self)
in_trans->type1 = TRANS_TYPE_SERVER;
in_trans->status = TRANS_STATUS_UP;
in_trans->is_term = self->is_term;
g_strncpy(in_trans->addr, self->addr,
sizeof(self->addr) - 1);
g_strncpy(in_trans->port, self->port,
sizeof(self->port) - 1);
g_sck_set_non_blocking(in_sck);
if (self->trans_conn_in(self, in_trans) != 0)
{

View File

@ -104,8 +104,6 @@ struct trans
char *listen_filename;
tis_term is_term; /* used to test for exit */
struct stream *wait_s;
char addr[256];
char port[256];
int no_stream_init_on_data_in;
int extra_flags; /* user defined */
void *extra_data; /* user defined */

View File

@ -114,7 +114,7 @@ struct xrdp_client_info
int rdp5_performanceflags;
int brush_cache_code; /* 0 = no cache 1 = 8x8 standard cache
2 = arbitrary dimensions */
char connection_description[256];
int max_bpp;
int jpeg; /* non standard bitmap cache v2 cap */
int offscreen_support_level;
@ -146,8 +146,6 @@ struct xrdp_client_info
int pointer_flags; /* 0 color, 1 new, 2 no new */
int use_fast_path;
int require_credentials; /* when true, credentials *must* be passed on cmd line */
char client_addr[256];
char client_port[256];
int security_layer; /* 0 = rdp, 1 = tls , 2 = hybrid */
int multimon; /* 0 = deny , 1 = allow */
@ -191,6 +189,9 @@ struct xrdp_client_info
long ssl_protocols;
char *tls_ciphers;
char client_ip[MAX_PEER_ADDRSTRLEN];
char client_description[MAX_PEER_DESCSTRLEN];
int client_os_major;
int client_os_minor;
@ -207,6 +208,6 @@ struct xrdp_client_info
};
/* yyyymmdd of last incompatible change to xrdp_client_info */
#define CLIENT_INFO_CURRENT_VERSION 20220320
#define CLIENT_INFO_CURRENT_VERSION 20220428
#endif

View File

@ -37,7 +37,22 @@
* ms-erref.h
******************************************************************************/
/**
* Size of buffer including terminator for an IP address as returned
* by g_sck_get_peer_ip_address(). See POSIX INET6_ADDRSTRLEN
*/
#define MAX_PEER_ADDRSTRLEN 46
/**
* Size of buffer including terminator for a socket description, as
* returned by g_sck_get_peer_description()
* Currently the largest is an IPv6 address (INET6_ADDRSTRLEN), plus
* []:<port> characters
*/
#define MAX_PEER_DESCSTRLEN (46 + 2 + 1 + 5)
#define INFO_CLIENT_NAME_BYTES 32
/**
* Maximum length of a string including the mandatory null terminator
* [MS-RDPBCGR] TS_INFO_PACKET(2.2.1.11.1.1)

View File

@ -176,30 +176,34 @@ If set to \fI0\fR, idle sessions will never be disconnected by timeout.
This works only with xorgxrdp sessions. Moreover, xorgxrdp must be v0.2.9 or later.
.TP
\fBPolicy\fR=\fI[Default|UBD|UBI|UBC|UBDI|UBDC]\fR
\fBPolicy\fR=\fI[Default|Separate|{UBDI}]\fR
Session allocation policy. Used to decide when to allocate a
new session. Set to one of the following values:
.br
.br
\fBDefault\fR - session per <User,BitPerPixel>
.br
\fBUBD\fR - session per <User,BitPerPixel,DisplaySize>
.br
\fBUBI\fR - session per <User,BitPerPixel,IPAddr>
.br
\fBUBC\fR - session per <User,BitPerPixel,Connection>
.br
\fBUBDI\fR - session per <User,BitPerPixel,DisplaySize,IPAddr>
.br
\fBUBDC\fR - session per <User,BitPerPixel,DisplaySize,Connection>
.br
.RS
.HP 12
\fBDefault\fR - Currently the same as "UB" for all session types
.HP 12
\fBSeparate\fR - All sessions are separate. Sessions can never be rejoined,
and will need to be cleaned up manually, or automatically by setting other
sesman options.
.P
Alternatively combine one-or-more of the following options
.HP 4
\fBU\fR - Sessions are separated per user
.HP 4
\fBB\fR - Sessions are separated by bits-per-pixel
.HP 4
\fBD\fR - Sessions are separated by initial display size
.HP 4
\fBI\fR - Sessions are separated by IP address
.RE
.br
Note that the \fBUser\fR and \fBBitPerPixel\fR criteria cannot be turned
.IP
Note that the \fBU\fR and \fBB\fR criteria cannot be turned
off. \fBDisplaySize\fR refers to the initial geometry of a connection,
as actual display sizes can change dynamically.
.br
.SH "SECURITY"
Following parameters can be used in the \fB[Security]\fR section.

View File

@ -217,7 +217,7 @@ int
scp_send_gateway_request(struct trans *trans,
const char *username,
const char *password,
const char *connection_description)
const char *ip_addr)
{
int rv;
@ -227,7 +227,7 @@ scp_send_gateway_request(struct trans *trans,
"sss",
username,
password,
connection_description);
ip_addr);
/* Wipe the output buffer to remove the password */
libipm_msg_out_erase(trans);
@ -241,13 +241,13 @@ int
scp_get_gateway_request(struct trans *trans,
const char **username,
const char **password,
const char **connection_description)
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,
connection_description);
ip_addr);
}
/*****************************************************************************/
@ -290,7 +290,7 @@ scp_send_create_session_request(struct trans *trans,
unsigned char bpp,
const char *shell,
const char *directory,
const char *connection_description)
const char *ip_addr)
{
int rv = libipm_msg_out_simple_send(
trans,
@ -304,7 +304,7 @@ scp_send_create_session_request(struct trans *trans,
bpp,
shell,
directory,
connection_description);
ip_addr);
/* Wipe the output buffer to remove the password */
libipm_msg_out_erase(trans);
@ -324,7 +324,7 @@ scp_get_create_session_request(struct trans *trans,
unsigned char *bpp,
const char **shell,
const char **directory,
const char **connection_description)
const char **ip_addr)
{
/* Intermediate values */
uint8_t i_type;
@ -346,7 +346,7 @@ scp_get_create_session_request(struct trans *trans,
&i_bpp,
shell,
directory,
connection_description);
ip_addr);
if (rv == 0)
{
@ -475,7 +475,7 @@ scp_send_list_sessions_response(
info->bpp,
info->start_time,
info->username,
info->connection_description);
info->start_ip_addr);
}
return rv;
@ -512,7 +512,7 @@ scp_get_list_sessions_response(
uint8_t i_bpp;
int64_t i_start_time;
char *i_username;
char *i_connection_description;
char *i_start_ip_addr;
rv = libipm_msg_in_parse(
trans,
@ -525,7 +525,7 @@ scp_get_list_sessions_response(
&i_bpp,
&i_start_time,
&i_username,
&i_connection_description);
&i_start_ip_addr);
if (rv == 0)
{
@ -533,7 +533,7 @@ scp_get_list_sessions_response(
* structure result, and the strings it contains */
unsigned int len = sizeof(struct scp_session_info) +
g_strlen(i_username) + 1 +
g_strlen(i_connection_description) + 1;
g_strlen(i_start_ip_addr) + 1;
if ((p = (struct scp_session_info *)g_malloc(len, 1)) == NULL)
{
*status = E_SCP_LS_NO_MEMORY;
@ -543,7 +543,7 @@ 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->connection_description =
p->start_ip_addr =
p->username + g_strlen(i_username) + 1;
/* Copy the data over */
@ -555,8 +555,7 @@ scp_get_list_sessions_response(
p->bpp = i_bpp;
p->start_time = i_start_time;
g_strcpy(p->username, i_username);
g_strcpy(p->connection_description,
i_connection_description);
g_strcpy(p->start_ip_addr, i_start_ip_addr);
}
}
}

View File

@ -177,7 +177,7 @@ scp_msg_in_reset(struct trans *trans);
* @param trans SCP transport
* @param username Username
* @param password Password
* @param connection_description Description of the connection
* @param ip_addr IP address for the client (or "" if not known)
* @return != 0 for error
*
* Server replies with E_SCP_GATEWAY_RESPONSE
@ -186,7 +186,7 @@ int
scp_send_gateway_request(struct trans *trans,
const char *username,
const char *password,
const char *connection_description);
const char *ip_addr);
/**
* Parse an incoming E_SCP_GATEWAY_REQUEST message (SCP server)
@ -194,14 +194,14 @@ scp_send_gateway_request(struct trans *trans,
* @param trans SCP transport
* @param[out] username Username
* @param[out] password Password
* @param[out] connection_description Description of the connection
* @param[out] ip_addr IP address for the client. May be ""
* @return != 0 for error
*/
int
scp_get_gateway_request(struct trans *trans,
const char **username,
const char **password,
const char **connection_description);
const char **ip_addr);
/**
* Send an E_SCP_GATEWAY_RESPONSE (SCP server)
@ -239,7 +239,7 @@ scp_get_gateway_response(struct trans *trans,
* @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 connection_description Description of the connection
* @param ip_addr IP address for the client (or "" if not known)
* @return != 0 for error
*
* Server replies with E_SCP_CREATE_SESSION_RESPONSE
@ -254,7 +254,7 @@ scp_send_create_session_request(struct trans *trans,
unsigned char bpp,
const char *shell,
const char *directory,
const char *connection_description);
const char *ip_addr);
/**
@ -269,7 +269,7 @@ scp_send_create_session_request(struct trans *trans,
* @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] connection_description Description of the connection
* @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
@ -285,7 +285,7 @@ scp_get_create_session_request(struct trans *trans,
unsigned char *bpp,
const char **shell,
const char **directory,
const char **connection_description);
const char **ip_addr);
/**
* Send an E_SCP_CREATE_SESSION_RESPONSE (SCP server)

View File

@ -58,7 +58,7 @@ struct scp_session_info
unsigned char bpp; ///< Session bits-per-pixel
time_t start_time; ///< When sesion was created
char *username; ///< Username for session
char *connection_description; ///< Initial connection to session
char *start_ip_addr; ///< IP address of starting client
};

View File

@ -360,7 +360,6 @@ struct xrdp_rdp *
xrdp_rdp_create(struct xrdp_session *session, struct trans *trans)
{
struct xrdp_rdp *self = (struct xrdp_rdp *)NULL;
int bytes;
LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_rdp_create");
self = (struct xrdp_rdp *)g_malloc(sizeof(struct xrdp_rdp), 1);
@ -378,10 +377,13 @@ xrdp_rdp_create(struct xrdp_session *session, struct trans *trans)
self->client_info.cache3_entries = 262;
self->client_info.cache3_size = 4096;
/* load client ip info */
bytes = sizeof(self->client_info.connection_description) - 1;
g_write_connection_description(trans->sck,
self->client_info.connection_description,
bytes);
g_sck_get_peer_ip_address(trans->sck,
self->client_info.client_ip,
sizeof(self->client_info.client_ip),
NULL);
g_sck_get_peer_description(trans->sck,
self->client_info.client_description,
sizeof(self->client_info.client_description));
self->mppc_enc = mppc_enc_new(PROTO_RDP_50);
#if defined(XRDP_NEUTRINORDP)
self->rfx_enc = rfx_context_new();
@ -914,6 +916,7 @@ int
xrdp_rdp_incoming(struct xrdp_rdp *self)
{
struct xrdp_iso *iso;
iso = self->sec_layer->mcs_layer->iso_layer;
if (xrdp_sec_incoming(self->sec_layer) != 0)
@ -924,18 +927,13 @@ xrdp_rdp_incoming(struct xrdp_rdp *self)
self->mcs_channel = self->sec_layer->mcs_layer->userid +
MCS_USERCHANNEL_BASE;
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_rdp->mcs_channel %d", self->mcs_channel);
g_strncpy(self->client_info.client_addr, iso->trans->addr,
sizeof(self->client_info.client_addr) - 1);
g_strncpy(self->client_info.client_port, iso->trans->port,
sizeof(self->client_info.client_port) - 1);
/* log TLS version and cipher of TLS connections */
if (iso->selectedProtocol > PROTOCOL_RDP)
{
LOG(LOG_LEVEL_INFO,
"TLS connection established from %s port %s: %s with cipher %s",
self->client_info.client_addr,
self->client_info.client_port,
"TLS connection established from %s %s with cipher %s",
self->client_info.client_description,
iso->trans->ssl_protocol,
iso->trans->cipher_name);
}
@ -952,11 +950,8 @@ xrdp_rdp_incoming(struct xrdp_rdp *self)
/* default */ "unknown";
LOG(LOG_LEVEL_INFO,
"Non-TLS connection established from %s port %s: "
"with security level : %s",
self->client_info.client_addr,
self->client_info.client_port,
security_level);
"Non-TLS connection established from %s with security level : %s",
self->client_info.client_description, security_level);
}
return 0;

View File

@ -268,10 +268,9 @@ lxrdp_connect(struct mod *mod)
}
#endif
LOG(LOG_LEVEL_ERROR, "NeutrinoRDP proxy connection: status [Failed],"
" RDP client [%s:%s], RDP server [%s:%d], RDP server username [%s],"
" RDP client [%s], RDP server [%s:%d], RDP server username [%s],"
" xrdp pamusername [%s], xrdp process id [%d]",
mod->client_info.client_addr,
mod->client_info.client_port,
mod->client_info.client_description,
mod->inst->settings->hostname,
mod->inst->settings->port,
mod->inst->settings->username,
@ -282,10 +281,9 @@ lxrdp_connect(struct mod *mod)
else
{
LOG(LOG_LEVEL_INFO, "NeutrinoRDP proxy connection: status [Success],"
" RDP client [%s:%s], RDP server [%s:%d], RDP server username [%s],"
" RDP client [%s], RDP server [%s:%d], RDP server username [%s],"
" xrdp pamusername [%s], xrdp process id [%d]",
mod->client_info.client_addr,
mod->client_info.client_port,
mod->client_info.client_description,
mod->inst->settings->hostname,
mod->inst->settings->port,
mod->inst->settings->username,
@ -531,10 +529,9 @@ lxrdp_end(struct mod *mod)
LOG_DEVEL(LOG_LEVEL_DEBUG, "lxrdp_end:");
LOG(LOG_LEVEL_INFO, "NeutrinoRDP proxy connection: status [Disconnect],"
" RDP client [%s:%s], RDP server [%s:%d], RDP server username [%s],"
" RDP client [%s], RDP server [%s:%d], RDP server username [%s],"
" xrdp pamusername [%s], xrdp process id [%d]",
mod->client_info.client_addr,
mod->client_info.client_port,
mod->client_info.client_description,
mod->inst->settings->hostname,
mod->inst->settings->port,
mod->inst->settings->username,

View File

@ -32,11 +32,13 @@
* @brief Validates user's password
* @param user user's login name
* @param pass user's password
* @param client_ip IP address of connecting client (or ""/NULL if not known)
* @return non-zero handle on success, 0 on failure
*
*/
long
auth_userpass(const char *user, const char *pass, int *errorcode);
auth_userpass(const char *user, const char *pass,
const char *client_ip, int *errorcode);
/**
*

View File

@ -37,6 +37,81 @@
#include "chansrv/chansrv_common.h"
#include "scp.h"
static const struct bitmask_char policy_bits[] =
{
{ SESMAN_CFG_SESS_POLICY_U, 'U' },
{ SESMAN_CFG_SESS_POLICY_B, 'B' },
{ SESMAN_CFG_SESS_POLICY_D, 'D' },
{ SESMAN_CFG_SESS_POLICY_I, 'I' },
BITMASK_CHAR_END_OF_LIST
};
/***************************************************************************//**
* Parse a session allocation policy string
*/
static unsigned int
parse_policy_string(const char *value)
{
unsigned int rv;
char unrecognised[16];
if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_DFLT_S))
{
rv = SESMAN_CFG_SESS_POLICY_DEFAULT;
}
else if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_SEP_S))
{
rv = SESMAN_CFG_SESS_POLICY_SEPARATE;
}
else
{
unrecognised[0] = '\0';
rv = g_charstr_to_bitmask(value, policy_bits, unrecognised,
sizeof(unrecognised));
if (unrecognised[0] != '\0')
{
LOG(LOG_LEVEL_WARNING, "Character(s) '%s' in the session"
" allocation policy are not recognised", unrecognised);
if (g_strchr(unrecognised, 'C') != NULL ||
g_strchr(unrecognised, 'c') != NULL)
{
/* Change from xrdp v0.9.x */
LOG(LOG_LEVEL_WARNING, "Character 'C' is no longer used"
" in session allocation policies - use '%s'",
SESMAN_CFG_SESS_POLICY_SEP_S);
}
}
}
return rv;
}
/******************************************************************************/
int
config_output_policy_string(unsigned int value,
char *buff, unsigned int bufflen)
{
int rv = 0;
if (bufflen > 0)
{
if (value & SESMAN_CFG_SESS_POLICY_DEFAULT)
{
rv = g_snprintf(buff, bufflen, "Default");
}
else if (value & SESMAN_CFG_SESS_POLICY_SEPARATE)
{
rv = g_snprintf(buff, bufflen, "Separate");
}
else
{
rv = g_bitmask_to_charstr(value, policy_bits, buff, bufflen, NULL);
}
}
return rv;
}
/***************************************************************************//**
*
* @brief Reads sesman [global] configuration section
@ -295,7 +370,8 @@ config_read_sessions(int file, struct config_sessions *se, struct list *param_n,
struct list *param_v)
{
int i;
char *buf;
const char *buf;
const char *value;
list_clear(param_v);
list_clear(param_n);
@ -306,70 +382,43 @@ config_read_sessions(int file, struct config_sessions *se, struct list *param_n,
se->max_idle_time = 0;
se->max_disc_time = 0;
se->kill_disconnected = 0;
se->policy = SESMAN_CFG_SESS_POLICY_DFLT;
se->policy = SESMAN_CFG_SESS_POLICY_DEFAULT;
file_read_section(file, SESMAN_CFG_SESSIONS, param_n, param_v);
for (i = 0; i < param_n->count; i++)
{
buf = (char *)list_get_item(param_n, i);
buf = (const char *)list_get_item(param_n, i);
value = (const char *)list_get_item(param_v, i);
if (0 == g_strcasecmp(buf, SESMAN_CFG_SESS_X11DISPLAYOFFSET))
{
se->x11_display_offset = g_atoi((char *)list_get_item(param_v, i));
se->x11_display_offset = g_atoi(value);
}
if (0 == g_strcasecmp(buf, SESMAN_CFG_SESS_MAX))
else if (0 == g_strcasecmp(buf, SESMAN_CFG_SESS_MAX))
{
se->max_sessions = g_atoi((char *)list_get_item(param_v, i));
se->max_sessions = g_atoi(value);
}
if (0 == g_strcasecmp(buf, SESMAN_CFG_SESS_KILL_DISC))
else if (0 == g_strcasecmp(buf, SESMAN_CFG_SESS_KILL_DISC))
{
se->kill_disconnected = g_text2bool((char *)list_get_item(param_v, i));
se->kill_disconnected = g_text2bool(value);
}
if (0 == g_strcasecmp(buf, SESMAN_CFG_SESS_IDLE_LIMIT))
else if (0 == g_strcasecmp(buf, SESMAN_CFG_SESS_IDLE_LIMIT))
{
se->max_idle_time = g_atoi((char *)list_get_item(param_v, i));
se->max_idle_time = g_atoi(value);
}
if (0 == g_strcasecmp(buf, SESMAN_CFG_SESS_DISC_LIMIT))
else if (0 == g_strcasecmp(buf, SESMAN_CFG_SESS_DISC_LIMIT))
{
se->max_disc_time = g_atoi((char *)list_get_item(param_v, i));
se->max_disc_time = g_atoi(value);
}
if (0 == g_strcasecmp(buf, SESMAN_CFG_SESS_POLICY_S))
else if (0 == g_strcasecmp(buf, SESMAN_CFG_SESS_POLICY_S))
{
char *value = (char *)list_get_item(param_v, i);
if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_DFLT_S))
{
se->policy = SESMAN_CFG_SESS_POLICY_DFLT;
}
else if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_UBD_S))
{
se->policy = SESMAN_CFG_SESS_POLICY_UBD;
}
else if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_UBI_S))
{
se->policy = SESMAN_CFG_SESS_POLICY_UBI;
}
else if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_UBC_S))
{
se->policy = SESMAN_CFG_SESS_POLICY_UBC;
}
else if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_UBDI_S))
{
se->policy = SESMAN_CFG_SESS_POLICY_UBDI;
}
else if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_UBDC_S))
{
se->policy = SESMAN_CFG_SESS_POLICY_UBDC;
}
else /* silently ignore typos */
{
se->policy = SESMAN_CFG_SESS_POLICY_DFLT;
}
se->policy = parse_policy_string(value);
}
}
@ -570,6 +619,7 @@ config_dump(struct config_sesman *config)
struct config_security *sc;
se = &(config->sess);
sc = &(config->sec);
char policy_s[64];
/* Global sesman configuration */
g_writeln("Filename: %s", config->sesman_ini);
@ -583,13 +633,15 @@ config_dump(struct config_sesman *config)
(config->auth_file_path ? config->auth_file_path : "disabled"));
/* Session configuration */
config_output_policy_string(se->policy, policy_s, sizeof(policy_s));
g_writeln("Session configuration:");
g_writeln(" MaxSessions: %d", se->max_sessions);
g_writeln(" X11DisplayOffset: %d", se->x11_display_offset);
g_writeln(" KillDisconnected: %d", se->kill_disconnected);
g_writeln(" IdleTimeLimit: %d", se->max_idle_time);
g_writeln(" DisconnectedTimeLimit: %d", se->max_disc_time);
g_writeln(" Policy: %d", se->policy);
g_writeln(" Policy: %s", policy_s);
/* Security configuration */
g_writeln("Security configuration:");

View File

@ -72,27 +72,18 @@
#define SESMAN_CFG_SESS_POLICY_S "Policy"
#define SESMAN_CFG_SESS_POLICY_DFLT_S "Default"
#define SESMAN_CFG_SESS_POLICY_UBD_S "UBD"
#define SESMAN_CFG_SESS_POLICY_UBI_S "UBI"
#define SESMAN_CFG_SESS_POLICY_UBC_S "UBC"
#define SESMAN_CFG_SESS_POLICY_UBDI_S "UBDI"
#define SESMAN_CFG_SESS_POLICY_UBDC_S "UBDC"
#define SESMAN_CFG_SESS_POLICY_SEP_S "Separate"
enum SESMAN_CFG_SESS_POLICY_BITS
{
SESMAN_CFG_SESS_POLICY_D = 0x01,
SESMAN_CFG_SESS_POLICY_I = 0x02,
SESMAN_CFG_SESS_POLICY_C = 0x04
};
enum SESMAN_CFG_SESS_POLICY
{
SESMAN_CFG_SESS_POLICY_DFLT = 0,
SESMAN_CFG_SESS_POLICY_UBD = SESMAN_CFG_SESS_POLICY_D,
SESMAN_CFG_SESS_POLICY_UBI = SESMAN_CFG_SESS_POLICY_I,
SESMAN_CFG_SESS_POLICY_UBC = SESMAN_CFG_SESS_POLICY_C,
SESMAN_CFG_SESS_POLICY_UBDI = SESMAN_CFG_SESS_POLICY_D | SESMAN_CFG_SESS_POLICY_I,
SESMAN_CFG_SESS_POLICY_UBDC = SESMAN_CFG_SESS_POLICY_D | SESMAN_CFG_SESS_POLICY_C
/* If these two are set, they override everything else */
SESMAN_CFG_SESS_POLICY_DEFAULT = (1 << 0),
SESMAN_CFG_SESS_POLICY_SEPARATE = (1 << 1),
/* Configuration bits */
SESMAN_CFG_SESS_POLICY_U = (1 << 2),
SESMAN_CFG_SESS_POLICY_B = (1 << 3),
SESMAN_CFG_SESS_POLICY_D = (1 << 4),
SESMAN_CFG_SESS_POLICY_I = (1 << 5)
};
/**
@ -180,7 +171,7 @@ struct config_sessions
* @var policy
* @brief session allocation policy
*/
enum SESMAN_CFG_SESS_POLICY policy;
unsigned int policy;
};
/**
@ -304,4 +295,16 @@ config_dump(struct config_sesman *config);
void
config_free(struct config_sesman *cs);
/**
* Converts a session allocation Policy value to a strin
* @param value - Session allocation policy value
* @param buff - Buffer for result
* @param bufflen - Length of buffer
* @return Length of string that would be required without a terminator
* to write the whole output (like snprintf())
*/
int
config_output_policy_string(unsigned int value,
char *buff, unsigned int bufflen);
#endif

View File

@ -41,27 +41,19 @@
* Logs an authentication failure message
*
* @param username Username
* @param connection_description Connection details
* @param ip_addr IP address, if known
*
* The message is intended for use by fail2ban. Make changes with care.
*/
static void
log_authfail_message(const char *username, const char *connection_description)
log_authfail_message(const char *username, const char *ip_addr)
{
char ip[64];
const char *ipp;
if (connection_description != NULL &&
connection_description[0] != '\0')
if (ip_addr == NULL || ip_addr[0] == '\0')
{
g_get_ip_from_description(connection_description, ip, sizeof(ip));
ipp = ip;
}
else
{
ipp = "unknown";
ip_addr = "unknown";
}
LOG(LOG_LEVEL_INFO, "AUTHFAIL: user=%s ip=%s time=%d",
username, ipp, g_time1());
username, ip_addr, g_time1());
}
/******************************************************************************/
@ -72,10 +64,9 @@ process_gateway_request(struct trans *trans)
int rv;
const char *username;
const char *password;
const char *connection_description;
const char *ip_addr;
rv = scp_get_gateway_request(trans, &username, &password,
&connection_description);
rv = scp_get_gateway_request(trans, &username, &password, &ip_addr);
if (rv == 0)
{
int errorcode = 0;
@ -84,7 +75,7 @@ process_gateway_request(struct trans *trans)
LOG(LOG_LEVEL_INFO, "Received authentication request for user: %s",
username);
data = auth_userpass(username, password, &errorcode);
data = auth_userpass(username, password, ip_addr, &errorcode);
if (data)
{
if (1 == access_login_allowed(username))
@ -103,7 +94,7 @@ process_gateway_request(struct trans *trans)
}
else
{
log_authfail_message(username, connection_description);
log_authfail_message(username, ip_addr);
}
rv = scp_send_gateway_response(trans, errorcode);
auth_end(data);
@ -128,7 +119,7 @@ process_create_session_request(struct trans *trans)
trans,
&sp.username, &password,
&sp.type, &sp.width, &sp.height, &sp.bpp,
&sp.shell, &sp.directory, &sp.connection_description);
&sp.shell, &sp.directory, &sp.ip_addr);
if (rv == 0)
{
@ -142,7 +133,7 @@ process_create_session_request(struct trans *trans)
SCP_SESSION_TYPE_TO_STR(sp.type),
sp.username);
data = auth_userpass(sp.username, password, &errorcode);
data = auth_userpass(sp.username, password, sp.ip_addr, &errorcode);
if (data)
{
s_item = session_get_bydata(&sp);
@ -150,12 +141,11 @@ process_create_session_request(struct trans *trans)
{
display = s_item->display;
guid = s_item->guid;
if (sp.connection_description[0] != '\0')
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.connection_description);
sp.username, display, s_item->pid, sp.ip_addr);
}
else
{
@ -172,12 +162,11 @@ process_create_session_request(struct trans *trans)
if (1 == access_login_allowed(sp.username))
{
if (sp.connection_description[0] != '\0')
if (sp.ip_addr[0] != '\0')
{
LOG(LOG_LEVEL_INFO,
"++ created session (access granted): "
"username %s, ip %s", sp.username,
sp.connection_description);
"username %s, ip %s", sp.username, sp.ip_addr);
}
else
{
@ -196,7 +185,7 @@ process_create_session_request(struct trans *trans)
}
else
{
log_authfail_message(sp.username, sp.connection_description);
log_authfail_message(sp.username, sp.ip_addr);
}
if (do_auth_end)
@ -230,7 +219,7 @@ process_list_sessions_request(struct trans *trans)
LOG(LOG_LEVEL_INFO,
"Received request to list sessions for user %s", username);
data = auth_userpass(username, password, &errorcode);
data = auth_userpass(username, password, NULL, &errorcode);
if (data)
{
struct scp_session_info *info = NULL;

View File

@ -69,13 +69,20 @@ DisconnectedTimeLimit=0
IdleTimeLimit=0
;; Policy - session allocation policy
; Type: enum [ "Default" | "UBD" | "UBI" | "UBC" | "UBDI" | "UBDC" ]
; "Default" session per <User,BitPerPixel>
; "UBD" session per <User,BitPerPixel,DisplaySize>
; "UBI" session per <User,BitPerPixel,IPAddr>
; "UBC" session per <User,BitPerPixel,Connection>
; "UBDI" session per <User,BitPerPixel,DisplaySize,IPAddr>
; "UBDC" session per <User,BitPerPixel,DisplaySize,Connection>
;
; Type: enum [ "Default" | "Separate" | Combination from {UBDI} ]
; "Default" Currently same as "UB"
; "Separate" All sessions are separate. Sessions can never be rejoined,
; and will need to be cleaned up manually, or automatically
; by setting other sesman options.
;
; Combination options:-
; U Sessions are separated per user
; B Sessions are separated by bits-per-pixel
; D Sessions are separated by initial display size
; I Sessions are separated by IP address
;
; The options U and B are always active, and cannot be de-selected.
Policy=Default
[Logging]

View File

@ -88,80 +88,91 @@ dumpItemsToString(struct list *self, char *outstr, int len)
struct session_item *
session_get_bydata(const struct session_parameters *sp)
{
char policy_str[64];
struct session_chain *tmp;
enum SESMAN_CFG_SESS_POLICY policy = g_cfg->sess.policy;
char ip[64];
char tmp_ip[64];
int policy = g_cfg->sess.policy;
if ((policy & SESMAN_CFG_SESS_POLICY_I) != 0)
if ((policy & SESMAN_CFG_SESS_POLICY_DEFAULT) != 0)
{
/* We'll need to compare on IP addresses */
g_get_ip_from_description(sp->connection_description,
ip, sizeof(ip));
}
else
{
ip[0] = '\0';
tmp_ip[0] = '\0';
/* In the past (i.e. xrdp before v0.9.14), the default
* session policy varied by sp->type. If this is needed again
* in the future, here is the place to add it */
policy = SESMAN_CFG_SESS_POLICY_U | SESMAN_CFG_SESS_POLICY_B;
}
config_output_policy_string(policy, policy_str, sizeof(policy_str));
LOG(LOG_LEVEL_DEBUG,
"session_get_bydata: search policy %d U %s W %d H %d bpp %d T %d IP %s",
policy, sp->username, sp->width, sp->height, sp->bpp,
sp->type, sp->connection_description);
"%s: search policy=%s type=%s U=%s 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->ip_addr);
/* 'Separate' policy never matches */
if (policy & SESMAN_CFG_SESS_POLICY_SEPARATE)
{
LOG(LOG_LEVEL_DEBUG, "%s: No matches possible", __func__);
return NULL;
}
for (tmp = g_sessions ; tmp != 0 ; tmp = tmp->next)
{
if ((policy & SESMAN_CFG_SESS_POLICY_I) != 0)
{
g_get_ip_from_description(tmp->item->connection_description,
tmp_ip, sizeof (tmp_ip));
}
struct session_item *item = tmp->item;
LOG(LOG_LEVEL_DEBUG,
"session_get_bydata: try %p U %s W %d H %d bpp %d T %d IP %s",
tmp->item,
tmp->item->name,
tmp->item->width, tmp->item->height,
tmp->item->bpp, tmp->item->type,
tmp->item->connection_description);
"%s: try %p type=%s U=%s B=%d D=(%dx%d) I=%s",
__func__,
item,
SCP_SESSION_TYPE_TO_STR(item->type),
item->name,
item->bpp,
item->width, item->height,
item->start_ip_addr);
if (g_strncmp(sp->username, tmp->item->name, 255) != 0 ||
tmp->item->bpp != sp->bpp ||
tmp->item->type != sp->type)
if (item->type != sp->type)
{
LOG(LOG_LEVEL_DEBUG, "%s: Type doesn't match", __func__);
continue;
}
if ((policy & SESMAN_CFG_SESS_POLICY_U) &&
g_strncmp(sp->username, item->name, sizeof(item->name) - 1) != 0)
{
LOG(LOG_LEVEL_DEBUG,
"session_get_bydata: Basic parameters don't match");
"%s: Username doesn't match for 'U' policy", __func__);
continue;
}
if ((policy & SESMAN_CFG_SESS_POLICY_B) && item->bpp != sp->bpp)
{
LOG(LOG_LEVEL_DEBUG,
"%s: bpp doesn't match for 'B' policy", __func__);
continue;
}
if ((policy & SESMAN_CFG_SESS_POLICY_D) &&
(tmp->item->width != sp->width || tmp->item->height != sp->height))
(item->width != sp->width || item->height != sp->height))
{
LOG(LOG_LEVEL_DEBUG,
"session_get_bydata: Dimensions don't match for 'D' policy");
"%s: Dimensions don't match for 'D' policy", __func__);
continue;
}
if ((policy & SESMAN_CFG_SESS_POLICY_I) && g_strcmp(ip, tmp_ip) != 0)
if ((policy & SESMAN_CFG_SESS_POLICY_I) &&
g_strcmp(item->start_ip_addr, sp->ip_addr) != 0)
{
LOG(LOG_LEVEL_DEBUG,
"session_get_bydata: IPs don't match for 'I' policy");
"%s: IPs don't match for 'I' policy", __func__);
continue;
}
if ((policy & SESMAN_CFG_SESS_POLICY_C) &&
g_strncmp(sp->connection_description, tmp->item->connection_description, 255) != 0)
{
LOG(LOG_LEVEL_DEBUG,
"session_get_bydata: connections don't match for 'C' policy");
}
LOG(LOG_LEVEL_DEBUG, "session_get_bydata: Got match");
return tmp->item;
LOG(LOG_LEVEL_DEBUG,
"%s: Got match, display=%d", __func__, item->display);
return item;
}
LOG(LOG_LEVEL_DEBUG, "%s: No matches found", __func__);
return 0;
}
@ -959,14 +970,15 @@ session_start(long data,
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->connection_description, s->username);
pid, display, s->width, s->height, s->bpp, s->ip_addr, s->username);
temp->item->pid = pid;
temp->item->display = display;
temp->item->width = s->width;
temp->item->height = s->height;
temp->item->bpp = s->bpp;
temp->item->data = data;
g_strncpy(temp->item->connection_description, s->connection_description, 255); /* store client ip data */
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->guid = *guid;
@ -1071,7 +1083,7 @@ session_kill(int pid)
/* deleting the session */
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->connection_description);
tmp->item->name, tmp->item->display, tmp->item->pid, tmp->item->start_ip_addr);
g_free(tmp->item);
if (prev == 0)
@ -1227,11 +1239,10 @@ session_get_byuser(const char *user, unsigned int *cnt, unsigned char flags)
(sess[index]).bpp = tmp->item->bpp;
(sess[index]).start_time = tmp->item->start_time;
(sess[index]).username = g_strdup(tmp->item->name);
(sess[index]).connection_description =
g_strdup(tmp->item->connection_description);
(sess[index]).start_ip_addr = g_strdup(tmp->item->start_ip_addr);
if ((sess[index]).username == NULL ||
(sess[index]).connection_description == NULL)
(sess[index]).start_ip_addr == NULL)
{
free_session_info_list(sess, *cnt);
(*cnt) = 0;
@ -1259,7 +1270,7 @@ free_session_info_list(struct scp_session_info *sesslist, unsigned int cnt)
for (i = 0 ; i < cnt ; ++i)
{
g_free(sesslist[i].username);
g_free(sesslist[i].connection_description);
g_free(sesslist[i].start_ip_addr);
}
}
@ -1374,7 +1385,7 @@ clone_session_params(const struct session_parameters *sp)
len += g_strlen(sp->username) + 1;
len += g_strlen(sp->shell) + 1;
len += g_strlen(sp->directory) + 1;
len += g_strlen(sp->connection_description) + 1;
len += g_strlen(sp->ip_addr) + 1;
if ((result = (struct session_parameters *)g_malloc(len, 0)) != NULL)
{
@ -1394,8 +1405,7 @@ clone_session_params(const struct session_parameters *sp)
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->connection_description,
result->connection_description);
COPY_STRING_MEMBER(sp->ip_addr, result->ip_addr);
#undef COPY_STRING_MEMBER
}

View File

@ -32,6 +32,7 @@
#include "guid.h"
#include "scp_application_types.h"
#include "xrdp_constants.h"
#define SESMAN_SESSION_STATUS_ACTIVE 0x01
#define SESMAN_SESSION_STATUS_IDLE 0x02
@ -68,7 +69,7 @@ struct session_item
time_t start_time;
// struct session_date disconnect_time; // Currently unused
// struct session_date idle_time; // Currently unused
char connection_description[256];
char start_ip_addr[MAX_PEER_ADDRSTRLEN];
struct guid guid;
};
@ -91,7 +92,7 @@ struct session_parameters
const char *username;
const char *shell;
const char *directory;
const char *connection_description;
const char *ip_addr;
};
/**

View File

@ -153,9 +153,9 @@ print_session(const struct scp_session_info *s)
printf("\tScreen size: %dx%d, color depth %d\n",
s->width, s->height, s->bpp);
printf("\tStarted: %s", ctime(&s->start_time));
if (s->connection_description[0] != '\0')
if (s->start_ip_addr[0] != '\0')
{
printf("\tConnection Description: %s\n", s->connection_description);
printf("\tStart IP address: %s\n", s->start_ip_addr);
}
}

View File

@ -51,7 +51,8 @@ auth_account_disabled(struct spwd *stp);
/******************************************************************************/
/* returns boolean */
long
auth_userpass(const char *user, const char *pass, int *errorcode)
auth_userpass(const char *user, const char *pass,
const char *client_ip, int *errorcode)
{
const char *encr;
const char *epass;

View File

@ -46,7 +46,8 @@
/******************************************************************************/
/* returns boolean */
long
auth_userpass(const char *user, const char *pass, int *errorcode)
auth_userpass(const char *user, const char *pass,
const char *client_ip, int *errorcode)
{
int ret = auth_userokay(user, NULL, "auth-xrdp", pass);
return ret;

View File

@ -400,8 +400,9 @@ cleanup:
/******************************************************************************/
/* returns boolean */
int
auth_userpass(const char *user, const char *pass, int *errorcode)
long
auth_userpass(const char *user, const char *pass,
const char *client_ip, int *errorcode)
{
struct k_opts opts;
struct k5_data k5;

View File

@ -32,6 +32,7 @@
#include "os_calls.h"
#include "log.h"
#include "string_calls.h"
#include "auth.h"
#include <stdio.h>
#include <security/pam_appl.h>
@ -212,7 +213,8 @@ get_service_name(char *service_name)
Stores the detailed error code in the errorcode variable*/
long
auth_userpass(const char *user, const char *pass, int *errorcode)
auth_userpass(const char *user, const char *pass,
const char *client_ip, int *errorcode)
{
int error;
struct t_auth_info *auth_info;
@ -239,10 +241,20 @@ auth_userpass(const char *user, const char *pass, int *errorcode)
return 0;
}
if (client_ip != NULL && client_ip[0] != '\0')
{
error = pam_set_item(auth_info->ph, PAM_RHOST, client_ip);
if (error != PAM_SUCCESS)
{
LOG(LOG_LEVEL_ERROR, "pam_set_item(PAM_RHOST) failed: %s",
pam_strerror(auth_info->ph, error));
}
}
error = pam_set_item(auth_info->ph, PAM_TTY, service_name);
if (error != PAM_SUCCESS)
{
LOG(LOG_LEVEL_ERROR, "pam_set_item failed: %s",
LOG(LOG_LEVEL_ERROR, "pam_set_item(PAM_TTY) failed: %s",
pam_strerror(auth_info->ph, error));
}

View File

@ -38,8 +38,9 @@
/******************************************************************************/
/* returns boolean */
int
auth_userpass(const char *user, const char *pass, int *errorcode)
long
auth_userpass(const char *user, const char *pass,
const char *client_ip, int *errorcode)
{
pam_handle_t *pamh;
pam_userpass_t userpass;

View File

@ -649,6 +649,336 @@ START_TEST(test_str2bm__empty_token)
}
END_TEST
/******************************************************************************/
START_TEST(test_bm2char__no_bits_defined)
{
int rv;
char buff[64];
int rest;
static const struct bitmask_char bits[] =
{
BITMASK_CHAR_END_OF_LIST
};
rv = g_bitmask_to_charstr(0xffff, bits, buff, sizeof(buff), &rest);
ck_assert_str_eq(buff, "");
ck_assert_int_eq(rv, 0);
ck_assert_int_eq(rest, 0xffff);
}
END_TEST
START_TEST(test_bm2char__all_bits_defined)
{
int rv;
char buff[64];
int rest;
static const struct bitmask_char bits[] =
{
{1 << 0, 'A'},
{1 << 1, 'B'},
{1 << 6, 'C'},
{1 << 7, 'D'},
BITMASK_CHAR_END_OF_LIST
};
int bitmask = 1 << 0 | 1 << 1 | 1 << 6 | 1 << 7;
rv = g_bitmask_to_charstr(bitmask, bits, buff, sizeof(buff), &rest);
ck_assert_str_eq(buff, "ABCD");
ck_assert_int_eq(rv, 4);
ck_assert_int_eq(rest, 0);
}
END_TEST
START_TEST(test_bm2char__some_bits_undefined)
{
int rv;
char buff[64];
int rest;
static const struct bitmask_char bits[] =
{
{1 << 0, 'A'},
{1 << 1, 'B'},
{1 << 6, 'C'},
{1 << 7, 'D'},
BITMASK_CHAR_END_OF_LIST
};
int bitmask = 1 << 0 | 1 << 1 | 1 << 16;
rv = g_bitmask_to_charstr(bitmask, bits, buff, sizeof(buff), &rest);
ck_assert_str_eq(buff, "AB");
ck_assert_int_eq(rv, 2);
ck_assert_int_eq(rest, (1 << 16));
}
END_TEST
START_TEST(test_bm2char__overflow_all_bits_defined)
{
int rv;
char buff[3];
int rest;
static const struct bitmask_char bits[] =
{
{1 << 0, 'A'},
{1 << 1, 'B'},
{1 << 6, 'C'},
{1 << 7, 'D'},
BITMASK_CHAR_END_OF_LIST
};
int bitmask = 1 << 0 | 1 << 1 | 1 << 6 | 1 << 7;
rv = g_bitmask_to_charstr(bitmask, bits, buff, sizeof(buff), &rest);
ck_assert_str_eq(buff, "AB");
ck_assert_int_eq(rv, 4);
ck_assert_int_eq(rest, 0);
}
END_TEST
START_TEST(test_bm2char__overflow_some_bits_undefined)
{
int rv;
char buff[2];
int rest;
static const struct bitmask_char bits[] =
{
{1 << 0, 'A'},
{1 << 1, 'B'},
{1 << 6, 'C'},
{1 << 7, 'D'},
BITMASK_CHAR_END_OF_LIST
};
int bitmask = 1 << 0 | 1 << 1 | 1 << 16;
rv = g_bitmask_to_charstr(bitmask, bits, buff, sizeof(buff), &rest);
ck_assert_str_eq(buff, "A");
ck_assert_int_eq(rv, 2);
ck_assert_int_eq(rest, (1 << 16));
}
END_TEST
START_TEST(test_bm2char__null_rest_param)
{
int rv;
char buff[10];
static const struct bitmask_char bits[] =
{
{1 << 0, 'A'},
{1 << 1, 'B'},
{1 << 6, 'C'},
{1 << 7, 'D'},
BITMASK_CHAR_END_OF_LIST
};
int bitmask = 1 << 0 | 1 << 1 | 1 << 16;
rv = g_bitmask_to_charstr(bitmask, bits, buff, sizeof(buff), NULL);
ck_assert_str_eq(buff, "AB");
ck_assert_int_eq(rv, 2);
}
END_TEST
/******************************************************************************/
START_TEST(test_char2bm__null_string)
{
int rv;
char buff[16] = { 'd', 'u', 'm', 'm', 'y' };
static const struct bitmask_char bits[] =
{
{1 << 0, 'A'},
BITMASK_CHAR_END_OF_LIST
};
rv = g_charstr_to_bitmask(NULL, bits, buff, sizeof(buff));
ck_assert_str_eq(buff, "");
ck_assert_int_eq(rv, 0);
}
END_TEST
START_TEST(test_char2bm__empty_string)
{
int rv;
char buff[16] = { 'd', 'u', 'm', 'm', 'y' };
static const struct bitmask_char bits[] =
{
{1 << 0, 'A'},
BITMASK_CHAR_END_OF_LIST
};
rv = g_charstr_to_bitmask("", bits, buff, sizeof(buff));
ck_assert_str_eq(buff, "");
ck_assert_int_eq(rv, 0);
}
END_TEST
START_TEST(test_char2bm__null_bitdefs)
{
int rv;
char buff[16] = { 'd', 'u', 'm', 'm', 'y' };
rv = g_charstr_to_bitmask("A", NULL, buff, sizeof(buff));
ck_assert_str_eq(buff, "");
ck_assert_int_eq(rv, 0);
}
END_TEST
START_TEST(test_char2bm__null_buffer)
{
int rv;
char buff[16] = { 'd', 'u', 'm', 'm', 'y' };
static const struct bitmask_char bits[] =
{
{1 << 0, 'A'},
BITMASK_CHAR_END_OF_LIST
};
rv = g_charstr_to_bitmask("B", bits, NULL, sizeof(buff));
ck_assert_str_eq(buff, "dummy");
ck_assert_int_eq(rv, 0);
}
END_TEST
START_TEST(test_char2bm__zero_buffer)
{
int rv;
char buff[1];
static const struct bitmask_char bits[] =
{
{1 << 0, 'A'},
BITMASK_CHAR_END_OF_LIST
};
rv = g_charstr_to_bitmask("B", bits, buff, 0);
ck_assert_int_eq(rv, 0);
}
END_TEST
START_TEST(test_char2bm__zero_mask)
{
int rv;
char buff[16] = { 'd', 'u', 'm', 'm', 'y' };
static const struct bitmask_char bits[] =
{
{0, 'A'}, /* mask 0 should not be detected as end of list */
{1 << 0, 'B'},
BITMASK_CHAR_END_OF_LIST
};
int bitmask = 1 << 0;
rv = g_charstr_to_bitmask("B", bits, buff, sizeof(buff));
ck_assert_str_eq(buff, "");
ck_assert_int_eq(rv, bitmask);
}
END_TEST
START_TEST(test_char2bm__all_defined)
{
int rv;
char buff[16] = { 'd', 'u', 'm', 'm', 'y' };
static const struct bitmask_char bits[] =
{
{1 << 0, 'A'},
{1 << 1, 'B'},
BITMASK_CHAR_END_OF_LIST
};
int bitmask = 1 << 0 | 1 << 1;
rv = g_charstr_to_bitmask("AB", bits, buff, sizeof(buff));
ck_assert_str_eq(buff, "");
ck_assert_int_eq(rv, bitmask);
}
END_TEST
START_TEST(test_char2bm__no_defined)
{
int rv;
char buff[16] = { 'd', 'u', 'm', 'm', 'y' };
static const struct bitmask_char bits[] =
{
{1 << 0, 'A'},
{1 << 1, 'B'},
BITMASK_CHAR_END_OF_LIST
};
int bitmask = 0;
rv = g_charstr_to_bitmask("CD", bits, buff, sizeof(buff));
ck_assert_str_eq(buff, "CD");
ck_assert_int_eq(rv, bitmask);
}
END_TEST
START_TEST(test_char2bm__some_defined)
{
int rv;
char buff[16] = { 'd', 'u', 'm', 'm', 'y' };
static const struct bitmask_char bits[] =
{
{1 << 0, 'A'},
{1 << 1, 'B'},
{1 << 2, 'C'},
BITMASK_CHAR_END_OF_LIST
};
int bitmask = 1 << 1;
rv = g_charstr_to_bitmask("0B1", bits, buff, sizeof(buff));
ck_assert_str_eq(buff, "01");
ck_assert_int_eq(rv, bitmask);
}
END_TEST
START_TEST(test_char2bm__overflow_undefined)
{
int rv;
char buff[16] = { 'd', 'u', 'm', 'm', 'y' };
static const struct bitmask_char bits[] =
{
{1 << 0, 'A'},
{1 << 1, 'B'},
{1 << 2, 'C'},
BITMASK_CHAR_END_OF_LIST
};
int bitmask = 1 << 1;
rv = g_charstr_to_bitmask("123456789Bvwxyz", bits, buff, 10);
/* vwxyz is not filled */
ck_assert_str_eq(buff, "123456789");
ck_assert_int_eq(rv, bitmask);
}
END_TEST
/******************************************************************************/
START_TEST(test_strtrim__trim_left)
@ -712,6 +1042,8 @@ make_suite_test_string(void)
TCase *tc_strnjoin;
TCase *tc_bm2str;
TCase *tc_str2bm;
TCase *tc_bm2char;
TCase *tc_char2bm;
TCase *tc_strtrim;
s = suite_create("String");
@ -757,6 +1089,27 @@ make_suite_test_string(void)
tcase_add_test(tc_str2bm, test_str2bm__first_delim_is_semicolon);
tcase_add_test(tc_str2bm, test_str2bm__empty_token);
tc_bm2char = tcase_create("bm2char");
suite_add_tcase(s, tc_bm2char);
tcase_add_test(tc_bm2char, test_bm2char__no_bits_defined);
tcase_add_test(tc_bm2char, test_bm2char__all_bits_defined);
tcase_add_test(tc_bm2char, test_bm2char__some_bits_undefined);
tcase_add_test(tc_bm2char, test_bm2char__overflow_all_bits_defined);
tcase_add_test(tc_bm2char, test_bm2char__overflow_some_bits_undefined);
tcase_add_test(tc_bm2char, test_bm2char__null_rest_param);
tc_char2bm = tcase_create("char2bm");
suite_add_tcase(s, tc_char2bm);
tcase_add_test(tc_char2bm, test_char2bm__null_string);
tcase_add_test(tc_char2bm, test_char2bm__empty_string);
tcase_add_test(tc_char2bm, test_char2bm__null_bitdefs);
tcase_add_test(tc_char2bm, test_char2bm__null_buffer);
tcase_add_test(tc_char2bm, test_char2bm__zero_buffer);
tcase_add_test(tc_char2bm, test_char2bm__zero_mask);
tcase_add_test(tc_char2bm, test_char2bm__all_defined);
tcase_add_test(tc_char2bm, test_char2bm__no_defined);
tcase_add_test(tc_char2bm, test_char2bm__some_defined);
tcase_add_test(tc_char2bm, test_char2bm__overflow_undefined);
tc_strtrim = tcase_create("strtrim");
suite_add_tcase(s, tc_strtrim);
tcase_add_test(tc_strtrim, test_strtrim__trim_left);

View File

@ -112,7 +112,7 @@ main_loop(char *local_port, char *remote_ip, char *remote_port, int hexdump)
{
while ((!g_terminated) && (error == 0))
{
acc_sck = g_tcp_accept(lis_sck);
acc_sck = g_sck_accept(lis_sck);
if ((acc_sck == -1) && g_tcp_last_error_would_block(lis_sck))
{

View File

@ -232,7 +232,7 @@ xrdp_mm_send_gateway_login(struct xrdp_mm *self, const char *username,
return scp_send_gateway_request(
self->sesman_trans, username, password,
self->wm->client_info->connection_description);
self->wm->client_info->client_ip);
}
/*****************************************************************************/
@ -301,7 +301,7 @@ xrdp_mm_send_login(struct xrdp_mm *self)
xserverbpp,
self->wm->client_info->program,
self->wm->client_info->directory,
self->wm->client_info->connection_description);
self->wm->client_info->client_ip);
}
}

View File

@ -683,12 +683,11 @@ xrdp_wm_init(struct xrdp_wm *self)
if (file_read_section(fd, section_name, names, values) != 0)
{
LOG(LOG_LEVEL_INFO,
"Module \"%s\" specified by %s from %s port %s "
"Module \"%s\" specified by %s from %s "
"is not configured. Using \"%s\" instead.",
section_name,
self->session->client_info->username,
self->session->client_info->client_addr,
self->session->client_info->client_port,
self->session->client_info->client_description,
default_section_name);
list_clear(names);
list_clear(values);

View File

@ -73,10 +73,9 @@ lib_mod_log_peer(struct mod *mod)
{
LOG(LOG_LEVEL_INFO, "lib_mod_log_peer: xrdp_pid=%d connected "
"to X11rdp_pid=%d X11rdp_uid=%d X11rdp_gid=%d "
"client_ip=%s client_port=%s",
"client=%s",
my_pid, pid, uid, gid,
mod->client_info.client_addr,
mod->client_info.client_port);
mod->client_info.client_description);
}
else
{