Re: [Openvpn-devel] [PATCH] add support for --dns option

2022-03-17 Thread Heiko Hund
Hi Gert

On Donnerstag, 17. März 2022 11:41:22 CET Gert Doering wrote:
> I wonder why we bother to actually *do* this?  As in "we already know
> that this can never overflow here" (because all strings involved are
> known, and the max width of %d is known, too), but *if* it ever did,
> calling the subsequent setenv_str() wouldn't be a good idea to do - no?

It's in the spirit of defensive programming. It cannot overflow now, but will 
likely overflow some time. However I thought that getting the value into env 
might still be worthwhile in some scenarios, even if the name is not complete, 
e.g. if the env is logged somewhere. The error message in the openvpn log, will 
lead to cause then.
 
> Can we make transform these into a miniwrapper that does
> like
> 
>for (i = 1, d = o->search_domains; d != NULL; i++, d = d->next)
>{
> _do_dns_env_thing( "dns_search_domain_%d", i, d->name );
>}

I actually had such a wrapper in place, but dumped it because I didn't like the 
fact that the value would have to come before the name in the argument list, 
because of the var-args. Since we have a format string with two %d (and there 
might be more / other formatting specifiers in the future), the wrapper would 
have to deal with ..., or we'd end up with two wrappers (or more if this is 
extended in the future). No matter what:

>const char* format = s->domain_type == DNS_RESOLVE_DOMAINS ?
>"dns_server_%d_resolve_domain_%d" : 
> "dns_server_%d_exclude_domain_%d";

requires it to be:

 _do_dns_env_thing(d->name, "dns_server_%d_resolve__domain_%d", i, j);

right now already. And that lead me to not making things wrapped.

However I could be talked into removing the checks for openvpn_snprintf()'s 
return value if there's a consensus, as it wouldn't introduce an actual issue. 
Just maybe a little harder to debug issues in future code possibly. Also not 
setting the env if sprintf fails sounds good, would do this rather:

if (openvpn_snprinf())
setenv_str();
else
name_ok = false;

Iff the value is really not useful in the env, when the name is incomplete. 
Bonus: no &=.

Heiko




___
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel


Re: [Openvpn-devel] [PATCH] add support for --dns option

2022-03-17 Thread Gert Doering
Hi,

(this is about v2)

On Sat, Mar 12, 2022 at 02:58:10PM +0100, Heiko Hund wrote:
> As a first step towards DNS configuration in openvpn and a unified way
> to push DNS related settings to clients in v2 and v3, this commit adds
> support for parsing the new --dns option. Later commits will add support
> for setting up DNS on different platforms.
> 
> For now, --dns and DNS related --dhcp-option can be used together for
> smoother transition. Settings from --dns will override ones --dhcp-option
> where applicable.
> 
> For detailed information about the option consult the documentation in
> this commit.
[..]
> +for (i = 1, d = o->search_domains; d != NULL; i++, d = d->next)
> +{
> +name_ok = openvpn_snprintf(env_name, sizeof(env_name), 
> "dns_search_domain_%d", i) && name_ok;
> +setenv_str(es, env_name, d->name);
> +}

With the "&& name_ok" this code does not really improve, even if it
was requested in the v1 review...

I wonder why we bother to actually *do* this?  As in "we already know
that this can never overflow here" (because all strings involved are 
known, and the max width of %d is known, too), but *if* it ever did, 
calling the subsequent setenv_str() wouldn't be a good idea to do - no?

Can we make transform these into a miniwrapper that does

 - openvpn_snprintf()
 - check result, warn if overflow
 - call setenv_str() otherwise

like

   for (i = 1, d = o->search_domains; d != NULL; i++, d = d->next)
   {
_do_dns_env_thing( "dns_search_domain_%d", i, d->name );
   }

so, shorter lines, clearer code, actual error checking, and no && ugliness :-)

(As far as I could see, it's all "setenv_str()" anyway)

gert
-- 
"If was one thing all people took for granted, was conviction that if you 
 feed honest figures into a computer, honest figures come out. Never doubted 
 it myself till I met a computer with a sense of humor."
 Robert A. Heinlein, The Moon is a Harsh Mistress

Gert Doering - Munich, Germany g...@greenie.muc.de


signature.asc
Description: PGP signature
___
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel


Re: [Openvpn-devel] [PATCH] add support for --dns option

2022-03-16 Thread Heiko Hund
On Samstag, 12. März 2022 14:58:10 CET Heiko Hund wrote:
> +name_ok = openvpn_snprintf(env_name, sizeof(env_name), 
> "dns_search_domain_%d", i) && name_ok; 

With some distance, I still like the &= version better from a readability 
standpoint.
Even though it's a bit unclean.

Heiko




___
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel


Re: [Openvpn-devel] [PATCH] add support for --dns option

2022-03-12 Thread Heiko Hund
Sorry, this is [PATCH v2].

Somehow I managed for send-email to override my --subject.




___
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel


[Openvpn-devel] [PATCH] add support for --dns option

2022-03-12 Thread Heiko Hund
As a first step towards DNS configuration in openvpn and a unified way
to push DNS related settings to clients in v2 and v3, this commit adds
support for parsing the new --dns option. Later commits will add support
for setting up DNS on different platforms.

For now, --dns and DNS related --dhcp-option can be used together for
smoother transition. Settings from --dns will override ones --dhcp-option
where applicable.

For detailed information about the option consult the documentation in
this commit.

Signed-off-by: Heiko Hund 
---
 doc/man-sections/client-options.rst |  59 
 doc/man-sections/script-options.rst |  19 ++
 doc/man-sections/server-options.rst |   2 +-
 src/openvpn/Makefile.am |   1 +
 src/openvpn/dns.c   | 495 
 src/openvpn/dns.h   | 164 +
 src/openvpn/openvpn.vcxproj |   4 +-
 src/openvpn/openvpn.vcxproj.filters |   8 +-
 src/openvpn/options.c   | 221 +
 src/openvpn/options.h   |   7 +
 src/openvpn/push.c  |   4 +
 src/openvpn/socket.c|  11 +
 src/openvpn/socket.h|   2 +
 13 files changed, 994 insertions(+), 3 deletions(-)
 create mode 100644 src/openvpn/dns.c
 create mode 100644 src/openvpn/dns.h

diff --git a/doc/man-sections/client-options.rst 
b/doc/man-sections/client-options.rst
index 92a02e28..2d7293c6 100644
--- a/doc/man-sections/client-options.rst
+++ b/doc/man-sections/client-options.rst
@@ -154,6 +154,65 @@ configuration.
 --connect-timeout n
   See ``--server-poll-timeout``.
 
+--dns args
+  Client DNS configuration to be used with the connection.
+
+  Valid syntaxes:
+  ::
+
+ dns search-domains domain [domain ...]
+ dns server n address addr[:port] [addr[:port]]
+ dns server n resolve-domains|exclude-domains domain [domain ...]
+ dns server n dnssec yes|optional|no
+ dns server n transport DoH|DoT|plain
+ dns server n sni server-name
+
+  The ``--dns search-domains`` directive takes one or more domain names
+  to be added as DNS domain suffixes. If it is repeated multiple times within
+  a configuration the domains are appended, thus e.g. domain names pushed by
+  a server will amend locally defined ones.
+
+  The ``--dns server`` directive is used to configure DNS server ``n``.
+  The server id ``n`` must be a value between -128 and 127. For pushed
+  DNS server options it must be between 0 and 127. The server id is used
+  to group options and also for ordering the list of configured DNS servers;
+  lower numbers come first. DNS servers being pushed to a client replace
+  already configured DNS servers with the same server id.
+
+  The ``address`` option configures the IPv4 and / or IPv6 address of
+  the DNS server. Optionally a port can be appended after a colon. IPv6
+  addresses need to be enclosed in brackets if a port is appended.
+
+  The ``resolve-domains`` and ``exclude-domains`` options take one or
+  more DNS domains which are explicitly resolved or explicitly not resolved
+  by a server. Only one of the options can be configured for a server.
+  ``resolve-domains`` is used to define a split-dns setup, where only
+  given domains are resolved by a server. ``exclude-domains`` is used to
+  define domains which will never be resolved by a server (e.g. domains
+  which can only be resolved locally). Systems which do not support fine
+  grained DNS domain configuration, will ignore these settings.
+
+  The ``dnssec`` option is used to configure validation of DNSSEC records.
+  While the exact semantics may differ for resolvers on different systems,
+  ``yes`` likely makes validation mandatory, ``no`` disables it, and 
``optional``
+  uses it opportunistically.
+
+  The ``transport`` option enables DNS-over-HTTPS (``DoH``) or DNS-over-TLS 
(``DoT``)
+  for a DNS server. The ``sni`` option can be used with them to specify the
+  ``server-name`` for TLS server name indication.
+
+  Each server has to have at least one address configured for a configuration
+  to be valid. All the other options can be omitted.
+
+  Note that not all options may be supported on all platforms. As soon support
+  for different systems is implemented, information will be added here how
+  unsupported options are treated.
+
+  The ``--dns`` option will eventually obsolete the ``--dhcp-option`` 
directive.
+  Until then it will replace configuration at the places ``--dhcp-option`` 
puts it,
+  so that ``--dns`` overrides ``--dhcp-option``. Thus, ``--dns`` can be used 
today
+  to migrate from ``--dhcp-option``.
+
 --explicit-exit-notify n
   In UDP client mode or point-to-point mode, send server/peer an exit
   notification if tunnel is restarted or OpenVPN process is exited. In
diff --git a/doc/man-sections/script-options.rst 
b/doc/man-sections/script-options.rst
index 22990f4f..c81efe9e 100644
--- a/doc/man-sections/script-options.rst
+++ b/doc/man-sections/script-options.rst
@@ -586,6 +586,25 

Re: [Openvpn-devel] [PATCH] add support for --dns option

2022-03-12 Thread Heiko Hund
On Mittwoch, 9. März 2022 13:40:32 CET Arne Schwabe wrote:
> Am 09.03.22 um 00:06 schrieb Heiko Hund:
> > +bool dns_server_priority_parse(long *priority, const char *str, bool
> > +[...]
> > +void show_dns_options(const struct dns_options *o);
> 
> These new functions are missing doxygen comments. We generally have the
> doxygen comments in the header files rather than in the c files.

Okay, I'll move the comments into the header file.

> > +--dns args
> > +  Client DNS configuration to be used with the connection.
> 
> This man page section sounds like all options are supported on all
> platforms while currently that is not the case. An explicit warning etc
> that says that some options like port, dnssec, doh etc are not supported
> on certain platforms should be included and also what happens if they
> are not.

Noted. What happens will likely be determined when we have the 
implementation(s) that actually take this option and try to apply it. Think it 
is too early to add this info to the manual, as it may change. Some ideas 
exist, but they have to prove themselves and survive public discussion. So far 
I have the idea that options will be ignored if they are not supported, and 
split DNS is turned into all DNS redirected to the pushed server(s) if they 
are unsupported. Again, this is very theoretical at this point and may change 
once facing reality.
 
> >  The ``--dns`` option will eventually obsolete the ``--dhcp-option``
> >  directive.> 
> > +  Until then it will add configuration at the places ``--dhcp-option``
> > puts it +  and will override it if both are given.
> 
> Is dhcp-option ignored when dns is present by newer client or are they
> mixed? This is a bit vague.

Will clarify.

> > +  long priority;
> 
> why a type that is 32 bit on some platforms and 64 bit on others? Either
> go with just int if 32 bit is enough or use long long or int64_t if we
> need 64 but long is a weird type.

int8_t would be enough, just need an extra few bits for the conversation from 
text. It is a long because strtol(3) returns a long, and I went with that. Not 
sure if casting after checks will gain much. If we decide to change this I'd 
rather use int8_t however, or a future somebody will ponder why the extra bits 
there, when the priority is really a 8 bit value. IMHO it is not worth the 
extra code, that's why I went with long. Compilers might align an 8 bit value 
anyways.

> > +name_ok &= openvpn_snprintf(env_name, sizeof(env_name),
> > "dns_server_%d_address4", i);
> bitwise and with a bool feels wrong. We should use && instead of & for
> boolean logic.

Since there is no &&= operator, I thought it's more readable with &=. The 
result is the same because of the way bool is defined. I'll convert it to 
logical operators for the v2 and then we'll see if it looks and feels better.

> > +  enum dns_security dnssec;
> > +  enum dns_server_transport transport;
> > +  char *sni;
> > +};
> 
> That should be probably be a const char* instead of a modifable char*

Right.

> >  gc_free(>gc);
> > 
> > +gc_free(>dns_options.gc);
> 
> having an extra gc in this way feels a bit strange. Since this is the
> only time it is initialised you can just as well just use o->gc instead.

Actually no. The --dns option is a bit special as it can partially replace 
local setting with pushed ones (i.e. override single dns servers and others 
not). The contained gc is used to allocate (and free) pulled options. If we'd 
use o->gc as well, the pulled options wouldn't be freed for a potentially long 
time, increasing the memory footprint over time.
 
> > +struct gc_arena dns_gc = gc_new();;
> 
> extra ;

Eagle eyes! =)

