mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-08-08 09:21:48 +08:00
Merge branch 'tmp-711' into 'master'
Set `sa` before attempting to set `sa->sin6_family` Closes #711 See merge request openconnect/ocserv!554
This commit is contained in:
@@ -26,6 +26,7 @@
|
|||||||
* /cert.cer
|
* /cert.cer
|
||||||
* /ca.pem
|
* /ca.pem
|
||||||
* /ca.cer
|
* /ca.cer
|
||||||
|
- Fix incorrect local address when using PROXY protocol with IPv6 (#711).
|
||||||
|
|
||||||
|
|
||||||
* Version 1.4.2 (released 2026-04-16)
|
* Version 1.4.2 (released 2026-04-16)
|
||||||
|
|||||||
@@ -443,8 +443,8 @@ int parse_proxy_proto_header(struct worker_st *ws, int fd)
|
|||||||
|
|
||||||
memset(&ws->remote_addr, 0, sizeof(ws->remote_addr));
|
memset(&ws->remote_addr, 0, sizeof(ws->remote_addr));
|
||||||
sa->sin_family = AF_INET;
|
sa->sin_family = AF_INET;
|
||||||
memcpy(&sa->sin_port, p + 8, 2);
|
|
||||||
memcpy(&sa->sin_addr, p, 4);
|
memcpy(&sa->sin_addr, p, 4);
|
||||||
|
memcpy(&sa->sin_port, p + 8, 2);
|
||||||
ws->remote_addr_len = sizeof(struct sockaddr_in);
|
ws->remote_addr_len = sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
memset(&ws->our_addr, 0, sizeof(ws->our_addr));
|
memset(&ws->our_addr, 0, sizeof(ws->our_addr));
|
||||||
@@ -473,8 +473,8 @@ int parse_proxy_proto_header(struct worker_st *ws, int fd)
|
|||||||
ws->remote_addr_len = sizeof(struct sockaddr_in6);
|
ws->remote_addr_len = sizeof(struct sockaddr_in6);
|
||||||
|
|
||||||
memset(&ws->our_addr, 0, sizeof(ws->our_addr));
|
memset(&ws->our_addr, 0, sizeof(ws->our_addr));
|
||||||
sa->sin6_family = AF_INET6;
|
|
||||||
sa = (void *)&ws->our_addr;
|
sa = (void *)&ws->our_addr;
|
||||||
|
sa->sin6_family = AF_INET6;
|
||||||
memcpy(&sa->sin6_addr, p + 16, 16);
|
memcpy(&sa->sin6_addr, p + 16, 16);
|
||||||
memcpy(&sa->sin6_port, p + 34, 2);
|
memcpy(&sa->sin6_port, p + 34, 2);
|
||||||
ws->our_addr_len = sizeof(struct sockaddr_in6);
|
ws->our_addr_len = sizeof(struct sockaddr_in6);
|
||||||
|
|||||||
@@ -130,6 +130,55 @@ static size_t build_v2_packet(uint8_t *buf, size_t bufsz,
|
|||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build a proxy protocol v2 packet with an IPv6 address block into buf[].
|
||||||
|
* Returns the total number of bytes written.
|
||||||
|
*/
|
||||||
|
static size_t build_v2_ipv6_packet(uint8_t *buf, size_t bufsz,
|
||||||
|
const struct in6_addr *src_addr,
|
||||||
|
uint16_t src_port,
|
||||||
|
const struct in6_addr *dst_addr,
|
||||||
|
uint16_t dst_port)
|
||||||
|
{
|
||||||
|
size_t pos = 0;
|
||||||
|
uint16_t sp, dp, plen;
|
||||||
|
|
||||||
|
memcpy(buf + pos, PP2_SIG, 12);
|
||||||
|
pos += 12;
|
||||||
|
buf[pos++] = 0x21; /* ver=2, PROXY command */
|
||||||
|
buf[pos++] = 0x21; /* AF_INET6 (0x2) | TCP (0x1) */
|
||||||
|
|
||||||
|
size_t len_offset = pos;
|
||||||
|
buf[pos++] = 0;
|
||||||
|
buf[pos++] = 0;
|
||||||
|
|
||||||
|
size_t payload_start = pos;
|
||||||
|
|
||||||
|
/* IPv6 address block (36 bytes):
|
||||||
|
* src IP (16 bytes)
|
||||||
|
* dst IP (16 bytes)
|
||||||
|
* src port (2 bytes, network order)
|
||||||
|
* dst port (2 bytes, network order)
|
||||||
|
*/
|
||||||
|
memcpy(buf + pos, src_addr, 16);
|
||||||
|
pos += 16;
|
||||||
|
memcpy(buf + pos, dst_addr, 16);
|
||||||
|
pos += 16;
|
||||||
|
sp = htons(src_port);
|
||||||
|
dp = htons(dst_port);
|
||||||
|
memcpy(buf + pos, &sp, 2);
|
||||||
|
pos += 2;
|
||||||
|
memcpy(buf + pos, &dp, 2);
|
||||||
|
pos += 2;
|
||||||
|
|
||||||
|
plen = (uint16_t)(pos - payload_start);
|
||||||
|
buf[len_offset] = (plen >> 8) & 0xff;
|
||||||
|
buf[len_offset + 1] = plen & 0xff;
|
||||||
|
|
||||||
|
assert(pos <= bufsz);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Feed pkt into a pipe and call parse_proxy_proto_header.
|
* Feed pkt into a pipe and call parse_proxy_proto_header.
|
||||||
* ws->conn_type must be set by the caller.
|
* ws->conn_type must be set by the caller.
|
||||||
@@ -275,5 +324,78 @@ int main(void)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* Test 6: IPv6 proxy protocol v2 — both remote and local addr correct */
|
||||||
|
/* */
|
||||||
|
/* Reproducer for the bug where sa->sin6_family was assigned before sa */
|
||||||
|
/* was redirected to &ws->our_addr, leaving our_addr.sin6_family == 0. */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
{
|
||||||
|
struct in6_addr src6, dst6;
|
||||||
|
struct sockaddr_in6 *rem6, *loc6;
|
||||||
|
|
||||||
|
memset(&ws, 0, sizeof(ws));
|
||||||
|
ws.conn_type = SOCK_TYPE_TCP;
|
||||||
|
|
||||||
|
inet_pton(AF_INET6, "2001:db8::1", &src6);
|
||||||
|
inet_pton(AF_INET6, "2001:db8::2", &dst6);
|
||||||
|
|
||||||
|
pkt_len = build_v2_ipv6_packet(pkt, sizeof(pkt), &src6, 1234,
|
||||||
|
&dst6, 443);
|
||||||
|
ret = run_parse(&ws, pkt, pkt_len);
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "Test 6: parse failed (%d)\n", ret);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ws.remote_addr_len != sizeof(struct sockaddr_in6)) {
|
||||||
|
fprintf(stderr, "Test 6: remote_addr_len wrong (%u)\n",
|
||||||
|
ws.remote_addr_len);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (ws.our_addr_len != sizeof(struct sockaddr_in6)) {
|
||||||
|
fprintf(stderr, "Test 6: our_addr_len wrong (%u)\n",
|
||||||
|
ws.our_addr_len);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rem6 = (void *)&ws.remote_addr;
|
||||||
|
loc6 = (void *)&ws.our_addr;
|
||||||
|
|
||||||
|
if (rem6->sin6_family != AF_INET6) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Test 6: remote sin6_family wrong: %d\n",
|
||||||
|
rem6->sin6_family);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* This check catches the bug: sin6_family was written to
|
||||||
|
* remote_addr a second time instead of to our_addr. */
|
||||||
|
if (loc6->sin6_family != AF_INET6) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Test 6: local sin6_family wrong: %d (expected %d)\n",
|
||||||
|
loc6->sin6_family, AF_INET6);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(&rem6->sin6_addr, &src6, 16) != 0) {
|
||||||
|
fprintf(stderr, "Test 6: remote address mismatch\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (memcmp(&loc6->sin6_addr, &dst6, 16) != 0) {
|
||||||
|
fprintf(stderr, "Test 6: local address mismatch\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (ntohs(rem6->sin6_port) != 1234) {
|
||||||
|
fprintf(stderr, "Test 6: remote port wrong: %u\n",
|
||||||
|
ntohs(rem6->sin6_port));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (ntohs(loc6->sin6_port) != 443) {
|
||||||
|
fprintf(stderr, "Test 6: local port wrong: %u\n",
|
||||||
|
ntohs(loc6->sin6_port));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user