Commit 45f6f2b5 authored by Bernd Krietenstein's avatar Bernd Krietenstein
Browse files

Fixed X509_PURPOSE issues (location and implementation)

parent 2e986986
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -4,6 +4,18 @@ use *;
#[cfg(any(libressl, all(ossl102, not(ossl110))))]
pub enum X509_VERIFY_PARAM_ID {}

#[repr(C)]
pub struct X509_PURPOSE {
    pub purpose: c_int,
    pub trust: c_int, // Default trust ID
    pub flags: c_int,
    pub check_purpose:
        Option<unsafe extern "C" fn(*const X509_PURPOSE, *const X509, c_int) -> c_int>,
    pub name: *mut c_char,
    pub sname: *mut c_char,
    pub usr_data: *mut c_void,
}

extern "C" {
    #[cfg(ossl110)]
    pub fn X509_LOOKUP_meth_free(method: *mut X509_LOOKUP_METHOD);
@@ -48,6 +60,9 @@ extern "C" {

    pub fn X509_STORE_set_default_paths(store: *mut X509_STORE) -> c_int;
    pub fn X509_STORE_set_flags(store: *mut X509_STORE, flags: c_ulong) -> c_int;
    pub fn X509_STORE_set_purpose(ctx: *mut X509_STORE, purpose: c_int) -> c_int;
    pub fn X509_STORE_set_trust(ctx: *mut X509_STORE, trust: c_int) -> c_int;

}

const_ptr_api! {
@@ -127,3 +142,10 @@ extern "C" {
    #[cfg(ossl102)]
    pub fn X509_VERIFY_PARAM_set_purpose(param: *mut X509_VERIFY_PARAM, purpose: c_int) -> c_int;
}

const_ptr_api! {
    extern "C" {
        pub fn X509_PURPOSE_get_by_sname(sname: #[const_ptr_if(any(ossl110, libressl280))] c_char) -> c_int;
        pub fn X509_PURPOSE_get0(idx: c_int) -> *mut X509_PURPOSE;
    }
}
+0 −23
Original line number Diff line number Diff line
@@ -147,26 +147,3 @@ pub unsafe fn X509_LOOKUP_add_dir(
        std::ptr::null_mut(),
    )
}

#[cfg(ossl102)]
pub const X509_PURPOSE_SSL_CLIENT: c_int = 1;
#[cfg(ossl102)]
pub const X509_PURPOSE_SSL_SERVER: c_int = 2;
#[cfg(ossl102)]
pub const X509_PURPOSE_NS_SSL_SERVER: c_int = 3;
#[cfg(ossl102)]
pub const X509_PURPOSE_SMIME_SIGN: c_int = 4;
#[cfg(ossl102)]
pub const X509_PURPOSE_SMIME_ENCRYPT: c_int = 5;
#[cfg(ossl102)]
pub const X509_PURPOSE_CRL_SIGN: c_int = 6;
#[cfg(ossl102)]
pub const X509_PURPOSE_ANY: c_int = 7;
#[cfg(ossl102)]
pub const X509_PURPOSE_OCSP_HELPER: c_int = 8;
#[cfg(ossl102)]
pub const X509_PURPOSE_TIMESTAMP_SIGN: c_int = 9;
#[cfg(ossl102)]
pub const X509_PURPOSE_MIN: c_int = 1;
#[cfg(ossl102)]
pub const X509_PURPOSE_MAX: c_int = 9;
+22 −0
Original line number Diff line number Diff line
@@ -58,15 +58,25 @@ pub const EXFLAG_FRESHEST: u32 = 0x1000;
#[cfg(any(ossl102, libressl261))]
pub const EXFLAG_SS: u32 = 0x2000;

#[cfg(not(boringssl))]
pub const X509v3_KU_DIGITAL_SIGNATURE: u32 = 0x0080;
#[cfg(not(boringssl))]
pub const X509v3_KU_NON_REPUDIATION: u32 = 0x0040;
#[cfg(not(boringssl))]
pub const X509v3_KU_KEY_ENCIPHERMENT: u32 = 0x0020;
#[cfg(not(boringssl))]
pub const X509v3_KU_DATA_ENCIPHERMENT: u32 = 0x0010;
#[cfg(not(boringssl))]
pub const X509v3_KU_KEY_AGREEMENT: u32 = 0x0008;
#[cfg(not(boringssl))]
pub const X509v3_KU_KEY_CERT_SIGN: u32 = 0x0004;
#[cfg(not(boringssl))]
pub const X509v3_KU_CRL_SIGN: u32 = 0x0002;
#[cfg(not(boringssl))]
pub const X509v3_KU_ENCIPHER_ONLY: u32 = 0x0001;
#[cfg(not(boringssl))]
pub const X509v3_KU_DECIPHER_ONLY: u32 = 0x8000;
#[cfg(not(boringssl))]
pub const X509v3_KU_UNDEF: u32 = 0xffff;

pub const XKU_SSL_SERVER: u32 = 0x1;
@@ -79,3 +89,15 @@ pub const XKU_TIMESTAMP: u32 = 0x40;
pub const XKU_DVCS: u32 = 0x80;
#[cfg(ossl110)]
pub const XKU_ANYEKU: u32 = 0x100;

pub const X509_PURPOSE_SSL_CLIENT: c_int = 1;
pub const X509_PURPOSE_SSL_SERVER: c_int = 2;
pub const X509_PURPOSE_NS_SSL_SERVER: c_int = 3;
pub const X509_PURPOSE_SMIME_SIGN: c_int = 4;
pub const X509_PURPOSE_SMIME_ENCRYPT: c_int = 5;
pub const X509_PURPOSE_CRL_SIGN: c_int = 6;
pub const X509_PURPOSE_ANY: c_int = 7;
pub const X509_PURPOSE_OCSP_HELPER: c_int = 8;
pub const X509_PURPOSE_TIMESTAMP_SIGN: c_int = 9;
pub const X509_PURPOSE_MIN: c_int = 1;
pub const X509_PURPOSE_MAX: c_int = 9;
+97 −0
Original line number Diff line number Diff line
@@ -227,6 +227,7 @@ impl X509Builder {
    /// Note that the version is zero-indexed; that is, a certificate corresponding to version 3 of
    /// the X.509 standard should pass `2` to this method.
    #[corresponds(X509_set_version)]
    #[allow(clippy::useless_conversion)]
    pub fn set_version(&mut self, version: i32) -> Result<(), ErrorStack> {
        unsafe { cvt(ffi::X509_set_version(self.0.as_ptr(), version as c_long)).map(|_| ()) }
    }
@@ -1181,6 +1182,7 @@ impl X509ReqBuilder {
    /// This corresponds to [`X509_REQ_set_version`].
    ///
    ///[`X509_REQ_set_version`]: https://www.openssl.org/docs/manmaster/crypto/X509_REQ_set_version.html
    #[allow(clippy::useless_conversion)]
    pub fn set_version(&mut self, version: i32) -> Result<(), ErrorStack> {
        unsafe {
            cvt(ffi::X509_REQ_set_version(
@@ -1737,3 +1739,98 @@ cfg_if! {
        }
    }
}

pub struct X509PurposeId(i32);

impl X509PurposeId {
    pub const SSL_CLIENT: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_SSL_CLIENT);
    pub const SSL_SERVER: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_SSL_SERVER);
    pub const NS_SSL_SERVER: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_NS_SSL_SERVER);
    pub const SMIME_SIGN: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_SMIME_SIGN);
    pub const SMIME_ENCRYPT: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_SMIME_ENCRYPT);
    pub const CRL_SIGN: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_CRL_SIGN);
    pub const ANY: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_ANY);
    pub const OCSP_HELPER: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_OCSP_HELPER);
    pub const TIMESTAMP_SIGN: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_TIMESTAMP_SIGN);

    pub fn value(&self) -> i32 {
        self.0
    }
}

