Re: Enforce encryption client-side

2021-05-07 Thread Daniel Shahaf
Nils-Johan Andreasson wrote on Fri, May 07, 2021 at 15:41:47 +0200:
> On Thu, May 6, 2021 at 3:24 PM Daniel Shahaf  wrote:
> 
> > Nils-Johan Andreasson wrote on Thu, May 06, 2021 at 14:48:01 +0200:
> > > I have indeed considered svn+ssh but there are other details involved
> > which
> > > makes me prefer to stay with svnserve and svn:// if possible.
> >
> > Does your library consider svn+foo:// secure?  If so, you can define an
> > svn+foo:// scheme that simply wraps plain old TCP sockets.  You have two
> > options for that, even: either «svn+nc://hostname/path» that uses nc(1)
> > or socat(1) to wrap a plain TCP socket, or a scheme that hardcodes
> > a specific hostname, that you then use in URLs whose hostname component is
> > ignored (can actually be left empty).
> 
> Clever!
> The library does indeed only consider svn:// insecure and it does not
> validate the scheme other than that. So, this would work (although it of
> course requires some configuration in the places I want to use it, but I
> can live with that).
> 
> It took me some reading and fiddling though to get this to work completely.
> nc wants parameters as 'nc  '.
> The command defined in subversion config under [tunnels] is called as:
>   svnserve -t
⋮
> Which in the end makes a command such as this work like a charm:
> svn info svn+nc://hostname:3699
> 
> Maybe you had a simpler way of achieving the same in mind?

No.  You _could_ inline the wrapper script into the configuration, along
these lines:
.
[tunnels]
nc = $SUBVERSION_TUNNEL_NC sh -c 'nc ${1%:*} ${1##*:}' :
.
but other than that, what you did is exactly what I had in mind.  Sorry
it wasn't clear the first time.

