mirror of
https://github.com/curl/curl.git
synced 2026-04-14 13:01:42 +08:00
tftp: pin the first used address
Store the used remote address on the first receive call and then make sure that it remains the same address on subsequent calls to reduce the risk of tampering. Doesn't make the transfer secure because it is still unauthenticated and clear text. Reported in Joshua's sarif data Closes #18658
This commit is contained in:
parent
a72e1552f2
commit
c4f9977c66
32
lib/tftp.c
32
lib/tftp.c
@ -126,6 +126,10 @@ struct tftp_packet {
|
||||
#define CURL_META_TFTP_CONN "meta:proto:tftp:conn"
|
||||
|
||||
struct tftp_conn {
|
||||
struct Curl_sockaddr_storage local_addr;
|
||||
struct Curl_sockaddr_storage remote_addr;
|
||||
struct tftp_packet rpacket;
|
||||
struct tftp_packet spacket;
|
||||
tftp_state_t state;
|
||||
tftp_mode_t mode;
|
||||
tftp_error_t error;
|
||||
@ -136,16 +140,13 @@ struct tftp_conn {
|
||||
int retry_time;
|
||||
int retry_max;
|
||||
time_t rx_time;
|
||||
struct Curl_sockaddr_storage local_addr;
|
||||
struct Curl_sockaddr_storage remote_addr;
|
||||
curl_socklen_t remote_addrlen;
|
||||
int rbytes;
|
||||
size_t sbytes;
|
||||
unsigned int blksize;
|
||||
unsigned int requested_blksize;
|
||||
unsigned short block;
|
||||
struct tftp_packet rpacket;
|
||||
struct tftp_packet spacket;
|
||||
BIT(remote_pinned);
|
||||
};
|
||||
|
||||
|
||||
@ -1094,18 +1095,31 @@ static CURLcode tftp_pollset(struct Curl_easy *data,
|
||||
static CURLcode tftp_receive_packet(struct Curl_easy *data,
|
||||
struct tftp_conn *state)
|
||||
{
|
||||
curl_socklen_t fromlen;
|
||||
CURLcode result = CURLE_OK;
|
||||
CURLcode result = CURLE_OK;
|
||||
struct Curl_sockaddr_storage remote_addr;
|
||||
curl_socklen_t fromlen = sizeof(remote_addr);
|
||||
|
||||
/* Receive the packet */
|
||||
fromlen = sizeof(state->remote_addr);
|
||||
state->rbytes = (int)recvfrom(state->sockfd,
|
||||
(void *)state->rpacket.data,
|
||||
(RECV_TYPE_ARG3)state->blksize + 4,
|
||||
0,
|
||||
(struct sockaddr *)&state->remote_addr,
|
||||
(struct sockaddr *)&remote_addr,
|
||||
&fromlen);
|
||||
state->remote_addrlen = fromlen;
|
||||
if(state->remote_pinned) {
|
||||
/* pinned, verify that it comes from the same address */
|
||||
if((state->remote_addrlen != fromlen) ||
|
||||
memcmp(&remote_addr, &state->remote_addr, fromlen)) {
|
||||
failf(data, "Data received from another address");
|
||||
return CURLE_RECV_ERROR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* pin address on first use */
|
||||
state->remote_pinned = TRUE;
|
||||
state->remote_addrlen = fromlen;
|
||||
memcpy(&state->remote_addr, &remote_addr, fromlen);
|
||||
}
|
||||
|
||||
/* Sanity check packet length */
|
||||
if(state->rbytes < 4) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user