> > +/* Free DNS options and reset them to pre-pull state */
> > +gc_free(>dns_options.gc);
> 
> There is an additional free for the gc here that has no matching
> gc_init. If your goal is to have a gc for the life time of prepull etc,
> then it is better to put it there as that is easier to see its lifetime
> than to have it only for DNS where the lifetime/ownership is not so clear.

The accompanying gc_init() is with the one for o->gc. Don't see how moving the 
gc into struct options_pre_connect would change anything substantially. The 
gc_init would still be done in init_options() then.

> I see also that this code makes no attempt to remove/refactor the old
> DHCP code. The only thing I see is the tuntap_options_copy_dns code.
> What the supposed way forward here? That also raises the question about
> platform specific code. Does that code now need two implementations? One
> for installing options from the dhcp structs and one from the DNS struct?
> 
> Some idea how this is going to go forward would be good.

There are several ideas. Instead of having a #ifdef hell, like for other 
platform specific code, I would prefer some sort of "dns plugin / script" way, 
where platform specific code could reside in individual units and linked / 
called on a on-demand basis. 

Re: [Openvpn-devel] [PATCH] add support for --dns option

2022-03-09 Thread Arne Schwabe

Am 09.03.22 um 00:06 schrieb Heiko Hund:

+
+bool dns_server_priority_parse(long *priority, const char *str, bool pulled);
+struct dns_server* dns_server_get(struct dns_server **entry, long priority, 
struct gc_arena *gc);
+void dns_domain_list_append(struct dns_domain **entry, char **domains, struct 
gc_arena *gc);
+bool dns_server_addr_parse(struct dns_server *server, const char *addr);
+bool dns_options_verify(int msglevel, const struct dns_options *o);
+struct dns_options clone_dns_options(const struct dns_options o, struct 
gc_arena *gc);
+void dns_options_preprocess_pull(struct dns_options *o);
+void dns_options_postprocess_pull(struct dns_options *o);
+void setenv_dns_options(const struct dns_options *o, struct env_set *es);
+void show_dns_options(const struct dns_options *o);