BTW, to support the default port:
.
nc = $SUBVERSION_TUNNEL_NC sh -c 'case $1 in *:*) ;; *) set -- ${1}:3690;; 
esac && nc ${1%:*} ${1##*:}' :

I've committed a related clarification in https://svn.apache.org/r1889629.
Thanks for raising that.

The other approach I described was to define a tunnel such as
.
[tunnels]
bar = $BAR sh -c "nc lorem.bar.example 3690"
.
which can then be used as «svn+bar:///some/path» with an empty hostname
component.  I used to do this, for two reasons: it made the URLs
shorter, and it let me change the SSH jumphost centrally across all my
working copies.

> In any case, thanks a lot all for your helpful inputs and suggestions -
> made my day!

You're welcome.

Daniel


Re: Enforce encryption client-side

2021-05-07 Thread Nils-Johan Andreasson
Clever!
The library does indeed only consider svn:// insecure and it does not
validate the scheme other than that. So, this would work (although it of
course requires some configuration in the places I want to use it, but I
can live with that).

It took me some reading and fiddling though to get this to work completely.
nc wants parameters as 'nc  '.
The command defined in subversion config under [tunnels] is called as:
  svnserve -t

This will make nc treat "svnserve" as the port and therefore refuse it.
Specifying hostname as hostname:port will not work either.

For now, I wrote a small bash script "nc-forwarder" with the following
contents:

#!/bin/bash
nc $(echo $1 | sed 's/:/ /g')

Made it executable
chmod +x nc-forwarder

Put it in the config:
[tunnels]
nc = /home/xx/.subversion/nc-forwarder

When run it simply executes nc with the first argument. In my case I use a
custom port so it replaces the colon with space which works great with nc.
If no custom port is used you can always add :3690 (or enhance the bash
script further to set that as default port).
All other arguments (svnserve -t) are at the same time scrapped.

Which in the end makes a command such as this work like a charm:
svn info svn+nc://hostname:3699

Maybe you had a simpler way of achieving the same in mind?

In any case, thanks a lot all for your helpful inputs and suggestions -
made my day!

Best regards,

Nils-Johan


On Thu, May 6, 2021 at 3:24 PM Daniel Shahaf  wrote:

> Nils-Johan Andreasson wrote on Thu, May 06, 2021 at 14:48:01 +0200:
> > I have indeed considered svn+ssh but there are other details involved
> which
> > makes me prefer to stay with svnserve and svn:// if possible.
>
> Does your library consider svn+foo:// secure?  If so, you can define an
> svn+foo:// scheme that simply wraps plain old TCP sockets.  You have two
> options for that, even: either «svn+nc://hostname/path» that uses nc(1)
> or socat(1) to wrap a plain TCP socket, or a scheme that hardcodes
> a specific hostname, that you then use in URLs whose hostname component is
> ignored (can actually be left empty).
>


Re: Enforce encryption client-side

2021-05-06 Thread Stefan Sperling
On Thu, May 06, 2021 at 09:15:44AM -0400, Mark Phippard wrote:
> I am not familiar with the SASL options in the client config

Neither was I, and after some investigation of the code I concluded
that there are none. They're only available in svnserve/libsvn_repos.
Client-side support for these options would need to be added in order
to satisfy the use case under discussion.


Re: Enforce encryption client-side

2021-05-06 Thread Daniel Shahaf
Nils-Johan Andreasson wrote on Thu, May 06, 2021 at 13:03:28 +0200:
> Thanks Stefan for your response and pointers!
> 
> There is no doubt my connections are already encrypted.
> The issue is that the external library I'm referring to supports specifying
> paths to source code using multiple protocols, e.g. svn:// (but also
> https://, http://, git://, ftp:// etc) and any svn:// source is generally
> considered insecure, just like http:// (but not for example https://). It
> is not verified in any way if that's actually the case, it's just based on
> the scheme prefix svn://
> 
> Using something like that I can hopefully convince the library maintainer
> to enable this flag by default and then consider an svn:// source secure by
> default (as connection would otherwise not succeed).

You could also point out to the library author that treating svn://foo/
as insecure would be wrong when foo is an IP address on a VPN, or
a loopback address, or an address of a virtualized box running on the same
hardware, and so on, even if no encryption is used at all.

Cheers,

Daniel


> I understand your point with that as long as "use-sasl = true" is
> configured on the server, the connection would abort if the client cannot
> communicate securely. However, this means that if this external library is
> pointed to a svn:// source with "use-sasl = false" the connection would
> succeed, which is what I'm trying to prevent here to guarantee no
> unencrypted connections are made.
> 
> Hope my point came through better this time?
> 
> Best regards,
> 
> Nils-Johan
> 
> 
> On Thu, May 6, 2021 at 11:40 AM Stefan Sperling  wrote:
> 
> > On Thu, May 06, 2021 at 11:21:57AM +0200, Nils-Johan Andreasson wrote:
> > > Hi there!
> > >
> > > I'm serving a repository using svnserve with SASL to make sure
> > > communication is always encrypted (config has use-sasl = true,
> > > min-encryption = 128 and max-encryption = 256).
> > > I know this enforces encryption server-side but is there any way to in
> > > addition also "require" encryption client-side? E.g. let's say if I do
> > 'svn
> > > checkout svn://my-insecure-host/repository' I want the command to abort
> > if
> > > the connection is not encrypted.
> >
> > The min-encryption paramter maps directly to the Cyrus SASL
> > secprops.min_ssf
> > paramter which is described here:
> >
> > https://www.cyrusimap.org/sasl/sasl/developer/programming.html#security-layers
> >
> > Quote:
> > "A connection supplying only integrity with no privacy would have an SSF
> > of 1.
> > A connection secured by 56-bit DES would have an SSF of 56.
> > To require a security layer, set min_ssf to the minimum acceptable security
> > layer strength."
> >
> > SVN servers and clients check the SASL_SSF property of their connection
> > here
> > and abort if SASL failed to negotiate encryption if encryption is
> > configured:
> >
> > https://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_svn/cyrus_auth.c?revision=1875971=markup#l726
> >
> > So your connections should already be encrypted. Perhaps the encryption
> > mechanism SASL is using is considered too weak by your external tool?
> > Would setting min-encryption = 256 help?
> > Or perhaps your external tool simply doesn't understand the SVN protocol?
> >
> > Cheers,
> > Stefan
> >


Re: Enforce encryption client-side

2021-05-06 Thread Daniel Shahaf
Nils-Johan Andreasson wrote on Thu, May 06, 2021 at 14:48:01 +0200:
> Is there a way (command) to remotely determine if the svn server behind
> 'hostname' has sasl enabled/uses encryption/enforces a min_ssf >= 128?
> Preferably without having to send any authentication credentials (to not
> risk sending anything in clear text).

Possibly.  Look into the handshake in subversion/libsvn_ra_svn/protocol,
Section 2, specifically the «auth-request» line (the second thing the
server sends).

You can try it on a toy example like this:

% svnadmin create r
% ${EDITOR:-ed} r/conf/svnserve.conf
% printf '%s\n' '( 2 ( edit-pipeline ) 17:svn://localhost/r )' | svnserve 
-i -r ./

Or on a real server with something like this:

% printf '( 2 ( edit-pipeline ) %d:%s )\n' "$(printf %s "$url" | wc -c)" 
"$url" | nc $url 3690

When I do that I get "Could not obtain the list of SASL mechanisms"
(E170001 SVN_ERR_RA_NOT_AUTHORIZED), but you should get an actual
response.  Does that response provide the information you seek?

> If so, an initialization step could hopefully be added which determines
> whether the source is deemed to be secure to access or not.


Re: Enforce encryption client-side

2021-05-06 Thread Daniel Shahaf
Nils-Johan Andreasson wrote on Thu, May 06, 2021 at 14:48:01 +0200:
> I have indeed considered svn+ssh but there are other details involved which
> makes me prefer to stay with svnserve and svn:// if possible.

Does your library consider svn+foo:// secure?  If so, you can define an
svn+foo:// scheme that simply wraps plain old TCP sockets.  You have two
options for that, even: either «svn+nc://hostname/path» that uses nc(1)
or socat(1) to wrap a plain TCP socket, or a scheme that hardcodes
a specific hostname, that you then use in URLs whose hostname component is
ignored (can actually be left empty).


Re: Enforce encryption client-side

2021-05-06 Thread Mark Phippard
On Thu, May 6, 2021 at 8:57 AM Nils-Johan Andreasson
 wrote:
>
> Thanks for excellent input!
>
> Unfortunately this external library is being very widely used and is not 
> shipped with svn included. Rather it relies on being able to use svn if 
> detected as installed on the system, so simply waiting for a new release 
> wouldn't be an option to make a library-wide change.
>
> The only other work-around I can come to think of would be if there is a way 
> to probe whether a server uses/requires encryption for communication.
> Let's say I access svn://hostname/repository
> Is there a way (command) to remotely determine if the svn server behind 
> 'hostname' has sasl enabled/uses encryption/enforces a min_ssf >= 128?
> Preferably without having to send any authentication credentials (to not risk 
> sending anything in clear text).
> If so, an initialization step could hopefully be added which determines 
> whether the source is deemed to be secure to access or not.
>
> I have indeed considered svn+ssh but there are other details involved which 
> makes me prefer to stay with svnserve and svn:// if possible.

All commands already accept the --config-option, so you could just
cherry pick something from your existing client configuration that you
pass on the command line and then ask your library to look for the
presence of that option(s) as a sign that the connection is encrypted.
I am not familiar with the SASL options in the client config, but this
is an example from the documentation:

--config-option servers:global:http-library=serf

So any value from the servers or config file can be passed on the command line.

Hope this helps

Mark


Re: Enforce encryption client-side

2021-05-06 Thread Nils-Johan Andreasson
Thanks for excellent input!

Unfortunately this external library is being very widely used and is not
shipped with svn included. Rather it relies on being able to use svn if
detected as installed on the system, so simply waiting for a new release
wouldn't be an option to make a library-wide change.

The only other work-around I can come to think of would be if there is a
way to probe whether a server uses/requires encryption for communication.
Let's say I access svn://hostname/repository
Is there a way (command) to remotely determine if the svn server behind
'hostname' has sasl enabled/uses encryption/enforces a min_ssf >= 128?
Preferably without having to send any authentication credentials (to not
risk sending anything in clear text).
If so, an initialization step could hopefully be added which determines
whether the source is deemed to be secure to access or not.

I have indeed considered svn+ssh but there are other details involved which
makes me prefer to stay with svnserve and svn:// if possible.

Best regards,

Nils-Johan


On Thu, May 6, 2021 at 1:52 PM Stefan Sperling  wrote:

> On Thu, May 06, 2021 at 01:03:28PM +0200, Nils-Johan Andreasson wrote:
> > Thanks Stefan for your response and pointers!
> >
> > There is no doubt my connections are already encrypted.
> > The issue is that the external library I'm referring to supports
> specifying
> > paths to source code using multiple protocols, e.g. svn:// (but also
> > https://, http://, git://, ftp:// etc) and any svn:// source is
> generally
> > considered insecure, just like http:// (but not for example https://).
> It
> > is not verified in any way if that's actually the case, it's just based
> on
> > the scheme prefix svn://
> >
> > So, what I'm looking for is a way to ensure an svn client command is only
> > allowed to execute if using an encrypted transport. E.g. something like:
> > svn --enforce-encryption checkout svn://hostname/repository
> > svn --min-encryption 128 checkout svn://hostname/repository
> > (or --disallow-unencrypted-transport, --require-sasl etc)
> >
> > Using something like that I can hopefully convince the library maintainer
> > to enable this flag by default and then consider an svn:// source secure
> by
> > default (as connection would otherwise not succeed).
> >
> > I understand your point with that as long as "use-sasl = true" is
> > configured on the server, the connection would abort if the client cannot
> > communicate securely. However, this means that if this external library
> is
> > pointed to a svn:// source with "use-sasl = false" the connection would
> > succeed, which is what I'm trying to prevent here to guarantee no
> > unencrypted connections are made.
> >
> > Hope my point came through better this time?
>
> Yes. It seems indeed impossible to enforce a min_sff parameter other than
> zero on the client side at present, which is an unfortunate omission.
> I am sure there is no technical reason which would prevent this from
> becoming configurable.
>
> If you or the third-party library maintainer are compiling your own
> client binaries, the easy way to fix this would be to set min_ssf here:
>
> https://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_svn/cyrus_auth.c?view=markup#l276
>
> When adding this an official Subversion feature, I would suggest to
> expose the SASL configuration parameters that svnserve is already using
> as part of the client-side configuration, and then ensuring that these
> parameters are applied after svn_ra_svn__default_secprops() is called.
> Note that any configuration file parameters can also be specified on
> the command line via the --config-option option so you won't necessarily
> need to add a new separate option to the command line interface if this
> feature gets implemented via config file options.
>
> I agree that this would be useful. However, someone would need to write
> a patch, and then you would have to wait for a Subversion 1.15 release
> to ship since this feature cannot be added in a 1.14 patch release due
> to our compatibility promises (a clean roll-back from 1.14.Y to 1.14.X
> without any configuration/parameter changes must remain possible). And
> your third party library would need to upgrade to that version once it
> has been released. All of this could take many months.
>
> Have you considered using svn+ssh instead?
>
> Cheers,
> Stefan
>


Re: Enforce encryption client-side

2021-05-06 Thread Stefan Sperling
On Thu, May 06, 2021 at 01:03:28PM +0200, Nils-Johan Andreasson wrote:
> Thanks Stefan for your response and pointers!
> 
> There is no doubt my connections are already encrypted.
> The issue is that the external library I'm referring to supports specifying
> paths to source code using multiple protocols, e.g. svn:// (but also
> https://, http://, git://, ftp:// etc) and any svn:// source is generally
> considered insecure, just like http:// (but not for example https://). It
> is not verified in any way if that's actually the case, it's just based on
> the scheme prefix svn://
> 
> So, what I'm looking for is a way to ensure an svn client command is only
> allowed to execute if using an encrypted transport. E.g. something like:
> svn --enforce-encryption checkout svn://hostname/repository
> svn --min-encryption 128 checkout svn://hostname/repository
> (or --disallow-unencrypted-transport, --require-sasl etc)
> 
> Using something like that I can hopefully convince the library maintainer
> to enable this flag by default and then consider an svn:// source secure by
> default (as connection would otherwise not succeed).
> 
> I understand your point with that as long as "use-sasl = true" is
> configured on the server, the connection would abort if the client cannot
> communicate securely. However, this means that if this external library is
> pointed to a svn:// source with "use-sasl = false" the connection would
> succeed, which is what I'm trying to prevent here to guarantee no
> unencrypted connections are made.
> 
> Hope my point came through better this time?

Yes. It seems indeed impossible to enforce a min_sff parameter other than
zero on the client side at present, which is an unfortunate omission.
I am sure there is no technical reason which would prevent this from
becoming configurable.

If you or the third-party library maintainer are compiling your own
client binaries, the easy way to fix this would be to set min_ssf here:
https://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_svn/cyrus_auth.c?view=markup#l276

When adding this an official Subversion feature, I would suggest to
expose the SASL configuration parameters that svnserve is already using
as part of the client-side configuration, and then ensuring that these
parameters are applied after svn_ra_svn__default_secprops() is called.
Note that any configuration file parameters can also be specified on
the command line via the --config-option option so you won't necessarily
need to add a new separate option to the command line interface if this
feature gets implemented via config file options.

I agree that this would be useful. However, someone would need to write
a patch, and then you would have to wait for a Subversion 1.15 release
to ship since this feature cannot be added in a 1.14 patch release due
to our compatibility promises (a clean roll-back from 1.14.Y to 1.14.X
without any configuration/parameter changes must remain possible). And
your third party library would need to upgrade to that version once it
has been released. All of this could take many months.

Have you considered using svn+ssh instead?

Cheers,
Stefan


Re: Enforce encryption client-side

2021-05-06 Thread Nils-Johan Andreasson
Thanks Stefan for your response and pointers!

There is no doubt my connections are already encrypted.
The issue is that the external library I'm referring to supports specifying
paths to source code using multiple protocols, e.g. svn:// (but also
https://, http://, git://, ftp:// etc) and any svn:// source is generally
considered insecure, just like http:// (but not for example https://). It
is not verified in any way if that's actually the case, it's just based on
the scheme prefix svn://

So, what I'm looking for is a way to ensure an svn client command is only
allowed to execute if using an encrypted transport. E.g. something like:
svn --enforce-encryption checkout svn://hostname/repository
svn --min-encryption 128 checkout svn://hostname/repository
(or --disallow-unencrypted-transport, --require-sasl etc)

Using something like that I can hopefully convince the library maintainer
to enable this flag by default and then consider an svn:// source secure by
default (as connection would otherwise not succeed).

I understand your point with that as long as "use-sasl = true" is
configured on the server, the connection would abort if the client cannot
communicate securely. However, this means that if this external library is
pointed to a svn:// source with "use-sasl = false" the connection would
succeed, which is what I'm trying to prevent here to guarantee no
unencrypted connections are made.

Hope my point came through better this time?

Best regards,

Nils-Johan


On Thu, May 6, 2021 at 11:40 AM Stefan Sperling  wrote:

> On Thu, May 06, 2021 at 11:21:57AM +0200, Nils-Johan Andreasson wrote:
> > Hi there!
> >
> > I'm serving a repository using svnserve with SASL to make sure
> > communication is always encrypted (config has use-sasl = true,
> > min-encryption = 128 and max-encryption = 256).
> > I know this enforces encryption server-side but is there any way to in
> > addition also "require" encryption client-side? E.g. let's say if I do
> 'svn
> > checkout svn://my-insecure-host/repository' I want the command to abort
> if
> > the connection is not encrypted.
>
> The min-encryption paramter maps directly to the Cyrus SASL
> secprops.min_ssf
> paramter which is described here:
>
> https://www.cyrusimap.org/sasl/sasl/developer/programming.html#security-layers
>
> Quote:
> "A connection supplying only integrity with no privacy would have an SSF
> of 1.
> A connection secured by 56-bit DES would have an SSF of 56.
> To require a security layer, set min_ssf to the minimum acceptable security
> layer strength."
>
> SVN servers and clients check the SASL_SSF property of their connection
> here
> and abort if SASL failed to negotiate encryption if encryption is
> configured:
>
> https://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_svn/cyrus_auth.c?revision=1875971=markup#l726
>
> So your connections should already be encrypted. Perhaps the encryption
> mechanism SASL is using is considered too weak by your external tool?
> Would setting min-encryption = 256 help?
> Or perhaps your external tool simply doesn't understand the SVN protocol?
>
> Cheers,
> Stefan
>


Re: Enforce encryption client-side

2021-05-06 Thread Stefan Sperling
On Thu, May 06, 2021 at 11:21:57AM +0200, Nils-Johan Andreasson wrote:
> Hi there!
> 
> I'm serving a repository using svnserve with SASL to make sure
> communication is always encrypted (config has use-sasl = true,
> min-encryption = 128 and max-encryption = 256).
> I know this enforces encryption server-side but is there any way to in
> addition also "require" encryption client-side? E.g. let's say if I do 'svn
> checkout svn://my-insecure-host/repository' I want the command to abort if
> the connection is not encrypted.

The min-encryption paramter maps directly to the Cyrus SASL secprops.min_ssf
paramter which is described here:
https://www.cyrusimap.org/sasl/sasl/developer/programming.html#security-layers

Quote:
"A connection supplying only integrity with no privacy would have an SSF of 1.
A connection secured by 56-bit DES would have an SSF of 56.
To require a security layer, set min_ssf to the minimum acceptable security
layer strength."

SVN servers and clients check the SASL_SSF property of their connection here
and abort if SASL failed to negotiate encryption if encryption is configured:
https://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_svn/cyrus_auth.c?revision=1875971=markup#l726

So your connections should already be encrypted. Perhaps the encryption
mechanism SASL is using is considered too weak by your external tool?
Would setting min-encryption = 256 help?
Or perhaps your external tool simply doesn't understand the SVN protocol?

Cheers,
Stefan


Enforce encryption client-side

2021-05-06 Thread Nils-Johan Andreasson
Hi there!

I'm serving a repository using svnserve with SASL to make sure
communication is always encrypted (config has use-sasl = true,
min-encryption = 128 and max-encryption = 256).
I know this enforces encryption server-side but is there any way to in
addition also "require" encryption client-side? E.g. let's say if I do 'svn
checkout svn://my-insecure-host/repository' I want the command to abort if
the connection is not encrypted.

The background to this question is that I'm using an external library which
sees all usage of svn:// protocol as insecure. In our case, it doesn't make
sense since we have encryption configured but to be able to use svn:// URLs
I need to configure this library to allow "insecure connections" which
affects a lot of other things and also creates warnings, unnecessarily.

My idea would be to suggest the library maintainer to let me configure an
additional parameter/config to supply to the svn binary to make sure
connection is only allowed if encrypted, e.g. 'svn --enforce-encryption
checkout svn://my-insecure-url/repository'. By that, the library could
trust connections to always be encrypted for a specific svn:// URL instead
of having to turn on a more library-wide "always allow unencrypted
connections" which is generally a bad idea.

Any ideas if this is achievable?

Thanks in advance!

Best regards,

NJ