Closed rodwiddowson closed 6 years ago
"win32" version="7.58.0.0"/> I (Rod) will add that making strings match versions is the way to madness and the only sensible way to proceed is to exbed this into a single config file and pass the value in to the build "Somehow".
Since #include "../include/curl/curlver.h"
is already included into libcurl.rc
, it's simple to add a MANIFEST_VERSION_STR
before "libcurl.manifest"
gets included by rc
. E.g.:
--- a/libcurl.rc 2017-01-19 19:43:19
+++ b/libcurl.rc 2018-02-22 16:15:53
@@ -22,7 +22,18 @@
#include <winver.h>
#include "../include/curl/curlver.h"
-LANGUAGE 0x09,0x01
+LANGUAGE 0, 0
+
+APPICON ICON "../curl.ico"
+
+#define _STR2(x) #x
+#define _STR(x) _STR2(x)
+
+#define MANIFEST_VERSION_STR _STR(LIBCURL_VERSION_MAJOR) "." \
+ _STR(LIBCURL_VERSION_MINOR) "." \
+ _STR(LIBCURL_VERSION_PATCH) ".0"
+
+CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "../lib/libcurl.manifest"
#define RC_VERSION LIBCURL_VERSION_MAJOR, LIBCURL_VERSION_MINOR, LIBCURL_VERSION_PATCH, 0
But I think manifests are not a good idea. And what is <winuser.h>
for?
download https://curl.haxx.se/favicon.ico and save it as "curl.ico" in the top level directory
add the file "lib/libcurl.manifest" to disable DLL hijacking per external manifest, and more
add the file "src/curl.manifest" to disable DLL hijacking per external manifest, and more
These are architecture-specific files: would'nt it be better (if possible) to store them in the corresponding architecture subdirectory ?
I don't think we should make any guarantee against DLL hijacking (planting) attacks. In this advisory I wrote
"Also note it is may still be possible for planting attacks to be done against load-time DLLs used by libcurl and the curl tool. This is because Windows loads those DLLs and their dependencies without specifying a path. There is nothing we can do to fix this, it is endemic in the design of Windows. We advise you to guard write permissions on your application directory."
Stefan disagrees and offers the solution that is being discussed in this thread, specifically loadFrom to specify the path. The problem is to prevent against DLL hijacking we'd have to know not just all the DLLs curl and libcurl are using but all the DLLs their dependencies are using as well. Therefore I think it's reasonable that we can't prevent DLL hijacking at load time unless we know every single thing that's loaded, and who's to say that some third party dependency won't change its dependencies in the future, also having the same problem.
Also wasn't there some issue using a manifest or am I not remembering that right @vszakats?
edit: Also loadFrom has some quirks https://stackoverflow.com/a/2137463
I agree with @jay . It's the application's responsibility to guard against such things, not libcurl's. And such a list of DLLs can get pretty long in some configurations.
What we could do, though, is to call Windows API functions like SetSearchPathMode, SetDllDirectory, and SetDefaultDllDirectories at startup in the curl tool.
I believe libcurl/curl should make sure to use best practices when dynamically loading a .dll
, but this already seems to be the case in Curl_load_library()
in lib/system_win32.c
. As for altering OS behaviour when implicitly loading .dll
s, it seems to be out of scope for a generic library.
As for the manifest issue, I had a patch proposal to resolve an issue caused by Windows versioning "peculiarities". This was done via a manifest embedded in curl.rc
(as opposed to a separate .mft
/.manifest
file.) This helps including a manifest in an unobtrusive way while also allowing to use .h
constants in it. It works with popular C compilers (MinGW, MSVC), though may break with some non-mainstream/niche ones (e.g. OpenWatcom — fixed since, or Borland C) due to bugs.
If the goal is to have the libcurl/curl version included in the linked manifest, the above method can be useful.
For avoidance of doubt: I have no position on this. I mostly hang out in kernel mode where thing are different. My role in this case was purely to capture it into github (and engender this conversation)
I'll happily close this case (or better still let @jay do it) if the community agree./
I am partially for this for version information and the icon, and I think we should drop the other things.
@gvanem wrote":
But I think manifests are not a good idea.
why?
I'm sensing that the team is leaning towards a "don't merge" on this suggestion.
The library doesn't need a manifest, the curl executable does.
If the executable doesn't have a manifest it runs in a restricted environment (an emulation, which you can see in task manager), similar to what Windows does to 32-bit binaries running in the 64-bit OS.
I (as a user) would prefer the executable with a manifest. Just as anybody would prefer an installer, and executable signed with a developer key to make sure they are original releases, not 3rd party, maybe hacked versions; of course the manifest doesn't do anything about this.
Lack of a manifest will alter behaviour of specific Win32 API calls. One of these is the infamous case of version detection functions returning phoney values. In context of curl, this will cause at least one feature to stay disabled even if the host OS version does support it. Specifically this condition will always return FALSE without a manifest. So, a manifest would be required to make this specific case work as expected.
As for a digital signature, it'd be real nice to be able to create them for free/open-source software built for Windows, but the reality is that it costs money and it's likely to cause a recurring (yearly?) administration burden (and certain privacy concerns) on the top of it. For projects/efforts without income, there isn't a reasonable solution for this ATM. (The infrastructure/tooling support is solvable/solved though, even with open tools. One slight downside is that a signature plays badly with reproducibility due to the embedded timestamp.)
UPDATE (2018-05-31): Real-life experience with code signing in an open-source project: https://github.com/ImageOptim/gifski/releases/tag/0.8.3 and related HN thread.
The curl project itself doesn't release binaries on its own, so it's always up to 3rd parties to create them. The next best (or maybe the best?) method for verifiability is reproducibility via deterministic builds.
It seems #2591 happens because of the lack of a manifest!?
@bagder Yes, it seems so.
Anyone up for writing a PR (or more) to make sure curl builds with a manifest? It seems like an easy way to fix #2591 and perhaps more.
This earlier PR (of mine) offered a viable (or at least potential) solution for this: https://github.com/curl/curl/pull/1221
Manifest has been added to curl.rc
in https://github.com/curl/curl/commit/ebd213270a017a6830928ee2e1f4a9cabc799898. Some build tools are already opted-in, remaining ones can opt-in by adding a resource compiler flag. The manifest automatically pulls curl version from existing curl headers. Same principal can be used with libcurl.rc
, should a manifest ever be needed there.
I've also made a brief test with the undocumented loadFrom
manifest items, but the resulting curl.exe
failed to run. When reading up about the topic, I learned that these Windows system .dll
s (aka KnownDLLs
) are always loaded from their fixed location, but it's even more likely they are already loaded into memory, in which case the existing copy will be reused. I don't see why these items would improve security for curl.exe
and considering their undocumented nature and the problems experienced, I'd side with not adding them. [Anyhow, in case any manifest item turns out to be beneficial, it's now a no-brainer to add it to curl.exe
. ]
Updated https://github.com/curl/curl/issues/2326#issuecomment-390327512 with links to a real-life recount of firing up a code signing certificate for an open-source project by its brave author.
So based on comment, can we say that this issue is now fixed? @vszakats ?
Yes, the manifest issue is fixed.
I had omitted the loadFrom
trick from above, because it's an undocumented keyword and I wasn't convinced it's necessary, though technically any further manifest elements can be added in the future as needed. Focus was on mainline C toolchains, i.e. Visual C and MinGW. For the rest (e.g. Open Watcom), some caveats apply, as detailed in the commit message.
The new manifest in turn fixes Windows version detection, which fixes ALPN use with SCHANNEL, for Visual C builds. MinGW builds have an unrelated, upstream issue detailed here. When upstream is fixed, libcurl code will need a tweak to detect ALPN support in Windows SDK (= Win32 headers) in a C compiler-agnostic way.
Thanks a lot, then I consider this particular issue closed!
Over Here Daniel noted (channelling Stefan Kanthak):
For the Windows build, please incorporate the following changes:
download https://curl.haxx.se/favicon.ico and save it as "curl.ico" in the top level directory
add the file "lib/libcurl.manifest" to disable DLL hijacking per external manifest, and more
NOTE: the underlined version string MUST reflect cURL's current version!
NOTE: ALL resources used with cURL are language-independent!
I (Rod) will add that making strings match versions is the way to madness and the only sensible way to proceed is to exbed this into a single config file and pass the value in to the build "Somehow".