These new functions are missing doxygen comments. We generally have the 
doxygen comments in the header files rather than in the c files.



+--dns args
+  Client DNS configuration to be used with the connection.


This man page section sounds like all options are supported on all 
platforms while currently that is not the case. An explicit warning etc 
that says that some options like port, dnssec, doh etc are not supported 
on certain platforms should be included and also what happens if they 
are not.



 The ``--dns`` option will eventually obsolete the ``--dhcp-option`` directive.
+  Until then it will add configuration at the places ``--dhcp-option`` puts it
+  and will override it if both are given.


Is dhcp-option ignored when dns is present by newer client or are they 
mixed? This is a bit vague.




+  long priority;


why a type that is 32 bit on some platforms and 64 bit on others? Either 
go with just int if 32 bit is enough or use long long or int64_t if we 
need 64 but long is a weird type.



+name_ok &= openvpn_snprintf(env_name, sizeof(env_name), 
"dns_server_%d_address4", i);


bitwise and with a bool feels wrong. We should use && instead of & for 
boolean logic.



+  enum dns_security dnssec;
+  enum dns_server_transport transport;
+  char *sni;
+};


That should be probably be a const char* instead of a modifable char*


 gc_free(>gc);
+gc_free(>dns_options.gc);


having an extra gc in this way feels a bit strange. Since this is the 
only time it is initialised you can just as well just use o->gc instead.




