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)))] |
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 | |
127 | assert!(number() > 0); |
128 | assert!(version().starts_with(expected_name())); |
129 | assert!(c_flags().starts_with("compiler:" )); |
130 | // some distributions patch out dates out of openssl so that the builds are reproducible |
131 | if !built_on().is_empty() { |
132 | assert!(built_on().starts_with("built on:" )); |
133 | } |
134 | assert!(dir().starts_with("OPENSSLDIR:" )); |
135 | } |
136 | |