diff --git a/common/os_calls.c b/common/os_calls.c index e3e157a6..dd2e964d 100644 --- a/common/os_calls.c +++ b/common/os_calls.c @@ -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, ""); + } + 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) diff --git a/common/os_calls.h b/common/os_calls.h index 82689fa1..3e254790 100644 --- a/common/os_calls.h +++ b/common/os_calls.h @@ -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); diff --git a/common/xrdp_client_info.h b/common/xrdp_client_info.h index c95d0649..f45195e8 100644 --- a/common/xrdp_client_info.h +++ b/common/xrdp_client_info.h @@ -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; diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index 3d7df482..a48fbaa2 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -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(); diff --git a/sesman/libscp/libscp_session.c b/sesman/libscp/libscp_session.c index baace5d1..ef9480e3 100644 --- a/sesman/libscp/libscp_session.c +++ b/sesman/libscp/libscp_session.c @@ -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; diff --git a/sesman/libscp/libscp_session.h b/sesman/libscp/libscp_session.h index 227f34e5..8c3f1d2c 100644 --- a/sesman/libscp/libscp_session.h +++ b/sesman/libscp/libscp_session.h @@ -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); diff --git a/sesman/libscp/libscp_types.h b/sesman/libscp/libscp_types.h index fcfbfa51..2f66b4d6 100644 --- a/sesman/libscp/libscp_types.h +++ b/sesman/libscp/libscp_types.h @@ -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; diff --git a/sesman/libscp/libscp_v0.c b/sesman/libscp/libscp_v0.c index e996e52c..c67f5cfa 100644 --- a/sesman/libscp/libscp_v0.c +++ b/sesman/libscp/libscp_v0.c @@ -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); } } } diff --git a/sesman/scp_v0.c b/sesman/scp_v0.c index d040280e..ecc9f88a 100644 --- a/sesman/scp_v0.c +++ b/sesman/scp_v0.c @@ -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) diff --git a/sesman/scp_v1.c b/sesman/scp_v1.c index 4d9fc3ce..a8a59ebd 100644 --- a/sesman/scp_v1.c +++ b/sesman/scp_v1.c @@ -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 { diff --git a/sesman/session.c b/sesman/session.c index a2968e1b..d2018581 100644 --- a/sesman/session.c +++ b/sesman/session.c @@ -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) diff --git a/sesman/session.h b/sesman/session.h index bb0f0df7..174e65df 100644 --- a/sesman/session.h +++ b/sesman/session.h @@ -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 diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index a371f082..13a165f0 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -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) {