summaryrefslogtreecommitdiff
path: root/protocols/Gadu-Gadu/src/libgadu/dcc7.cpp
diff options
context:
space:
mode:
authorGoraf <22941576+Goraf@users.noreply.github.com>2018-01-18 17:57:36 +0100
committerGoraf <22941576+Goraf@users.noreply.github.com>2018-01-19 01:39:33 +0100
commitfb40ed2b6385b9e3a85b35ba27f3a42207d22234 (patch)
tree9de6415c9c28c68d2fe750abe2c95c3a89ba08ca /protocols/Gadu-Gadu/src/libgadu/dcc7.cpp
parent97bb7e79c15952e7f9bf47caef4e3c09dd63c8df (diff)
Gadu-Gadu: update libgadu to 1.11.4
Diffstat (limited to 'protocols/Gadu-Gadu/src/libgadu/dcc7.cpp')
-rw-r--r--protocols/Gadu-Gadu/src/libgadu/dcc7.cpp74
1 files changed, 47 insertions, 27 deletions
diff --git a/protocols/Gadu-Gadu/src/libgadu/dcc7.cpp b/protocols/Gadu-Gadu/src/libgadu/dcc7.cpp
index 465a3cae4a..b9f6ef2faa 100644
--- a/protocols/Gadu-Gadu/src/libgadu/dcc7.cpp
+++ b/protocols/Gadu-Gadu/src/libgadu/dcc7.cpp
@@ -154,7 +154,7 @@ static struct gg_dcc7 *gg_dcc7_session_find(struct gg_session *sess, gg_dcc7_id_
for (tmp = sess->dcc7_list; tmp; tmp = tmp->next) {
if (empty) {
- if (tmp->peer_uin == uin && !tmp->state == GG_STATE_WAITING_FOR_ACCEPT)
+ if (tmp->peer_uin == uin && tmp->state == GG_STATE_WAITING_FOR_ACCEPT)
return tmp;
} else {
if (!memcmp(&tmp->cid, &id, sizeof(id)))
@@ -228,11 +228,12 @@ static int gg_dcc7_connect(struct gg_dcc7 *dcc)
* \internal Tworzy gniazdo nasłuchujące dla połączenia bezpośredniego
*
* \param dcc Struktura połączenia
- * \param port Preferowany port (jeśli równy 0 lub -1, próbuje się domyślnego)
+ * \param addr Preferowany adres (jeśli równy 0, nasłuchujemy na wszystkich interfejsach)
+ * \param port Preferowany port (jeśli równy 0, nasłuchujemy na losowym)
*
* \return 0 jeśli się powiodło, -1 w przypadku błędu
*/
-static int gg_dcc7_listen(struct gg_dcc7 *dcc, uint16_t port)
+static int gg_dcc7_listen(struct gg_dcc7 *dcc, uint32_t addr, uint16_t port)
{
struct sockaddr_in sin;
int sin_len = sizeof(sin);
@@ -252,12 +253,13 @@ static int gg_dcc7_listen(struct gg_dcc7 *dcc, uint16_t port)
return -1;
}
+ memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = INADDR_ANY;
+ sin.sin_addr.s_addr = addr;
sin.sin_port = htons(port);
if (bind(fd, (struct sockaddr*) &sin, sizeof(sin)) == -1) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_listen() unable to bind to port %d\n", port);
+ gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_listen() unable to bind to %s:%d\n", inet_ntoa(sin.sin_addr), port);
goto fail;
}
@@ -272,6 +274,7 @@ static int gg_dcc7_listen(struct gg_dcc7 *dcc, uint16_t port)
}
dcc->fd = fd;
+ dcc->local_addr = sin.sin_addr.s_addr;
dcc->local_port = ntohs(sin.sin_port);
dcc->state = GG_STATE_LISTENING;
@@ -298,39 +301,36 @@ static int gg_dcc7_listen_and_send_info(struct gg_dcc7 *dcc)
{
struct gg_dcc7_info pkt;
uint16_t external_port;
- uint16_t local_port;
- uint32_t count;
+ uint32_t external_addr;
+ struct in_addr addr;
gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_listen_and_send_info(%p)\n", dcc);
if (dcc == NULL)
return -1;
- if (!dcc->sess->client_port)
- local_port = dcc->sess->external_port;
- else
- local_port = dcc->sess->client_port;
-
- if (gg_dcc7_listen(dcc, local_port) == -1)
+ if (gg_dcc7_listen(dcc, dcc->sess->client_addr, dcc->sess->client_port) == -1)
return -1;
- if (!dcc->sess->external_port || dcc->local_port != local_port)
- external_port = dcc->local_port;
- else
+ if (dcc->sess->external_port != 0)
external_port = dcc->sess->external_port;
-
- if (!dcc->sess->external_addr || dcc->local_port != local_port)
- dcc->local_addr = dcc->sess->client_addr;
else
- dcc->local_addr = dcc->sess->external_addr;
+ external_port = dcc->local_port;
+
+ if (dcc->sess->external_addr != 0)
+ external_addr = dcc->sess->external_addr;
+ else
+ external_addr = dcc->local_addr;
+
+ addr.s_addr = external_addr;
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// dcc7_listen_and_send_info() sending IP address %s and port %d\n", inet_ntoa(*((struct in_addr*) &dcc->local_addr)), external_port);
+ gg_debug_dcc(dcc, GG_DEBUG_MISC, "// dcc7_listen_and_send_info() sending IP address %s and port %d\n", inet_ntoa(addr), external_port);
memset(&pkt, 0, sizeof(pkt));
pkt.uin = gg_fix32(dcc->peer_uin);
pkt.type = GG_DCC7_TYPE_P2P;
pkt.id = dcc->cid;
- snprintf((char*) pkt.info, sizeof(pkt.info), "%s %d", inet_ntoa(*((struct in_addr*) &dcc->local_addr)), external_port);
- snprintf((char*) pkt.hash, sizeof(pkt.hash), "%u", dcc->local_addr + external_port * rand());
+ snprintf((char*) pkt.info, sizeof(pkt.info), "%s %d", inet_ntoa(addr), external_port);
+ snprintf((char*) pkt.hash, sizeof(pkt.hash), "%u", external_addr + external_port * rand());
return gg_send_packet(dcc->sess, GG_DCC7_INFO, &pkt, sizeof(pkt), NULL);
}
@@ -446,7 +446,7 @@ static struct gg_dcc7 *gg_dcc7_send_file_common(struct gg_session *sess, uin_t r
dcc->size = (unsigned int)size;
dcc->seek = seek;
- strncpy((char*) dcc->filename, filename1250, GG_DCC7_FILENAME_LEN - 1);
+ strncpy((char*) dcc->filename, filename1250, GG_DCC7_FILENAME_LEN);
dcc->filename[GG_DCC7_FILENAME_LEN] = 0;
memcpy(dcc->hash, hash, GG_DCC7_HASH_LEN);
@@ -699,7 +699,9 @@ int gg_dcc7_handle_id(struct gg_session *sess, struct gg_event *e, const void *p
s.uin_to = gg_fix32(tmp->peer_uin);
s.size = gg_fix32(tmp->size);
- strncpy((char*) s.filename, (char*) tmp->filename, GG_DCC7_FILENAME_LEN);
+ /* Uwaga: To nie jest ciąg kończony zerem.
+ * Note: This is not a null-terminated string. */
+ strncpy((char*) s.filename, (char*) tmp->filename, sizeof(s.filename));
tmp->state = GG_STATE_WAITING_FOR_ACCEPT;
tmp->timeout = GG_DCC7_TIMEOUT_FILE_ACK;
@@ -805,6 +807,8 @@ int gg_dcc7_handle_info(struct gg_session *sess, struct gg_event *e, const void
if (dcc->state == GG_STATE_WAITING_FOR_INFO) {
gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() waiting for info so send one\n");
gg_dcc7_listen_and_send_info(dcc);
+ e->type = GG_EVENT_DCC7_PENDING;
+ e->event.dcc7_pending.dcc7 = dcc;
return 0;
}
@@ -1025,7 +1029,7 @@ int gg_dcc7_handle_new(struct gg_session *sess, struct gg_event *e, const void *
}
dcc->size = gg_fix32(p->size);
- strncpy((char*) dcc->filename, (char*) p->filename, GG_DCC7_FILENAME_LEN - 1);
+ strncpy((char*) dcc->filename, (char*) p->filename, GG_DCC7_FILENAME_LEN);
dcc->filename[GG_DCC7_FILENAME_LEN] = 0;
memcpy(dcc->hash, p->hash, GG_DCC7_HASH_LEN);
@@ -1489,6 +1493,9 @@ struct gg_event *gg_dcc7_watch_fd(struct gg_dcc7 *dcc)
dcc->check = GG_CHECK_WRITE;
dcc->timeout = GG_DEFAULT_TIMEOUT;
+ e->type = GG_EVENT_DCC7_PENDING;
+ e->event.dcc7_pending.dcc7 = dcc;
+
return e;
}
@@ -1538,6 +1545,7 @@ struct gg_event *gg_dcc7_watch_fd(struct gg_dcc7 *dcc)
char buf[256];
struct gg_dcc7_relay_reply *pkt;
struct gg_dcc7_relay_reply_server srv;
+ size_t max_relay_count = (sizeof(buf) - sizeof(*pkt)) / sizeof(srv);
int res;
int i;
@@ -1555,7 +1563,7 @@ struct gg_event *gg_dcc7_watch_fd(struct gg_dcc7 *dcc)
pkt = (struct gg_dcc7_relay_reply*) buf;
- if (gg_fix32(pkt->magic) != GG_DCC7_RELAY_REPLY || gg_fix32(pkt->rcount) < 1 || gg_fix32(pkt->rcount > 256) || gg_fix32(pkt->len) < sizeof(*pkt) + gg_fix32(pkt->rcount) * sizeof(srv)) {
+ if (gg_fix32(pkt->magic) != GG_DCC7_RELAY_REPLY || gg_fix32(pkt->rcount) < 1 || gg_fix32(pkt->rcount) > 256 || gg_fix32(pkt->len) < sizeof(*pkt) + gg_fix32(pkt->rcount) * sizeof(srv)) {
gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_wathc_fd() invalid reply\n");
errno = EINVAL;
e->type = GG_EVENT_DCC7_ERROR;
@@ -1571,6 +1579,18 @@ struct gg_event *gg_dcc7_watch_fd(struct gg_dcc7 *dcc)
dcc->relay_index = 0;
dcc->relay_count = gg_fix32(pkt->rcount);
+
+ if (dcc->relay_count > 0xffff ||
+ (size_t)dcc->relay_count > max_relay_count)
+ {
+ gg_debug_dcc(dcc, GG_DEBUG_MISC,
+ "// gg_dcc7_watch_fd() relay_count out "
+ "of bounds (%d)\n", dcc->relay_count);
+ dcc->relay_count = 0;
+ free(e);
+ return NULL;
+ }
+
dcc->relay_list = (gg_dcc7_relay*)malloc(dcc->relay_count * sizeof(gg_dcc7_relay_t));
if (dcc->relay_list == NULL) {