Merge pull request #1976 from matt335672/fail2ban_support
Fail2ban support (#1076)
This commit is contained in:
commit
ce23c824ea
@ -1389,11 +1389,9 @@ g_sck_accept(int sck, char *addr, int addr_bytes, char *port, int port_bytes)
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* TODO: this function writes not only IP address, name is confusing
|
||||
*/
|
||||
|
||||
void
|
||||
g_write_ip_address(int rcv_sck, char *ip_address, int bytes)
|
||||
g_write_connection_description(int rcv_sck, char *description, int bytes)
|
||||
{
|
||||
char *addr;
|
||||
int port;
|
||||
@ -1454,18 +1452,57 @@ g_write_ip_address(int rcv_sck, char *ip_address, int bytes)
|
||||
|
||||
if (ok)
|
||||
{
|
||||
g_snprintf(ip_address, bytes, "%s:%d - socket: %d", addr, port, rcv_sck);
|
||||
g_snprintf(description, bytes, "%s:%d - socket: %d", addr, port, rcv_sck);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
g_snprintf(ip_address, bytes, "NULL:NULL - socket: %d", rcv_sck);
|
||||
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)
|
||||
{
|
||||
if (bytes > 0)
|
||||
{
|
||||
/* Look for the space after ip:port */
|
||||
const char *end = g_strchr(description, ' ');
|
||||
if (end == NULL)
|
||||
{
|
||||
end = description; /* Means we've failed */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Look back for the last ':' */
|
||||
while (end > description && *end != ':')
|
||||
{
|
||||
--end;
|
||||
}
|
||||
}
|
||||
|
||||
if (end == description)
|
||||
{
|
||||
g_snprintf(ip, bytes, "<unknown>");
|
||||
}
|
||||
else if ((end - description) < (bytes - 1))
|
||||
{
|
||||
g_strncpy(ip, description, end - description);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_strncpy(ip, description, bytes - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return ip;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void
|
||||
g_sleep(int msecs)
|
||||
|
@ -93,7 +93,18 @@ 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_ip_address(int rcv_sck, char *ip_address, int bytes);
|
||||
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())
|
||||
* @param ip buffer to write IP address to
|
||||
* @param bytes Size of ip buffer
|
||||
* @return Pointer to IP for convenience
|
||||
*/
|
||||
const char *g_get_ip_from_description(const char *description,
|
||||
char *ip, 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);
|
||||
|
@ -91,7 +91,7 @@ struct xrdp_client_info
|
||||
int rdp5_performanceflags;
|
||||
int brush_cache_code; /* 0 = no cache 1 = 8x8 standard cache
|
||||
2 = arbitrary dimensions */
|
||||
char client_ip[256];
|
||||
char connection_description[256];
|
||||
int max_bpp;
|
||||
int jpeg; /* non standard bitmap cache v2 cap */
|
||||
int offscreen_support_level;
|
||||
|
@ -378,8 +378,10 @@ 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.client_ip) - 1;
|
||||
g_write_ip_address(trans->sck, self->client_info.client_ip, bytes);
|
||||
bytes = sizeof(self->client_info.connection_description) - 1;
|
||||
g_write_connection_description(trans->sck,
|
||||
self->client_info.connection_description,
|
||||
bytes);
|
||||
self->mppc_enc = mppc_enc_new(PROTO_RDP_50);
|
||||
#if defined(XRDP_NEUTRINORDP)
|
||||
self->rfx_enc = rfx_context_new();
|
||||
|
@ -307,24 +307,24 @@ scp_session_set_directory(struct SCP_SESSION *s, const char *str)
|
||||
|
||||
/*******************************************************************/
|
||||
int
|
||||
scp_session_set_client_ip(struct SCP_SESSION *s, const char *str)
|
||||
scp_session_set_connection_description(struct SCP_SESSION *s, const char *str)
|
||||
{
|
||||
if (0 == str)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "[session:%d] set_client_ip: null ip", __LINE__);
|
||||
LOG(LOG_LEVEL_WARNING, "[session:%d] set_connection_description: null description", __LINE__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (0 != s->client_ip)
|
||||
if (0 != s->connection_description)
|
||||
{
|
||||
g_free(s->client_ip);
|
||||
g_free(s->connection_description);
|
||||
}
|
||||
|
||||
s->client_ip = g_strdup(str);
|
||||
s->connection_description = g_strdup(str);
|
||||
|
||||
if (0 == s->client_ip)
|
||||
if (0 == s->connection_description)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "[session:%d] set_client_ip: strdup error", __LINE__);
|
||||
LOG(LOG_LEVEL_WARNING, "[session:%d] set_connection_description: strdup error", __LINE__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -439,7 +439,7 @@ scp_session_destroy(struct SCP_SESSION *s)
|
||||
g_free(s->domain);
|
||||
g_free(s->program);
|
||||
g_free(s->directory);
|
||||
g_free(s->client_ip);
|
||||
g_free(s->connection_description);
|
||||
g_free(s->errstr);
|
||||
g_free(s);
|
||||
}
|
||||
@ -464,7 +464,7 @@ scp_session_clone(const struct SCP_SESSION *s)
|
||||
result->domain = g_strdup(s->domain);
|
||||
result->program = g_strdup(s->program);
|
||||
result->directory = g_strdup(s->directory);
|
||||
result->client_ip = g_strdup(s->client_ip);
|
||||
result->connection_description = g_strdup(s->connection_description);
|
||||
|
||||
/* Did all the string copies succeed? */
|
||||
if ((s->username != NULL && result->username == NULL) ||
|
||||
@ -474,7 +474,7 @@ scp_session_clone(const struct SCP_SESSION *s)
|
||||
(s->domain != NULL && result->domain == NULL) ||
|
||||
(s->program != NULL && result->program == NULL) ||
|
||||
(s->directory != NULL && result->directory == NULL) ||
|
||||
(s->client_ip != NULL && result->client_ip == NULL))
|
||||
(s->connection_description != NULL && result->connection_description == NULL))
|
||||
{
|
||||
scp_session_destroy(result);
|
||||
result = NULL;
|
||||
|
@ -85,7 +85,7 @@ int
|
||||
scp_session_set_directory(struct SCP_SESSION *s, const char *str);
|
||||
|
||||
int
|
||||
scp_session_set_client_ip(struct SCP_SESSION *s, const char *str);
|
||||
scp_session_set_connection_description(struct SCP_SESSION *s, const char *str);
|
||||
|
||||
int
|
||||
scp_session_set_hostname(struct SCP_SESSION *s, const char *str);
|
||||
|
@ -84,7 +84,7 @@ struct SCP_SESSION
|
||||
char *domain;
|
||||
char *program;
|
||||
char *directory;
|
||||
char *client_ip;
|
||||
char *connection_description;
|
||||
tui8 guid[16];
|
||||
/* added for state */
|
||||
int current_cmd;
|
||||
|
@ -355,13 +355,13 @@ scp_v0s_accept(struct trans *atrans, struct SCP_SESSION *session)
|
||||
if (s_check_rem(in_s, 2))
|
||||
{
|
||||
/* reading client IP address */
|
||||
if (!in_string16(in_s, buf, "client IP"))
|
||||
if (!in_string16(in_s, buf, "connection description"))
|
||||
{
|
||||
return SCP_SERVER_STATE_SIZE_ERR;
|
||||
}
|
||||
if (buf[0] != '\0')
|
||||
{
|
||||
scp_session_set_client_ip(session, buf);
|
||||
scp_session_set_connection_description(session, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,17 +77,18 @@ scp_v0_process(struct trans *t, struct SCP_SESSION *s)
|
||||
else if (data)
|
||||
{
|
||||
s_item = session_get_bydata(s->username, s->width, s->height,
|
||||
s->bpp, s->type, s->client_ip);
|
||||
s->bpp, s->type, s->connection_description);
|
||||
|
||||
if (s_item != 0)
|
||||
{
|
||||
display = s_item->display;
|
||||
g_memcpy(s->guid, s_item->guid, 16);
|
||||
if (0 != s->client_ip)
|
||||
if (0 != s->connection_description)
|
||||
{
|
||||
LOG( LOG_LEVEL_INFO, "++ reconnected session: username %s, "
|
||||
"display :%d.0, session_pid %d, ip %s",
|
||||
s->username, display, s_item->pid, s->client_ip);
|
||||
s->username, display, s_item->pid,
|
||||
s->connection_description);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -109,10 +110,10 @@ scp_v0_process(struct trans *t, struct SCP_SESSION *s)
|
||||
g_random((char *)guid, 16);
|
||||
scp_session_set_guid(s, guid);
|
||||
|
||||
if (0 != s->client_ip)
|
||||
if (0 != s->connection_description)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "++ created session (access granted): "
|
||||
"username %s, ip %s", s->username, s->client_ip);
|
||||
"username %s, ip %s", s->username, s->connection_description);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -157,8 +158,15 @@ scp_v0_process(struct trans *t, struct SCP_SESSION *s)
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "Username or password error for user: %s",
|
||||
s->username);
|
||||
char ip[64];
|
||||
g_get_ip_from_description(s->connection_description, ip, sizeof(ip));
|
||||
/*
|
||||
* The message is intended for use by fail2ban, so for
|
||||
* future-proofing we only log the IP address rather than the
|
||||
* connection description */
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"AUTHFAIL: user=%s ip=%s time=%d",
|
||||
s->username, ip, g_time1());
|
||||
scp_v0s_deny_connection(t);
|
||||
}
|
||||
if (do_auth_end)
|
||||
|
@ -79,9 +79,17 @@ scp_v1_process1(struct trans *t, struct SCP_SESSION *s)
|
||||
}
|
||||
else
|
||||
{
|
||||
char ip[64];
|
||||
g_get_ip_from_description(s->connection_description,
|
||||
ip, sizeof(ip));
|
||||
/*
|
||||
* The message is intended for use by fail2ban, so for
|
||||
* future-proofing we only log the IP address rather than the
|
||||
* connection description */
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"AUTHFAIL: user=%s ip=%s time=%d",
|
||||
s->username, ip, g_time1());
|
||||
scp_v1s_deny_connection(t, "Login failed");
|
||||
LOG(LOG_LEVEL_INFO, "Login failed for user %s. "
|
||||
"Connection terminated", s->username);
|
||||
return SCP_SERVER_STATE_END;
|
||||
}
|
||||
return SCP_SERVER_STATE_OK;
|
||||
@ -108,10 +116,10 @@ scp_v1_process1(struct trans *t, struct SCP_SESSION *s)
|
||||
LOG(LOG_LEVEL_DEBUG, "No disconnected sessions for this user "
|
||||
"- we create a new one");
|
||||
|
||||
if (0 != s->client_ip)
|
||||
if (0 != s->connection_description)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "++ created session (access granted): "
|
||||
"username %s, ip %s", s->username, s->client_ip);
|
||||
"username %s, ip %s", s->username, s->connection_description);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -219,9 +227,9 @@ scp_v1_process43(struct trans *t, struct SCP_SESSION *s)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "scp_v1s_reconnect_session failed");
|
||||
}
|
||||
if (0 != s->client_ip)
|
||||
if (0 != s->connection_description)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "++ reconnected session: username %s, display :%d.0, session_pid %d, ip %s", s->username, display, sitem->pid, s->client_ip);
|
||||
LOG(LOG_LEVEL_INFO, "++ reconnected session: username %s, display :%d.0, session_pid %d, ip %s", s->username, display, sitem->pid, s->connection_description);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -92,10 +92,11 @@ dumpItemsToString(struct list *self, char *outstr, int len)
|
||||
/******************************************************************************/
|
||||
struct session_item *
|
||||
session_get_bydata(const char *name, int width, int height, int bpp, int type,
|
||||
const char *client_ip)
|
||||
const char *connection_description)
|
||||
{
|
||||
struct session_chain *tmp;
|
||||
enum SESMAN_CFG_SESS_POLICY policy = g_cfg->sess.policy;
|
||||
char ip[64];
|
||||
|
||||
tmp = g_sessions;
|
||||
|
||||
@ -115,27 +116,49 @@ session_get_bydata(const char *name, int width, int height, int bpp, int type,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((policy & SESMAN_CFG_SESS_POLICY_I) != 0)
|
||||
{
|
||||
/* We'll need to compare on IP addresses */
|
||||
g_get_ip_from_description(connection_description, ip, sizeof(ip));
|
||||
}
|
||||
else
|
||||
{
|
||||
ip[0] = '\0';
|
||||
}
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"session_get_bydata: search policy %d U %s W %d H %d bpp %d T %d IP %s",
|
||||
policy, name, width, height, bpp, type, client_ip);
|
||||
policy, name, width, height, bpp, type, connection_description);
|
||||
|
||||
while (tmp != 0)
|
||||
{
|
||||
char tmp_ip[64];
|
||||
|
||||
if ((policy & SESMAN_CFG_SESS_POLICY_I) != 0)
|
||||
{
|
||||
g_get_ip_from_description(tmp->item->connection_description,
|
||||
tmp_ip, sizeof (tmp_ip));
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp_ip[0] = '\0';
|
||||
}
|
||||
|
||||
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->client_ip);
|
||||
tmp->item->connection_description);
|
||||
|
||||
if (g_strncmp(name, tmp->item->name, 255) == 0 &&
|
||||
(!(policy & SESMAN_CFG_SESS_POLICY_D) ||
|
||||
(tmp->item->width == width && tmp->item->height == height)) &&
|
||||
(!(policy & SESMAN_CFG_SESS_POLICY_I) ||
|
||||
(g_strncmp_d(client_ip, tmp->item->client_ip, ':', 255) == 0)) &&
|
||||
(g_strcmp(ip, tmp_ip) == 0)) &&
|
||||
(!(policy & SESMAN_CFG_SESS_POLICY_C) ||
|
||||
(g_strncmp(client_ip, tmp->item->client_ip, 255) == 0)) &&
|
||||
(g_strncmp(connection_description, tmp->item->connection_description, 255) == 0)) &&
|
||||
tmp->item->bpp == bpp &&
|
||||
tmp->item->type == type)
|
||||
{
|
||||
@ -925,14 +948,14 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
|
||||
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->client_ip, s->username);
|
||||
pid, display, s->width, s->height, s->bpp, s->connection_description, 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->client_ip, s->client_ip, 255); /* store client ip 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);
|
||||
|
||||
@ -1064,7 +1087,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->client_ip);
|
||||
tmp->item->name, tmp->item->display, tmp->item->pid, tmp->item->connection_description);
|
||||
g_free(tmp->item);
|
||||
|
||||
if (prev == 0)
|
||||
|
@ -75,7 +75,7 @@ struct session_item
|
||||
struct session_date connect_time;
|
||||
struct session_date disconnect_time;
|
||||
struct session_date idle_time;
|
||||
char client_ip[256];
|
||||
char connection_description[256];
|
||||
tui8 guid[16];
|
||||
};
|
||||
|
||||
@ -93,7 +93,7 @@ struct session_chain
|
||||
*/
|
||||
struct session_item *
|
||||
session_get_bydata(const char *name, int width, int height, int bpp, int type,
|
||||
const char *client_ip);
|
||||
const char *connection_description);
|
||||
#ifndef session_find_item
|
||||
#define session_find_item(a, b, c, d, e, f) session_get_bydata(a, b, c, d, e, f);
|
||||
#endif
|
||||
|
@ -261,10 +261,10 @@ xrdp_mm_send_login(struct xrdp_mm *self)
|
||||
out_uint16_be(s, index);
|
||||
out_uint8a(s, self->wm->client_info->directory, index);
|
||||
|
||||
/* send client ip */
|
||||
index = g_strlen(self->wm->client_info->client_ip);
|
||||
/* send client connection description */
|
||||
index = g_strlen(self->wm->client_info->connection_description);
|
||||
out_uint16_be(s, index);
|
||||
out_uint8a(s, self->wm->client_info->client_ip, index);
|
||||
out_uint8a(s, self->wm->client_info->connection_description, index);
|
||||
|
||||
s_mark_end(s);
|
||||
|
||||
@ -1765,6 +1765,7 @@ xrdp_mm_process_login_response(struct xrdp_mm *self, struct stream *s)
|
||||
char port[256];
|
||||
tui8 guid[16];
|
||||
tui8 *pguid;
|
||||
char username[256];
|
||||
|
||||
rv = 0;
|
||||
in_uint16_be(s, ok);
|
||||
@ -1775,11 +1776,19 @@ xrdp_mm_process_login_response(struct xrdp_mm *self, struct stream *s)
|
||||
in_uint8a(s, guid, 16);
|
||||
pguid = guid;
|
||||
}
|
||||
|
||||
if (xrdp_mm_get_value(self, "username",
|
||||
username, sizeof(username) - 1) != 0)
|
||||
{
|
||||
g_strcpy(username, "???");
|
||||
}
|
||||
|
||||
if (ok)
|
||||
{
|
||||
self->display = display;
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO,
|
||||
"login successful for display %d", display);
|
||||
"login successful for user %s on display %d",
|
||||
username, display);
|
||||
|
||||
if (xrdp_mm_setup_mod1(self) == 0)
|
||||
{
|
||||
@ -1804,8 +1813,23 @@ xrdp_mm_process_login_response(struct xrdp_mm *self, struct stream *s)
|
||||
}
|
||||
else
|
||||
{
|
||||
char displayinfo[64];
|
||||
|
||||
if (display == 0)
|
||||
{
|
||||
/* A returned display of zero doesn't mean anything useful, and
|
||||
* can confuse the user. It's most likely authentication has
|
||||
* failed and no display was allocated */
|
||||
displayinfo[0] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
g_snprintf(displayinfo, sizeof(displayinfo),
|
||||
" on display %d", display);
|
||||
}
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO,
|
||||
"login failed for display %d", display);
|
||||
"login failed for user %s%s",
|
||||
username, displayinfo);
|
||||
xrdp_wm_show_log(self->wm);
|
||||
if (self->wm->hide_log_window)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user