#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include <openssl/asn1.h>
#include <openssl/objects.h>
#include <openssl/bio.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
typedef X509_STORE* Crypt__OpenSSL__VerifyX509;
typedef X509* Crypt__OpenSSL__X509;
static int verify_cb(int ok, X509_STORE_CTX *ctx) {
if (!ok)
switch (X509_STORE_CTX_get_error (ctx)) {
case X509_V_ERR_CERT_HAS_EXPIRED:
/* case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: */
case X509_V_ERR_INVALID_CA:
case X509_V_ERR_PATH_LENGTH_EXCEEDED:
case X509_V_ERR_INVALID_PURPOSE:
case X509_V_ERR_CRL_HAS_EXPIRED:
case X509_V_ERR_CRL_NOT_YET_VALID:
case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
ok = 1;
break;
}
return(ok);
}
static const char *ssl_error(void) {
return ERR_error_string(ERR_get_error(), NULL);
}
static const char *ctx_error(X509_STORE_CTX *ctx) {
return X509_verify_cert_error_string(X509_STORE_CTX_get_error (ctx));
}
MODULE = Crypt::OpenSSL::VerifyX509 PACKAGE = Crypt::OpenSSL::VerifyX509
PROTOTYPES: DISABLE
#if OPENSSL_API_COMPAT >= 0x10100000L
#undef ERR_load_crypto_strings
#define ERR_load_crypto_strings() /* nothing */
#undef OpenSSL_add_all_algorithms
# define OpenSSL_add_all_algorithms() /* nothing */
#endif
BOOT:
ERR_load_crypto_strings();
ERR_load_ERR_strings();
OpenSSL_add_all_algorithms();
Crypt::OpenSSL::VerifyX509
new(class, cafile_str)
SV *class
SV *cafile_str
PREINIT:
int i = 1;
X509_LOOKUP *lookup = NULL;
STRLEN len;
char *cafile;
CODE:
(void) SvPV_nolen(class);
RETVAL = X509_STORE_new();
if (RETVAL == NULL)
croak("failure to allocate x509 store: %s", ssl_error());
X509_STORE_set_verify_cb_func(RETVAL,verify_cb);
/* load CA file given */
lookup = X509_STORE_add_lookup(RETVAL, X509_LOOKUP_file());
if (lookup == NULL)
croak("failure to add file lookup to store: %s", ssl_error());
cafile = SvPV(cafile_str, len);
i = X509_LOOKUP_load_file(lookup, cafile, X509_FILETYPE_PEM);
if (!i)
croak("load CA cert: %s", ssl_error());
/* default hash_dir lookup */
lookup = X509_STORE_add_lookup(RETVAL,X509_LOOKUP_hash_dir());
if (lookup == NULL)
croak("failure to add hash_dir lookup to store: %s", ssl_error());
X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT);
ERR_clear_error();
OUTPUT:
RETVAL
int
verify(store, x509)
Crypt::OpenSSL::VerifyX509 store;
Crypt::OpenSSL::X509 x509;
PREINIT:
X509_STORE_CTX *csc;
CODE:
if (x509 == NULL)
croak("no cert to verify");
csc = X509_STORE_CTX_new();
if (csc == NULL)
croak("csc new: %s", ssl_error());
X509_STORE_set_flags(store, 0);
if (!X509_STORE_CTX_init(csc,store,x509,NULL))
croak("store ctx init: %s", ssl_error());
RETVAL = X509_verify_cert(csc);
X509_STORE_CTX_free(csc);
if (!RETVAL)
croak("verify: %s", ctx_error(csc));
OUTPUT:
RETVAL
void
DESTROY(store)
Crypt::OpenSSL::VerifyX509 store;
PPCODE:
if (store) X509_STORE_free(store); store = 0;
#if OPENSSL_API_COMPAT >= 0x10100000L
void
__X509_cleanup(void)
PPCODE:
/* deinitialisation is done automatically */
#else
void
__X509_cleanup(void)
PPCODE:
CRYPTO_cleanup_all_ex_data();
ERR_free_strings();
ERR_remove_state(0);
EVP_cleanup();
#endif