impl From<i32> for X509PurposeId {
    fn from(id: i32) -> Self {
        X509PurposeId(id)
    }
}

/// fake free method, since X509_PURPOSE is static
unsafe fn no_free_purpose(_purps: *mut ffi::X509_PURPOSE) {}

foreign_type_and_impl_send_sync! {
    type CType = ffi::X509_PURPOSE;
    fn drop = no_free_purpose;

    /// Adjust parameters associated with certificate verification.
    pub struct X509Purpose;
    /// Reference to `X509Purpose`.
    pub struct X509PurposeRef;
}

impl X509Purpose {
    /// Get the internal table index of an X509_PURPOSE for a given short name. Valid short
    /// names include
    ///  - "sslclient",
    ///  - "sslserver",
    ///  - "nssslserver",
    ///  - "smimesign",
    ///  - "smimeencrypt",
    ///  - "crlsign",
    ///  - "any",
    ///  - "ocsphelper",
    ///  - "timestampsign"
    /// The index can be used with `X509Purpose::from_idx()` to get the purpose.
    #[allow(clippy::unnecessary_cast)]
    pub fn get_by_sname(sname: &str) -> Result<i32, ErrorStack> {
        unsafe {
            let sname = CString::new(sname).unwrap();
            cfg_if! {
                if #[cfg(any(ossl110, libressl280))] {
                    let purpose = cvt_n(ffi::X509_PURPOSE_get_by_sname(sname.as_ptr() as *const _))?;
                } else {
                    let purpose = cvt_n(ffi::X509_PURPOSE_get_by_sname(sname.as_ptr() as *mut _))?;
                }
            }
            Ok(purpose as i32)
        }
    }

    /// Get an `X509PurposeRef` for a given index value. The index can be obtained from e.g.
    /// `X509Purpose::get_by_sname()`.
    #[corresponds(X509_PURPOSE_get0)]
    pub fn from_idx(idx: i32) -> Result<&'static X509PurposeRef, ErrorStack> {
        unsafe {
            let ptr = cvt_p(ffi::X509_PURPOSE_get0(idx))?;
            Ok(X509PurposeRef::from_ptr(ptr))
        }
    }
}

