Re: Duplicate headers created with set-header

2019-11-29 Thread Robert Samuel Newson
Awesome, thanks for the fast turnaround.

B.

> On 29 Nov 2019, at 11:04, Christopher Faulet  wrote:
> 
> Le 29/11/2019 à 10:46, Robert Samuel Newson a écrit :
>> Hi,
>> I've discovered it is possible to make haproxy (2.0.9 and 2.0.10, at least) 
>> produce duplicate headers using the set-header directive (which is defined 
>> as "This does the same as "http-request add-header" except that the header 
>> name  is first removed if it existed.").
>> This only happens when HTX is enabled. The essential part is that the 
>> variable substitution uses values that are not set.
> 
> Hi,
> 
> There is indeed a bug and a pretty obvious one. The function looking for a 
> header fails if the value is empty while it should not. This bug should be 
> fixed now in all HTX versions (2.2-dev, 2.1, 2.0 and 1.9).
> 
> Thanks,
> -- 
> Christopher Faulet




Re: Duplicate headers created with set-header

2019-11-29 Thread Christopher Faulet

Le 29/11/2019 à 10:46, Robert Samuel Newson a écrit :

Hi,

I've discovered it is possible to make haproxy (2.0.9 and 2.0.10, at least) produce duplicate 
headers using the set-header directive (which is defined as "This does the same as 
"http-request add-header" except that the header name  is first removed if it 
existed.").

This only happens when HTX is enabled. The essential part is that the variable 
substitution uses values that are not set.



Hi,

There is indeed a bug and a pretty obvious one. The function looking for a 
header fails if the value is empty while it should not. This bug should be fixed 
now in all HTX versions (2.2-dev, 2.1, 2.0 and 1.9).


Thanks,
--
Christopher Faulet



Duplicate headers created with set-header

2019-11-29 Thread Robert Samuel Newson
Hi,

I've discovered it is possible to make haproxy (2.0.9 and 2.0.10, at least) 
produce duplicate headers using the set-header directive (which is defined as 
"This does the same as "http-request add-header" except that the header name  
is first removed if it existed.").

This only happens when HTX is enabled. The essential part is that the variable 
substitution uses values that are not set.

Here is my configuration, narrowed down to its essentials;


defaults
  mode http
  option http-use-htx
  timeout client 30s
  timeout connect 5s
  timeout queue 5s
  timeout server 30s
  timeout tarpit 10s

frontend http-in
  bind 127.0.0.1:5984
  acl header_is_set hdr_len(X-Header) gt 0
  http-request set-header X-Header %[hdr(x-foo)] unless header_is_set
  http-request set-header X-Header %[hdr(x-bar)] unless header_is_set
  http-request set-header X-Header baz unless header_is_set
  default_backend http-out

backend http-out
  server db1 127.0.0.1:15984 check inter 1s

Here is the non-HTX output;


GET / HTTP/1.1
Host: localhost:5984
User-Agent: curl/7.64.1
Accept: */*
X-Header: baz

Here is the HTX output;

GET / HTTP/1.1
host: localhost:5984
user-agent: curl/7.64.1
accept: */*
x-header:
x-header:
x-header: baz

and my version info in detail;

HA-Proxy version 2.0.10 2019/11/25 - https://haproxy.org/
Build options :
  TARGET  = linux-glibc
  CPU = generic
  CC  = gcc
  CFLAGS  = -m64 -march=x86-64 -O2 -g -fno-strict-aliasing 
-Wdeclaration-after-statement -fwrapv -Wno-unused-label -Wno-sign-compare 
-Wno-unused-parameter -Wno-old-style-declaration -Wno-ignored-qualifiers 
-Wno-clobbered -Wno-missing-field-initializers -Wtype-limits
  OPTIONS = USE_PCRE2=1 USE_PCRE2_JIT=1 USE_THREAD=1 USE_PTHREAD_PSHARED=1 
USE_REGPARM=1 USE_STATIC_PCRE2=1 USE_OPENSSL=1 USE_LUA=1 USE_SLZ=1 USE_TFO=1 
USE_SYSTEMD=1

Feature list : +EPOLL -KQUEUE -MY_EPOLL -MY_SPLICE +NETFILTER -PCRE -PCRE_JIT 
+PCRE2 +PCRE2_JIT +POLL -PRIVATE_CACHE +THREAD +PTHREAD_PSHARED +REGPARM 
-STATIC_PCRE +STATIC_PCRE2 +TPROXY +LINUX_TPROXY +LINUX_SPLICE +LIBCRYPT 
+CRYPT_H -VSYSCALL +GETADDRINFO +OPENSSL +LUA +FUTEX +ACCEPT4 -MY_ACCEPT4 -ZLIB 
+SLZ +CPU_AFFINITY +TFO +NS +DL +RT -DEVICEATLAS -51DEGREES -WURFL +SYSTEMD 
-OBSOLETE_LINKER +PRCTL +THREAD_DUMP -EVPORTS

Default settings :
  bufsize = 16384, maxrewrite = 1024, maxpollevents = 200

Built with multi-threading support (MAX_THREADS=64, default=8).
Built with OpenSSL version : OpenSSL 1.1.1d  10 Sep 2019
Running on OpenSSL version : OpenSSL 1.1.1d  10 Sep 2019
OpenSSL library supports TLS extensions : yes
OpenSSL library supports SNI : yes
OpenSSL library supports : TLSv1.0 TLSv1.1 TLSv1.2 TLSv1.3
Built with Lua version : Lua 5.3.4
Built with network namespace support.
Built with transparent proxy support using: IP_TRANSPARENT IPV6_TRANSPARENT 
IP_FREEBIND
Built with libslz for stateless compression.
Compression algorithms supported : identity("identity"), deflate("deflate"), 
raw-deflate("deflate"), gzip("gzip")
Built with PCRE2 version : 10.30 2017-08-14
PCRE2 library supports JIT : yes
Encrypted password support via crypt(3): yes

Available polling systems :
  epoll : pref=300,  test result OK
   poll : pref=200,  test result OK
 select : pref=150,  test result OK
Total: 3 (3 usable), will use epoll.

Available multiplexer protocols :
(protocols marked as  cannot be specified using 'proto' keyword)
  h2 : mode=HTXside=FE|BE mux=H2
  h2 : mode=HTTP   side=FEmux=H2
: mode=HTXside=FE|BE mux=H1
: mode=TCP|HTTP   side=FE|BE mux=PASS

Available services : none

Available filters :
[SPOE] spoe
[COMP] compression
[CACHE] cache
[TRACE] trace