Unverified Commit 59f9df9a authored by Igor Taranenko's avatar Igor Taranenko
Browse files

Add X509Ref::version

parent 15419c24
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -225,6 +225,13 @@ extern "C" {
    pub fn X509_get_pubkey(x: *mut X509) -> *mut EVP_PKEY;

    pub fn X509_set_version(x: *mut X509, version: c_long) -> c_int;
    /// Returns certificate version previously set through `X509_set_version` or the default which
    /// is `0`.
    ///
    /// **Important.** The corresponding OpenSSL method is not expected to fail under its
    /// correct implementation. Despite that, the method invocation passes through scopes which
    /// _may_ result in error. Having that it is encouraged to validate returned value.
    pub fn X509_get_version(x: *const X509) -> c_long;
    pub fn X509_set_serialNumber(x: *mut X509, sn: *mut ASN1_INTEGER) -> c_int;
    pub fn X509_get_serialNumber(x: *mut X509) -> *mut ASN1_INTEGER;
    pub fn X509_set_issuer_name(x: *mut X509, name: *mut X509_NAME) -> c_int;
+34 −1
Original line number Diff line number Diff line
@@ -129,7 +129,7 @@ extern crate tempdir;
#[doc(inline)]
pub use ffi::init;

use libc::c_int;
use libc::{c_int, c_long};

use error::ErrorStack;

@@ -199,3 +199,36 @@ fn cvt_n(r: c_int) -> Result<c_int, ErrorStack> {
        Ok(r)
    }
}

/// Checks that `r` is not negative.
/// # Returns
/// `r`, if it passes validation.
fn cvt_long_n(r: c_long) -> Result<c_long, ErrorStack> {
    if r < 0 {
        // Covered with `cvt_long_n_is_negative()` test
        Err(ErrorStack::get())
    } else {
        // Covered with `cvt_long_n_is_positive()`, `cvt_long_n_is_0()` tests
        Ok(r)
    }
}

#[cfg(test)]
mod tests {
    use cvt_long_n;

    #[test]
    fn cvt_long_n_is_positive() {
        cvt_long_n(1).expect("Positive value should pass validation");
    }

    #[test]
    fn cvt_long_n_is_0() {
        cvt_long_n(0).expect("Zero value should pass validation");
    }

    #[test]
    fn cvt_long_n_is_negative() {
        cvt_long_n(-1).expect_err("Negative value should not pass validation");
    }
}
+57 −2
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ use pkey::{HasPrivate, HasPublic, PKey, PKeyRef, Public};
use ssl::SslRef;
use stack::{Stack, StackRef, Stackable};
use string::OpensslString;
use {cvt, cvt_n, cvt_p};
use {cvt, cvt_long_n, cvt_n, cvt_p};

#[cfg(any(ossl102, libressl261))]
pub mod verify;
@@ -40,7 +40,48 @@ pub mod extension;
pub mod store;

#[cfg(test)]
mod tests;
mod tests {
    use x509::X509Builder;

    /// Tests `X509Ref::version` happy path.
    #[test]
    fn x509_ref_version() {
        let mut builder = X509Builder::new().unwrap();
        let expected_version = 2;
        builder.set_version(expected_version).expect("Failed to set certificate version");
        let cert = builder.build();
        let actual_version = cert.version().expect("Failed to obtain certificate version");
        assert_eq!(
            expected_version as i64, actual_version, "Obtained certificate version is incorrect");
    }

    /// Tests `X509Ref::version`. Checks case when no version has been set, so a default one is
    /// returned.
    #[test]
    fn x509_ref_version_no_version_set() {
        let cert = X509Builder::new().unwrap().build();
        let actual_version = cert.version().expect("Failed to obtain certificate version");
        assert_eq!(0, actual_version, "Default certificate version is incorrect");
    }

    /// Tests `X509Ref::version`. Checks case when there was an attempt to set incorrect version
    /// before a call to the tested method.
    ///
    /// _Note._ As for now this test is disabled since OpenSSL erroneously allows to set any number
    /// as a certificate version. See corresponding [`issue`].
    ///
    /// [`issue`]: https://github.com/openssl/openssl/issues/12138
    #[test]
    #[ignore]
    fn x509_ref_version_incorrect_version_set() {
        let mut builder = X509Builder::new().unwrap();
        builder.set_version(-1)
            .expect_err("It should not be possible to set negative certificate version");
        let cert = builder.build();
        let actual_version = cert.version().expect("Failed to obtain certificate version");
        assert_eq!(0, actual_version, "Default certificate version is incorrect");
    }
}

foreign_type_and_impl_send_sync! {
    type CType = ffi::X509_STORE_CTX;
@@ -548,6 +589,20 @@ impl X509Ref {
        }
    }

    /// Returns certificate version. If this certificate has no explicit version set, it defaults to
    /// version&nbsp;1.
    ///
    /// Note that `0` return value stands for version 1, `1`&nbsp;&ndash; for version 2 and so on.
    ///
    /// This corresponds to [`X509_get_version`].
    ///
    /// [`X509_get_version`]: https://www.openssl.org/docs/man1.1.1/man3/X509_get_version.html
    pub fn version(&self) -> Result<i64, ErrorStack> {
        // Covered with `x509_ref_version()`, `x509_ref_version_no_version_set()`,
        // `x509_ref_version_incorrect_version_set()` tests
        unsafe { cvt_long_n(ffi::X509_get_version(self.as_ptr())) }
    }

    /// Check if the certificate is signed using the given public key.
    ///
    /// Only the signature is checked: no other checks (such as certificate chain validity)