Certificate error codes
This commit is contained in:
parent
f8be641536
commit
0b287710c4
66
ffi.rs
66
ffi.rs
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
use std::libc::{c_int, c_void, c_long, c_ulong, c_char};
|
||||
|
||||
// openssl/ssl.h
|
||||
pub type SSL_CTX = c_void;
|
||||
pub type SSL_METHOD = c_void;
|
||||
pub type SSL = c_void;
|
||||
|
|
@ -36,6 +35,70 @@ pub static SSL_ERROR_WANT_ACCEPT: c_int = 8;
|
|||
pub static SSL_VERIFY_NONE: c_int = 0;
|
||||
pub static SSL_VERIFY_PEER: c_int = 1;
|
||||
|
||||
pub static X509_V_OK: c_int = 0;
|
||||
/* illegal error (for uninitialized values, to avoid X509_V_OK): 1 */
|
||||
|
||||
pub static X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: c_int = 2;
|
||||
pub static X509_V_ERR_UNABLE_TO_GET_CRL: c_int = 3;
|
||||
pub static X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: c_int = 4;
|
||||
pub static X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: c_int = 5;
|
||||
pub static X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: c_int = 6;
|
||||
pub static X509_V_ERR_CERT_SIGNATURE_FAILURE: c_int = 7;
|
||||
pub static X509_V_ERR_CRL_SIGNATURE_FAILURE: c_int = 8;
|
||||
pub static X509_V_ERR_CERT_NOT_YET_VALID: c_int = 9;
|
||||
pub static X509_V_ERR_CERT_HAS_EXPIRED: c_int = 10;
|
||||
pub static X509_V_ERR_CRL_NOT_YET_VALID: c_int = 11;
|
||||
pub static X509_V_ERR_CRL_HAS_EXPIRED: c_int = 12;
|
||||
pub static X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: c_int = 13;
|
||||
pub static X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: c_int = 14;
|
||||
pub static X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: c_int = 15;
|
||||
pub static X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: c_int = 16;
|
||||
pub static X509_V_ERR_OUT_OF_MEM: c_int = 17;
|
||||
pub static X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: c_int = 18;
|
||||
pub static X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: c_int = 19;
|
||||
pub static X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: c_int = 20;
|
||||
pub static X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: c_int = 21;
|
||||
pub static X509_V_ERR_CERT_CHAIN_TOO_LONG: c_int = 22;
|
||||
pub static X509_V_ERR_CERT_REVOKED: c_int = 23;
|
||||
pub static X509_V_ERR_INVALID_CA: c_int = 24;
|
||||
pub static X509_V_ERR_PATH_LENGTH_EXCEEDED: c_int = 25;
|
||||
pub static X509_V_ERR_INVALID_PURPOSE: c_int = 26;
|
||||
pub static X509_V_ERR_CERT_UNTRUSTED: c_int = 27;
|
||||
pub static X509_V_ERR_CERT_REJECTED: c_int = 28;
|
||||
/* These are 'informational' when looking for issuer cert */
|
||||
pub static X509_V_ERR_SUBJECT_ISSUER_MISMATCH: c_int = 29;
|
||||
pub static X509_V_ERR_AKID_SKID_MISMATCH: c_int = 30;
|
||||
pub static X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: c_int = 31;
|
||||
pub static X509_V_ERR_KEYUSAGE_NO_CERTSIGN: c_int = 32;
|
||||
|
||||
pub static X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: c_int = 33;
|
||||
pub static X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION: c_int = 34;
|
||||
pub static X509_V_ERR_KEYUSAGE_NO_CRL_SIGN: c_int = 35;
|
||||
pub static X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION: c_int = 36;
|
||||
pub static X509_V_ERR_INVALID_NON_CA: c_int = 37;
|
||||
pub static X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED: c_int = 38;
|
||||
pub static X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE: c_int = 39;
|
||||
pub static X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED: c_int = 40;
|
||||
|
||||
pub static X509_V_ERR_INVALID_EXTENSION: c_int = 41;
|
||||
pub static X509_V_ERR_INVALID_POLICY_EXTENSION: c_int = 42;
|
||||
pub static X509_V_ERR_NO_EXPLICIT_POLICY: c_int = 43;
|
||||
pub static X509_V_ERR_DIFFERENT_CRL_SCOPE: c_int = 44;
|
||||
pub static X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE: c_int = 45;
|
||||
|
||||
pub static X509_V_ERR_UNNESTED_RESOURCE: c_int = 46;
|
||||
|
||||
pub static X509_V_ERR_PERMITTED_VIOLATION: c_int = 47;
|
||||
pub static X509_V_ERR_EXCLUDED_VIOLATION: c_int = 48;
|
||||
pub static X509_V_ERR_SUBTREE_MINMAX: c_int = 49;
|
||||
pub static X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE: c_int = 51;
|
||||
pub static X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX: c_int = 52;
|
||||
pub static X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: c_int = 53;
|
||||
pub static X509_V_ERR_CRL_PATH_VALIDATION_ERROR: c_int = 54;
|
||||
|
||||
/* The application is not happy */
|
||||
pub static X509_V_ERR_APPLICATION_VERIFICATION: c_int = 50;
|
||||
|
||||
#[link_args = "-lssl -lcrypto"]
|
||||
extern "C" {
|
||||
pub fn ERR_get_error() -> c_ulong;
|
||||
|
|
@ -64,6 +127,7 @@ extern "C" {
|
|||
pub fn X509_STORE_CTX_get_ex_data(ctx: *X509_STORE_CTX, idx: c_int)
|
||||
-> *c_void;
|
||||
pub fn X509_STORE_CTX_get_current_cert(ct: *X509_STORE_CTX) -> *X509;
|
||||
pub fn X509_STORE_CTX_get_error(ctx: *X509_STORE_CTX) -> c_int;
|
||||
|
||||
pub fn SSL_new(ctx: *SSL_CTX) -> *SSL;
|
||||
pub fn SSL_free(ssl: *SSL);
|
||||
|
|
|
|||
88
lib.rs
88
lib.rs
|
|
@ -1,4 +1,4 @@
|
|||
#[feature(struct_variant)];
|
||||
#[feature(struct_variant, macro_rules)];
|
||||
|
||||
// Needed for rustdoc-ng
|
||||
#[link(name="rust-ssl", vers="0.1",
|
||||
|
|
@ -15,6 +15,7 @@ use std::io::{Stream, Reader, Writer, Decorator};
|
|||
use std::vec;
|
||||
|
||||
use self::error::{SslError, SslSessionClosed, StreamEof};
|
||||
use self::hack::X509ValidationError;
|
||||
|
||||
pub mod error;
|
||||
|
||||
|
|
@ -159,6 +160,11 @@ pub struct X509StoreContext {
|
|||
}
|
||||
|
||||
impl X509StoreContext {
|
||||
pub fn get_error(&self) -> Option<X509ValidationError> {
|
||||
let err = unsafe { ffi::X509_STORE_CTX_get_error(self.ctx) };
|
||||
X509ValidationError::from_raw(err)
|
||||
}
|
||||
|
||||
pub fn get_current_cert(&self) -> Option<X509> {
|
||||
let ptr = unsafe { ffi::X509_STORE_CTX_get_current_cert(self.ctx) };
|
||||
|
||||
|
|
@ -175,6 +181,86 @@ pub struct X509 {
|
|||
priv x509: *ffi::X509
|
||||
}
|
||||
|
||||
macro_rules! make_validation_error(
|
||||
($ok_val:ident, $($name:ident = $val:ident,)+) => (
|
||||
pub mod hack {
|
||||
use std::libc::c_int;
|
||||
|
||||
pub enum X509ValidationError {
|
||||
$($name,)+
|
||||
X509UnknownError(c_int)
|
||||
}
|
||||
|
||||
impl X509ValidationError {
|
||||
#[doc(hidden)]
|
||||
pub fn from_raw(err: c_int) -> Option<X509ValidationError> {
|
||||
match err {
|
||||
super::ffi::$ok_val => None,
|
||||
$(super::ffi::$val => Some($name),)+
|
||||
err => Some(X509UnknownError(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
make_validation_error!(X509_V_OK,
|
||||
X509UnableToGetIssuerCert = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT,
|
||||
X509UnableToGetCrl = X509_V_ERR_UNABLE_TO_GET_CRL,
|
||||
X509UnableToDecryptCertSignature = X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE,
|
||||
X509UnableToDecryptCrlSignature = X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE,
|
||||
X509UnableToDecodeIssuerPublicKey = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY,
|
||||
X509CertSignatureFailure = X509_V_ERR_CERT_SIGNATURE_FAILURE,
|
||||
X509CrlSignatureFailure = X509_V_ERR_CRL_SIGNATURE_FAILURE,
|
||||
X509CertNotYetValid = X509_V_ERR_CERT_NOT_YET_VALID,
|
||||
X509CertHasExpired = X509_V_ERR_CERT_HAS_EXPIRED,
|
||||
X509CrlNotYetValid = X509_V_ERR_CRL_NOT_YET_VALID,
|
||||
X509CrlHasExpired = X509_V_ERR_CRL_HAS_EXPIRED,
|
||||
X509ErrorInCertNotBeforeField = X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD,
|
||||
X509ErrorInCertNotAfterField = X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD,
|
||||
X509ErrorInCrlLastUpdateField = X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD,
|
||||
X509ErrorInCrlNextUpdateField = X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD,
|
||||
X509OutOfMem = X509_V_ERR_OUT_OF_MEM,
|
||||
X509DepthZeroSelfSignedCert = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT,
|
||||
X509SelfSignedCertInChain = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN,
|
||||
X509UnableToGetIssuerCertLocally = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY,
|
||||
X509UnableToVerifyLeafSignature = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE,
|
||||
X509CertChainTooLong = X509_V_ERR_CERT_CHAIN_TOO_LONG,
|
||||
X509CertRevoked = X509_V_ERR_CERT_REVOKED,
|
||||
X509InvalidCA = X509_V_ERR_INVALID_CA,
|
||||
X509PathLengthExceeded = X509_V_ERR_PATH_LENGTH_EXCEEDED,
|
||||
X509InvalidPurpose = X509_V_ERR_INVALID_PURPOSE,
|
||||
X509CertUntrusted = X509_V_ERR_CERT_UNTRUSTED,
|
||||
X509CertRejected = X509_V_ERR_CERT_REJECTED,
|
||||
X509SubjectIssuerMismatch = X509_V_ERR_SUBJECT_ISSUER_MISMATCH,
|
||||
X509AkidSkidMismatch = X509_V_ERR_AKID_SKID_MISMATCH,
|
||||
X509AkidIssuerSerialMismatch = X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH,
|
||||
X509KeyusageNoCertsign = X509_V_ERR_KEYUSAGE_NO_CERTSIGN,
|
||||
X509UnableToGetCrlIssuer = X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER,
|
||||
X509UnhandledCriticalExtension = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION,
|
||||
X509KeyusageNoCrlSign = X509_V_ERR_KEYUSAGE_NO_CRL_SIGN,
|
||||
X509UnhandledCriticalCrlExtension = X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION,
|
||||
X509InvalidNonCA = X509_V_ERR_INVALID_NON_CA,
|
||||
X509ProxyPathLengthExceeded = X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED,
|
||||
X509KeyusageNoDigitalSignature = X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE,
|
||||
X509ProxyCertificatesNotAllowed = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED,
|
||||
X509InvalidExtension = X509_V_ERR_INVALID_EXTENSION,
|
||||
X509InavlidPolicyExtension = X509_V_ERR_INVALID_POLICY_EXTENSION,
|
||||
X509NoExplicitPolicy = X509_V_ERR_NO_EXPLICIT_POLICY,
|
||||
X509DifferentCrlScope = X509_V_ERR_DIFFERENT_CRL_SCOPE,
|
||||
X509UnsupportedExtensionFeature = X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE,
|
||||
X509UnnestedResource = X509_V_ERR_UNNESTED_RESOURCE,
|
||||
X509PermittedVolation = X509_V_ERR_PERMITTED_VIOLATION,
|
||||
X509ExcludedViolation = X509_V_ERR_EXCLUDED_VIOLATION,
|
||||
X509SubtreeMinmax = X509_V_ERR_SUBTREE_MINMAX,
|
||||
X509UnsupportedConstraintType = X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE,
|
||||
X509UnsupportedConstraintSyntax = X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX,
|
||||
X509UnsupportedNameSyntax = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX,
|
||||
X509CrlPathValidationError= X509_V_ERR_CRL_PATH_VALIDATION_ERROR,
|
||||
X509ApplicationVerification = X509_V_ERR_APPLICATION_VERIFICATION,
|
||||
)
|
||||
|
||||
struct Ssl {
|
||||
ssl: *ffi::SSL
|
||||
}
|
||||
|
|
|
|||
30
test.rs
30
test.rs
|
|
@ -1,4 +1,4 @@
|
|||
#[feature(struct_variant)];
|
||||
#[feature(struct_variant, macro_rules)];
|
||||
|
||||
use std::io::Writer;
|
||||
use std::io::net::tcp::TcpStream;
|
||||
|
|
@ -115,6 +115,34 @@ fn test_verify_callback_load_certs() {
|
|||
assert!(SslStream::try_new(&ctx, stream).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verify_trusted_get_error_ok() {
|
||||
fn callback(_preverify_ok: bool, x509_ctx: X509StoreContext) -> bool {
|
||||
assert!(x509_ctx.get_error().is_none());
|
||||
true
|
||||
}
|
||||
let stream = TcpStream::connect(FromStr::from_str("127.0.0.1:15418").unwrap()).unwrap();
|
||||
let mut ctx = SslContext::new(Sslv23);
|
||||
ctx.set_verify(SslVerifyPeer, Some(callback));
|
||||
match ctx.set_CA_file("test/cert.pem") {
|
||||
None => {}
|
||||
Some(err) => fail!("Unexpected error {:?}", err)
|
||||
}
|
||||
assert!(SslStream::try_new(&ctx, stream).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verify_trusted_get_error_err() {
|
||||
fn callback(_preverify_ok: bool, x509_ctx: X509StoreContext) -> bool {
|
||||
assert!(x509_ctx.get_error().is_some());
|
||||
false
|
||||
}
|
||||
let stream = TcpStream::connect(FromStr::from_str("127.0.0.1:15418").unwrap()).unwrap();
|
||||
let mut ctx = SslContext::new(Sslv23);
|
||||
ctx.set_verify(SslVerifyPeer, Some(callback));
|
||||
assert!(SslStream::try_new(&ctx, stream).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write() {
|
||||
let stream = TcpStream::connect(FromStr::from_str("127.0.0.1:15418").unwrap()).unwrap();
|
||||
|
|
|
|||
Loading…
Reference in New Issue