aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Fackler <[email protected]>2013-11-16 21:09:45 -0800
committerSteven Fackler <[email protected]>2013-11-16 21:09:45 -0800
commit0b287710c408a510adffbd471e227fd1f87e2780 (patch)
tree94e803ce47ec747064801be430d6f3ba5df4c5c9
parentStart of x509 interface (diff)
downloadrust-openssl-0b287710c408a510adffbd471e227fd1f87e2780.tar.xz
rust-openssl-0b287710c408a510adffbd471e227fd1f87e2780.zip
Certificate error codes
-rw-r--r--ffi.rs66
-rw-r--r--lib.rs88
-rw-r--r--test.rs30
3 files changed, 181 insertions, 3 deletions
diff --git a/ffi.rs b/ffi.rs
index cbb6e492..7f367605 100644
--- a/ffi.rs
+++ b/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);
diff --git a/lib.rs b/lib.rs
index fb223c4d..6393ce95 100644
--- a/lib.rs
+++ b/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
}
diff --git a/test.rs b/test.rs
index cc9e8bab..b3c466c9 100644
--- a/test.rs
+++ b/test.rs
@@ -1,4 +1,4 @@
-#[feature(struct_variant)];
+#[feature(struct_variant, macro_rules)];
use std::io::Writer;
use std::io::net::tcp::TcpStream;
@@ -116,6 +116,34 @@ fn test_verify_callback_load_certs() {
}
#[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();
let mut stream = SslStream::new(&SslContext::new(Sslv23), stream);