Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed OpenSSL bindings to work with LibreSSL #6917

Merged
merged 3 commits into from
Oct 15, 2018
Merged

Fixed OpenSSL bindings to work with LibreSSL #6917

merged 3 commits into from
Oct 15, 2018

Conversation

LVMBDV
Copy link

@LVMBDV LVMBDV commented Oct 7, 2018

  • Reworked Fixed OpenSSL bindings to recognize LibreSSL #5676 with sane fallbacks, like falling back to using just pkg-config if the header files are inaccessible.
  • Replaced flags like OPENSSL_110 with actual version number values e.g. OPENSSL_VERSION is 0x10102000 when its version is 1.1.2.
  • When we can't check the headers but can use pkg-config, we assume OpenSSL is installed and set the version values accordingly. Although this behavior is a bit iffy for systems that have LibreSSL installed without the headers but the current behavior also works exactly like this AFAIU.

@LVMBDV
Copy link
Author

LVMBDV commented Oct 8, 2018

The fail on build 12969 seems irrelevant. Ready for a review :)

@bcardiff
Copy link
Member

bcardiff commented Oct 8, 2018

Build restarted.

I would prefer to use compare_versions macro method instead of versions hex encoded. Is there any reason why not to do it that way?

@straight-shoota
Copy link
Member

Is there any reason why not to do it that way?

Is there a string representation of the library version available that would fit with compare_versions? OPENSSL_VERSION is just a binary value.

@LVMBDV
Copy link
Author

LVMBDV commented Oct 8, 2018

There is a string representation of the library version inside the same header file.
For LibreSSL, it's LIBRESSL_VERSION_TEXT which is formatted like:
"LibreSSL 2.7.4"
And for OpenSSL, it's OPENSSL_VERSION_TEXT which is formatted like:
"OpenSSL 1.0.2q-dev xx XXX xxxx"

I could use the MAJOR.MINOR.PATCH parts of both if you prefer, but I think
OPENSSL_VERSION >= 0x10100000
is more readable than
compare_versions(OPENSSL_VERSION, "1.1.0") >= 0

@bcardiff
Copy link
Member

bcardiff commented Oct 8, 2018

Even if there is no string representation, I don't see the value of using custom integer value vs initializing manually a string semver value.

It's better to keep one single idiom for version.

So either we needed to extract the semver from ..._VERSION_TEXT or initialize those semver strings manually where this PR now uses integers. The later is good enough for me.

@ysbaddaden
Copy link
Contributor

The official version check in OpenSSL is the hexadecimal check. As ugly as it may look, we should follow it.

What really bothers me is the amount and complexity of macro run calls to extract 2 definitions from the C headers :-(

@LVMBDV
Copy link
Author

LVMBDV commented Oct 8, 2018

I reworked the checks to work with compare_versions and tried to get the semver strings from pkg-config but turns out it doesn't always output semver-compatible versions.

Edit: Let's try to .gsub(/[^0-9.]/, "") it :)

@LVMBDV
Copy link
Author

LVMBDV commented Oct 9, 2018

The second solution seems to pass too. It's a bit simpler as it uses the header file only to check for LibreSSL and uses pkg-config to get the semver strings.

Both commits are valid solutions, pick your favorite :)

OPENSSL_VERSION = "0.0.0"
{% else %}
LIBRESSL_VERSION = "0.0.0"
OPENSSL_VERSION = {{ `command -v pkg-config > /dev/null && pkg-config --silence-errors --modversion libssl || printf %s 0.0.0`.split.last.gsub(/[^0-9.]/, "") }}
Copy link
Contributor

@j8r j8r Oct 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hash pkg-config 2>/dev/null is shorter and has the same effect than command -v pkg-config >/dev/null.

You can also do this command once, before {% if from_libressl %}:
{% ssl_version = `hash pkg-config 2>/dev/null && pkg-config --silence-errors --modversion libssl || printf %s 0.0.0`.split.last.gsub(/[^0-9.]/, "") %}

And then:
LIBRESSL_VERSION = {{ ssl_version }}
OPENSSL_VERSION = {{ ssl_version }}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, you're right. I remember thinking about storing the libssl version last night, wonder why it slipped my mind later. I will do that when I get on my computer.

OPENSSL_102 = {{ `command -v pkg-config > /dev/null && pkg-config --atleast-version=1.0.2 libcrypto || printf %s false`.stringify != "false" }}
{% from_libressl = (`hash pkg-config 2> /dev/null || printf %s false` != "false") &&
(`test -f $(pkg-config --silence-errors --variable=includedir libcrypto)/openssl/opensslv.h || printf %s false` != "false") &&
(`printf %s "#include <openssl/opensslv.h>\nlibressl_version_number" | #{(env("cc") || "cc").id} #{`pkg-config --cflags --silence-errors libcrypto || true`.chomp} -E -`.chomp.split('\n').last == "libressl_version_number") %}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps use $(pkg-config ...) here instead of #{`pkg-config ...`}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#{(env("cc") || "cc").id} could be inserted directly into the command, as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the entire boolean expression could just be evaluated in the shell... I'm not sure if that brings any benefits but it would avoid conceptually switching between shell and macro interpreter back and forth.

@LVMBDV
Copy link
Author

LVMBDV commented Oct 13, 2018

The fail on build 13549 seems irrelevant to me. Is it from master?

@RX14
Copy link
Contributor

RX14 commented Oct 13, 2018

@LVMBDV no it's just a transient OOM error, I've restarted the build.

@RX14
Copy link
Contributor

RX14 commented Oct 13, 2018

Tested on my machine, this works well. Has this been tested on alpine?

@Sija
Copy link
Contributor

Sija commented Oct 13, 2018

I could use the MAJOR.MINOR.PATCH parts of both if you prefer, but I think
OPENSSL_VERSION >= 0x10100000
is more readable than
compare_versions(OPENSSL_VERSION, "1.1.0") >= 0

Somewhat agreed, perhaps it's worth adding 3rd argument which would specify the operator for comparison, turning your example into: compare_versions(OPENSSL_VERSION, ">=", "1.1.0")?

@j8r
Copy link
Contributor

j8r commented Oct 13, 2018

To test this features, it would be really nice to have an Alpine Linux CI when the language is compiled with:

  • Libressl
  • musl-libc
  • static linking?

@RX14 RX14 added this to the 0.27.0 milestone Oct 13, 2018
Copy link
Member

@sdogruyol sdogruyol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @LVMBDV 👍

@sdogruyol sdogruyol merged commit 3817a99 into crystal-lang:master Oct 15, 2018
This was referenced Apr 16, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants