| 1 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 2 | // you may not use this file except in compliance with the License. |
| 3 | // You may obtain a copy of the License at |
| 4 | // |
| 5 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 6 | // |
| 7 | // Unless required by applicable law or agreed to in writing, software |
| 8 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 9 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 10 | // See the License for the specific language governing permissions and |
| 11 | // limitations under the License. |
| 12 | // |
| 13 | |
| 14 | //! Build and version information. |
| 15 | |
| 16 | use cfg_if::cfg_if; |
| 17 | use openssl_macros::corresponds; |
| 18 | use std::ffi::CStr; |
| 19 | |
| 20 | cfg_if! { |
| 21 | if #[cfg(any(ossl110, libressl271))] { |
| 22 | use ffi::{ |
| 23 | OPENSSL_VERSION, OPENSSL_CFLAGS, OPENSSL_BUILT_ON, OPENSSL_PLATFORM, OPENSSL_DIR, |
| 24 | OpenSSL_version_num, OpenSSL_version, |
| 25 | }; |
| 26 | } else { |
| 27 | use ffi::{ |
| 28 | SSLEAY_VERSION as OPENSSL_VERSION, SSLEAY_CFLAGS as OPENSSL_CFLAGS, |
| 29 | SSLEAY_BUILT_ON as OPENSSL_BUILT_ON, SSLEAY_PLATFORM as OPENSSL_PLATFORM, |
| 30 | SSLEAY_DIR as OPENSSL_DIR, SSLeay as OpenSSL_version_num, |
| 31 | SSLeay_version as OpenSSL_version, |
| 32 | }; |
| 33 | } |
| 34 | } |
| 35 | |
| 36 | /// OPENSSL_VERSION_NUMBER is a numeric release version identifier: |
| 37 | /// |
| 38 | /// `MNNFFPPS: major minor fix patch status` |
| 39 | /// |
| 40 | /// The status nibble has one of the values 0 for development, 1 to e for betas 1 to 14, and f for release. |
| 41 | /// |
| 42 | /// for example |
| 43 | /// |
| 44 | /// `0x000906000 == 0.9.6 dev` |
| 45 | /// `0x000906023 == 0.9.6b beta 3` |
| 46 | /// `0x00090605f == 0.9.6e release` |
| 47 | #[corresponds (OpenSSL_version_num)] |
| 48 | pub fn number() -> i64 { |
| 49 | unsafe { OpenSSL_version_num() as i64 } |
| 50 | } |
| 51 | |
| 52 | /// The text variant of the version number and the release date. For example, "OpenSSL 0.9.5a 1 Apr 2000". |
| 53 | #[corresponds (OpenSSL_version)] |
| 54 | pub fn version() -> &'static str { |
| 55 | unsafe { |
| 56 | CStrResult<&str, Utf8Error>::from_ptr(OpenSSL_version(OPENSSL_VERSION)) |
| 57 | .to_str() |
| 58 | .unwrap() |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | /// The compiler flags set for the compilation process in the form "compiler: ..." if available or |
| 63 | /// "compiler: information not available" otherwise. |
| 64 | #[corresponds (OpenSSL_version)] |
| 65 | pub fn c_flags() -> &'static str { |
| 66 | unsafe { |
| 67 | CStrResult<&str, Utf8Error>::from_ptr(OpenSSL_version(OPENSSL_CFLAGS)) |
| 68 | .to_str() |
| 69 | .unwrap() |
| 70 | } |
| 71 | } |
| 72 | |
| 73 | /// The date of the build process in the form "built on: ..." if available or "built on: date not available" otherwise. |
| 74 | #[corresponds (OpenSSL_version)] |
| 75 | pub fn built_on() -> &'static str { |
| 76 | unsafe { |
| 77 | CStrResult<&str, Utf8Error>::from_ptr(OpenSSL_version(OPENSSL_BUILT_ON)) |
| 78 | .to_str() |
| 79 | .unwrap() |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | /// The "Configure" target of the library build in the form "platform: ..." if available or "platform: information not available" otherwise. |
| 84 | #[corresponds (OpenSSL_version)] |
| 85 | pub fn platform() -> &'static str { |
| 86 | unsafe { |
| 87 | CStrResult<&str, Utf8Error>::from_ptr(OpenSSL_version(OPENSSL_PLATFORM)) |
| 88 | .to_str() |
| 89 | .unwrap() |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | /// The "OPENSSLDIR" setting of the library build in the form "OPENSSLDIR: "..."" if available or "OPENSSLDIR: N/A" otherwise. |
| 94 | #[corresponds (OpenSSL_version)] |
| 95 | pub fn dir() -> &'static str { |
| 96 | unsafe { |
| 97 | CStrResult<&str, Utf8Error>::from_ptr(OpenSSL_version(OPENSSL_DIR)) |
| 98 | .to_str() |
| 99 | .unwrap() |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | /// This test ensures that we do not segfault when calling the functions of this module |
| 104 | /// and that the strings respect a reasonable format. |
| 105 | #[test ] |
| 106 | fn test_versions() { |
| 107 | println!("Number: '{}'" , number()); |
| 108 | println!("Version: '{}'" , version()); |
| 109 | println!("C flags: '{}'" , c_flags()); |
| 110 | println!("Built on: '{}'" , built_on()); |
| 111 | println!("Platform: '{}'" , platform()); |
| 112 | println!("Dir: '{}'" , dir()); |
| 113 | |
| 114 | #[cfg (not(any(libressl, boringssl, awslc)))] |
| 115 | fn expected_name() -> &'static str { |
| 116 | "OpenSSL" |
| 117 | } |
| 118 | #[cfg (libressl)] |
| 119 | fn expected_name() -> &'static str { |
| 120 | "LibreSSL" |
| 121 | } |
| 122 | #[cfg (boringssl)] |
| 123 | fn expected_name() -> &'static str { |
| 124 | "BoringSSL" |
| 125 | } |
| 126 | #[cfg (awslc)] |
| 127 | fn expected_name() -> &'static str { |
| 128 | "AWS-LC" |
| 129 | } |
| 130 | |
| 131 | assert!(number() > 0); |
| 132 | assert!(version().starts_with(expected_name())); |
| 133 | assert!(c_flags().starts_with("compiler:" )); |
| 134 | // some distributions patch out dates out of openssl so that the builds are reproducible |
| 135 | if !built_on().is_empty() { |
| 136 | assert!(built_on().starts_with("built on:" )); |
| 137 | } |
| 138 | } |
| 139 | |