Skip to content

Comments

Fix default installation paths on mingw [1.1.1]#9400

Closed
levitte wants to merge 1 commit intoopenssl:OpenSSL_1_1_1-stablefrom
levitte:fix-insecure-default-paths
Closed

Fix default installation paths on mingw [1.1.1]#9400
levitte wants to merge 1 commit intoopenssl:OpenSSL_1_1_1-stablefrom
levitte:fix-insecure-default-paths

Conversation

@levitte
Copy link
Member

@levitte levitte commented Jul 17, 2019

Mingw config targets assumed that resulting programs and libraries are
installed in a Unix-like environment and the default installation
prefix was therefore set to '/usr/local'.

However, mingw programs are installed in a Windows environment, and
the installation directories should therefore have Windows defaults,
i.e. the same kind of defaults as the VC config targets.

A difficulty is, however, that a "cross compiled" build can't figure
out the system defaults from environment the same way it's done when
building "natively", so we have to fall back to hard coded defaults in
that case.

Tests can still be performed when cross compiled on a non-Windows
platform, since all tests only depend on the source and build
directory, and otherwise relies on normal local paths.

@levitte levitte added 1.1.0 branch: 1.1.1 Applies to OpenSSL_1_1_1-stable branch (EOL) labels Jul 17, 2019
@levitte
Copy link
Member Author

levitte commented Jul 17, 2019

Note that this is for 1.1.1 and probably 1.1.0, not for master. For master, I plan on using the platform perl modules to get paths right, which is completely different from this solution.

@levitte levitte force-pushed the fix-insecure-default-paths branch from 783395f to 56f3cb5 Compare July 17, 2019 14:40
@levitte
Copy link
Member Author

levitte commented Jul 17, 2019

Oh, I just realised this is an issue on 1.0.2 as well... not installation wise, but certainly when it comes to the default OPENSSLDIR

@petrovr
Copy link

petrovr commented Jul 17, 2019 via email

@levitte
Copy link
Member Author

levitte commented Jul 17, 2019

The proposed mingw paths mimic quite exactly the paths used with a VC build. As I've understood it, it's not at all certain that a program built with mingw toolchains are run in a full fledged mingw environment.

@mattcaswell
Copy link
Member

The proposed mingw paths mimic quite exactly the paths used with a VC build. As I've understood it, it's not at all certain that a program built with mingw toolchains are run in a full fledged mingw environment.

Right. I don't understand @petrovr's concern. The point is that if you are using the mingw toolchain you are (probably) intending the resulting binaries to be used on "native" Windows and not inside a posix environment. Therefore default paths should be correct for native Windows (as is done with VC builds).

@petrovr
Copy link

petrovr commented Jul 19, 2019 via email

@levitte
Copy link
Member Author

levitte commented Jul 20, 2019

The real problem is OPENSSLDIR and ENGINESDIR, which currently default to /usr/local/ssl and /usr/local/lib/engines-1.1 respectively, and are saved as such in the library.

As far as I understand, once in code, these paths are not translated to anything Windowsy by open() or fopen(), so they end up being interpreted as C:\usr\local\ssl and C:\usr\local\lib\engines-1.1 (C might be another device, but that doesn't really matter) by the underlying Windows RTLs.

@petrovr
Copy link

petrovr commented Jul 20, 2019 via email

@levitte
Copy link
Member Author

levitte commented Jul 22, 2019

Another way to resolve issue is 'package manager'. During installation some paths are stored into registry and then project code reads from them. This give another 'relocatable' solution - database (file) that maps a number of locations(paths) to real installation.

What should happen when those registry keys aren't present? Are we supposed to add such keys in our installation targets? What paths should they have? ... see how it still gets back to defining some kind of default path for stuff?

@petrovr
Copy link

petrovr commented Jul 22, 2019 via email

@levitte
Copy link
Member Author

levitte commented Jul 23, 2019

It could be implemented with project specific 'file'

So OK, a single path. Still something that needs a default.

Also, mind you, this is for 1.1.1. We can't radically change it to suddenly require this information to exist in the config file ('cause that's the idea, right?)

Mingw config targets assumed that resulting programs and libraries are
installed in a Unix-like environment and the default installation
prefix was therefore set to '/usr/local'.

However, mingw programs are installed in a Windows environment, and
the installation directories should therefore have Windows defaults,
i.e. the same kind of defaults as the VC config targets.

A difficulty is, however, that a "cross compiled" build can't figure
out the system defaults from environment the same way it's done when
building "natively", so we have to fall back to hard coded defaults in
that case.

Tests can still be performed when cross compiled on a non-Windows
platform, since all tests only depend on the source and build
directory, and otherwise relies on normal local paths.

CVE-2019-1552
@levitte levitte force-pushed the fix-insecure-default-paths branch from 56f3cb5 to 3c83dbb Compare July 25, 2019 11:08
@mattcaswell mattcaswell added the approval: done This pull request has the required number of approvals label Jul 25, 2019
levitte added a commit that referenced this pull request Jul 25, 2019
Mingw config targets assumed that resulting programs and libraries are
installed in a Unix-like environment and the default installation
prefix was therefore set to '/usr/local'.

However, mingw programs are installed in a Windows environment, and
the installation directories should therefore have Windows defaults,
i.e. the same kind of defaults as the VC config targets.

A difficulty is, however, that a "cross compiled" build can't figure
out the system defaults from environment the same way it's done when
building "natively", so we have to fall back to hard coded defaults in
that case.

Tests can still be performed when cross compiled on a non-Windows
platform, since all tests only depend on the source and build
directory, and otherwise relies on normal local paths.

CVE-2019-1552

Reviewed-by: Matt Caswell <[email protected]>
(Merged from #9400)
@levitte
Copy link
Member Author

levitte commented Jul 25, 2019

Merged.

1.1.1:
54aa9d5 Fix default installation paths on mingw

The 1.1.0 port wasn't as simple as clean cherry-pick. I will add another PR to that effect.

@levitte
Copy link
Member Author

levitte commented Jul 25, 2019

#9460

@levitte levitte closed this Jul 25, 2019
@vszakats
Copy link
Contributor

vszakats commented Aug 2, 2019

First of all, thanks for this fix!

After reviewing the commit, I have one remark and one question:

  1. The current defaulting logic remains having an issue for 32-bit (mingw) builds. In this scenario the default prefixes now begin with C:/Program Files (x86)/OpenSSL/. This path however, only exists on 64-bit Windows systems, and missing on 32-bit Windows installations and thus can be created by a non-admin freely. This means that a 32-bit Windows build of OpenSSL, running on a 32-bit Windows install remains vulnerable to the code injection. My local mitigation for this was to use a prefix under C:/Windows/, which exists regardless of Windows flavour and where non-admins can't create new files and directories.

  2. Is it now possible to manually set PREFIX/OPENSSLDIR/--prefix= to a custom, Windows path in a cross-build scenario?

    With the last stable releases this fails, because Windows absolute paths were misdetected as relative ones, making the build process bail out early with the error: Directory given with --prefix MUST be absolute. Another issue was that when passing a prefix containing spaces, the build process broke due to unquoted build paths that got the prefix appended to them. I could only fix the first issue by patching Configure, and the second one by using (once again) C:/Windows/ prefix, which has no spaces.

@levitte
Copy link
Member Author

levitte commented Aug 2, 2019

Regarding 2: yes, it should be possible to do. We specifically use File::Spec::Win32 with mingw in the Makefile template, so Windows path semantics apply. Feel free to try that out, I haven't tested that very much, so if there are kinks that need sorting out, now's the time!

@levitte
Copy link
Member Author

levitte commented Aug 2, 2019

Regarding 1: I have a hard time seeing C:/Windows/ as a feasible choice, I'd rather leave that space to Microsoft. So question is how to behave... you're entirely right that we assume a 64-bit Windows environment, even for 32-bit builds, simply because that is pretty much norm today (why Microsoft thought it was wise to reuse the old name for the new stuff and give old stuff a new name, I cannot understand)...

@vszakats
Copy link
Contributor

vszakats commented Aug 2, 2019

@levitte: Yes, C:/Windows/ isn't ideal either for different reasons. In fact for Windows it'd be perhaps most ideal to have an option to disable all dynamic library and config loads from fixed locations, precisely because on Windows there is no such fixed common location as /usr/local or /etc/ on *nix systems. [ As for these names, with reuse, spaces and all, well, ¯\_(ツ)_/¯ ]

Back to 1; I've made a cross-compile test (from macOS to mingw64) with latest master, and experiencing the same error as before:

./Configure mingw64 \
  --cross-compile-prefix=x86_64-w64-mingw32- \
  --prefix=C:/Windows/System32/OpenSSL

output:

Failure!  build file wasn't produced.
Please read INSTALL and associated NOTES files.  You may also have to look over
your available compiler tool chain or change your configuration.

Directory given with --prefix MUST be absolute

The one with a vulnerable-on-Windows *nix path builds fine:

./Configure mingw64 \
  --cross-compile-prefix=x86_64-w64-mingw32- \
  --prefix=/usr/local

The check is done in lines below in Configure, and it uses a bare call into Perl's native file_name_is_absolute(), where that function only works correctly on paths matching Perl's platform, which is in this case: This is perl 5, version 30, subversion 0 (v5.30.0) built for darwin-thread-multi-2level.

        elsif (/^[-+]/)
                {
                if (/^--prefix=(.*)$/)
                        {
                        $config{prefix}=$1;
                        die "Directory given with --prefix MUST be absolute\n"
                                unless file_name_is_absolute($config{prefix});
                        }

@levitte
Copy link
Member Author

levitte commented Aug 2, 2019

Ah, thanks for the pointer, I forgot to look there...

It will take a few days before I can do anything with this, though... I'm essentially away from the computer until next Thursday.

@vszakats
Copy link
Contributor

vszakats commented Aug 2, 2019

No worries/hurries, I got this for now with a simple patch, just take any time you need. Feel free to drop me a line to make tests.

@levitte
Copy link
Member Author

levitte commented Aug 2, 2019

Would you mind creating an issue? That would be helpful, as closed PRs are a bit hard for me to keep track of...

@vszakats
Copy link
Contributor

vszakats commented Aug 2, 2019

Fair point! — I've opened a new one here: #9520

@vszakats
Copy link
Contributor

It turns out that C:\Program Files*\ is a localized name, so it will be something else on certain non-English Windows versions. It mean this current hard-coded default is even worse that originally thought. As suggested earlier this summer, it'd be best to fully disable the use of hard-coded path in Windows builds, or if this isn't something acceptable for OpenSSL, it'd be better to use C:\Windows\[...], which has a somewhat better chance to be a non-writable folder on most systems. It also lacks a space, so it would actually work with the current build system, when cross-built.

@levitte
Copy link
Member Author

levitte commented Oct 15, 2019

Yeah, that might be the better solution, really, to simply refuse to configure without at least --prefix set. That's actually a fairly easy thing to do...

I won't do it immediately, but will keep that in mind.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approval: done This pull request has the required number of approvals branch: 1.1.1 Applies to OpenSSL_1_1_1-stable branch (EOL)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants