Nick([email protected]) on 2020.02.11 06:41:32 +0000:
> >Synopsis:    relayd silently ignores ill-defined protocol mixtures
> >Category:    system
> >Environment:
>       System      : OpenBSD 6.6
>       Details     : OpenBSD 6.6 (GENERIC.MP) #372: Sat Oct 12 10:56:27 MDT 
> 2019
>                        
> [email protected]:/usr/src/sys/arch/amd64/compile/GENERIC.MP
> 
>       Architecture: OpenBSD.amd64
>       Machine     : amd64
> 
> >Description:
> 
>       a. Multiple `protocol`s lines are allowed in a relay but only the 
> *last* defines
>       what happens. It would be so much more helpful if this was a straight 
> error.

        
>       b. tcp/tls/http options can be set in `dns protocol`s -- though they 
> are ignored.
>       This should also be an error.

Here is a diff for both a. and b.

ok?

(benno_relayd_protocol_only_once.diff)

diff --git usr.sbin/relayd/parse.y usr.sbin/relayd/parse.y
index 2fad6bee5bf..cac18491d87 100644
--- usr.sbin/relayd/parse.y
+++ usr.sbin/relayd/parse.y
@@ -1088,7 +1088,6 @@ proto             : relay_proto PROTO STRING      {
                                yyerror("invalid TLS protocol");
                                YYERROR;
                        }
-
                        TAILQ_INSERT_TAIL(conf->sc_protos, proto, entry);
                }
                ;
@@ -1102,10 +1101,38 @@ protopts_l      : protopts_l protoptsl nl
                | protoptsl optnl
                ;
 
-protoptsl      : ssltls tlsflags
-               | ssltls '{' tlsflags_l '}'
-               | TCP tcpflags
-               | TCP '{' tcpflags_l '}'
+protoptsl      : ssltls {
+                       if (!(proto->type == RELAY_PROTO_TCP ||
+                           proto->type == RELAY_PROTO_HTTP)) {
+                               yyerror("can set tls options only for "
+                                   "tcp or http protocols");
+                               YYERROR;
+                       }
+               } tlsflags
+               | ssltls {
+                       if (!(proto->type == RELAY_PROTO_TCP ||
+                           proto->type == RELAY_PROTO_HTTP)) {
+                               yyerror("can set tls options only for "
+                                   "tcp or http protocols");
+                               YYERROR;
+                       }
+               } '{' tlsflags_l '}'
+               | TCP {
+                       if (!(proto->type == RELAY_PROTO_TCP ||
+                           proto->type == RELAY_PROTO_HTTP)) {
+                               yyerror("can set tcp options only for "
+                                   "tcp or http protocols");
+                               YYERROR;
+                       }
+               } tcpflags
+               | TCP {
+                       if (!(proto->type == RELAY_PROTO_TCP ||
+                           proto->type == RELAY_PROTO_HTTP)) {
+                               yyerror("can set tcp options only for "
+                                   "tcp or http protocols");
+                               YYERROR;
+                       }
+               } '{' tcpflags_l '}'
                | HTTP {
                        if (proto->type != RELAY_PROTO_HTTP) {
                                yyerror("can set http options only for "
@@ -1905,6 +1932,11 @@ relayoptsl       : LISTEN ON STRING port opttls {
                | PROTO STRING                  {
                        struct protocol *p;
 
+                       if (rlay->rl_conf.proto != EMPTY_ID) {
+                               yyerror("more than one protocol specified");
+                               YYERROR;
+                       }
+                               
                        TAILQ_FOREACH(p, conf->sc_protos, entry)
                                if (!strcmp(p->name, $2))
                                        break;



> >How-To-Repeat:
>       
>       a.
>       
>       This relayd speaks DNS on UDP port 80:
>       
>       ```
>       $ cat > relayd.conf <<EOF
>       table <web> { "127.0.0.1" }
>       table <app> { "127.0.0.1" }
>       
>       http protocol A {
>               return error
>       
>               match request path "/app/*" forward to <app>
>       }
>       
>       dns protocol B {
>               return error
>       }
>       
>       relay P {
>               listen on 0.0.0.0 port 80
>       
>               protocol A
>               forward to <web> port 8080
>       
>               protocol B
>               forward to <app> port 8082
>       }
>       EOF
>       $ doas relayd -f relayd.conf
>       ```
>       
>       ```
>       $ fstat | grep relayd | grep internet
>       _relayd  relayd     29047   10* internet dgram udp *:80
>       _relayd  relayd     40704   10* internet dgram udp *:80
>       _relayd  relayd     21221   10* internet dgram udp *:80
>       _relayd  relayd     88624    4* internet raw icmp 0x0
>       _relayd  relayd     88624    5* internet raw icmp 0x0
>       _relayd  relayd     88624    6* internet6 raw ipv6-icmp 0x0
>       _relayd  relayd     88624    7* internet6 raw ipv6-icmp 0x0
>       
>       ```
> 
>       while this one speaks http:
> 
>       ```
>       $ cat > relayd.conf <<EOF
>       table <web> { "127.0.0.1" }
>       table <app> { "127.0.0.1" }
> 
>       dns protocol A {
>               return error
> 
>               match request path "/app/*" forward to <app>
>       }
> 
>       http protocol B {
>               return error
>       }
> 
>       relay P {
>               listen on 0.0.0.0 port 80
> 
>               protocol A
>               forward to <web> port 8080
> 
>               protocol B
>               forward to <app> port 8082
>       }
>       EOF
>       $ doas relayd -f relayd.conf
>       ```
> 
>       ```
>       $ fstat | grep relayd | grep internet
>       _relayd  relayd      2564   10* internet stream tcp 0x0 *:80
>       _relayd  relayd     29428   10* internet stream tcp 0x0 *:80
>       _relayd  relayd     61476   10* internet stream tcp 0x0 *:80
>       _relayd  relayd     90200    4* internet raw icmp 0x0
>       _relayd  relayd     90200    5* internet raw icmp 0x0
>       _relayd  relayd     90200    6* internet6 raw ipv6-icmp 0x0
>       _relayd  relayd     90200    7* internet6 raw ipv6-icmp 0x0
>       $
>       $ curl http://localhost # demonstrate that relayd is speaking http
>       <!DOCTYPE html>
>       <html>
>       <head>
>       <title>500 Internal Server Error</title>
>       <style type="text/css"><!--
>       body { background-color: #a00000; color: white; font-family: 'Comic 
> Sans MS', 'Chalkboard SE', 'Comic Neue', sans-serif; }
>       hr { border: 0; border-bottom: 1px dashed; }
> 
>       --></style>
>       </head>
>       <body>
>       <h1>Internal Server Error</h1>
>       <div id='m'></div>
>       <div id='l'></div>
>       <hr><address>OpenBSD relayd at 0.0.0.0 port 80</address>
>       </body>
>       </html>
>       ```
> 
>       b.
> 
>       You can see in the latter example that `match request path` is legal in
>       `dns protocol` blocks which makes no sense.
> 

Reply via email to