+struct gc_arena dns_gc = gc_new();;


extra ;

+/* Free DNS options and reset them to pre-pull state */
+gc_free(>dns_options.gc);


There is an additional free for the gc here that has no matching 
gc_init. If your goal is to have a gc for the life time of prepull etc, 
then it is better to put it there as that is easier to see its lifetime 
than to have it only for DNS where the lifetime/ownership is not so clear.



I see also that this code makes no attempt to remove/refactor the old 
DHCP code. The only thing I see is the tuntap_options_copy_dns code. 
What the supposed way forward here? That also raises the question about 
platform specific code. Does that code now need two implementations? One 
for installing options from the dhcp structs and one from the DNS struct?


Some idea how this is going to go forward would be good.

Arne


___
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel


Re: [Openvpn-devel] [PATCH] add support for --dns option

2022-03-09 Thread Frank Lichtenheld
Acked-By: Frank Lichtenheld 

I have reviewed this on Github already and had no further issues.

> Heiko Hund  hat am 09.03.2022 00:06 geschrieben:
> 
>  
> As a first step towards DNS configuration in openvpn and a unified way
> to push DNS related settings to clients in v2 and v3, this commit adds
> support for parsing the new --dns option. Later commits will add support
> for setting up DNS on different platforms.
> 
> For now, --dns and DNS related --dhcp-option can be used together for
> smoother transition. Settings from --dns will override ones --dhcp-option
> where applicable.
> 
> For detailed information about the option consult the documentation in
> this commit.
> 
> Signed-off-by: Heiko Hund 

Grüße,
--
Frank Lichtenheld


___
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel


[Openvpn-devel] [PATCH] add support for --dns option

2022-03-08 Thread Heiko Hund
As a first step towards DNS configuration in openvpn and a unified way
to push DNS related settings to clients in v2 and v3, this commit adds
support for parsing the new --dns option. Later commits will add support
for setting up DNS on different platforms.

For now, --dns and DNS related --dhcp-option can be used together for
smoother transition. Settings from --dns will override ones --dhcp-option
where applicable.

For detailed information about the option consult the documentation in
this commit.

Signed-off-by: Heiko Hund 
---
 doc/man-sections/client-options.rst |  55 +++
 doc/man-sections/script-options.rst |  19 +
 doc/man-sections/server-options.rst |   2 +-
 src/openvpn/Makefile.am |   1 +
 src/openvpn/dns.c   | 561 
 src/openvpn/dns.h   |  89 +
 src/openvpn/openvpn.vcxproj |   4 +-
 src/openvpn/openvpn.vcxproj.filters |   8 +-
 src/openvpn/options.c   | 221 +++
 src/openvpn/options.h   |   7 +
 src/openvpn/push.c  |   4 +
 src/openvpn/socket.c|  11 +
 src/openvpn/socket.h|   2 +
 13 files changed, 981 insertions(+), 3 deletions(-)
 create mode 100644 src/openvpn/dns.c
 create mode 100644 src/openvpn/dns.h

diff --git a/doc/man-sections/client-options.rst 
b/doc/man-sections/client-options.rst
index 92a02e28..bdfe6aac 100644
--- a/doc/man-sections/client-options.rst
+++ b/doc/man-sections/client-options.rst
@@ -154,6 +154,61 @@ configuration.
 --connect-timeout n
   See ``--server-poll-timeout``.
 
+--dns args
+  Client DNS configuration to be used with the connection.
+
+  Valid syntaxes:
+  ::
+
+ dns search-domains domain [domain ...]
+ dns server n address addr[:port] [addr[:port]]
+ dns server n resolve-domains|exclude-domains domain [domain ...]
+ dns server n dnssec yes|optional|no
+ dns server n transport DoH|DoT|plain
+ dns server n sni server-name
+
+  The ``--dns search-domains`` directive takes one or more domain names
+  to be added as DNS domain suffixes. If it is repeated multiple times within
+  a configuration the domains are appended, thus e.g. domain names pushed by
+  a server will amend locally defined ones.
+
+  The ``--dns server`` directive is used to configure DNS server ``n``.
+  The server id ``n`` must be a value between -128 and 127. For pushed
+  DNS server options it must be between 0 and 127. The server id is used
+  to group options and also for ordering the list of configured DNS servers;
+  lower numbers come first. DNS servers being pushed to a client replace
+  already configured DNS servers with the same server id.
+
+  The ``address`` option configures the IPv4 and / or IPv6 address of
+  the DNS server. Optionally a port can be appended after a colon. IPv6
+  addresses need to be enclosed in brackets if a port is appended.
+
+  The ``resolve-domains`` and ``exclude-domains`` options take one or
+  more DNS domains which are explicitly resolved or explicitly not resolved
+  by a server. Only one of the options can be configured for a server.
+  ``resolve-domains`` is used to define a split-dns setup, where only
+  given domains are resolved by a server. ``exclude-domains`` is used to
+  define domains which will never be resolved by a server (e.g. domains
+  which can only be resolved locally). Systems which do not support fine
+  grained DNS domain configuration, will ignore these settings.
+
+  The ``dnssec`` option is used to configure validation of DNSSEC records.
+  While the exact semantics may differ for resolvers on different systems,
+  ``yes`` likely makes validation mandatory, ``no`` disables it, and 
``optional``
+  uses it opportunistically.
+
+  The ``transport`` option enables DNS-over-HTTPS (``DoH``) or DNS-over-TLS 
(``DoT``)
+  for a DNS server. The ``sni`` option can be used with them to specify the
+  ``server-name`` for TLS server name indication.
+
+  Each server has to have at least one address configured for a configuration
+  to be valid. All the other options can be omitted.
+
+  The ``--dns`` option will eventually obsolete the ``--dhcp-option`` 
directive.
+  Until then it will add configuration at the places ``--dhcp-option`` puts it
+  and will override it if both are given. So, ``--dns`` can be used today to
+  migrate from ``--dhcp-option``.
+
 --explicit-exit-notify n
   In UDP client mode or point-to-point mode, send server/peer an exit
   notification if tunnel is restarted or OpenVPN process is exited. In
diff --git a/doc/man-sections/script-options.rst 
b/doc/man-sections/script-options.rst
index 22990f4f..c81efe9e 100644
--- a/doc/man-sections/script-options.rst
+++ b/doc/man-sections/script-options.rst
@@ -586,6 +586,25 @@ instances.
 netsh.exe calls which sometimes just do not work right with interface
 names). Set prior to ``--up`` or ``--down`` script execution.
 
+:code:`dns_*`
+The ``--dns`` configuration options will