impl X509PurposeRef {
    /// Get the purpose value from an X509Purpose structure. This value is one of
    /// - `X509_PURPOSE_SSL_CLIENT`
    /// - `X509_PURPOSE_SSL_SERVER`
    /// - `X509_PURPOSE_NS_SSL_SERVER`
    /// - `X509_PURPOSE_SMIME_SIGN`
    /// - `X509_PURPOSE_SMIME_ENCRYPT`
    /// - `X509_PURPOSE_CRL_SIGN`
    /// - `X509_PURPOSE_ANY`
    /// - `X509_PURPOSE_OCSP_HELPER`
    /// - `X509_PURPOSE_TIMESTAMP_SIGN`
    pub fn purpose(&self) -> X509PurposeId {
        unsafe {
            let x509_purpose: *mut ffi::X509_PURPOSE = self.as_ptr();
            X509PurposeId::from((*x509_purpose).purpose)
        }
    }
}
+15 −1
Original line number Diff line number Diff line
@@ -51,8 +51,9 @@ use crate::ssl::SslFiletype;
use crate::stack::StackRef;
#[cfg(any(ossl102, libressl261))]
use crate::x509::verify::{X509VerifyFlags, X509VerifyParamRef};
use crate::x509::{X509Object, X509};
use crate::x509::{X509Object, X509PurposeId, X509};
use crate::{cvt, cvt_p};
use libc::c_int;
use openssl_macros::corresponds;
#[cfg(not(boringssl))]
use std::ffi::CString;
@@ -125,6 +126,19 @@ impl X509StoreBuilderRef {
        unsafe { cvt(ffi::X509_STORE_set_flags(self.as_ptr(), flags.bits())).map(|_| ()) }
    }

    /// Sets the certificate purpose.
    /// The purpose value can be obtained by `X509Purpose::get_by_sname()`
    #[corresponds(X509_STORE_set_purpose)]
    pub fn set_purpose(&mut self, purpose: X509PurposeId) -> Result<(), ErrorStack> {
        unsafe {
            cvt(ffi::X509_STORE_set_purpose(
                self.as_ptr(),
                purpose.value() as c_int,
            ))
            .map(|_| ())
        }
    }

    /// Sets certificate chain validation related parameters.
    #[corresponds[X509_STORE_set1_param]]
    #[cfg(any(ossl102, libressl261))]
Loading