/* SSLeay.xs - Perl module for using Eric Young's implementation of SSL
*
* Copyright (c) 1996-2002 Sampo Kellomaki <sampo@iki.fi>
* Copyright (C) 2005 Florian Ragwitz <rafl@debian.org>
* Copyright (C) 2005 Mike McCauley <mikem@airspayce.com>
*
* All Rights Reserved.
*
* Change data removed. See Changes
*
* $Id: SSLeay.xs 513 2018-01-03 21:46:53Z mikem-guest $
*
* The distribution and use of this module are subject to the conditions
* listed in LICENSE file at the root of the Net-SSLeay
* distribution (i.e. same license as Perl itself).
*/
/* ####
* #### PLEASE READ THE FOLLOWING RULES BEFORE YOU START EDITING THIS FILE! ####
* ####
*
* Function naming conventions:
*
* 1/ never change the already existing function names (all calling convention) in a way
* that may cause backward incompatibility (e.g. add ALIAS with old name if necessary)
*
* 2/ it is recommended to keep the original openssl function names for functions that are:
*
* 1:1 wrappers to the original openssl functions
* see for example: X509_get_issuer_name(cert) >> Net::SSLeay::X509_get_issuer_name($cert)
*
* nearly 1:1 wrappers implementing only necessary "glue" e.g. buffer handling
* see for example: RAND_seed(buf,len) >> Net::SSLeay::RAND_seed($buf)
*
* 3/ OpenSSL functions starting with "SSL_" are added into SSLeay.xs with "SLL_" prefix
* (e.g. SSL_CTX_new) but keep in mind that they will be available in Net::SSLeay without
* "SSL_" prefix (e.g. Net::SSLeay::CTX_new) - keep this for all new functions
*
* 4/ The names of functions which do not fit rule 2/ (which means they implement some non
* trivial code around original openssl function or do more complex tasks) should be
* prefixed with "P_" - see for example: P_ASN1_TIME_set_isotime
*
* 5/ Exceptions from rules above:
* functions that are part or wider set of already existing function not following this rule
* for example: there already exists: PEM_get_string_X509_CRL + PEM_get_string_X509_REQ and you want
* to add PEM_get_string_SOMETHING - then no need to follow 3/ (do not prefix with "P_")
*
* Support for different openssl versions, different platforms, different compilers:
*
* 1/ SSleay.xs is expected to build/pass test suite
* - with openssl 0.9.6 and newer versions
* - with perl 5.8 and newer versions
*
* 2/ Fix all compiler warnings - we expect 100% clean build
*
* 3/ If you add a function which is available since certain openssl version
* use proper #ifdefs to assure that SSLeay.xs will compile also with older versions
* which are missing this function
*
* 4/ Even warnings arising from different use of "const" in different openssl versions
* needs to be hanled with #ifdefs - see for example: X509_NAME_add_entry_by_txt
*
* 5/ avoid using global C variables (it is very likely to break thread-safetyness)
* use rather global MY_CXT structure
*
* 6/ avoid using any UNIX/POSIX specific functions, keep in mind that SSLeay.xs must
* compile also on non-UNIX platforms like MS Windows and others
*
* 7/ avoid using c++ comments "//" (or other c++ features accepted by some c compiler)
* even if your compiler can handle them without warnings
*
* Passing test suite:
*
* 1/ any changes to SSLeay.xs must not introduce a failure of existing test suite
*
* 2/ it is strongly recommended to create test(s) for newly added function(s), especially
* when the new function is not only a 1:1 wrapper but contains a complex code
*
* 3/ it is mandatory to add a documentation for all newly added functions into SSLeay.pod
* otherwise t/local/02_pod_coverage.t fail (and you will be asked to add some doc into
* your patch)
*
* Preferred code layout:
*
* 1/ for simple 1:1 XS wrappers use:
*
* a/ functions with short "signature" (short list of args):
*
* long
* SSL_set_tmp_dh(SSL *ssl,DH *dh)
*
* b/ functions with long "signature" (long list of args):
* simply when approach a/ does not fit to 120 columns
*
* void
* SSL_any_functions(library_flag,function_name,reason,file_name,line)
* int library_flag
* int function_name
* int reason
* char *file_name
* int line
*
* 2/ for XS functions with full implementation use identation like this:
*
* int
* RAND_bytes(buf, num)
* SV *buf
* int num
* PREINIT:
* int rc;
* unsigned char *random;
* CODE:
* / * some code here * /
* RETVAL = rc;
* OUTPUT:
* RETVAL
*
*
* Runtime debugging:
*
* with TRACE(level,fmt,...) you can output debug messages.
* it behaves the same as
* warn sprintf($msg,...) if $Net::SSLeay::trace>=$level
* would do in Perl (e.g. it is using also the $Net::SSLeay::trace variable)
*
*
* THE LAST RULE:
*
* The fact that some parts of SSLeay.xs do not follow the rules above is not
* a reason why any new code can also break these rules in the same way
*
*/
/* Prevent warnings about strncpy from Windows compilers */
#define _CRT_SECURE_NO_DEPRECATE
#ifdef __cplusplus
extern "C" {
#endif
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include <stdarg.h>
#define NEED_newRV_noinc
#define NEED_sv_2pv_flags
#define NEED_my_snprintf
#include "ppport.h"
#ifdef __cplusplus
}
#endif
/* OpenSSL-0.9.3a has some strange warning about this in
* openssl/des.h
*/
#undef _
/* Sigh: openssl 1.0 has
typedef void *BLOCK;
which conflicts with perls
typedef struct block BLOCK;
*/
#define BLOCK OPENSSL_BLOCK
#include <openssl/err.h>
#include <openssl/lhash.h>
#include <openssl/rand.h>
#include <openssl/buffer.h>
#include <openssl/ssl.h>
#include <openssl/pkcs12.h>
#ifndef OPENSSL_NO_COMP
#include <openssl/comp.h> /* openssl-0.9.6a forgets to include this */
#endif
#ifndef OPENSSL_NO_MD2
#include <openssl/md2.h>
#endif
#ifndef OPENSSL_NO_MD4
#include <openssl/md4.h>
#endif
#ifndef OPENSSL_NO_MD5
#include <openssl/md5.h> /* openssl-SNAP-20020227 does not automatically include this */
#endif
#if OPENSSL_VERSION_NUMBER >= 0x00905000L
#include <openssl/ripemd.h>
#endif
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#if OPENSSL_VERSION_NUMBER >= 0x0090700fL
/* requires 0.9.7+ */
#ifndef OPENSSL_NO_ENGINE
#include <openssl/engine.h>
#endif
#endif
#ifdef OPENSSL_FIPS
#include <openssl/fips.h>
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
#include <openssl/ocsp.h>
#endif
#undef BLOCK
/* Debugging output - to enable use:
*
* perl Makefile.PL DEFINE=-DSHOW_XS_DEBUG
* make
*
*/
#ifdef SHOW_XS_DEBUG
#define PR1(s) fprintf(stderr,s);
#define PR2(s,t) fprintf(stderr,s,t);
#define PR3(s,t,u) fprintf(stderr,s,t,u);
#define PR4(s,t,u,v) fprintf(stderr,s,t,u,v);
#else
#define PR1(s)
#define PR2(s,t)
#define PR3(s,t,u)
#define PR4(s,t,u,v)
#endif
static void TRACE(int level,char *msg,...) {
va_list args;
SV *trace = get_sv("Net::SSLeay::trace",0);
if (trace && SvIOK(trace) && SvIV(trace)>=level) {
char buf[4096];
va_start(args,msg);
vsnprintf(buf,4095,msg,args);
warn("%s",buf);
}
}
#include "constants.c"
/* ============= thread-safety related stuff ============== */
#define MY_CXT_KEY "Net::SSLeay::_guts" XS_VERSION
typedef struct {
HV* global_cb_data;
UV tid;
} my_cxt_t;
START_MY_CXT
#ifdef USE_ITHREADS
static perl_mutex LIB_init_mutex;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
static perl_mutex *GLOBAL_openssl_mutex = NULL;
#endif
#endif
static int LIB_initialized;
UV get_my_thread_id(void) /* returns threads->tid() value */
{
dSP;
UV tid = 0;
int count = 0;
#ifdef USE_ITHREADS
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVpv("threads", 0)));
PUTBACK;
count = call_method("tid", G_SCALAR|G_EVAL);
SPAGAIN;
/* Caution: recent perls do not appear support threads->tid() */
if (SvTRUE(ERRSV) || count != 1)
{
/* if compatible threads not loaded or an error occurs return 0 */
tid = 0;
}
else
tid = (UV)POPi;
PUTBACK;
FREETMPS;
LEAVE;
#endif
return tid;
}
/* IMPORTANT NOTE:
* openssl locking was implemented according to http://www.openssl.org/docs/crypto/threads.html
* we implement both static and dynamic locking as described on URL above
* locking is supported when OPENSSL_THREADS macro is defined which means openssl-0.9.7 or newer
* we intentionally do not implement cleanup of openssl's threading as it causes troubles
* with apache-mpm-worker+mod_perl+mod_ssl+net-ssleay
*/
#if defined(USE_ITHREADS) && defined(OPENSSL_THREADS)
#if OPENSSL_VERSION_NUMBER < 0x10100000L
static void openssl_locking_function(int mode, int type, const char *file, int line)
{
PR3("openssl_locking_function %d %d\n", mode, type);
if (!GLOBAL_openssl_mutex) return;
if (mode & CRYPTO_LOCK)
MUTEX_LOCK(&GLOBAL_openssl_mutex[type]);
else
MUTEX_UNLOCK(&GLOBAL_openssl_mutex[type]);
}
#if OPENSSL_VERSION_NUMBER < 0x10000000L
static unsigned long openssl_threadid_func(void)
{
dMY_CXT;
return (unsigned long)(MY_CXT.tid);
}
#else
void openssl_threadid_func(CRYPTO_THREADID *id)
{
dMY_CXT;
CRYPTO_THREADID_set_numeric(id, (unsigned long)(MY_CXT.tid));
}
#endif
struct CRYPTO_dynlock_value
{
perl_mutex mutex;
};
struct CRYPTO_dynlock_value * openssl_dynlocking_create_function (const char *file, int line)
{
struct CRYPTO_dynlock_value *retval;
New(0, retval, 1, struct CRYPTO_dynlock_value);
if (!retval) return NULL;
MUTEX_INIT(&retval->mutex);
return retval;
}
void openssl_dynlocking_lock_function (int mode, struct CRYPTO_dynlock_value *l, const char *file, int line)
{
if (!l) return;
if (mode & CRYPTO_LOCK)
MUTEX_LOCK(&l->mutex);
else
MUTEX_UNLOCK(&l->mutex);
}
void openssl_dynlocking_destroy_function (struct CRYPTO_dynlock_value *l, const char *file, int line)
{
if (!l) return;
MUTEX_DESTROY(&l->mutex);
Safefree(l);
}
#endif
void openssl_threads_init(void)
{
int i;
PR1("STARTED: openssl_threads_init\n");
#if OPENSSL_VERSION_NUMBER < 0x10100000L
/* initialize static locking */
if ( !CRYPTO_get_locking_callback() ) {
#if OPENSSL_VERSION_NUMBER < 0x10000000L
if ( !CRYPTO_get_id_callback() ) {
#else
if ( !CRYPTO_THREADID_get_callback() ) {
#endif
PR2("openssl_threads_init static locking %d\n", CRYPTO_num_locks());
New(0, GLOBAL_openssl_mutex, CRYPTO_num_locks(), perl_mutex);
if (!GLOBAL_openssl_mutex) return;
for (i=0; i<CRYPTO_num_locks(); i++) MUTEX_INIT(&GLOBAL_openssl_mutex[i]);
CRYPTO_set_locking_callback((void (*)(int,int,const char *,int))openssl_locking_function);
#ifndef WIN32
/* no need for threadid_func() on Win32 */
#if OPENSSL_VERSION_NUMBER < 0x10000000L
CRYPTO_set_id_callback(openssl_threadid_func);
#else
CRYPTO_THREADID_set_callback(openssl_threadid_func);
#endif
#endif
}
}
/* initialize dynamic locking */
if ( !CRYPTO_get_dynlock_create_callback() &&
!CRYPTO_get_dynlock_lock_callback() &&
!CRYPTO_get_dynlock_destroy_callback() ) {
PR1("openssl_threads_init dynamic locking\n");
CRYPTO_set_dynlock_create_callback(openssl_dynlocking_create_function);
CRYPTO_set_dynlock_lock_callback(openssl_dynlocking_lock_function);
CRYPTO_set_dynlock_destroy_callback(openssl_dynlocking_destroy_function);
}
#endif
}
#endif
/* ============= typedefs to agument TYPEMAP ============== */
typedef void callback_no_ret(void);
typedef RSA * cb_ssl_int_int_ret_RSA(SSL * ssl,int is_export, int keylength);
typedef DH * cb_ssl_int_int_ret_DH(SSL * ssl,int is_export, int keylength);
typedef STACK_OF(X509_NAME) X509_NAME_STACK;
typedef int perl_filehandle_t;
/* ======= special handler used by EVP_MD_do_all_sorted ======= */
#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
static void handler_list_md_fn(const EVP_MD *m, const char *from, const char *to, void *arg)
{
/* taken from apps/dgst.c */
const char *mname;
if (!m) return; /* Skip aliases */
mname = OBJ_nid2ln(EVP_MD_type(m));
if (strcmp(from, mname)) return; /* Skip shortnames */
#if OPENSSL_VERSION_NUMBER < 0x10100000L
if (EVP_MD_flags(m) & EVP_MD_FLAG_PKEY_DIGEST) return; /* Skip clones */
#endif
if (strchr(mname, ' ')) mname= EVP_MD_name(m);
av_push(arg, newSVpv(mname,0));
}
#endif
/* ============= callbacks - basic info =============
*
* PLEASE READ THIS BEFORE YOU ADD ANY NEW CALLBACK!!
*
* There are basically 2 types of callbacks used in SSLeay:
*
* 1/ "one-time" callbacks - these are created+used+destroyed within one perl function implemented in XS
* these callbacks use a cpecial C structupe simple_cb_data_t to pass necessary data
* there are 2 related helper functions: simple_cb_data_new() + simple_cb_data_free
* for example see implementation of these functions:
* - RSA_generate_key
* - PEM_read_bio_PrivateKey
*
* 2/ "advanced" callbacks - these are setup/destroyed by one function but used by another function; these
* callbacks use global hash MY_CXT.global_cb_data to store perl functions + data to be uset at callback time
* there are 2 related helper functions: cb_data_advanced_put() + cb_data_advanced_get for manipulating
* global hash MY_CXT.global_cb_data which work like this:
* cb_data_advanced_put(<pointer>, "data_name", dataSV)
* >>>
* global_cb_data->{"ptr_<pointer>"}->{"data_name"} = dataSV)
* or
* data = cb_data_advanced_get(<pointer>, "data_name")
* >>>
* my $data = global_cb_data->{"ptr_<pointer>"}->{"data_name"}
* for example see implementation of these functions:
* - SSL_CTX_set_verify
* - SSL_set_verify
* - SSL_CTX_set_cert_verify_callback
* - SSL_CTX_set_default_passwd_cb
* - SSL_CTX_set_default_passwd_cb_userdata
* - SSL_set_session_secret_cb
*
* If you want to add a new callback:
* - you very likely need a new function "your_callback_name_invoke()"
* - decide whether your case fits case 1/ or 2/ (and implement likewise existing functions)
* - try to avoid adding a new style of callback implementation (or ask Net::SSLeay maintainers before)
*
*/
/* ============= callback stuff - generic functions============== */
struct _ssleay_cb_t {
SV* func;
SV* data;
};
typedef struct _ssleay_cb_t simple_cb_data_t;
simple_cb_data_t* simple_cb_data_new(SV* func, SV* data)
{
simple_cb_data_t* cb;
New(0, cb, 1, simple_cb_data_t);
if (cb) {
SvREFCNT_inc(func);
SvREFCNT_inc(data);
cb->func = func;
cb->data = (data == &PL_sv_undef) ? NULL : data;
}
return cb;
}
void simple_cb_data_free(simple_cb_data_t* cb)
{
if (cb) {
if (cb->func) {
SvREFCNT_dec(cb->func);
cb->func = NULL;
}
if (cb->data) {
SvREFCNT_dec(cb->data);
cb->data = NULL;
}
}
Safefree(cb);
}
int cb_data_advanced_put(void *ptr, const char* data_name, SV* data)
{
HV * L2HV;
SV ** svtmp;
int len;
char key_name[500];
dMY_CXT;
len = my_snprintf(key_name, sizeof(key_name), "ptr_%p", ptr);
if (len == sizeof(key_name)) return 0; /* error - key_name too short*/
/* get or create level-2 hash */
svtmp = hv_fetch(MY_CXT.global_cb_data, key_name, strlen(key_name), 0);
if (svtmp == NULL) {
L2HV = newHV();
hv_store(MY_CXT.global_cb_data, key_name, strlen(key_name), newRV_noinc((SV*)L2HV), 0);
}
else {
if (!SvOK(*svtmp) || !SvROK(*svtmp)) return 0;
#if defined(MUTABLE_PTR)
L2HV = (HV*)MUTABLE_PTR(SvRV(*svtmp));
#else
L2HV = (HV*)(SvRV(*svtmp));
#endif
}
/* first delete already stored value */
hv_delete(L2HV, data_name, strlen(data_name), G_DISCARD);
if (data!=NULL)
if (SvOK(data))
hv_store(L2HV, data_name, strlen(data_name), data, 0);
return 1;
}
SV* cb_data_advanced_get(void *ptr, const char* data_name)
{
HV * L2HV;
SV ** svtmp;
int len;
char key_name[500];
dMY_CXT;
len = my_snprintf(key_name, sizeof(key_name), "ptr_%p", ptr);
if (len == sizeof(key_name)) return &PL_sv_undef; /* return undef on error - key_name too short*/
/* get level-2 hash */
svtmp = hv_fetch(MY_CXT.global_cb_data, key_name, strlen(key_name), 0);
if (svtmp == NULL) return &PL_sv_undef;
if (!SvOK(*svtmp)) return &PL_sv_undef;
if (!SvROK(*svtmp)) return &PL_sv_undef;
#if defined(MUTABLE_PTR)
L2HV = (HV*)MUTABLE_PTR(SvRV(*svtmp));
#else
L2HV = (HV*)(SvRV(*svtmp));
#endif
/* get stored data */
svtmp = hv_fetch(L2HV, data_name, strlen(data_name), 0);
if (svtmp == NULL) return &PL_sv_undef;
if (!SvOK(*svtmp)) return &PL_sv_undef;
return *svtmp;
}
int cb_data_advanced_drop(void *ptr)
{
int len;
char key_name[500];
dMY_CXT;
len = my_snprintf(key_name, sizeof(key_name), "ptr_%p", ptr);
if (len == sizeof(key_name)) return 0; /* error - key_name too short*/
hv_delete(MY_CXT.global_cb_data, key_name, strlen(key_name), G_DISCARD);
return 1;
}
/* ============= callback stuff - invoke functions ============== */
static int ssleay_verify_callback_invoke (int ok, X509_STORE_CTX* x509_store)
{
dSP;
SSL* ssl;
int count = -1, res;
SV *cb_func;
PR1("STARTED: ssleay_verify_callback_invoke\n");
ssl = X509_STORE_CTX_get_ex_data(x509_store, SSL_get_ex_data_X509_STORE_CTX_idx());
cb_func = cb_data_advanced_get(ssl, "ssleay_verify_callback!!func");
if (!SvOK(cb_func)) {
SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(ssl);
cb_func = cb_data_advanced_get(ssl_ctx, "ssleay_verify_callback!!func");
}
if (!SvOK(cb_func))
croak("Net::SSLeay: verify_callback called, but not set to point to any perl function.\n");
ENTER;
SAVETMPS;
PR2("verify callback glue ok=%d\n", ok);
PUSHMARK(sp);
EXTEND( sp, 2 );
PUSHs( sv_2mortal(newSViv(ok)) );
PUSHs( sv_2mortal(newSViv(PTR2IV(x509_store))) );
PUTBACK;
PR1("About to call verify callback.\n");
count = call_sv(cb_func, G_SCALAR);
PR1("Returned from verify callback.\n");
SPAGAIN;
if (count != 1)
croak ( "Net::SSLeay: verify_callback perl function did not return a scalar.\n");
res = POPi;
PUTBACK;
FREETMPS;
LEAVE;
return res;
}
static int ssleay_ctx_passwd_cb_invoke(char *buf, int size, int rwflag, void *userdata)
{
dSP;
int count = -1;
char *res;
SV *cb_func, *cb_data;
PR1("STARTED: ssleay_ctx_passwd_cb_invoke\n");
cb_func = cb_data_advanced_get(userdata, "ssleay_ctx_passwd_cb!!func");
cb_data = cb_data_advanced_get(userdata, "ssleay_ctx_passwd_cb!!data");
if(!SvOK(cb_func))
croak ("Net::SSLeay: ssleay_ctx_passwd_cb_invoke called, but not set to point to any perl function.\n");
ENTER;
SAVETMPS;
PUSHMARK(sp);
XPUSHs(sv_2mortal(newSViv(rwflag)));
XPUSHs(sv_2mortal(newSVsv(cb_data)));
PUTBACK;
count = call_sv( cb_func, G_SCALAR );
SPAGAIN;
if (count != 1)
croak("Net::SSLeay: ssleay_ctx_passwd_cb_invoke perl function did not return a scalar.\n");
res = POPp;
if (res == NULL) {
*buf = '\0';
} else {
strncpy(buf, res, size);
buf[size - 1] = '\0';
}
PUTBACK;
FREETMPS;
LEAVE;
return strlen(buf);
}
#if OPENSSL_VERSION_NUMBER >= 0x1010006fL /* In OpenSSL 1.1.0 but actually called for $ssl from 1.1.0f */
#ifndef LIBRESSL_VERSION_NUMBER
#ifndef OPENSSL_IS_BORINGSSL
static int ssleay_ssl_passwd_cb_invoke(char *buf, int size, int rwflag, void *userdata)
{
dSP;
int count = -1;
char *res;
SV *cb_func, *cb_data;
PR1("STARTED: ssleay_ssl_passwd_cb_invoke\n");
cb_func = cb_data_advanced_get(userdata, "ssleay_ssl_passwd_cb!!func");
cb_data = cb_data_advanced_get(userdata, "ssleay_ssl_passwd_cb!!data");
if(!SvOK(cb_func))
croak ("Net::SSLeay: ssleay_ssl_passwd_cb_invoke called, but not set to point to any perl function.\n");
ENTER;
SAVETMPS;
PUSHMARK(sp);
XPUSHs(sv_2mortal(newSViv(rwflag)));
XPUSHs(sv_2mortal(newSVsv(cb_data)));
PUTBACK;
count = call_sv( cb_func, G_SCALAR );
SPAGAIN;
if (count != 1)
croak("Net::SSLeay: ssleay_ssl_passwd_cb_invoke perl function did not return a scalar.\n");
res = POPp;
if (res == NULL) {
*buf = '\0';
} else {
strncpy(buf, res, size);
buf[size - 1] = '\0';
}
PUTBACK;
FREETMPS;
LEAVE;
return strlen(buf);
}
#endif /* !BoringSSL */
#endif /* !LibreSSL */
#endif /* >= 1.1.0f */
int ssleay_ctx_cert_verify_cb_invoke(X509_STORE_CTX* x509_store_ctx, void* data)
{
dSP;
int count = -1;
int res;
SV * cb_func, *cb_data;
void *ptr;
SSL *ssl;
PR1("STARTED: ssleay_ctx_cert_verify_cb_invoke\n");
#if OPENSSL_VERSION_NUMBER < 0x0090700fL
ssl = X509_STORE_CTX_get_ex_data(x509_store_ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
ptr = (void*) SSL_get_SSL_CTX(ssl);
#else
ssl = NULL;
ptr = (void*) data;
#endif
cb_func = cb_data_advanced_get(ptr, "ssleay_ctx_cert_verify_cb!!func");
cb_data = cb_data_advanced_get(ptr, "ssleay_ctx_cert_verify_cb!!data");
if(!SvOK(cb_func))
croak ("Net::SSLeay: ssleay_ctx_cert_verify_cb_invoke called, but not set to point to any perl function.\n");
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSViv(PTR2IV(x509_store_ctx))));
XPUSHs(sv_2mortal(newSVsv(cb_data)));
PUTBACK;
count = call_sv(cb_func, G_SCALAR);
SPAGAIN;
if (count != 1)
croak("Net::SSLeay: ssleay_ctx_cert_verify_cb_invoke perl function did not return a scalar.\n");
res = POPi;
PUTBACK;
FREETMPS;
LEAVE;
return res;
}
#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
int tlsext_servername_callback_invoke(SSL *ssl, int *ad, void *arg)
{
dSP;
int count = -1;
int res;
SV * cb_func, *cb_data;
PR1("STARTED: tlsext_servername_callback_invoke\n");
cb_func = cb_data_advanced_get(arg, "tlsext_servername_callback!!func");
cb_data = cb_data_advanced_get(arg, "tlsext_servername_callback!!data");
if(!SvOK(cb_func))
croak ("Net::SSLeay: tlsext_servername_callback_invoke called, but not set to point to any perl function.\n");
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSViv(PTR2IV(ssl))));
XPUSHs(sv_2mortal(newSVsv(cb_data)));
PUTBACK;
count = call_sv(cb_func, G_SCALAR);
SPAGAIN;
if (count != 1)
croak("Net::SSLeay: tlsext_servername_callback_invoke perl function did not return a scalar.\n");
res = POPi;
PUTBACK;
FREETMPS;
LEAVE;
return res;
}
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_TLSEXT)
int tlsext_status_cb_invoke(SSL *ssl, void *arg)
{
dSP;
SV *cb_func, *cb_data;
SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
int len,res,nres = -1;
const unsigned char *p = NULL;
OCSP_RESPONSE *ocsp_response = NULL;
cb_func = cb_data_advanced_get(ctx, "tlsext_status_cb!!func");
cb_data = cb_data_advanced_get(ctx, "tlsext_status_cb!!data");
if ( ! SvROK(cb_func) || (SvTYPE(SvRV(cb_func)) != SVt_PVCV))
croak ("Net::SSLeay: tlsext_status_cb_invoke called, but not set to point to any perl function.\n");
len = SSL_get_tlsext_status_ocsp_resp(ssl, &p);
if (p) ocsp_response = d2i_OCSP_RESPONSE(NULL, &p, len);
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSViv(PTR2IV(ssl))));
PUSHs( sv_2mortal(newSViv(PTR2IV(ocsp_response))) );
XPUSHs(sv_2mortal(newSVsv(cb_data)));
PUTBACK;
nres = call_sv(cb_func, G_SCALAR);
if (ocsp_response) OCSP_RESPONSE_free(ocsp_response);
SPAGAIN;
if (nres != 1)
croak("Net::SSLeay: tlsext_status_cb_invoke perl function did not return a scalar.\n");
res = POPi;
PUTBACK;
FREETMPS;
LEAVE;
return res;
}
int session_ticket_ext_cb_invoke(SSL *ssl, const unsigned char *data, int len, void *arg)
{
dSP;
SV *cb_func, *cb_data;
int res,nres = -1;
cb_func = cb_data_advanced_get(arg, "session_ticket_ext_cb!!func");
cb_data = cb_data_advanced_get(arg, "session_ticket_ext_cb!!data");
if ( ! SvROK(cb_func) || (SvTYPE(SvRV(cb_func)) != SVt_PVCV))
croak ("Net::SSLeay: session_ticket_ext_cb_invoke called, but not set to point to any perl function.\n");
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSViv(PTR2IV(ssl))));
XPUSHs(sv_2mortal(newSVpvn((const char *)data, len)));
XPUSHs(sv_2mortal(newSVsv(cb_data)));
PUTBACK;
nres = call_sv(cb_func, G_SCALAR);
SPAGAIN;
if (nres != 1)
croak("Net::SSLeay: session_ticket_ext_cb_invoke perl function did not return a scalar.\n");
res = POPi;
PUTBACK;
FREETMPS;
LEAVE;
return res;
}
#endif
#if defined(SSL_F_SSL_SET_HELLO_EXTENSION) || defined(SSL_F_SSL_SET_SESSION_TICKET_EXT)
int ssleay_session_secret_cb_invoke(SSL* s, void* secret, int *secret_len,
STACK_OF(SSL_CIPHER) *peer_ciphers,
const SSL_CIPHER **cipher, void *arg)
{
dSP;
int count = -1, res, i;
AV *ciphers = newAV();
SV *pref_cipher = sv_newmortal();
SV * cb_func, *cb_data;
SV * secretsv;
PR1("STARTED: ssleay_session_secret_cb_invoke\n");
cb_func = cb_data_advanced_get(arg, "ssleay_session_secret_cb!!func");
cb_data = cb_data_advanced_get(arg, "ssleay_session_secret_cb!!data");
if(!SvOK(cb_func))
croak ("Net::SSLeay: ssleay_ctx_passwd_cb_invoke called, but not set to point to any perl function.\n");
ENTER;
SAVETMPS;
PUSHMARK(SP);
secretsv = sv_2mortal( newSVpv(secret, *secret_len));
XPUSHs(secretsv);
for (i=0; i<sk_SSL_CIPHER_num(peer_ciphers); i++) {
const SSL_CIPHER *c = sk_SSL_CIPHER_value(peer_ciphers,i);
av_store(ciphers, i, sv_2mortal(newSVpv(SSL_CIPHER_get_name(c), 0)));
}
XPUSHs(sv_2mortal(newRV_inc((SV*)ciphers)));
XPUSHs(sv_2mortal(newRV_inc(pref_cipher)));
XPUSHs(sv_2mortal(newSVsv(cb_data)));
PUTBACK;
count = call_sv( cb_func, G_SCALAR );
SPAGAIN;
if (count != 1)
croak ("Net::SSLeay: ssleay_session_secret_cb_invoke perl function did not return a scalar.\n");
res = POPi;
if (res) {
/* See if there is a preferred cipher selected, if so it is an index into the stack */
if (SvIOK(pref_cipher))
*cipher = sk_SSL_CIPHER_value(peer_ciphers, SvIV(pref_cipher));
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
{
/* Use any new master secret set by the callback function in secret */
STRLEN newsecretlen;
char* newsecretdata = SvPV(secretsv, newsecretlen);
memcpy(secret, newsecretdata, newsecretlen);
}
#endif
}
PUTBACK;
FREETMPS;
LEAVE;
return res;
}
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_PSK)
#define NET_SSLEAY_CAN_PSK_CLIENT_CALLBACK
unsigned int ssleay_set_psk_client_callback_invoke(SSL *ssl, const char *hint,
char *identity, unsigned int max_identity_len,
unsigned char *psk, unsigned int max_psk_len)
{
dSP;
int count = -1;
char *identity_val, *psk_val;
unsigned int psk_len = 0;
BIGNUM *psk_bn = NULL;
SV * cb_func;
SV * hintsv;
PR1("STARTED: ssleay_set_psk_client_callback_invoke\n");
cb_func = cb_data_advanced_get(ssl, "ssleay_set_psk_client_callback!!func");
if(!SvOK(cb_func))
croak ("Net::SSLeay: ssleay_set_psk_client_callback_invoke called, but not set to point to any perl function.\n");
ENTER;
SAVETMPS;
PUSHMARK(SP);
if (hint != NULL) {
hintsv = sv_2mortal( newSVpv(hint, strlen(hint)));
XPUSHs(hintsv);
}
PUTBACK;
count = call_sv( cb_func, G_ARRAY );
SPAGAIN;
if (count != 2)
croak ("Net::SSLeay: ssleay_set_psk_client_callback_invoke perl function did not return 2 values.\n");
psk_val = POPpx;
identity_val = POPpx;
my_snprintf(identity, max_identity_len, "%s", identity_val);
if (BN_hex2bn(&psk_bn, psk_val) > 0) {
if (BN_num_bytes(psk_bn) <= max_psk_len) {
psk_len = BN_bn2bin(psk_bn, psk);
}
BN_free(psk_bn);
}
PUTBACK;
FREETMPS;
LEAVE;
return psk_len;
}
unsigned int ssleay_ctx_set_psk_client_callback_invoke(SSL *ssl, const char *hint,
char *identity, unsigned int max_identity_len,
unsigned char *psk, unsigned int max_psk_len)
{
dSP;
SSL_CTX *ctx;
int count = -1;
char *identity_val, *psk_val;
unsigned int psk_len = 0;
BIGNUM *psk_bn = NULL;
SV * cb_func;
SV * hintsv;
ctx = SSL_get_SSL_CTX(ssl);
PR1("STARTED: ssleay_ctx_set_psk_client_callback_invoke\n");
cb_func = cb_data_advanced_get(ctx, "ssleay_ctx_set_psk_client_callback!!func");
if(!SvOK(cb_func))
croak ("Net::SSLeay: ssleay_ctx_set_psk_client_callback_invoke called, but not set to point to any perl function.\n");
ENTER;
SAVETMPS;
PUSHMARK(SP);
if (hint != NULL) {
hintsv = sv_2mortal( newSVpv(hint, strlen(hint)));
XPUSHs(hintsv);
}
PUTBACK;
count = call_sv( cb_func, G_ARRAY );
SPAGAIN;
if (count != 2)
croak ("Net::SSLeay: ssleay_ctx_set_psk_client_callback_invoke perl function did not return 2 values.\n");
psk_val = POPpx;
identity_val = POPpx;
my_snprintf(identity, max_identity_len, "%s", identity_val);
if (BN_hex2bn(&psk_bn, psk_val) > 0) {
if (BN_num_bytes(psk_bn) <= max_psk_len) {
psk_len = BN_bn2bin(psk_bn, psk);
}
BN_free(psk_bn);
}
PUTBACK;
FREETMPS;
LEAVE;
return psk_len;
}
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_NEXTPROTONEG)) || (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_TLSEXT))
int next_proto_helper_AV2protodata(AV * list, unsigned char *out)
{
int i, last_index, ptr = 0;
last_index = av_len(list);
if (last_index<0) return 0;
for(i=0; i<=last_index; i++) {
char *p = SvPV_nolen(*av_fetch(list, i, 0));
size_t len = strlen(p);
if (len>255) return 0;
if (out) {
/* if out == NULL we only calculate the length of output */
out[ptr] = (unsigned char)len;
strncpy((char*)out+ptr+1, p, len);
}
ptr += strlen(p) + 1;
}
return ptr;
}
int next_proto_helper_protodata2AV(AV * list, const unsigned char *in, unsigned int inlen)
{
unsigned int i = 0;
unsigned char il;
if (!list || inlen<2) return 0;
while (i<inlen) {
il = in[i++];
if (i+il > inlen) return 0;
av_push(list, newSVpv((const char*)in+i, il));
i += il;
}
return 1;
}
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_NEXTPROTONEG) && !defined(LIBRESSL_VERSION_NUMBER)
int next_proto_select_cb_invoke(SSL *ssl, unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen, void *arg)
{
SV *cb_func, *cb_data;
unsigned char *next_proto_data;
size_t next_proto_len;
int next_proto_status;
SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
/* this n_a is required for building with old perls: */
STRLEN n_a;
PR1("STARTED: next_proto_select_cb_invoke\n");
cb_func = cb_data_advanced_get(ctx, "next_proto_select_cb!!func");
cb_data = cb_data_advanced_get(ctx, "next_proto_select_cb!!data");
/* clear last_status value = store undef */
cb_data_advanced_put(ssl, "next_proto_select_cb!!last_status", NULL);
cb_data_advanced_put(ssl, "next_proto_select_cb!!last_negotiated", NULL);
if (SvROK(cb_func) && (SvTYPE(SvRV(cb_func)) == SVt_PVCV)) {
int count = -1;
AV *list = newAV();
SV *tmpsv;
dSP;
if (!next_proto_helper_protodata2AV(list, in, inlen)) return SSL_TLSEXT_ERR_ALERT_FATAL;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSViv(PTR2IV(ssl))));
XPUSHs(sv_2mortal(newRV_inc((SV*)list)));
XPUSHs(sv_2mortal(newSVsv(cb_data)));
PUTBACK;
count = call_sv( cb_func, G_ARRAY );
SPAGAIN;
if (count != 2)
croak ("Net::SSLeay: next_proto_select_cb_invoke perl function did not return 2 values.\n");
next_proto_data = (unsigned char*)POPpx;
next_proto_status = POPi;
next_proto_len = strlen((const char*)next_proto_data);
if (next_proto_len<=255) {
/* store last_status + last_negotiated into global hash */
cb_data_advanced_put(ssl, "next_proto_select_cb!!last_status", newSViv(next_proto_status));
tmpsv = newSVpv((const char*)next_proto_data, next_proto_len);
cb_data_advanced_put(ssl, "next_proto_select_cb!!last_negotiated", tmpsv);
*out = (unsigned char *)SvPVX(tmpsv);
*outlen = next_proto_len;
}
PUTBACK;
FREETMPS;
LEAVE;
return next_proto_len>255 ? SSL_TLSEXT_ERR_ALERT_FATAL : SSL_TLSEXT_ERR_OK;
}
else if (SvROK(cb_data) && (SvTYPE(SvRV(cb_data)) == SVt_PVAV)) {
next_proto_len = next_proto_helper_AV2protodata((AV*)SvRV(cb_data), NULL);
Newx(next_proto_data, next_proto_len, unsigned char);
if (!next_proto_data) return SSL_TLSEXT_ERR_ALERT_FATAL;
next_proto_len = next_proto_helper_AV2protodata((AV*)SvRV(cb_data), next_proto_data);
next_proto_status = SSL_select_next_proto(out, outlen, in, inlen, next_proto_data, next_proto_len);
/* store last_status + last_negotiated into global hash */
cb_data_advanced_put(ssl, "next_proto_select_cb!!last_status", newSViv(next_proto_status));
cb_data_advanced_put(ssl, "next_proto_select_cb!!last_negotiated", newSVpv((const char*)*out, *outlen));
Safefree(next_proto_data);
return SSL_TLSEXT_ERR_OK;
}
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
int next_protos_advertised_cb_invoke(SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg_unused)
{
SV *cb_func, *cb_data;
unsigned char *protodata = NULL;
unsigned short protodata_len = 0;
SV *tmpsv;
AV *tmpav;
SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
PR1("STARTED: next_protos_advertised_cb_invoke");
cb_func = cb_data_advanced_get(ctx, "next_protos_advertised_cb!!func");
cb_data = cb_data_advanced_get(ctx, "next_protos_advertised_cb!!data");
if (SvROK(cb_func) && (SvTYPE(SvRV(cb_func)) == SVt_PVCV)) {
int count = -1;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSViv(PTR2IV(ssl))));
XPUSHs(sv_2mortal(newSVsv(cb_data)));
PUTBACK;
count = call_sv( cb_func, G_SCALAR );
SPAGAIN;
if (count != 1)
croak ("Net::SSLeay: next_protos_advertised_cb_invoke perl function did not return scalar value.\n");
tmpsv = POPs;
if (SvOK(tmpsv) && SvROK(tmpsv) && (SvTYPE(SvRV(tmpsv)) == SVt_PVAV)) {
tmpav = (AV*)SvRV(tmpsv);
protodata_len = next_proto_helper_AV2protodata(tmpav, NULL);
Newx(protodata, protodata_len, unsigned char);
if (protodata) next_proto_helper_AV2protodata(tmpav, protodata);
}
PUTBACK;
FREETMPS;
LEAVE;
}
else if (SvROK(cb_data) && (SvTYPE(SvRV(cb_data)) == SVt_PVAV)) {
tmpav = (AV*)SvRV(cb_data);
protodata_len = next_proto_helper_AV2protodata(tmpav, NULL);
Newx(protodata, protodata_len, unsigned char);
if (protodata) next_proto_helper_AV2protodata(tmpav, protodata);
}
if (protodata) {
tmpsv = newSVpv((const char*)protodata, protodata_len);
Safefree(protodata);
cb_data_advanced_put(ssl, "next_protos_advertised_cb!!last_advertised", tmpsv);
*out = (unsigned char *)SvPVX(tmpsv);
*outlen = protodata_len;
return SSL_TLSEXT_ERR_OK;
}
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_TLSEXT)
int alpn_select_cb_invoke(SSL *ssl, const unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen, void *arg)
{
SV *cb_func, *cb_data;
unsigned char *alpn_data;
size_t alpn_len;
SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
PR1("STARTED: alpn_select_cb_invoke\n");
cb_func = cb_data_advanced_get(ctx, "alpn_select_cb!!func");
cb_data = cb_data_advanced_get(ctx, "alpn_select_cb!!data");
if (SvROK(cb_func) && (SvTYPE(SvRV(cb_func)) == SVt_PVCV)) {
int count = -1;
AV *list = newAV();
SV *tmpsv;
SV *alpn_data_sv;
dSP;
if (!next_proto_helper_protodata2AV(list, in, inlen)) return SSL_TLSEXT_ERR_ALERT_FATAL;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSViv(PTR2IV(ssl))));
XPUSHs(sv_2mortal(newRV_inc((SV*)list)));
XPUSHs(sv_2mortal(newSVsv(cb_data)));
PUTBACK;
count = call_sv( cb_func, G_ARRAY );
SPAGAIN;
if (count != 1)
croak ("Net::SSLeay: alpn_select_cb perl function did not return exactly 1 value.\n");
alpn_data_sv = POPs;
if (SvOK(alpn_data_sv)) {
alpn_data = (unsigned char*)SvPV_nolen(alpn_data_sv);
alpn_len = strlen((const char*)alpn_data);
if (alpn_len <= 255) {
tmpsv = newSVpv((const char*)alpn_data, alpn_len);
*out = (unsigned char *)SvPVX(tmpsv);
*outlen = alpn_len;
}
} else {
alpn_data = NULL;
alpn_len = 0;
}
PUTBACK;
FREETMPS;
LEAVE;
if (alpn_len>255) return SSL_TLSEXT_ERR_ALERT_FATAL;
return alpn_data ? SSL_TLSEXT_ERR_OK : SSL_TLSEXT_ERR_NOACK;
}
else if (SvROK(cb_data) && (SvTYPE(SvRV(cb_data)) == SVt_PVAV)) {
int status;
alpn_len = next_proto_helper_AV2protodata((AV*)SvRV(cb_data), NULL);
Newx(alpn_data, alpn_len, unsigned char);
if (!alpn_data) return SSL_TLSEXT_ERR_ALERT_FATAL;
alpn_len = next_proto_helper_AV2protodata((AV*)SvRV(cb_data), alpn_data);
/* This is the same function that is used for NPN. */
status = SSL_select_next_proto((unsigned char **)out, outlen, in, inlen, alpn_data, alpn_len);
Safefree(alpn_data);
return status == OPENSSL_NPN_NEGOTIATED ? SSL_TLSEXT_ERR_OK : SSL_TLSEXT_ERR_NOACK;
}
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
#endif
int pem_password_cb_invoke(char *buf, int bufsize, int rwflag, void *data) {
dSP;
char *str;
int count = -1;
size_t str_len = 0;
simple_cb_data_t* cb = (simple_cb_data_t*)data;
/* this n_a is required for building with old perls: */
STRLEN n_a;
PR1("STARTED: pem_password_cb_invoke\n");
if (cb->func && SvOK(cb->func)) {
ENTER;
SAVETMPS;
PUSHMARK(sp);
XPUSHs(sv_2mortal( newSViv(bufsize-1) ));
XPUSHs(sv_2mortal( newSViv(rwflag) ));
if (cb->data) XPUSHs( cb->data );
PUTBACK;
count = call_sv( cb->func, G_SCALAR );
SPAGAIN;
buf[0] = 0; /* start with an empty password */
if (count != 1) {
croak("Net::SSLeay: pem_password_cb_invoke perl function did not return a scalar.\n");
}
else {
str = POPpx;
str_len = strlen(str);
if (str_len+1 < bufsize) {
strcpy(buf, str);
}
else {
str_len = 0;
warn("Net::SSLeay: pem_password_cb_invoke password too long\n");
}
}
PUTBACK;
FREETMPS;
LEAVE;
}
return str_len;
}
void ssleay_RSA_generate_key_cb_invoke(int i, int n, void* data)
{
dSP;
int count = -1;
simple_cb_data_t* cb = (simple_cb_data_t*)data;
/* PR1("STARTED: ssleay_RSA_generate_key_cb_invoke\n"); / * too noisy */
if (cb->func && SvOK(cb->func)) {
ENTER;
SAVETMPS;
PUSHMARK(sp);
XPUSHs(sv_2mortal( newSViv(i) ));
XPUSHs(sv_2mortal( newSViv(n) ));
if (cb->data) XPUSHs( cb->data );
PUTBACK;
count = call_sv( cb->func, G_VOID|G_DISCARD );
if (count != 0)
croak ("Net::SSLeay: ssleay_RSA_generate_key_cb_invoke "
"perl function did return something in void context.\n");
SPAGAIN;
FREETMPS;
LEAVE;
}
}
void ssleay_info_cb_invoke(const SSL *ssl, int where, int ret)
{
dSP;
SV *cb_func, *cb_data;
cb_func = cb_data_advanced_get((void*)ssl, "ssleay_info_cb!!func");
cb_data = cb_data_advanced_get((void*)ssl, "ssleay_info_cb!!data");
if ( ! SvROK(cb_func) || (SvTYPE(SvRV(cb_func)) != SVt_PVCV))
croak ("Net::SSLeay: ssleay_info_cb_invoke called, but not set to point to any perl function.\n");
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSViv(PTR2IV(ssl))));
XPUSHs(sv_2mortal(newSViv(where)) );
XPUSHs(sv_2mortal(newSViv(ret)) );
XPUSHs(sv_2mortal(newSVsv(cb_data)));
PUTBACK;
call_sv(cb_func, G_VOID);
SPAGAIN;
PUTBACK;
FREETMPS;
LEAVE;
}
void ssleay_ctx_info_cb_invoke(const SSL *ssl, int where, int ret)
{
dSP;
SV *cb_func, *cb_data;
SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
cb_func = cb_data_advanced_get(ctx, "ssleay_ctx_info_cb!!func");
cb_data = cb_data_advanced_get(ctx, "ssleay_ctx_info_cb!!data");
if ( ! SvROK(cb_func) || (SvTYPE(SvRV(cb_func)) != SVt_PVCV))
croak ("Net::SSLeay: ssleay_ctx_info_cb_invoke called, but not set to point to any perl function.\n");
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSViv(PTR2IV(ssl))));
XPUSHs(sv_2mortal(newSViv(where)) );
XPUSHs(sv_2mortal(newSViv(ret)) );
XPUSHs(sv_2mortal(newSVsv(cb_data)));
PUTBACK;
call_sv(cb_func, G_VOID);
SPAGAIN;
PUTBACK;
FREETMPS;
LEAVE;
}
/*
* Support for tlsext_ticket_key_cb_invoke was already in 0.9.8 but it was
* broken in various ways during the various 1.0.0* versions.
* Better enable it only starting with 1.0.1.
*/
#if defined(SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB) && OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_TLSEXT)
#define NET_SSLEAY_CAN_TICKET_KEY_CB
int tlsext_ticket_key_cb_invoke(
SSL *ssl,
unsigned char *key_name,
unsigned char *iv,
EVP_CIPHER_CTX *ectx,
HMAC_CTX *hctx,
int enc
){
dSP;
int count,usable_rv_count,hmac_key_len = 0;
SV *cb_func, *cb_data;
STRLEN svlen;
unsigned char key[48]; /* key[0..15] aes, key[16..32] or key[16..48] hmac */
unsigned char name[16];
SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
PR1("STARTED: tlsext_ticket_key_cb_invoke\n");
cb_func = cb_data_advanced_get(ctx, "tlsext_ticket_key_cb!!func");
cb_data = cb_data_advanced_get(ctx, "tlsext_ticket_key_cb!!data");
if (!SvROK(cb_func) || (SvTYPE(SvRV(cb_func)) != SVt_PVCV))
croak("callback must be a code reference");
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVsv(cb_data)));
if (!enc) {
/* call as getkey(data,this_name) -> (key,current_name) */
XPUSHs(sv_2mortal(newSVpv((const char *)key_name,16)));
} else {
/* call as getkey(data) -> (key,current_name) */
}
PUTBACK;
count = call_sv( cb_func, G_ARRAY );
SPAGAIN;
if (count>2)
croak("too much return values - only (name,key) should be returned");
usable_rv_count = 0;
if (count>0) {
SV *sname = POPs;
if (SvOK(sname)) {
unsigned char *pname = (unsigned char *)SvPV(sname,svlen);
if (svlen > 16)
croak("name must be at at most 16 bytes, got %d",(int)svlen);
if (svlen == 0)
croak("name should not be empty");
memset(name, 0, 16);
memcpy(name,pname,svlen);
usable_rv_count++;
}
}
if (count>1) {
SV *skey = POPs;
if (SvOK(skey)) {
unsigned char *pkey = (unsigned char *)SvPV(skey,svlen);
if (svlen != 32 && svlen != 48)
croak("key must be 32 or 48 random bytes, got %d",(int)svlen);
hmac_key_len = (int)svlen - 16;
memcpy(key,pkey,(int)svlen);
usable_rv_count++;
}
}
PUTBACK;
FREETMPS;
LEAVE;
if (!enc && usable_rv_count == 0) {
TRACE(2,"no key returned for ticket");
return 0;
}
if (usable_rv_count != 2)
croak("key functions needs to return (key,name)");
if (enc) {
/* encrypt ticket information with given key */
RAND_bytes(iv, 16);
EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key, iv);
HMAC_Init_ex(hctx,key+16,hmac_key_len,EVP_sha256(),NULL);
memcpy(key_name,name,16);
return 1;
} else {
HMAC_Init_ex(hctx,key+16,hmac_key_len,EVP_sha256(),NULL);
EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key, iv);
if (memcmp(name,key_name,16) == 0)
return 1; /* current key was used */
else
return 2; /* different key was used, need to be renewed */
}
}
#endif
/* ============= end of callback stuff, begin helper functions ============== */
time_t ASN1_TIME_timet(ASN1_TIME *asn1t) {
struct tm t;
const char *p = (const char*) asn1t->data;
size_t msec = 0, tz = 0, i, l;
time_t result;
int adj = 0;
if (asn1t->type == V_ASN1_UTCTIME) {
if (asn1t->length<12 || asn1t->length>17) return 0;
if (asn1t->length>12) tz = 12;
} else {
if (asn1t->length<14) return 0;
if (asn1t->length>14) {
if (p[14] == '.') {
msec = 14;
for(i=msec+1;i<asn1t->length && p[i]>='0' && p[i]<='9';i++) ;
if (i<asn1t->length) tz = i;
} else {
tz = 14;
}
}
}
l = msec ? msec : tz ? tz : asn1t->length;
for(i=0;i<l;i++) {
if (p[i]<'0' || p[i]>'9') return 0;
}
/* extract data and time */
memset(&t,0,sizeof(t));
if (asn1t->type == V_ASN1_UTCTIME) { /* YY - two digit year */
t.tm_year = (p[0]-'0')*10 + (p[1]-'0');
if (t.tm_year < 70) t.tm_year += 100;
i=2;
} else { /* YYYY */
t.tm_year = (p[0]-'0')*1000 + (p[1]-'0')*100 + (p[2]-'0')*10 + p[3]-'0';
t.tm_year -= 1900;
i=4;
}
t.tm_mon = (p[i+0]-'0')*10 + (p[i+1]-'0') -1; /* MM, starts with 0 in tm */
t.tm_mday = (p[i+2]-'0')*10 + (p[i+3]-'0'); /* DD */
t.tm_hour = (p[i+4]-'0')*10 + (p[i+5]-'0'); /* hh */
t.tm_min = (p[i+6]-'0')*10 + (p[i+7]-'0'); /* mm */
t.tm_sec = (p[i+8]-'0')*10 + (p[i+9]-'0'); /* ss */
/* skip msec, because time_t does not support it */
if (tz) {
/* TZ is 'Z' or [+-]DDDD and after TZ the string must stop*/
if (p[tz] == 'Z') {
if (asn1t->length>tz+1 ) return 0;
} else if (asn1t->length<tz+5 || (p[tz]!='-' && p[tz]!='+')) {
return 0;
} else {
if (asn1t->length>tz+5 ) return 0;
for(i=tz+1;i<tz+5;i++) {
if (p[i]<'0' || p[i]>'9') return 0;
}
adj = ((p[tz+1]-'0')*10 + (p[tz+2]-'0'))*3600
+ ((p[tz+3]-'0')*10 + (p[tz+4]-'0'))*60;
if (p[tz]=='+') adj*= -1; /* +0500: subtract 5 hours to get UTC */
}
}
result = mktime(&t);
if (result == -1) return 0; /* broken time */
return result + adj + ( t.tm_isdst ? 3600:0 );
}
X509 * find_issuer(X509 *cert,X509_STORE *store, STACK_OF(X509) *chain) {
int i;
X509 *issuer = NULL;
/* search first in the chain */
if (chain) {
for(i=0;i<sk_X509_num(chain);i++) {
if ( X509_check_issued(sk_X509_value(chain,i),cert) == X509_V_OK ) {
TRACE(2,"found issuer in chain");
issuer = sk_X509_value(chain,i);
}
}
}
/* if not in the chain it might be in the store */
if ( !issuer && store ) {
X509_STORE_CTX *stx = X509_STORE_CTX_new();
if (stx && X509_STORE_CTX_init(stx,store,cert,NULL)) {
int ok = X509_STORE_CTX_get1_issuer(&issuer,stx,cert);
if (ok<0) {
int err = ERR_get_error();
if(err) {
TRACE(2,"failed to get issuer: %s",ERR_error_string(err,NULL));
} else {
TRACE(2,"failed to get issuer: unknown error");
}
} else if (ok == 0 ) {
TRACE(2,"failed to get issuer(0)");
} else {
TRACE(2,"got issuer");
}
}
if (stx) X509_STORE_CTX_free(stx);
}
return issuer;
}
SV* bn2sv(BIGNUM* p_bn)
{
return p_bn != NULL
? sv_2mortal(newSViv((IV) BN_dup(p_bn)))
: &PL_sv_undef;
}
/* ============= end of helper functions ============== */
MODULE = Net::SSLeay PACKAGE = Net::SSLeay PREFIX = SSL_
PROTOTYPES: ENABLE
BOOT:
{
MY_CXT_INIT;
LIB_initialized = 0;
#ifdef USE_ITHREADS
MUTEX_INIT(&LIB_init_mutex);
#ifdef OPENSSL_THREADS
/* If we running under ModPerl, we dont need our own thread locking because
* perl threads are not supported under mod-perl, and we can fall back to the thread
* locking built in to mod-ssl
*/
if (!hv_fetch(get_hv("ENV", 1), "MOD_PERL", 8, 0))
openssl_threads_init();
#endif
#endif
/* initialize global shared callback data hash */
MY_CXT.global_cb_data = newHV();
MY_CXT.tid = get_my_thread_id();
PR3("BOOT: tid=%d my_perl=0x%p\n", MY_CXT.tid, my_perl);
}
void
CLONE(...)
CODE:
MY_CXT_CLONE;
/* reset all callback related data as we want to prevent
* cross-thread callbacks
* TODO: later somebody can make the global hash MY_CXT.global_cb_data
* somehow shared between threads
*/
MY_CXT.global_cb_data = newHV();
MY_CXT.tid = get_my_thread_id();
PR3("CLONE: tid=%d my_perl=0x%p\n", MY_CXT.tid, my_perl);
double
constant(name)
char * name
CODE:
errno = 0;
RETVAL = constant(name, strlen(name));
OUTPUT:
RETVAL
int
hello()
CODE:
PR1("\tSSLeay Hello World!\n");
RETVAL = 1;
OUTPUT:
RETVAL
#define REM0 "============= version related functions =============="
unsigned long
SSLeay()
const char *
SSLeay_version(type=SSLEAY_VERSION)
int type
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
unsigned long
OpenSSL_version_num()
const char *
OpenSSL_version(t=OPENSSL_VERSION)
int t
#endif /* OpenSSL 1.1.0 */
#define REM1 "============= SSL CONTEXT functions =============="
SSL_CTX *
SSL_CTX_new()
CODE:
RETVAL = SSL_CTX_new (SSLv23_method());
OUTPUT:
RETVAL
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#ifndef OPENSSL_NO_SSL2
SSL_CTX *
SSL_CTX_v2_new()
CODE:
RETVAL = SSL_CTX_new (SSLv2_method());
OUTPUT:
RETVAL
#endif
#endif
#ifndef OPENSSL_NO_SSL3
SSL_CTX *
SSL_CTX_v3_new()
CODE:
RETVAL = SSL_CTX_new (SSLv3_method());
OUTPUT:
RETVAL
#endif
SSL_CTX *
SSL_CTX_v23_new()
CODE:
RETVAL = SSL_CTX_new (SSLv23_method());
OUTPUT:
RETVAL
SSL_CTX *
SSL_CTX_tlsv1_new()
CODE:
RETVAL = SSL_CTX_new (TLSv1_method());
OUTPUT:
RETVAL
#ifdef SSL_TXT_TLSV1_1
SSL_CTX *
SSL_CTX_tlsv1_1_new()
CODE:
RETVAL = SSL_CTX_new (TLSv1_1_method());
OUTPUT:
RETVAL
#endif
#ifdef SSL_TXT_TLSV1_2
SSL_CTX *
SSL_CTX_tlsv1_2_new()
CODE:
RETVAL = SSL_CTX_new (TLSv1_2_method());
OUTPUT:
RETVAL
#endif
SSL_CTX *
SSL_CTX_new_with_method(meth)
SSL_METHOD * meth
CODE:
RETVAL = SSL_CTX_new (meth);
OUTPUT:
RETVAL
void
SSL_CTX_free(ctx)
SSL_CTX * ctx
CODE:
cb_data_advanced_drop(ctx); /* clean callback related data from global hash */
SSL_CTX_free(ctx);
int
SSL_CTX_add_session(ctx,ses)
SSL_CTX * ctx
SSL_SESSION * ses
int
SSL_CTX_remove_session(ctx,ses)
SSL_CTX * ctx
SSL_SESSION * ses
void
SSL_CTX_flush_sessions(ctx,tm)
SSL_CTX * ctx
long tm
int
SSL_CTX_set_default_verify_paths(ctx)
SSL_CTX * ctx
int
SSL_CTX_load_verify_locations(ctx,CAfile,CApath)
SSL_CTX * ctx
char * CAfile
char * CApath
CODE:
RETVAL = SSL_CTX_load_verify_locations (ctx,
CAfile?(*CAfile?CAfile:NULL):NULL,
CApath?(*CApath?CApath:NULL):NULL
);
OUTPUT:
RETVAL
void
SSL_CTX_set_verify(ctx,mode,callback=&PL_sv_undef)
SSL_CTX * ctx
int mode
SV * callback
CODE:
/* Former versions of SSLeay checked if the callback was a true boolean value
* and didn't call it if it was false. Therefor some people set the callback
* to '0' if they don't want to use it (IO::Socket::SSL for example). Therefor
* we don't execute the callback if it's value isn't something true to retain
* backwards compatibility.
*/
if (callback==NULL || !SvOK(callback) || !SvTRUE(callback)) {
SSL_CTX_set_verify(ctx, mode, NULL);
cb_data_advanced_put(ctx, "ssleay_verify_callback!!func", NULL);
} else {
cb_data_advanced_put(ctx, "ssleay_verify_callback!!func", newSVsv(callback));
SSL_CTX_set_verify(ctx, mode, &ssleay_verify_callback_invoke);
}
int
SSL_get_error(s,ret)
SSL * s
int ret
#define REM10 "============= SSL functions =============="
SSL *
SSL_new(ctx)
SSL_CTX * ctx
void
SSL_free(s)
SSL * s
CODE:
cb_data_advanced_drop(s); /* clean callback related data from global hash */
SSL_free(s);
#if 0 /* this seems to be gone in 0.9.0 */
void
SSL_debug(file)
char * file
#endif
int
SSL_accept(s)
SSL * s
void
SSL_clear(s)
SSL * s
int
SSL_connect(s)
SSL * s
#if defined(WIN32)
int
SSL_set_fd(s,fd)
SSL * s
perl_filehandle_t fd
CODE:
RETVAL = SSL_set_fd(s,_get_osfhandle(fd));
OUTPUT:
RETVAL
int
SSL_set_rfd(s,fd)
SSL * s
perl_filehandle_t fd
CODE:
RETVAL = SSL_set_rfd(s,_get_osfhandle(fd));
OUTPUT:
RETVAL
int
SSL_set_wfd(s,fd)
SSL * s
perl_filehandle_t fd
CODE:
RETVAL = SSL_set_wfd(s,_get_osfhandle(fd));
OUTPUT:
RETVAL
#else
int
SSL_set_fd(s,fd)
SSL * s
perl_filehandle_t fd
int
SSL_set_rfd(s,fd)
SSL * s
perl_filehandle_t fd
int
SSL_set_wfd(s,fd)
SSL * s
perl_filehandle_t fd
#endif
int
SSL_get_fd(s)
SSL * s
AV *
SSL_read(s,max=32768)
SSL * s
int max
PREINIT:
char *buf;
int got;
PPCODE:
New(0, buf, max, char);
got = SSL_read(s, buf, max);
/* If in list context, return 2-item list:
* first return value: data gotten, or undef on error (got<0)
* second return value: result from SSL_read()
*/
if (GIMME_V==G_ARRAY) {
EXTEND(SP, 2);
PUSHs(sv_2mortal(got>=0 ? newSVpvn(buf, got) : newSV(0)));
PUSHs(sv_2mortal(newSViv(got)));
/* If in scalar or void context, return data gotten, or undef on error. */
} else {
EXTEND(SP, 1);
PUSHs(sv_2mortal(got>=0 ? newSVpvn(buf, got) : newSV(0)));
}
Safefree(buf);
void
SSL_peek(s,max=32768)
SSL * s
int max
PREINIT:
char *buf;
int got;
PPCODE:
New(0, buf, max, char);
got = SSL_peek(s, buf, max);
/* If in list context, return 2-item list:
* first return value: data gotten, or undef on error (got<0)
* second return value: result from SSL_peek()
*/
if (GIMME_V==G_ARRAY) {
EXTEND(SP, 2);
PUSHs(sv_2mortal(got>=0 ? newSVpvn(buf, got) : newSV(0)));
PUSHs(sv_2mortal(newSViv(got)));
/* If in scalar or void context, return data gotten, or undef on error. */
} else {
EXTEND(SP, 1);
PUSHs(sv_2mortal(got>=0 ? newSVpvn(buf, got) : newSV(0)));
}
Safefree(buf);
int
SSL_write(s,buf)
SSL * s
PREINIT:
STRLEN len;
INPUT:
char * buf = SvPV( ST(1), len);
CODE:
RETVAL = SSL_write (s, buf, (int)len);
OUTPUT:
RETVAL
int
SSL_write_partial(s,from,count,buf)
SSL * s
int from
int count
PREINIT:
STRLEN ulen;
IV len;
INPUT:
char * buf = SvPV( ST(3), ulen);
CODE:
/*
if (SvROK( ST(3) )) {
SV* t = SvRV( ST(3) );
buf = SvPV( t, len);
} else
buf = SvPV( ST(3), len);
*/
PR4("write_partial from=%d count=%d len=%ul\n",from,count,ulen);
/*PR2("buf='%s'\n",&buf[from]); / * too noisy */
len = (IV)ulen;
len -= from;
if (len < 0) {
croak("from beyound end of buffer");
RETVAL = -1;
} else
RETVAL = SSL_write (s, &(buf[from]), (count<=len)?count:len);
OUTPUT:
RETVAL
int
SSL_use_RSAPrivateKey(s,rsa)
SSL * s
RSA * rsa
int
SSL_use_RSAPrivateKey_ASN1(s,d,len)
SSL * s
unsigned char * d
long len
int
SSL_use_RSAPrivateKey_file(s,file,type)
SSL * s
char * file
int type
int
SSL_CTX_use_RSAPrivateKey_file(ctx,file,type)
SSL_CTX * ctx
char * file
int type
int
SSL_use_PrivateKey(s,pkey)
SSL * s
EVP_PKEY * pkey
int
SSL_use_PrivateKey_ASN1(pk,s,d,len)
int pk
SSL * s
unsigned char * d
long len
int
SSL_use_PrivateKey_file(s,file,type)
SSL * s
char * file
int type
int
SSL_CTX_use_PrivateKey_file(ctx,file,type)
SSL_CTX * ctx
char * file
int type
int
SSL_use_certificate(s,x)
SSL * s
X509 * x
int
SSL_use_certificate_ASN1(s,d,len)
SSL * s
unsigned char * d
long len
int
SSL_use_certificate_file(s,file,type)
SSL * s
char * file
int type
int
SSL_CTX_use_certificate_file(ctx,file,type)
SSL_CTX * ctx
char * file
int type
const char *
SSL_state_string(s)
SSL * s
const char *
SSL_rstate_string(s)
SSL * s
const char *
SSL_state_string_long(s)
SSL * s
const char *
SSL_rstate_string_long(s)
SSL * s
long
SSL_get_time(ses)
SSL_SESSION * ses
long
SSL_set_time(ses,t)
SSL_SESSION * ses
long t
long
SSL_get_timeout(ses)
SSL_SESSION * ses
long
SSL_set_timeout(ses,t)
SSL_SESSION * ses
long t
void
SSL_copy_session_id(to,from)
SSL * to
SSL * from
void
SSL_set_read_ahead(s,yes=1)
SSL * s
int yes
int
SSL_get_read_ahead(s)
SSL * s
int
SSL_pending(s)
SSL * s
int
SSL_CTX_set_cipher_list(s,str)
SSL_CTX * s
char * str
const char *
SSL_get_cipher_list(s,n)
SSL * s
int n
int
SSL_set_cipher_list(s,str)
SSL * s
char * str
const char *
SSL_get_cipher(s)
SSL * s
void
SSL_get_shared_ciphers(s,ignored_param1=0,ignored_param2=0)
SSL *s
int ignored_param1
int ignored_param2
PREINIT:
char buf[8192];
CODE:
ST(0) = sv_newmortal(); /* undef to start with */
if(SSL_get_shared_ciphers(s, buf, sizeof(buf)))
sv_setpvn(ST(0), buf, strlen(buf));
X509 *
SSL_get_peer_certificate(s)
SSL * s
void
SSL_get_peer_cert_chain(s)
SSL * s
PREINIT:
STACK_OF(X509) *chain = NULL;
X509 *x;
int i;
PPCODE:
chain = SSL_get_peer_cert_chain(s);
if( chain == NULL ) {
XSRETURN_EMPTY;
}
for (i=0; i<sk_X509_num(chain); i++) {
x = sk_X509_value(chain, i);
XPUSHs(sv_2mortal(newSViv(PTR2IV(x))));
}
void
SSL_set_verify(s,mode,callback)
SSL * s
int mode
SV * callback
CODE:
if (callback==NULL || !SvOK(callback)) {
SSL_set_verify(s, mode, NULL);
cb_data_advanced_put(s, "ssleay_verify_callback!!func", NULL);
}
else {
cb_data_advanced_put(s, "ssleay_verify_callback!!func", newSVsv(callback));
SSL_set_verify(s, mode, &ssleay_verify_callback_invoke);
}
void
SSL_set_bio(s,rbio,wbio)
SSL * s
BIO * rbio
BIO * wbio
BIO *
SSL_get_rbio(s)
SSL * s
BIO *
SSL_get_wbio(s)
SSL * s
SSL_SESSION *
SSL_SESSION_new()
int
SSL_SESSION_print(fp,ses)
BIO * fp
SSL_SESSION * ses
void
SSL_SESSION_free(ses)
SSL_SESSION * ses
int
i2d_SSL_SESSION(in,pp)
SSL_SESSION * in
unsigned char * &pp
int
SSL_set_session(to,ses)
SSL * to
SSL_SESSION * ses
#if OPENSSL_VERSION_NUMBER < 0x0090707fL
#define REM3 "NOTE: before 0.9.7g"
SSL_SESSION *
d2i_SSL_SESSION(a,pp,length)
SSL_SESSION * &a
unsigned char * &pp
long length
#else
SSL_SESSION *
d2i_SSL_SESSION(a,pp,length)
SSL_SESSION * &a
const unsigned char * &pp
long length
#endif
#define REM30 "SSLeay-0.9.0 defines these as macros. I expand them here for safety's sake"
SSL_SESSION *
SSL_get_session(s)
SSL * s
ALIAS:
SSL_get0_session = 1
SSL_SESSION *
SSL_get1_session(s)
SSL * s
X509 *
SSL_get_certificate(s)
SSL * s
#if OPENSSL_VERSION_NUMBER >= 0x0090806fL
#define REM18 "NOTE: requires 0.9.8f+"
SSL_CTX *
SSL_get_SSL_CTX(s)
SSL * s
SSL_CTX *
SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx)
long
SSL_ctrl(ssl,cmd,larg,parg)
SSL * ssl
int cmd
long larg
char * parg
#endif
long
SSL_CTX_ctrl(ctx,cmd,larg,parg)
SSL_CTX * ctx
int cmd
long larg
char * parg
long
SSL_get_options(ssl)
SSL * ssl
long
SSL_set_options(ssl,op)
SSL * ssl
long op
long
SSL_CTX_get_options(ctx)
SSL_CTX * ctx
long
SSL_CTX_set_options(ctx,op)
SSL_CTX * ctx
long op
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
struct lhash_st_SSL_SESSION *
SSL_CTX_sessions(ctx)
SSL_CTX * ctx
#else
LHASH *
SSL_CTX_sessions(ctx)
SSL_CTX * ctx
CODE:
/* NOTE: This should be deprecated. Corresponding macro was removed from ssl.h as of 0.9.2 */
if (ctx == NULL) croak("NULL SSL context passed as argument.");
RETVAL = ctx -> sessions;
OUTPUT:
RETVAL
#endif
unsigned long
SSL_CTX_sess_number(ctx)
SSL_CTX * ctx
int
SSL_CTX_sess_connect(ctx)
SSL_CTX * ctx
int
SSL_CTX_sess_connect_good(ctx)
SSL_CTX * ctx
int
SSL_CTX_sess_connect_renegotiate(ctx)
SSL_CTX * ctx
int
SSL_CTX_sess_accept(ctx)
SSL_CTX * ctx
int
SSL_CTX_sess_accept_renegotiate(ctx)
SSL_CTX * ctx
int
SSL_CTX_sess_accept_good(ctx)
SSL_CTX * ctx
int
SSL_CTX_sess_hits(ctx)
SSL_CTX * ctx
int
SSL_CTX_sess_cb_hits(ctx)
SSL_CTX * ctx
int
SSL_CTX_sess_misses(ctx)
SSL_CTX * ctx
int
SSL_CTX_sess_timeouts(ctx)
SSL_CTX * ctx
int
SSL_CTX_sess_cache_full(ctx)
SSL_CTX * ctx
int
SSL_CTX_sess_get_cache_size(ctx)
SSL_CTX * ctx
long
SSL_CTX_sess_set_cache_size(ctx,size)
SSL_CTX * ctx
int size
int
SSL_want(s)
SSL * s
#if OPENSSL_VERSION_NUMBER < 0x10100000L
int
SSL_state(s)
SSL * s
int
SSL_get_state(ssl)
SSL * ssl
CODE:
RETVAL = SSL_state(ssl);
OUTPUT:
RETVAL
#else
int
SSL_state(s)
SSL * s
CODE:
RETVAL = SSL_get_state(s);
OUTPUT:
RETVAL
int
SSL_get_state(s)
SSL * s
#endif
#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
long
SSL_set_tlsext_host_name(SSL *ssl, const char *name)
const char *
SSL_get_servername(const SSL *s, int type=TLSEXT_NAMETYPE_host_name)
int
SSL_get_servername_type(const SSL *s)
void
SSL_CTX_set_tlsext_servername_callback(ctx,callback=&PL_sv_undef,data=&PL_sv_undef)
SSL_CTX * ctx
SV * callback
SV * data
CODE:
if (callback==NULL || !SvOK(callback)) {
SSL_CTX_set_tlsext_servername_callback(ctx, NULL);
SSL_CTX_set_tlsext_servername_arg(ctx, NULL);
cb_data_advanced_put(ctx, "tlsext_servername_callback!!data", NULL);
cb_data_advanced_put(ctx, "tlsext_servername_callback!!func", NULL);
} else {
cb_data_advanced_put(ctx, "tlsext_servername_callback!!data", newSVsv(data));
cb_data_advanced_put(ctx, "tlsext_servername_callback!!func", newSVsv(callback));
SSL_CTX_set_tlsext_servername_callback(ctx, &tlsext_servername_callback_invoke);
SSL_CTX_set_tlsext_servername_arg(ctx, (void*)ctx);
}
#endif
#if OPENSSL_VERSION_NUMBER >= 0x1010006fL /* In OpenSSL 1.1.0 but actually called for $ssl starting from 1.1.0f */
#ifndef LIBRESSL_VERSION_NUMBER
#ifndef OPENSSL_IS_BORINGSSL
void
SSL_set_default_passwd_cb(ssl,callback=&PL_sv_undef)
SSL * ssl
SV * callback
CODE:
if (callback==NULL || !SvOK(callback)) {
SSL_set_default_passwd_cb(ssl, NULL);
SSL_set_default_passwd_cb_userdata(ssl, NULL);
cb_data_advanced_put(ssl, "ssleay_ssl_passwd_cb!!func", NULL);
}
else {
cb_data_advanced_put(ssl, "ssleay_ssl_passwd_cb!!func", newSVsv(callback));
SSL_set_default_passwd_cb_userdata(ssl, (void*)ssl);
SSL_set_default_passwd_cb(ssl, &ssleay_ssl_passwd_cb_invoke);
}
void
SSL_set_default_passwd_cb_userdata(ssl,data=&PL_sv_undef)
SSL * ssl
SV * data
CODE:
/* SSL_set_default_passwd_cb_userdata is set in SSL_set_default_passwd_cb */
if (data==NULL || !SvOK(data)) {
cb_data_advanced_put(ssl, "ssleay_ssl_passwd_cb!!data", NULL);
}
else {
cb_data_advanced_put(ssl, "ssleay_ssl_passwd_cb!!data", newSVsv(data));
}
#endif /* !BoringSSL */
#endif /* !LibreSSL */
#endif /* >= 1.1.0f */
const BIO_METHOD *
BIO_f_ssl()
const BIO_METHOD *
BIO_s_mem()
unsigned long
ERR_get_error()
unsigned long
ERR_peek_error()
void
ERR_put_error(lib,func,reason,file,line)
int lib
int func
int reason
char * file
int line
void
ERR_clear_error()
char *
ERR_error_string(error,buf=NULL)
unsigned long error
char * buf
CODE:
RETVAL = ERR_error_string(error,buf);
OUTPUT:
RETVAL
void
SSL_load_error_strings()
void
ERR_load_crypto_strings()
int
SSL_FIPS_mode_set(int onoff)
CODE:
#ifdef USE_ITHREADS
MUTEX_LOCK(&LIB_init_mutex);
#endif
#ifdef OPENSSL_FIPS
RETVAL = FIPS_mode_set(onoff);
if (!RETVAL)
{
ERR_load_crypto_strings();
ERR_print_errors_fp(stderr);
}
#else
RETVAL = 1;
fprintf(stderr, "SSL_FIPS_mode_set not available: OpenSSL not compiled with FIPS support\n");
#endif
#ifdef USE_ITHREADS
MUTEX_UNLOCK(&LIB_init_mutex);
#endif
OUTPUT:
RETVAL
int
SSL_library_init()
ALIAS:
SSLeay_add_ssl_algorithms = 1
OpenSSL_add_ssl_algorithms = 2
add_ssl_algorithms = 3
CODE:
#ifdef USE_ITHREADS
MUTEX_LOCK(&LIB_init_mutex);
#endif
RETVAL = 0;
if (!LIB_initialized) {
RETVAL = SSL_library_init();
LIB_initialized = 1;
}
#ifdef USE_ITHREADS
MUTEX_UNLOCK(&LIB_init_mutex);
#endif
OUTPUT:
RETVAL
#if OPENSSL_VERSION_NUMBER >= 0x0090700fL
#define REM5 "NOTE: requires 0.9.7+"
void
ENGINE_load_builtin_engines()
void
ENGINE_register_all_complete()
ENGINE*
ENGINE_by_id(id)
char * id
int
ENGINE_set_default(e, flags)
ENGINE * e
int flags
#endif
void
ERR_load_SSL_strings()
void
ERR_load_RAND_strings()
int
RAND_bytes(buf, num)
SV *buf
int num
PREINIT:
int rc;
unsigned char *random;
CODE:
New(0, random, num, unsigned char);
rc = RAND_bytes(random, num);
sv_setpvn(buf, (const char*)random, num);
Safefree(random);
RETVAL = rc;
OUTPUT:
RETVAL
int
RAND_pseudo_bytes(buf, num)
SV *buf
int num
PREINIT:
int rc;
unsigned char *random;
CODE:
New(0, random, num, unsigned char);
rc = RAND_pseudo_bytes(random, num);
sv_setpvn(buf, (const char*)random, num);
Safefree(random);
RETVAL = rc;
OUTPUT:
RETVAL
void
RAND_add(buf, num, entropy)
SV *buf
int num
double entropy
PREINIT:
STRLEN len;
CODE:
RAND_add((const void *)SvPV(buf, len), num, entropy);
int
RAND_poll()
int
RAND_status()
SV *
RAND_file_name(num)
size_t num
PREINIT:
char *buf;
CODE:
New(0, buf, num, char);
if (!RAND_file_name(buf, num)) {
Safefree(buf);
XSRETURN_UNDEF;
}
RETVAL = newSVpv(buf, 0);
Safefree(buf);
OUTPUT:
RETVAL
void
RAND_seed(buf)
PREINIT:
STRLEN len;
INPUT:
char * buf = SvPV( ST(1), len);
CODE:
RAND_seed (buf, (int)len);
void
RAND_cleanup()
int
RAND_load_file(file_name, how_much)
char * file_name
int how_much
int
RAND_write_file(file_name)
char * file_name
#define REM40 "Minimal X509 stuff..., this is a bit ugly and should be put in its own modules Net::SSLeay::X509.pm"
#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
int
X509_check_host(X509 *cert, const char *name, unsigned int flags = 0, SV *peername = &PL_sv_undef)
PREINIT:
char *c_peername = NULL;
CODE:
RETVAL = X509_check_host(cert, name, 0, flags, (items == 4) ? &c_peername : NULL);
if (items == 4)
sv_setpv(peername, c_peername);
OUTPUT:
RETVAL
CLEANUP:
if (c_peername)
OPENSSL_free(c_peername);
int
X509_check_email(X509 *cert, const char *address, unsigned int flags = 0)
CODE:
RETVAL = X509_check_email(cert, address, 0, flags);
OUTPUT:
RETVAL
int
X509_check_ip(X509 *cert, SV *address, unsigned int flags = 0)
PREINIT:
unsigned char *c_address;
size_t addresslen;
CODE:
c_address = (unsigned char *)SvPV(address, addresslen);
RETVAL = X509_check_ip(cert, c_address, addresslen, flags);
OUTPUT:
RETVAL
int
X509_check_ip_asc(X509 *cert, const char *address, unsigned int flags = 0)
#endif
X509_NAME*
X509_get_issuer_name(cert)
X509 * cert
X509_NAME*
X509_get_subject_name(cert)
X509 * cert
void *
X509_get_ex_data(cert,idx)
X509 * cert
int idx
int
X509_get_ex_new_index(argl,argp=NULL,new_func=NULL,dup_func=NULL,free_func=NULL)
long argl
void * argp
CRYPTO_EX_new * new_func
CRYPTO_EX_dup * dup_func
CRYPTO_EX_free * free_func
void *
X509_get_app_data(cert)
X509 * cert
CODE:
RETVAL = X509_get_ex_data(cert,0);
OUTPUT:
RETVAL
int
X509_set_ex_data(cert,idx,data)
X509 * cert
int idx
void * data
int
X509_set_app_data(cert,arg)
X509 * cert
char * arg
CODE:
RETVAL = X509_set_ex_data(cert,0,arg);
OUTPUT:
RETVAL
int
X509_set_issuer_name(X509 *x, X509_NAME *name)
int
X509_set_subject_name(X509 *x, X509_NAME *name)
int
X509_set_version(X509 *x, long version)
int
X509_set_pubkey(X509 *x, EVP_PKEY *pkey)
long
X509_get_version(X509 *x)
EVP_PKEY *
X509_get_pubkey(X509 *x)
ASN1_INTEGER *
X509_get_serialNumber(X509 *x)
int
X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial)
int
X509_certificate_type(X509 *x, EVP_PKEY *pubkey=NULL);
int
X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
int
X509_verify(X509 *x, EVP_PKEY *r)
X509_NAME *
X509_NAME_new()
unsigned long
X509_NAME_hash(X509_NAME *name)
void
X509_NAME_oneline(name)
X509_NAME * name
PREINIT:
char * buf;
CODE:
ST(0) = sv_newmortal(); /* Undefined to start with */
if ((buf = X509_NAME_oneline(name, NULL, 0))) {
sv_setpvn( ST(0), buf, strlen(buf));
OPENSSL_free(buf); /* mem was allocated by openssl */
}
void
X509_NAME_print_ex(name,flags=XN_FLAG_RFC2253,utf8_decode=0)
X509_NAME * name
unsigned long flags
int utf8_decode
PREINIT:
char * buf;
BIO * bp;
int n, i, ident=0;
CODE:
ST(0) = sv_newmortal(); /* undef to start with */
bp = BIO_new(BIO_s_mem());
if (bp) {
if (X509_NAME_print_ex(bp, name, ident, flags)) {
n = BIO_ctrl_pending(bp);
New(0, buf, n, char);
if (buf) {
i = BIO_read(bp,buf,n);
if (i>=0 && i<=n) {
sv_setpvn(ST(0), buf, i);
if (utf8_decode) sv_utf8_decode(ST(0));
}
Safefree(buf);
}
}
BIO_free(bp);
}
void
X509_NAME_get_text_by_NID(name,nid)
X509_NAME * name
int nid
PREINIT:
char* buf;
int length;
CODE:
ST(0) = sv_newmortal(); /* Undefined to start with */
length = X509_NAME_get_text_by_NID(name, nid, NULL, 0);
if (length>=0) {
New(0, buf, length+1, char);
if (X509_NAME_get_text_by_NID(name, nid, buf, length + 1)>=0)
sv_setpvn( ST(0), buf, length);
Safefree(buf);
}
#if OPENSSL_VERSION_NUMBER >= 0x0090500fL
#define REM17 "requires 0.9.5+"
int
X509_NAME_add_entry_by_NID(name,nid,type,bytes,loc=-1,set=0)
X509_NAME *name
int nid
int type
int loc
int set
PREINIT:
STRLEN len;
INPUT:
unsigned char *bytes = (unsigned char *)SvPV(ST(3), len);
CODE:
RETVAL = X509_NAME_add_entry_by_NID(name,nid,type,bytes,len,loc,set);
OUTPUT:
RETVAL
int
X509_NAME_add_entry_by_OBJ(name,obj,type,bytes,loc=-1,set=0)
X509_NAME *name
ASN1_OBJECT *obj
int type
int loc
int set
PREINIT:
STRLEN len;
INPUT:
unsigned char *bytes = (unsigned char *)SvPV(ST(3), len);
CODE:
RETVAL = X509_NAME_add_entry_by_OBJ(name,obj,type,bytes,len,loc,set);
OUTPUT:
RETVAL
int
X509_NAME_add_entry_by_txt(name,field,type,bytes,loc=-1,set=0)
X509_NAME *name
char *field
int type
int loc
int set
PREINIT:
STRLEN len;
INPUT:
unsigned char *bytes = (unsigned char *)SvPV(ST(3), len);
CODE:
RETVAL = X509_NAME_add_entry_by_txt(name,field,type,bytes,len,loc,set);
OUTPUT:
RETVAL
#endif
int
X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b)
int
X509_NAME_entry_count(X509_NAME *name)
X509_NAME_ENTRY *
X509_NAME_get_entry(X509_NAME *name, int loc)
ASN1_STRING *
X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne)
ASN1_OBJECT *
X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne)
void
X509_CRL_free(X509_CRL *x)
X509_CRL *
X509_CRL_new()
#if OPENSSL_VERSION_NUMBER >= 0x0090700fL
#define REM19 "requires 0.9.7+"
int
X509_CRL_set_version(X509_CRL *x, long version)
int
X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name)
int
X509_CRL_set_lastUpdate(X509_CRL *x, ASN1_TIME *tm)
int
X509_CRL_set_nextUpdate(X509_CRL *x, ASN1_TIME *tm)
int
X509_CRL_sort(X509_CRL *x)
#endif
long
X509_CRL_get_version(X509_CRL *x)
X509_NAME *
X509_CRL_get_issuer(X509_CRL *x)
ASN1_TIME *
X509_CRL_get_lastUpdate(X509_CRL *x)
ASN1_TIME *
X509_CRL_get_nextUpdate(X509_CRL *x)
int
X509_CRL_verify(X509_CRL *a, EVP_PKEY *r)
int
X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md)
#if OPENSSL_VERSION_NUMBER >= 0x0090700fL
#define REM20 "requires 0.9.7+"
int
P_X509_CRL_set_serial(crl,crl_number)
X509_CRL *crl
ASN1_INTEGER * crl_number;
CODE:
RETVAL = 0;
if (crl && crl_number)
if (X509_CRL_add1_ext_i2d(crl, NID_crl_number, crl_number, 0, 0)) RETVAL = 1;
OUTPUT:
RETVAL
ASN1_INTEGER *
P_X509_CRL_get_serial(crl)
X509_CRL *crl
INIT:
int i;
CODE:
RETVAL = (ASN1_INTEGER *)X509_CRL_get_ext_d2i(crl, NID_crl_number, &i, NULL);
if (!RETVAL || i==-1) XSRETURN_UNDEF;
OUTPUT:
RETVAL
void
P_X509_CRL_add_revoked_serial_hex(crl,serial_hex,rev_time,reason_code=0,comp_time=NULL)
X509_CRL *crl
char * serial_hex
ASN1_TIME *rev_time
long reason_code
ASN1_TIME *comp_time
PREINIT:
BIGNUM *bn = NULL;
ASN1_INTEGER *sn;
X509_REVOKED *rev;
ASN1_ENUMERATED *rsn = NULL;
int rv;
PPCODE:
rv=0;
rev = X509_REVOKED_new();
if (rev) {
if (BN_hex2bn(&bn, serial_hex)) {
sn = BN_to_ASN1_INTEGER(bn, NULL);
if (sn) {
X509_REVOKED_set_serialNumber(rev, sn);
ASN1_INTEGER_free(sn);
rv = 1;
}
BN_free(bn);
}
}
if (!rv) XSRETURN_IV(0);
if (!rev_time) XSRETURN_IV(0);
if (!X509_REVOKED_set_revocationDate(rev, rev_time)) XSRETURN_IV(0);
if(reason_code) {
rv = 0;
rsn = ASN1_ENUMERATED_new();
if (rsn) {
if (ASN1_ENUMERATED_set(rsn, reason_code))
if (X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rsn, 0, 0))
rv=1;
ASN1_ENUMERATED_free(rsn);
}
if (!rv) XSRETURN_IV(0);
}
if(comp_time) {
X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0);
}
if(!X509_CRL_add0_revoked(crl, rev)) XSRETURN_IV(0);
XSRETURN_IV(1);
#endif
X509_REQ *
X509_REQ_new()
void
X509_REQ_free(X509_REQ *x)
X509_NAME *
X509_REQ_get_subject_name(X509_REQ *x)
int
X509_REQ_set_subject_name(X509_REQ *x, X509_NAME *name)
int
X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey)
EVP_PKEY *
X509_REQ_get_pubkey(X509_REQ *x)
int
X509_REQ_sign(X509_REQ *x, EVP_PKEY *pk, const EVP_MD *md)
int
X509_REQ_verify(X509_REQ *x, EVP_PKEY *r)
int
X509_REQ_set_version(X509_REQ *x, long version)
long
X509_REQ_get_version(X509_REQ *x)
int
X509_REQ_get_attr_count(const X509_REQ *req);
int
X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos=-1)
int
X509_REQ_get_attr_by_OBJ(const X509_REQ *req, ASN1_OBJECT *obj, int lastpos=-1)
int
X509_REQ_add1_attr_by_NID(req,nid,type,bytes)
X509_REQ *req
int nid
int type
PREINIT:
STRLEN len;
INPUT:
unsigned char *bytes = (unsigned char *)SvPV(ST(3), len);
CODE:
RETVAL = X509_REQ_add1_attr_by_NID(req,nid,type,bytes,len);
OUTPUT:
RETVAL
#if OPENSSL_VERSION_NUMBER >= 0x0090700fL
#define REM21 "requires 0.9.7+"
void
P_X509_REQ_get_attr(req,n)
X509_REQ *req
int n
INIT:
X509_ATTRIBUTE * att;
int count, i;
ASN1_STRING * s;
ASN1_TYPE * t;
PPCODE:
att = X509_REQ_get_attr(req,n);
count = X509_ATTRIBUTE_count(att);
for (i=0; i<count; i++) {
t = X509_ATTRIBUTE_get0_type(att, i);
s = t->value.asn1_string;
XPUSHs(sv_2mortal(newSViv(PTR2IV(s))));
}
#endif
int
P_X509_REQ_add_extensions(x,...)
X509_REQ *x
PREINIT:
int i=1;
int nid;
char *data;
X509_EXTENSION *ex;
STACK_OF(X509_EXTENSION) *stack;
CODE:
if (items>1) {
RETVAL = 1;
stack = sk_X509_EXTENSION_new_null();
while(i+1<items) {
nid = SvIV(ST(i));
data = SvPV_nolen(ST(i+1));
i+=2;
ex = X509V3_EXT_conf_nid(NULL, NULL, nid, data);
if (ex)
sk_X509_EXTENSION_push(stack, ex);
else
RETVAL = 0;
}
X509_REQ_add_extensions(x, stack);
sk_X509_EXTENSION_pop_free(stack, X509_EXTENSION_free);
}
else
RETVAL = 0;
OUTPUT:
RETVAL
int
P_X509_add_extensions(x,ca_cert,...)
X509 *x
X509 *ca_cert
PREINIT:
int i=2;
int nid;
char *data;
X509_EXTENSION *ex;
X509V3_CTX ctx;
CODE:
if (items>1) {
RETVAL = 1;
while(i+1<items) {
nid = SvIV(ST(i));
data = SvPV_nolen(ST(i+1));
i+=2;
X509V3_set_ctx(&ctx, ca_cert, x, NULL, NULL, 0);
ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, data);
if (ex) {
X509_add_ext(x,ex,-1);
X509_EXTENSION_free(ex);
}
else {
warn("failure during X509V3_EXT_conf_nid() for nid=%d\n", nid);
ERR_print_errors_fp(stderr);
RETVAL = 0;
}
}
}
else
RETVAL = 0;
OUTPUT:
RETVAL
void
P_X509_copy_extensions(x509_req,x509,override=1)
X509_REQ *x509_req
X509 *x509
int override
PREINIT:
STACK_OF(X509_EXTENSION) *exts = NULL;
X509_EXTENSION *ext, *tmpext;
ASN1_OBJECT *obj;
int i, idx, ret = 1;
PPCODE:
if (!x509 || !x509_req) XSRETURN_IV(0);
exts = X509_REQ_get_extensions(x509_req);
for(i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
ext = sk_X509_EXTENSION_value(exts, i);
obj = X509_EXTENSION_get_object(ext);
idx = X509_get_ext_by_OBJ(x509, obj, -1);
/* Does extension exist? */
if (idx != -1) {
if (override) continue; /* don't override existing extension */
/* Delete all extensions of same type */
do {
tmpext = X509_get_ext(x509, idx);
X509_delete_ext(x509, idx);
X509_EXTENSION_free(tmpext);
idx = X509_get_ext_by_OBJ(x509, obj, -1);
} while (idx != -1);
}
if (!X509_add_ext(x509, ext, -1)) ret = 0;
}
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
XSRETURN_IV(ret);
X509 *
X509_STORE_CTX_get_current_cert(x509_store_ctx)
X509_STORE_CTX * x509_store_ctx
int
X509_STORE_CTX_get_ex_new_index(argl,argp=NULL,new_func=NULL,dup_func=NULL,free_func=NULL)
long argl
void * argp
CRYPTO_EX_new * new_func
CRYPTO_EX_dup * dup_func
CRYPTO_EX_free * free_func
void *
X509_STORE_CTX_get_ex_data(x509_store_ctx,idx)
X509_STORE_CTX * x509_store_ctx
int idx
void *
X509_STORE_CTX_get_app_data(x509_store_ctx)
X509_STORE_CTX * x509_store_ctx
CODE:
RETVAL = X509_STORE_CTX_get_ex_data(x509_store_ctx,0);
OUTPUT:
RETVAL
void
X509_get_fingerprint(cert,type)
X509 * cert
char * type
PREINIT:
const EVP_MD *digest_tp = NULL;
unsigned char digest[EVP_MAX_MD_SIZE];
unsigned int dsz, k = 0;
char text[EVP_MAX_MD_SIZE * 3 + 1];
CODE:
#ifndef OPENSSL_NO_MD5
if (!k && !strcmp(type,"md5")) {
k = 1; digest_tp = EVP_md5();
}
#endif
if (!k && !strcmp(type,"sha1")) {
k = 1; digest_tp = EVP_sha1();
}
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
#ifndef OPENSSL_NO_SHA256
if (!k && !strcmp(type,"sha256")) {
k = 1; digest_tp = EVP_sha256();
}
#endif
#endif
if (!k && !strcmp(type,"ripemd160")) {
k = 1; digest_tp = EVP_ripemd160();
}
if (!k) /* Default digest */
digest_tp = EVP_sha1();
if ( digest_tp == NULL ) {
/* Out of memory */
XSRETURN_UNDEF;
}
if (!X509_digest(cert, digest_tp, digest, &dsz)) {
/* Out of memory */
XSRETURN_UNDEF;
}
text[0] = '\0';
for(k=0; k<dsz; k++) {
sprintf(&text[strlen(text)], "%02X:", digest[k]);
}
text[strlen(text)-1] = '\0';
ST(0) = sv_newmortal(); /* Undefined to start with */
sv_setpvn( ST(0), text, strlen(text));
void
X509_get_subjectAltNames(cert)
X509 * cert
PPCODE:
int i, j, count = 0;
X509_EXTENSION *subjAltNameExt = NULL;
STACK_OF(GENERAL_NAME) *subjAltNameDNs = NULL;
GENERAL_NAME *subjAltNameDN = NULL;
int num_gnames;
if ( (i = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1)) >= 0
&& (subjAltNameExt = X509_get_ext(cert, i))
&& (subjAltNameDNs = X509V3_EXT_d2i(subjAltNameExt)))
{
num_gnames = sk_GENERAL_NAME_num(subjAltNameDNs);
for (j = 0; j < num_gnames; j++)
{
subjAltNameDN = sk_GENERAL_NAME_value(subjAltNameDNs, j);
switch (subjAltNameDN->type)
{
case GEN_OTHERNAME:
EXTEND(SP, 2);
count++;
PUSHs(sv_2mortal(newSViv(subjAltNameDN->type)));
PUSHs(sv_2mortal(newSVpv((const char*)ASN1_STRING_data(subjAltNameDN->d.otherName->value->value.utf8string), ASN1_STRING_length(subjAltNameDN->d.otherName->value->value.utf8string))));
break;
case GEN_EMAIL:
case GEN_DNS:
case GEN_URI:
EXTEND(SP, 2);
count++;
PUSHs(sv_2mortal(newSViv(subjAltNameDN->type)));
PUSHs(sv_2mortal(newSVpv((const char*)ASN1_STRING_data(subjAltNameDN->d.ia5), ASN1_STRING_length(subjAltNameDN->d.ia5))));
break;
case GEN_DIRNAME:
{
char * buf = X509_NAME_oneline(subjAltNameDN->d.dirn, NULL, 0);
EXTEND(SP, 2);
count++;
PUSHs(sv_2mortal(newSViv(subjAltNameDN->type)));
PUSHs(sv_2mortal(newSVpv((buf), strlen((buf)))));
break;
}
case GEN_IPADD:
EXTEND(SP, 2);
count++;
PUSHs(sv_2mortal(newSViv(subjAltNameDN->type)));
PUSHs(sv_2mortal(newSVpv((const char*)subjAltNameDN->d.ip->data, subjAltNameDN->d.ip->length)));
break;
}
}
sk_GENERAL_NAME_pop_free(subjAltNameDNs, GENERAL_NAME_free);
}
XSRETURN(count * 2);
#if OPENSSL_VERSION_NUMBER >= 0x0090700fL
void
P_X509_get_crl_distribution_points(cert)
X509 * cert
INIT:
GENERAL_NAMES *gnames;
GENERAL_NAME *gn;
STACK_OF(DIST_POINT) *points;
DIST_POINT *p;
int i, j;
PPCODE:
points = X509_get_ext_d2i(cert, NID_crl_distribution_points, NULL, NULL);
if (points)
for (i = 0; i < sk_DIST_POINT_num(points); i++) {
p = sk_DIST_POINT_value(points, i);
if (!p->distpoint)
continue;
if (p->distpoint->type == 0) {
/* full name */
gnames = p->distpoint->name.fullname;
for (j = 0; j < sk_GENERAL_NAME_num(gnames); j++) {
gn = sk_GENERAL_NAME_value(gnames, j);
if (gn->type == GEN_URI) {
XPUSHs(sv_2mortal(newSVpv((char*)ASN1_STRING_data(gn->d.ia5),ASN1_STRING_length(gn->d.ia5))));
}
}
}
else {
/* relative name - not supported */
/* XXX-TODO: the code below is just an idea; do not enable it without proper test case
BIO *bp;
char *buf;
int n;
X509_NAME ntmp;
ntmp.entries = p->distpoint->name.relativename;
bp = BIO_new(BIO_s_mem());
if (bp) {
X509_NAME_print_ex(bp, &ntmp, 0, XN_FLAG_RFC2253);
n = BIO_ctrl_pending(bp);
New(0, buf, n, char);
if (buf) {
j = BIO_read(bp,buf,n);
if (j>=0 && j<=n) XPUSHs(sv_2mortal(newSVpvn(buf,j)));
Safefree(buf);
}
BIO_free(bp);
}
*/
}
}
void
P_X509_get_ocsp_uri(cert)
X509 * cert
PPCODE:
AUTHORITY_INFO_ACCESS *info;
int i;
info = X509_get_ext_d2i(cert, NID_info_access, NULL, NULL);
if (!info) XSRETURN_UNDEF;
for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
if (OBJ_obj2nid(ad->method) == NID_ad_OCSP
&& ad->location->type == GEN_URI) {
XPUSHs(sv_2mortal(newSVpv(
(char*)ASN1_STRING_data(ad->location->d.uniformResourceIdentifier),
ASN1_STRING_length(ad->location->d.uniformResourceIdentifier)
)));
if (GIMME == G_SCALAR) break; /* get only first */
}
}
void
P_X509_get_ext_key_usage(cert,format=0)
X509 * cert
int format
PREINIT:
EXTENDED_KEY_USAGE *extusage;
int i, nid;
char buffer[100]; /* openssl doc: a buffer length of 80 should be more than enough to handle any OID encountered in practice */
ASN1_OBJECT *o;
PPCODE:
extusage = X509_get_ext_d2i(cert, NID_ext_key_usage, NULL, NULL);
for(i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) {
o = sk_ASN1_OBJECT_value(extusage,i);
nid = OBJ_obj2nid(o);
OBJ_obj2txt(buffer, sizeof(buffer)-1, o, 1);
if(format==0)
XPUSHs(sv_2mortal(newSVpv(buffer,0))); /* format 0: oid */
else if(format==1 && nid>0)
XPUSHs(sv_2mortal(newSViv(nid))); /* format 1: nid */
else if(format==2 && nid>0)
XPUSHs(sv_2mortal(newSVpv(OBJ_nid2sn(nid),0))); /* format 2: shortname */
else if(format==3 && nid>0)
XPUSHs(sv_2mortal(newSVpv(OBJ_nid2ln(nid),0))); /* format 3: longname */
}
#endif
void
P_X509_get_key_usage(cert)
X509 * cert
INIT:
ASN1_BIT_STRING * u;
PPCODE:
u = X509_get_ext_d2i(cert, NID_key_usage, NULL, NULL);
if (u) {
if (ASN1_BIT_STRING_get_bit(u,0)) XPUSHs(sv_2mortal(newSVpv("digitalSignature",0)));
if (ASN1_BIT_STRING_get_bit(u,1)) XPUSHs(sv_2mortal(newSVpv("nonRepudiation",0)));
if (ASN1_BIT_STRING_get_bit(u,2)) XPUSHs(sv_2mortal(newSVpv("keyEncipherment",0)));
if (ASN1_BIT_STRING_get_bit(u,3)) XPUSHs(sv_2mortal(newSVpv("dataEncipherment",0)));
if (ASN1_BIT_STRING_get_bit(u,4)) XPUSHs(sv_2mortal(newSVpv("keyAgreement",0)));
if (ASN1_BIT_STRING_get_bit(u,5)) XPUSHs(sv_2mortal(newSVpv("keyCertSign",0)));
if (ASN1_BIT_STRING_get_bit(u,6)) XPUSHs(sv_2mortal(newSVpv("cRLSign",0)));
if (ASN1_BIT_STRING_get_bit(u,7)) XPUSHs(sv_2mortal(newSVpv("encipherOnly",0)));
if (ASN1_BIT_STRING_get_bit(u,8)) XPUSHs(sv_2mortal(newSVpv("decipherOnly",0)));
}
void
P_X509_get_netscape_cert_type(cert)
X509 * cert
INIT:
ASN1_BIT_STRING * u;
PPCODE:
u = X509_get_ext_d2i(cert, NID_netscape_cert_type, NULL, NULL);
if (u) {
if (ASN1_BIT_STRING_get_bit(u,0)) XPUSHs(sv_2mortal(newSVpv("client",0)));
if (ASN1_BIT_STRING_get_bit(u,1)) XPUSHs(sv_2mortal(newSVpv("server",0)));
if (ASN1_BIT_STRING_get_bit(u,2)) XPUSHs(sv_2mortal(newSVpv("email",0)));
if (ASN1_BIT_STRING_get_bit(u,3)) XPUSHs(sv_2mortal(newSVpv("objsign",0)));
if (ASN1_BIT_STRING_get_bit(u,4)) XPUSHs(sv_2mortal(newSVpv("reserved",0)));
if (ASN1_BIT_STRING_get_bit(u,5)) XPUSHs(sv_2mortal(newSVpv("sslCA",0)));
if (ASN1_BIT_STRING_get_bit(u,6)) XPUSHs(sv_2mortal(newSVpv("emailCA",0)));
if (ASN1_BIT_STRING_get_bit(u,7)) XPUSHs(sv_2mortal(newSVpv("objCA",0)));
}
int
X509_get_ext_by_NID(x,nid,loc=-1)
X509* x
int nid
int loc
X509_EXTENSION *
X509_get_ext(x,loc)
X509* x
int loc
int
X509_EXTENSION_get_critical(X509_EXTENSION *ex)
ASN1_OCTET_STRING *
X509_EXTENSION_get_data(X509_EXTENSION *ne)
ASN1_OBJECT *
X509_EXTENSION_get_object(X509_EXTENSION *ex)
int
X509_get_ext_count(X509 *x)
int
X509_CRL_get_ext_count(X509_CRL *x)
int
X509_CRL_get_ext_by_NID(x,ni,loc=-1)
X509_CRL* x
int ni
int loc
X509_EXTENSION *
X509_CRL_get_ext(x,loc)
X509_CRL* x
int loc
void
X509V3_EXT_print(ext,flags=0,utf8_decode=0)
X509_EXTENSION * ext
unsigned long flags
int utf8_decode
PREINIT:
BIO * bp;
char * buf;
int i, n;
int indent=0;
CODE:
ST(0) = sv_newmortal(); /* undef to start with */
bp = BIO_new(BIO_s_mem());
if (bp) {
if(X509V3_EXT_print(bp,ext,flags,indent)) {
n = BIO_ctrl_pending(bp);
New(0, buf, n, char);
if (buf) {
i = BIO_read(bp,buf,n);
if (i>=0 && i<=n) {
sv_setpvn(ST(0), buf, i);
if (utf8_decode) sv_utf8_decode(ST(0));
}
Safefree(buf);
}
}
BIO_free(bp);
}
void *
X509V3_EXT_d2i(ext)
X509_EXTENSION *ext
X509_STORE_CTX *
X509_STORE_CTX_new()
int
X509_verify_cert(x509_store_ctx)
X509_STORE_CTX * x509_store_ctx
int
X509_STORE_CTX_get_error(x509_store_ctx)
X509_STORE_CTX * x509_store_ctx
int
X509_STORE_CTX_get_error_depth(x509_store_ctx)
X509_STORE_CTX * x509_store_ctx
int
X509_STORE_CTX_set_ex_data(x509_store_ctx,idx,data)
X509_STORE_CTX * x509_store_ctx
int idx
void * data
int
X509_STORE_CTX_set_app_data(x509_store_ctx,arg)
X509_STORE_CTX * x509_store_ctx
char * arg
CODE:
RETVAL = X509_STORE_CTX_set_ex_data(x509_store_ctx,0,arg);
OUTPUT:
RETVAL
void
X509_STORE_CTX_set_error(x509_store_ctx,s)
X509_STORE_CTX * x509_store_ctx
int s
void
X509_STORE_CTX_set_cert(x509_store_ctx,x)
X509_STORE_CTX * x509_store_ctx
X509 * x
int
X509_STORE_add_cert(ctx, x)
X509_STORE *ctx
X509 *x
int
X509_STORE_add_crl(ctx, x)
X509_STORE *ctx
X509_CRL *x
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
void
X509_STORE_set_flags(ctx, flags)
X509_STORE *ctx
long flags
void
X509_STORE_set_purpose(ctx, purpose)
X509_STORE *ctx
int purpose
void
X509_STORE_set_trust(ctx, trust)
X509_STORE *ctx
int trust
int
X509_STORE_set1_param(ctx, pm)
X509_STORE *ctx
X509_VERIFY_PARAM *pm
#endif
int
X509_load_cert_file(ctx, file, type)
X509_LOOKUP *ctx
char *file
int type
int
X509_load_crl_file(ctx, file, type)
X509_LOOKUP *ctx
char *file
int type
int
X509_load_cert_crl_file(ctx, file, type)
X509_LOOKUP *ctx
char *file
int type
const char *
X509_verify_cert_error_string(n)
long n
ASN1_INTEGER *
ASN1_INTEGER_new()
void
ASN1_INTEGER_free(ASN1_INTEGER *i)
int
ASN1_INTEGER_set(ASN1_INTEGER *i, long val)
long
ASN1_INTEGER_get(ASN1_INTEGER *a)
void
P_ASN1_INTEGER_set_hex(i,str)
ASN1_INTEGER * i
char * str
INIT:
BIGNUM *bn;
int rv = 1;
PPCODE:
bn = BN_new();
if (!BN_hex2bn(&bn, str)) XSRETURN_IV(0);
if (!BN_to_ASN1_INTEGER(bn, i)) rv = 0;
BN_free(bn);
XSRETURN_IV(rv);
void
P_ASN1_INTEGER_set_dec(i,str)
ASN1_INTEGER * i
char * str
INIT:
BIGNUM *bn;
int rv = 1;
PPCODE:
bn = BN_new();
if (!BN_dec2bn(&bn, str)) XSRETURN_IV(0);
if (!BN_to_ASN1_INTEGER(bn, i)) rv = 0;
BN_free(bn);
XSRETURN_IV(rv);
void
P_ASN1_INTEGER_get_hex(i)
ASN1_INTEGER * i
INIT:
BIGNUM *bn;
char *result;
PPCODE:
bn = BN_new();
if (!bn) XSRETURN_UNDEF;
ASN1_INTEGER_to_BN(i, bn);
result = BN_bn2hex(bn);
BN_free(bn);
if (!result) XSRETURN_UNDEF;
XPUSHs(sv_2mortal(newSVpv((const char*)result, strlen(result))));
OPENSSL_free(result);
void
P_ASN1_INTEGER_get_dec(i)
ASN1_INTEGER * i
INIT:
BIGNUM *bn;
char *result;
PPCODE:
bn = BN_new();
if (!bn) XSRETURN_UNDEF;
ASN1_INTEGER_to_BN(i, bn);
result = BN_bn2dec(bn);
BN_free(bn);
if (!result) XSRETURN_UNDEF;
XPUSHs(sv_2mortal(newSVpv((const char*)result, strlen(result))));
OPENSSL_free(result);
void
P_ASN1_STRING_get(s,utf8_decode=0)
ASN1_STRING * s
int utf8_decode
PREINIT:
SV * u8;
PPCODE:
u8 = newSVpv((const char*)ASN1_STRING_data(s), ASN1_STRING_length(s));
if (utf8_decode) sv_utf8_decode(u8);
XPUSHs(sv_2mortal(u8));
ASN1_TIME *
X509_get_notBefore(cert)
X509 * cert
ASN1_TIME *
X509_get_notAfter(cert)
X509 * cert
ASN1_TIME *
X509_gmtime_adj(s, adj)
ASN1_TIME * s
long adj
ASN1_TIME *
ASN1_TIME_set(s,t)
ASN1_TIME *s
time_t t
void
ASN1_TIME_free(s)
ASN1_TIME *s
time_t
ASN1_TIME_timet(s)
ASN1_TIME *s
ASN1_TIME *
ASN1_TIME_new()
void
P_ASN1_TIME_put2string(tm)
ASN1_TIME * tm
PREINIT:
BIO *bp=NULL;
int i=0;
char buffer[256];
ALIAS:
P_ASN1_UTCTIME_put2string = 1
CODE:
ST(0) = sv_newmortal(); /* undef retval to start with */
if (tm) {
bp = BIO_new(BIO_s_mem());
if (bp) {
ASN1_TIME_print(bp,tm);
i = BIO_read(bp,buffer,255);
buffer[i] = '\0';
if (i>0)
sv_setpvn(ST(0), buffer, i);
BIO_free(bp);
}
}
#if OPENSSL_VERSION_NUMBER >= 0x0090705f
#define REM15 "NOTE: requires 0.9.7e+"
void
P_ASN1_TIME_get_isotime(tm)
ASN1_TIME *tm
PREINIT:
ASN1_GENERALIZEDTIME *tmp = NULL;
char buf[256];
CODE:
buf[0] = '\0';
/* ASN1_TIME_to_generalizedtime is buggy on pre-0.9.7e */
ASN1_TIME_to_generalizedtime(tm,&tmp);
if (tmp) {
if (ASN1_GENERALIZEDTIME_check(tmp)) {
if (strlen((char*)tmp->data)>=14 && strlen((char*)tmp->data)<200) {
strcpy (buf,"yyyy-mm-ddThh:mm:ss");
strncpy(buf, (char*)tmp->data, 4);
strncpy(buf+5, (char*)tmp->data+4, 2);
strncpy(buf+8, (char*)tmp->data+6, 2);
strncpy(buf+11,(char*)tmp->data+8, 2);
strncpy(buf+14,(char*)tmp->data+10,2);
strncpy(buf+17,(char*)tmp->data+12,2);
if (strlen((char*)tmp->data)>14) strcat(buf+19,(char*)tmp->data+14);
}
}
ASN1_GENERALIZEDTIME_free(tmp);
}
ST(0) = sv_newmortal();
sv_setpv(ST(0), buf);
void
P_ASN1_TIME_set_isotime(tm,str)
ASN1_TIME *tm
const char *str
PREINIT:
ASN1_TIME t;
char buf[256];
int i,rv;
CODE:
if (!tm) XSRETURN_UNDEF;
/* we support only "2012-03-22T23:55:33" or "2012-03-22T23:55:33Z" or "2012-03-22T23:55:33<timezone>" */
if (strlen(str) < 19) XSRETURN_UNDEF;
for (i=0; i<4; i++) if ((str[i] > '9') || (str[i] < '0')) XSRETURN_UNDEF;
for (i=5; i<7; i++) if ((str[i] > '9') || (str[i] < '0')) XSRETURN_UNDEF;
for (i=8; i<10; i++) if ((str[i] > '9') || (str[i] < '0')) XSRETURN_UNDEF;
for (i=11; i<13; i++) if ((str[i] > '9') || (str[i] < '0')) XSRETURN_UNDEF;
for (i=14; i<16; i++) if ((str[i] > '9') || (str[i] < '0')) XSRETURN_UNDEF;
for (i=17; i<19; i++) if ((str[i] > '9') || (str[i] < '0')) XSRETURN_UNDEF;
strncpy(buf, str, 4);
strncpy(buf+4, str+5, 2);
strncpy(buf+6, str+8, 2);
strncpy(buf+8, str+11, 2);
strncpy(buf+10, str+14, 2);
strncpy(buf+12, str+17, 2);
buf[14] = '\0';
if (strlen(str)>19 && strlen(str)<200) strcat(buf,str+19);
/* WORKAROUND: ASN1_TIME_set_string() not available in 0.9.8 !!!*/
/* in 1.0.0 we would simply: rv = ASN1_TIME_set_string(tm,buf); */
t.length = strlen(buf);
t.data = (unsigned char *)buf;
t.flags = 0;
t.type = V_ASN1_UTCTIME;
if (!ASN1_TIME_check(&t)) {
t.type = V_ASN1_GENERALIZEDTIME;
if (!ASN1_TIME_check(&t)) XSRETURN_UNDEF;
}
tm->type = t.type;
tm->flags = t.flags;
if (!ASN1_STRING_set(tm,t.data,t.length)) XSRETURN_UNDEF;
rv = 1;
/* end of ASN1_TIME_set_string() reimplementation */
ST(0) = sv_newmortal();
sv_setiv(ST(0), rv); /* 1 = success, undef = failure */
#endif
int
EVP_PKEY_copy_parameters(to,from)
EVP_PKEY * to
EVP_PKEY * from
EVP_PKEY *
EVP_PKEY_new()
void
EVP_PKEY_free(EVP_PKEY *pkey)
int
EVP_PKEY_assign_RSA(EVP_PKEY *pkey, RSA *key)
int
EVP_PKEY_bits(EVP_PKEY *pkey)
int
EVP_PKEY_size(EVP_PKEY *pkey)
#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
int
EVP_PKEY_id(const EVP_PKEY *pkey)
#endif
void
PEM_get_string_X509(x509)
X509 * x509
PREINIT:
BIO *bp;
int i, n;
char *buf;
CODE:
ST(0) = sv_newmortal(); /* undef to start with */
bp = BIO_new(BIO_s_mem());
if (bp && x509) {
PEM_write_bio_X509(bp,x509);
n = BIO_ctrl_pending(bp);
New(0, buf, n, char);
if (buf) {
i = BIO_read(bp,buf,n);
if (i>=0 && i<=n) sv_setpvn(ST(0), buf, i);
Safefree(buf);
}
BIO_free(bp);
}
void
PEM_get_string_X509_REQ(x509_req)
X509_REQ * x509_req
PREINIT:
BIO *bp;
int i, n;
char *buf;
CODE:
ST(0) = sv_newmortal(); /* undef to start with */
bp = BIO_new(BIO_s_mem());
if (bp && x509_req) {
PEM_write_bio_X509_REQ(bp,x509_req);
n = BIO_ctrl_pending(bp);
New(0, buf, n, char);
if (buf) {
i = BIO_read(bp,buf,n);
if (i>=0 && i<=n) sv_setpvn(ST(0), buf, i);
Safefree(buf);
}
BIO_free(bp);
}
void
PEM_get_string_X509_CRL(x509_crl)
X509_CRL * x509_crl
PREINIT:
BIO *bp;
int i, n;
char *buf;
CODE:
ST(0) = sv_newmortal(); /* undef to start with */
bp = BIO_new(BIO_s_mem());
if (bp && x509_crl) {
PEM_write_bio_X509_CRL(bp,x509_crl);
n = BIO_ctrl_pending(bp);
New(0, buf, n, char);
if (buf) {
i = BIO_read(bp,buf,n);
if (i>=0 && i<=n) sv_setpvn(ST(0), buf, i);
Safefree(buf);
}
BIO_free(bp);
}
void
PEM_get_string_PrivateKey(pk,passwd=NULL,enc_alg=NULL)
EVP_PKEY * pk
char * passwd
const EVP_CIPHER * enc_alg
PREINIT:
BIO *bp;
int i, n;
char *buf;
size_t passwd_len = 0;
pem_password_cb * cb = NULL;
void * u = NULL;
CODE:
ST(0) = sv_newmortal(); /* undef to start with */
bp = BIO_new(BIO_s_mem());
if (bp && pk) {
if (passwd) passwd_len = strlen(passwd);
if (passwd_len>0) {
/* encrypted key */
if (!enc_alg)
PEM_write_bio_PrivateKey(bp,pk,EVP_des_cbc(),(unsigned char *)passwd,passwd_len,cb,u);
else
PEM_write_bio_PrivateKey(bp,pk,enc_alg,(unsigned char *)passwd,passwd_len,cb,u);
}
else {
/* unencrypted key */
PEM_write_bio_PrivateKey(bp,pk,NULL,(unsigned char *)passwd,passwd_len,cb,u);
}
n = BIO_ctrl_pending(bp);
New(0, buf, n, char);
if (buf) {
i = BIO_read(bp,buf,n);
if (i>=0 && i<=n) sv_setpvn(ST(0), buf, i);
Safefree(buf);
}
BIO_free(bp);
}
int
CTX_use_PKCS12_file(ctx, file, password=NULL)
SSL_CTX *ctx
char *file
char *password
PREINIT:
PKCS12 *p12;
EVP_PKEY *private_key;
X509 *certificate;
FILE *fp;
CODE:
RETVAL = 0;
if ((fp = fopen (file, "rb"))) {
#if OPENSSL_VERSION_NUMBER >= 0x0090700fL
OPENSSL_add_all_algorithms_noconf();
#else
OpenSSL_add_all_algorithms();
#endif
if ((p12 = d2i_PKCS12_fp(fp, NULL))) {
if (PKCS12_parse(p12, password, &private_key, &certificate, NULL)) {
if (private_key) {
if (SSL_CTX_use_PrivateKey(ctx, private_key)) RETVAL = 1;
EVP_PKEY_free(private_key);
}
if (certificate) {
if (SSL_CTX_use_certificate(ctx, certificate)) RETVAL = 1;
X509_free(certificate);
}
}
PKCS12_free(p12);
}
if (!RETVAL) ERR_print_errors_fp(stderr);
fclose(fp);
}
OUTPUT:
RETVAL
void
P_PKCS12_load_file(file, load_chain=0, password=NULL)
char *file
int load_chain
char *password
PREINIT:
PKCS12 *p12;
EVP_PKEY *private_key = NULL;
X509 *certificate = NULL;
STACK_OF(X509) *cachain = NULL;
X509 *x;
FILE *fp;
int i, result;
PPCODE:
if ((fp = fopen (file, "rb"))) {
#if OPENSSL_VERSION_NUMBER >= 0x0090700fL
OPENSSL_add_all_algorithms_noconf();
#else
OpenSSL_add_all_algorithms();
#endif
if ((p12 = d2i_PKCS12_fp(fp, NULL))) {
if(load_chain)
result= PKCS12_parse(p12, password, &private_key, &certificate, &cachain);
else
result= PKCS12_parse(p12, password, &private_key, &certificate, NULL);
if (result) {
if (private_key)
XPUSHs(sv_2mortal(newSViv(PTR2IV(private_key))));
else
XPUSHs(sv_2mortal(newSVpv(NULL,0))); /* undef */
if (certificate)
XPUSHs(sv_2mortal(newSViv(PTR2IV(certificate))));
else
XPUSHs(sv_2mortal(newSVpv(NULL,0))); /* undef */
if (cachain) {
for (i=0; i<sk_X509_num(cachain); i++) {
x = sk_X509_value(cachain, i);
XPUSHs(sv_2mortal(newSViv(PTR2IV(x))));
}
sk_X509_free(cachain);
}
}
PKCS12_free(p12);
}
fclose(fp);
}
#ifndef OPENSSL_NO_MD2
void
MD2(data)
PREINIT:
STRLEN len;
unsigned char md[MD2_DIGEST_LENGTH];
unsigned char * ret;
INPUT:
unsigned char* data = (unsigned char *) SvPV( ST(0), len);
CODE:
ret = MD2(data,len,md);
if (ret!=NULL) {
XSRETURN_PVN((char *) md, MD2_DIGEST_LENGTH);
} else {
XSRETURN_UNDEF;
}
#endif
#ifndef OPENSSL_NO_MD4
void
MD4(data)
PREINIT:
STRLEN len;
unsigned char md[MD4_DIGEST_LENGTH];
INPUT:
unsigned char* data = (unsigned char *) SvPV( ST(0), len );
CODE:
if (MD4(data,len,md)) {
XSRETURN_PVN((char *) md, MD4_DIGEST_LENGTH);
} else {
XSRETURN_UNDEF;
}
#endif
#ifndef OPENSSL_NO_MD5
void
MD5(data)
PREINIT:
STRLEN len;
unsigned char md[MD5_DIGEST_LENGTH];
INPUT:
unsigned char * data = (unsigned char *) SvPV( ST(0), len);
CODE:
if (MD5(data,len,md)) {
XSRETURN_PVN((char *) md, MD5_DIGEST_LENGTH);
} else {
XSRETURN_UNDEF;
}
#endif
#if OPENSSL_VERSION_NUMBER >= 0x00905000L
void
RIPEMD160(data)
PREINIT:
STRLEN len;
unsigned char md[RIPEMD160_DIGEST_LENGTH];
INPUT:
unsigned char * data = (unsigned char *) SvPV( ST(0), len);
CODE:
if (RIPEMD160(data,len,md)) {
XSRETURN_PVN((char *) md, RIPEMD160_DIGEST_LENGTH);
} else {
XSRETURN_UNDEF;
}
#endif
#if !defined(OPENSSL_NO_SHA)
void
SHA1(data)
PREINIT:
STRLEN len;
unsigned char md[SHA_DIGEST_LENGTH];
INPUT:
unsigned char * data = (unsigned char *) SvPV( ST(0), len);
CODE:
if (SHA1(data,len,md)) {
XSRETURN_PVN((char *) md, SHA_DIGEST_LENGTH);
} else {
XSRETURN_UNDEF;
}
#endif
#if !defined(OPENSSL_NO_SHA256) && OPENSSL_VERSION_NUMBER >= 0x0090800fL
void
SHA256(data)
PREINIT:
STRLEN len;
unsigned char md[SHA256_DIGEST_LENGTH];
INPUT:
unsigned char * data = (unsigned char *) SvPV( ST(0), len);
CODE:
if (SHA256(data,len,md)) {
XSRETURN_PVN((char *) md, SHA256_DIGEST_LENGTH);
} else {
XSRETURN_UNDEF;
}
#endif
#if !defined(OPENSSL_NO_SHA512) && OPENSSL_VERSION_NUMBER >= 0x0090800fL
void
SHA512(data)
PREINIT:
STRLEN len;
unsigned char md[SHA512_DIGEST_LENGTH];
INPUT:
unsigned char * data = (unsigned char *) SvPV( ST(0), len);
CODE:
if (SHA512(data,len,md)) {
XSRETURN_PVN((char *) md, SHA512_DIGEST_LENGTH);
} else {
XSRETURN_UNDEF;
}
#endif
#ifndef OPENSSL_NO_SSL2
#if OPENSSL_VERSION_NUMBER < 0x10000000L
const SSL_METHOD *
SSLv2_method()
#endif
#endif
#ifndef OPENSSL_NO_SSL3
#if OPENSSL_VERSION_NUMBER < 0x10002000L
const SSL_METHOD *
SSLv3_method()
#endif
#endif
const SSL_METHOD *
SSLv23_method()
const SSL_METHOD *
SSLv23_server_method()
const SSL_METHOD *
SSLv23_client_method()
const SSL_METHOD *
TLSv1_method()
const SSL_METHOD *
TLSv1_server_method()
const SSL_METHOD *
TLSv1_client_method()
#ifdef SSL_TXT_TLSV1_1
const SSL_METHOD *
TLSv1_1_method()
const SSL_METHOD *
TLSv1_1_server_method()
const SSL_METHOD *
TLSv1_1_client_method()
#endif
#ifdef SSL_TXT_TLSV1_2
const SSL_METHOD *
TLSv1_2_method()
const SSL_METHOD *
TLSv1_2_server_method()
const SSL_METHOD *
TLSv1_2_client_method()
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) || (LIBRESSL_VERSION_NUMBER >= 0x20020002L)
const SSL_METHOD *
TLS_method()
const SSL_METHOD *
TLS_server_method()
const SSL_METHOD *
TLS_client_method()
#endif /* OpenSSL 1.1.0 or LibreSSL 2.2.2 */
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) || (LIBRESSL_VERSION_NUMBER >= 0x2060000fL)
int
SSL_CTX_set_min_proto_version(ctx, version)
SSL_CTX * ctx
int version
int
SSL_CTX_set_max_proto_version(ctx, version)
SSL_CTX * ctx
int version
int
SSL_set_min_proto_version(ssl, version)
SSL * ssl
int version
int
SSL_set_max_proto_version(ssl, version)
SSL * ssl
int version
#endif /* OpenSSL 1.1.0 or LibreSSL 2.6.0 */
#if OPENSSL_VERSION_NUMBER >= 0x1010007fL && !defined(LIBRESSL_VERSION_NUMBER)
int
SSL_CTX_get_min_proto_version(ctx)
SSL_CTX * ctx
int
SSL_CTX_get_max_proto_version(ctx)
SSL_CTX * ctx
int
SSL_get_min_proto_version(ssl)
SSL * ssl
int
SSL_get_max_proto_version(ssl)
SSL * ssl
#endif /* OpenSSL 1.1.0g */
#if OPENSSL_VERSION_NUMBER < 0x10000000L
int
SSL_set_ssl_method(ssl, method)
SSL * ssl
SSL_METHOD * method
#else
int
SSL_set_ssl_method(ssl, method)
SSL * ssl
const SSL_METHOD * method
#endif
const SSL_METHOD *
SSL_get_ssl_method(ssl)
SSL * ssl
#define REM_AUTOMATICALLY_GENERATED_1_09
BIO *
BIO_new_buffer_ssl_connect(ctx)
SSL_CTX * ctx
BIO *
BIO_new_file(filename,mode)
char * filename
char * mode
BIO *
BIO_new_ssl(ctx,client)
SSL_CTX * ctx
int client
BIO *
BIO_new_ssl_connect(ctx)
SSL_CTX * ctx
BIO *
BIO_new(type)
BIO_METHOD * type;
int
BIO_free(bio)
BIO * bio;
void
BIO_read(s,max=32768)
BIO * s
int max
PREINIT:
char *buf = NULL;
int got;
CODE:
New(0, buf, max, char);
ST(0) = sv_newmortal(); /* Undefined to start with */
if ((got = BIO_read(s, buf, max)) >= 0)
sv_setpvn( ST(0), buf, got);
Safefree(buf);
int
BIO_write(s,buf)
BIO * s
PREINIT:
STRLEN len;
INPUT:
char * buf = SvPV( ST(1), len);
CODE:
RETVAL = BIO_write (s, buf, (int)len);
OUTPUT:
RETVAL
int
BIO_eof(s)
BIO * s
int
BIO_pending(s)
BIO * s
int
BIO_wpending(s)
BIO * s
int
BIO_ssl_copy_session_id(to,from)
BIO * to
BIO * from
void
BIO_ssl_shutdown(ssl_bio)
BIO * ssl_bio
int
SSL_add_client_CA(ssl,x)
SSL * ssl
X509 * x
const char *
SSL_alert_desc_string(value)
int value
const char *
SSL_alert_desc_string_long(value)
int value
const char *
SSL_alert_type_string(value)
int value
const char *
SSL_alert_type_string_long(value)
int value
long
SSL_callback_ctrl(ssl,i,fp)
SSL * ssl
int i
callback_no_ret * fp
int
SSL_check_private_key(ctx)
SSL * ctx
#if OPENSSL_VERSION_NUMBER < 0x009080dfL
#define REM8 "NOTE: before 0.9.8m"
char *
SSL_CIPHER_description(cipher,buf,size)
SSL_CIPHER * cipher
char * buf
int size
#else
char *
SSL_CIPHER_description(cipher,buf,size)
const SSL_CIPHER * cipher
char * buf
int size
#endif
#if OPENSSL_VERSION_NUMBER < 0x0090707fL
#define REM9 "NOTE: before 0.9.7g"
const char *
SSL_CIPHER_get_name(SSL_CIPHER *c)
int
SSL_CIPHER_get_bits(c,alg_bits=NULL)
SSL_CIPHER * c
int * alg_bits
#else
const char *
SSL_CIPHER_get_name(const SSL_CIPHER *c)
int
SSL_CIPHER_get_bits(c,alg_bits=NULL)
const SSL_CIPHER * c
int * alg_bits
#endif
#ifndef OPENSSL_NO_COMP
int
SSL_COMP_add_compression_method(id,cm)
int id
COMP_METHOD * cm
#endif
int
SSL_CTX_add_client_CA(ctx,x)
SSL_CTX * ctx
X509 * x
long
SSL_CTX_callback_ctrl(ctx,i,fp)
SSL_CTX * ctx
int i
callback_no_ret * fp
int
SSL_CTX_check_private_key(ctx)
SSL_CTX * ctx
void *
SSL_CTX_get_ex_data(ssl,idx)
SSL_CTX * ssl
int idx
int
SSL_CTX_get_quiet_shutdown(ctx)
SSL_CTX * ctx
long
SSL_CTX_get_timeout(ctx)
SSL_CTX * ctx
int
SSL_CTX_get_verify_depth(ctx)
SSL_CTX * ctx
int
SSL_CTX_get_verify_mode(ctx)
SSL_CTX * ctx
void
SSL_CTX_set_cert_store(ctx,store)
SSL_CTX * ctx
X509_STORE * store
X509_STORE *
SSL_CTX_get_cert_store(ctx)
SSL_CTX * ctx
void
SSL_CTX_set_cert_verify_callback(ctx,callback,data=&PL_sv_undef)
SSL_CTX * ctx
SV * callback
SV * data
CODE:
if (callback==NULL || !SvOK(callback)) {
SSL_CTX_set_cert_verify_callback(ctx, NULL, NULL);
cb_data_advanced_put(ctx, "ssleay_ctx_cert_verify_cb!!func", NULL);
cb_data_advanced_put(ctx, "ssleay_ctx_cert_verify_cb!!data", NULL);
}
else {
cb_data_advanced_put(ctx, "ssleay_ctx_cert_verify_cb!!func", newSVsv(callback));
cb_data_advanced_put(ctx, "ssleay_ctx_cert_verify_cb!!data", newSVsv(data));
#if OPENSSL_VERSION_NUMBER >= 0x0090700fL
SSL_CTX_set_cert_verify_callback(ctx, ssleay_ctx_cert_verify_cb_invoke, ctx);
#else
SSL_CTX_set_cert_verify_callback(ctx, ssleay_ctx_cert_verify_cb_invoke, (char*)ctx);
#endif
}
X509_NAME_STACK *
SSL_CTX_get_client_CA_list(ctx)
SSL_CTX *ctx
void
SSL_CTX_set_client_CA_list(ctx,list)
SSL_CTX * ctx
X509_NAME_STACK * list
void
SSL_CTX_set_default_passwd_cb(ctx,callback=&PL_sv_undef)
SSL_CTX * ctx
SV * callback
CODE:
if (callback==NULL || !SvOK(callback)) {
SSL_CTX_set_default_passwd_cb(ctx, NULL);
SSL_CTX_set_default_passwd_cb_userdata(ctx, NULL);
cb_data_advanced_put(ctx, "ssleay_ctx_passwd_cb!!func", NULL);
}
else {
cb_data_advanced_put(ctx, "ssleay_ctx_passwd_cb!!func", newSVsv(callback));
SSL_CTX_set_default_passwd_cb_userdata(ctx, (void*)ctx);
SSL_CTX_set_default_passwd_cb(ctx, &ssleay_ctx_passwd_cb_invoke);
}
void
SSL_CTX_set_default_passwd_cb_userdata(ctx,data=&PL_sv_undef)
SSL_CTX * ctx
SV * data
CODE:
/* SSL_CTX_set_default_passwd_cb_userdata is set in SSL_CTX_set_default_passwd_cb */
if (data==NULL || !SvOK(data)) {
cb_data_advanced_put(ctx, "ssleay_ctx_passwd_cb!!data", NULL);
}
else {
cb_data_advanced_put(ctx, "ssleay_ctx_passwd_cb!!data", newSVsv(data));
}
int
SSL_CTX_set_ex_data(ssl,idx,data)
SSL_CTX * ssl
int idx
void * data
int
SSL_CTX_set_purpose(s,purpose)
SSL_CTX * s
int purpose
void
SSL_CTX_set_quiet_shutdown(ctx,mode)
SSL_CTX * ctx
int mode
#if OPENSSL_VERSION_NUMBER < 0x10000000L
int
SSL_CTX_set_ssl_version(ctx,meth)
SSL_CTX * ctx
SSL_METHOD * meth
#else
int
SSL_CTX_set_ssl_version(ctx,meth)
SSL_CTX * ctx
const SSL_METHOD * meth
#endif
long
SSL_CTX_set_timeout(ctx,t)
SSL_CTX * ctx
long t
int
SSL_CTX_set_trust(s,trust)
SSL_CTX * s
int trust
void
SSL_CTX_set_verify_depth(ctx,depth)
SSL_CTX * ctx
int depth
int
SSL_CTX_use_certificate(ctx,x)
SSL_CTX * ctx
X509 * x
int
SSL_CTX_use_certificate_chain_file(ctx,file)
SSL_CTX * ctx
const char * file
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
int
SSL_use_certificate_chain_file(ssl,file)
SSL * ssl
const char * file
#endif /* OpenSSL 1.1.0 */
int
SSL_CTX_use_PrivateKey(ctx,pkey)
SSL_CTX * ctx
EVP_PKEY * pkey
int
SSL_CTX_use_RSAPrivateKey(ctx,rsa)
SSL_CTX * ctx
RSA * rsa
int
SSL_do_handshake(s)
SSL * s
SSL *
SSL_dup(ssl)
SSL * ssl
const SSL_CIPHER *
SSL_get_current_cipher(s)
SSL * s
long
SSL_get_default_timeout(s)
SSL * s
void *
SSL_get_ex_data(ssl,idx)
SSL * ssl
int idx
size_t
SSL_get_finished(ssl,buf,count=2*EVP_MAX_MD_SIZE)
SSL *ssl
SV *buf
size_t count
PREINIT:
unsigned char *finished;
size_t finished_len;
CODE:
Newx(finished, count, unsigned char);
finished_len = SSL_get_finished(ssl, finished, count);
if (count > finished_len)
count = finished_len;
sv_setpvn(buf, (const char *)finished, count);
Safefree(finished);
RETVAL = finished_len;
OUTPUT:
RETVAL
size_t
SSL_get_peer_finished(ssl,buf,count=2*EVP_MAX_MD_SIZE)
SSL *ssl
SV *buf
size_t count
PREINIT:
unsigned char *finished;
size_t finished_len;
CODE:
Newx(finished, count, unsigned char);
finished_len = SSL_get_peer_finished(ssl, finished, count);
if (count > finished_len)
count = finished_len;
sv_setpvn(buf, (const char *)finished, count);
Safefree(finished);
RETVAL = finished_len;
OUTPUT:
RETVAL
int
SSL_get_quiet_shutdown(ssl)
SSL * ssl
int
SSL_get_shutdown(ssl)
SSL * ssl
int
SSL_get_verify_depth(s)
SSL * s
int
SSL_get_verify_mode(s)
SSL * s
long
SSL_get_verify_result(ssl)
SSL * ssl
int
SSL_renegotiate(s)
SSL * s
#if OPENSSL_VERSION_NUMBER < 0x10000000L
int
SSL_SESSION_cmp(a,b)
SSL_SESSION * a
SSL_SESSION * b
#endif
void *
SSL_SESSION_get_ex_data(ss,idx)
SSL_SESSION * ss
int idx
long
SSL_SESSION_get_time(s)
SSL_SESSION * s
long
SSL_SESSION_get_timeout(s)
SSL_SESSION * s
int
SSL_SESSION_print_fp(fp,ses)
FILE * fp
SSL_SESSION * ses
int
SSL_SESSION_set_ex_data(ss,idx,data)
SSL_SESSION * ss
int idx
void * data
long
SSL_SESSION_set_time(s,t)
SSL_SESSION * s
long t
long
SSL_SESSION_set_timeout(s,t)
SSL_SESSION * s
long t
void
SSL_set_accept_state(s)
SSL * s
void
sk_X509_NAME_free(sk)
X509_NAME_STACK *sk
int
sk_X509_NAME_num(sk)
X509_NAME_STACK *sk
X509_NAME *
sk_X509_NAME_value(sk,i)
X509_NAME_STACK *sk
int i
X509_NAME_STACK *
SSL_get_client_CA_list(s)
SSL * s
void
SSL_set_client_CA_list(s,list)
SSL * s
X509_NAME_STACK * list
void
SSL_set_connect_state(s)
SSL * s
int
SSL_set_ex_data(ssl,idx,data)
SSL * ssl
int idx
void * data
void
SSL_set_info_callback(ssl,callback,data=&PL_sv_undef)
SSL * ssl
SV * callback
SV * data
CODE:
if (callback==NULL || !SvOK(callback)) {
SSL_set_info_callback(ssl, NULL);
cb_data_advanced_put(ssl, "ssleay_info_cb!!func", NULL);
cb_data_advanced_put(ssl, "ssleay_info_cb!!data", NULL);
} else {
cb_data_advanced_put(ssl, "ssleay_info_cb!!func", newSVsv(callback));
cb_data_advanced_put(ssl, "ssleay_info_cb!!data", newSVsv(data));
SSL_set_info_callback(ssl, ssleay_info_cb_invoke);
}
void
SSL_CTX_set_info_callback(ctx,callback,data=&PL_sv_undef)
SSL_CTX * ctx
SV * callback
SV * data
CODE:
if (callback==NULL || !SvOK(callback)) {
SSL_CTX_set_info_callback(ctx, NULL);
cb_data_advanced_put(ctx, "ssleay_ctx_info_cb!!func", NULL);
cb_data_advanced_put(ctx, "ssleay_ctx_info_cb!!data", NULL);
} else {
cb_data_advanced_put(ctx, "ssleay_ctx_info_cb!!func", newSVsv(callback));
cb_data_advanced_put(ctx, "ssleay_ctx_info_cb!!data", newSVsv(data));
SSL_CTX_set_info_callback(ctx, ssleay_ctx_info_cb_invoke);
}
int
SSL_set_purpose(s,purpose)
SSL * s
int purpose
void
SSL_set_quiet_shutdown(ssl,mode)
SSL * ssl
int mode
void
SSL_set_shutdown(ssl,mode)
SSL * ssl
int mode
int
SSL_set_trust(s,trust)
SSL * s
int trust
void
SSL_set_verify_depth(s,depth)
SSL * s
int depth
void
SSL_set_verify_result(ssl,v)
SSL * ssl
long v
int
SSL_shutdown(s)
SSL * s
int
SSL_version(ssl)
SSL * ssl
#define REM_MANUALLY_ADDED_1_09
X509_NAME_STACK *
SSL_load_client_CA_file(file)
const char * file
int
SSL_add_file_cert_subjects_to_stack(stackCAs,file)
X509_NAME_STACK * stackCAs
const char * file
#ifndef WIN32
#ifndef VMS
#ifndef MAC_OS_pre_X
int
SSL_add_dir_cert_subjects_to_stack(stackCAs,dir)
X509_NAME_STACK * stackCAs
const char * dir
#endif
#endif
#endif
int
SSL_CTX_get_ex_new_index(argl,argp=NULL,new_func=NULL,dup_func=NULL,free_func=NULL)
long argl
void * argp
CRYPTO_EX_new * new_func
CRYPTO_EX_dup * dup_func
CRYPTO_EX_free * free_func
int
SSL_CTX_set_session_id_context(ctx,sid_ctx,sid_ctx_len)
SSL_CTX * ctx
const unsigned char * sid_ctx
unsigned int sid_ctx_len
int
SSL_set_session_id_context(ssl,sid_ctx,sid_ctx_len)
SSL * ssl
const unsigned char * sid_ctx
unsigned int sid_ctx_len
#if OPENSSL_VERSION_NUMBER < 0x10100000L
void
SSL_CTX_set_tmp_rsa_callback(ctx, cb)
SSL_CTX * ctx
cb_ssl_int_int_ret_RSA * cb
void
SSL_set_tmp_rsa_callback(ssl, cb)
SSL * ssl
cb_ssl_int_int_ret_RSA * cb
#endif
void
SSL_CTX_set_tmp_dh_callback(ctx, dh)
SSL_CTX * ctx
cb_ssl_int_int_ret_DH * dh
void
SSL_set_tmp_dh_callback(ssl,dh)
SSL * ssl
cb_ssl_int_int_ret_DH * dh
int
SSL_get_ex_new_index(argl,argp=NULL,new_func=NULL,dup_func=NULL,free_func=NULL)
long argl
void * argp
CRYPTO_EX_new * new_func
CRYPTO_EX_dup * dup_func
CRYPTO_EX_free * free_func
int
SSL_SESSION_get_ex_new_index(argl,argp=NULL,new_func=NULL,dup_func=NULL,free_func=NULL)
long argl
void * argp
CRYPTO_EX_new * new_func
CRYPTO_EX_dup * dup_func
CRYPTO_EX_free * free_func
#define REM_SEMIAUTOMATIC_MACRO_GEN_1_09
long
SSL_clear_num_renegotiations(ssl)
SSL * ssl
CODE:
RETVAL = SSL_ctrl(ssl,SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS,0,NULL);
OUTPUT:
RETVAL
long
SSL_CTX_add_extra_chain_cert(ctx,x509)
SSL_CTX * ctx
X509 * x509
CODE:
RETVAL = SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char*)x509);
OUTPUT:
RETVAL
void *
SSL_CTX_get_app_data(ctx)
SSL_CTX * ctx
CODE:
RETVAL = SSL_CTX_get_ex_data(ctx,0);
OUTPUT:
RETVAL
long
SSL_CTX_get_mode(ctx)
SSL_CTX * ctx
CODE:
RETVAL = SSL_CTX_ctrl(ctx,SSL_CTRL_MODE,0,NULL);
OUTPUT:
RETVAL
long
SSL_CTX_get_read_ahead(ctx)
SSL_CTX * ctx
CODE:
RETVAL = SSL_CTX_ctrl(ctx,SSL_CTRL_GET_READ_AHEAD,0,NULL);
OUTPUT:
RETVAL
long
SSL_CTX_get_session_cache_mode(ctx)
SSL_CTX * ctx
CODE:
RETVAL = SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_MODE,0,NULL);
OUTPUT:
RETVAL
#if OPENSSL_VERSION_NUMBER < 0x10100000L
long
SSL_CTX_need_tmp_RSA(ctx)
SSL_CTX * ctx
CODE:
RETVAL = SSL_CTX_ctrl(ctx,SSL_CTRL_NEED_TMP_RSA,0,NULL);
OUTPUT:
RETVAL
#endif
int
SSL_CTX_set_app_data(ctx,arg)
SSL_CTX * ctx
char * arg
CODE:
RETVAL = SSL_CTX_set_ex_data(ctx,0,arg);
OUTPUT:
RETVAL
long
SSL_CTX_set_mode(ctx,op)
SSL_CTX * ctx
long op
CODE:
RETVAL = SSL_CTX_ctrl(ctx,SSL_CTRL_MODE,op,NULL);
OUTPUT:
RETVAL
long
SSL_CTX_set_read_ahead(ctx,m)
SSL_CTX * ctx
long m
CODE:
RETVAL = SSL_CTX_ctrl(ctx,SSL_CTRL_SET_READ_AHEAD,m,NULL);
OUTPUT:
RETVAL
long
SSL_CTX_set_session_cache_mode(ctx,m)
SSL_CTX * ctx
long m
CODE:
RETVAL = SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL);
OUTPUT:
RETVAL
long
SSL_CTX_set_tmp_dh(ctx,dh)
SSL_CTX * ctx
DH * dh
#if OPENSSL_VERSION_NUMBER < 0x10100000L
long
SSL_CTX_set_tmp_rsa(ctx,rsa)
SSL_CTX * ctx
RSA * rsa
#endif
#if OPENSSL_VERSION_NUMBER > 0x10000000L && !defined OPENSSL_NO_EC
EC_KEY *
EC_KEY_new_by_curve_name(nid)
int nid
void
EC_KEY_free(key)
EC_KEY * key
long
SSL_CTX_set_tmp_ecdh(ctx,ecdh)
SSL_CTX * ctx
EC_KEY * ecdh
int
EVP_PKEY_assign_EC_KEY(pkey,key)
EVP_PKEY * pkey
EC_KEY * key
EC_KEY *
EC_KEY_generate_key(curve)
SV *curve;
CODE:
EC_GROUP *group = NULL;
EC_KEY *eckey = NULL;
int nid;
RETVAL = 0;
if (SvIOK(curve)) {
nid = SvIV(curve);
} else {
nid = OBJ_sn2nid(SvPV_nolen(curve));
#if OPENSSL_VERSION_NUMBER > 0x10002000L
if (!nid) nid = EC_curve_nist2nid(SvPV_nolen(curve));
#endif
if (!nid) croak("unknown curve %s",SvPV_nolen(curve));
}
group = EC_GROUP_new_by_curve_name(nid);
if (!group) croak("unknown curve nid=%d",nid);
EC_GROUP_set_asn1_flag(group,OPENSSL_EC_NAMED_CURVE);
eckey = EC_KEY_new();
if ( eckey
&& EC_KEY_set_group(eckey, group)
&& EC_KEY_generate_key(eckey)) {
RETVAL = eckey;
} else {
if (eckey) EC_KEY_free(eckey);
}
if (group) EC_GROUP_free(group);
OUTPUT:
RETVAL
#endif
void *
SSL_get_app_data(s)
SSL * s
CODE:
RETVAL = SSL_get_ex_data(s,0);
OUTPUT:
RETVAL
int
SSL_get_cipher_bits(s,np=NULL)
SSL * s
int * np
CODE:
RETVAL = SSL_CIPHER_get_bits(SSL_get_current_cipher(s),np);
OUTPUT:
RETVAL
long
SSL_get_mode(ssl)
SSL * ssl
CODE:
RETVAL = SSL_ctrl(ssl,SSL_CTRL_MODE,0,NULL);
OUTPUT:
RETVAL
void
SSL_set_state(ssl,state)
SSL * ssl
int state
CODE:
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
/* not available */
#elif defined(OPENSSL_NO_SSL_INTERN)
SSL_set_state(ssl,state);
#else
ssl->state = state;
#endif
#if OPENSSL_VERSION_NUMBER < 0x10100000L
long
SSL_need_tmp_RSA(ssl)
SSL * ssl
CODE:
RETVAL = SSL_ctrl(ssl,SSL_CTRL_NEED_TMP_RSA,0,NULL);
OUTPUT:
RETVAL
#endif
long
SSL_num_renegotiations(ssl)
SSL * ssl
CODE:
RETVAL = SSL_ctrl(ssl,SSL_CTRL_GET_NUM_RENEGOTIATIONS,0,NULL);
OUTPUT:
RETVAL
void *
SSL_SESSION_get_app_data(ses)
SSL_SESSION * ses
CODE:
RETVAL = SSL_SESSION_get_ex_data(ses,0);
OUTPUT:
RETVAL
long
SSL_session_reused(ssl)
SSL * ssl
int
SSL_SESSION_set_app_data(s,a)
SSL_SESSION * s
void * a
CODE:
RETVAL = SSL_SESSION_set_ex_data(s,0,(char *)a);
OUTPUT:
RETVAL
int
SSL_set_app_data(s,arg)
SSL * s
void * arg
CODE:
RETVAL = SSL_set_ex_data(s,0,(char *)arg);
OUTPUT:
RETVAL
long
SSL_set_mode(ssl,op)
SSL * ssl
long op
CODE:
RETVAL = SSL_ctrl(ssl,SSL_CTRL_MODE,op,NULL);
OUTPUT:
RETVAL
int
SSL_set_pref_cipher(s,n)
SSL * s
const char * n
CODE:
RETVAL = SSL_set_cipher_list(s,n);
OUTPUT:
RETVAL
long
SSL_set_tmp_dh(ssl,dh)
SSL * ssl
DH * dh
#if OPENSSL_VERSION_NUMBER < 0x10100000L
long
SSL_set_tmp_rsa(ssl,rsa)
SSL * ssl
char * rsa
CODE:
RETVAL = SSL_ctrl(ssl,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa);
OUTPUT:
RETVAL
#endif
#ifdef __ANDROID__
RSA *
RSA_generate_key(bits,ee,perl_cb=&PL_sv_undef,perl_data=&PL_sv_undef)
int bits
unsigned long ee
SV* perl_cb
SV* perl_data
PREINIT:
simple_cb_data_t* cb_data = NULL;
CODE:
/* Android does not have RSA_generate_key. This equivalent is contributed by Brian Fraser for Android */
/* but is not portable to old OpenSSLs where RSA_generate_key_ex is not available */
int rc;
RSA * ret;
BIGNUM *e;
e = BN_new();
BN_set_word(e, ee);
cb_data = simple_cb_data_new(perl_cb, perl_data);
BN_GENCB new_cb;
BN_GENCB_set_old(&new_cb, ssleay_RSA_generate_key_cb_invoke, cb_data);
ret = RSA_new();
rc = RSA_generate_key_ex(ret, bits, e, &new_cb);
if (rc == -1 || ret == NULL)
croak("Couldn't generate RSA key");
simple_cb_data_free(cb_data);
BN_free(e);
e = NULL;
RETVAL = ret;
OUTPUT:
RETVAL
#else
RSA *
RSA_generate_key(bits,e,perl_cb=&PL_sv_undef,perl_data=&PL_sv_undef)
int bits
unsigned long e
SV* perl_cb
SV* perl_data
PREINIT:
simple_cb_data_t* cb = NULL;
CODE:
cb = simple_cb_data_new(perl_cb, perl_data);
RETVAL = RSA_generate_key(bits, e, ssleay_RSA_generate_key_cb_invoke, cb);
simple_cb_data_free(cb);
OUTPUT:
RETVAL
#endif
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
void
RSA_get_key_parameters(rsa)
RSA * rsa
PPCODE:
{
/* Caution: returned list consists of SV pointers to BIGNUMs, which would need to be blessed as Crypt::OpenSSL::Bignum for further use */
XPUSHs(bn2sv(rsa->n));
XPUSHs(bn2sv(rsa->e));
XPUSHs(bn2sv(rsa->d));
XPUSHs(bn2sv(rsa->p));
XPUSHs(bn2sv(rsa->q));
XPUSHs(bn2sv(rsa->dmp1));
XPUSHs(bn2sv(rsa->dmq1));
XPUSHs(bn2sv(rsa->iqmp));
}
#endif
void
RSA_free(r)
RSA * r
X509 *
X509_new()
void
X509_free(a)
X509 * a
X509_CRL *
d2i_X509_CRL_bio(BIO *bp,void *unused=NULL)
X509_REQ *
d2i_X509_REQ_bio(BIO *bp,void *unused=NULL)
X509 *
d2i_X509_bio(BIO *bp,void *unused=NULL)
DH *
PEM_read_bio_DHparams(bio,x=NULL,cb=NULL,u=NULL)
BIO * bio
void * x
pem_password_cb * cb
void * u
X509_CRL *
PEM_read_bio_X509_CRL(bio,x=NULL,cb=NULL,u=NULL)
BIO * bio
void * x
pem_password_cb * cb
void * u
X509 *
PEM_read_bio_X509(BIO *bio,void *x=NULL,void *cb=NULL,void *u=NULL)
X509_REQ *
PEM_read_bio_X509_REQ(BIO *bio,void *x=NULL,pem_password_cb *cb=NULL,void *u=NULL)
EVP_PKEY *
PEM_read_bio_PrivateKey(bio,perl_cb=&PL_sv_undef,perl_data=&PL_sv_undef)
BIO *bio
SV* perl_cb
SV* perl_data
PREINIT:
simple_cb_data_t* cb = NULL;
CODE:
RETVAL = 0;
if (SvOK(perl_cb)) {
/* setup our callback */
cb = simple_cb_data_new(perl_cb, perl_data);
RETVAL = PEM_read_bio_PrivateKey(bio, NULL, pem_password_cb_invoke, (void*)cb);
simple_cb_data_free(cb);
}
else if (!SvOK(perl_cb) && SvOK(perl_data) && SvPOK(perl_data)) {
/* use perl_data as the password */
RETVAL = PEM_read_bio_PrivateKey(bio, NULL, NULL, SvPVX(perl_data));
}
else if (!SvOK(perl_cb) && !SvOK(perl_data)) {
/* will trigger default password callback */
RETVAL = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
}
OUTPUT:
RETVAL
void
DH_free(dh)
DH * dh
long
SSL_total_renegotiations(ssl)
SSL * ssl
CODE:
RETVAL = SSL_ctrl(ssl,SSL_CTRL_GET_TOTAL_RENEGOTIATIONS,0,NULL);
OUTPUT:
RETVAL
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
void
SSL_SESSION_get_master_key(s)
SSL_SESSION * s
PREINIT:
size_t master_key_length;
unsigned char* master_key;
CODE:
ST(0) = sv_newmortal(); /* Undefined to start with */
master_key_length = SSL_SESSION_get_master_key(s, 0, 0); /* get the length */
New(0, master_key, master_key_length, unsigned char);
SSL_SESSION_get_master_key(s, master_key, master_key_length);
sv_setpvn(ST(0), (const char*)master_key, master_key_length);
Safefree(master_key);
#else
void
SSL_SESSION_get_master_key(s)
SSL_SESSION * s
CODE:
ST(0) = sv_newmortal(); /* Undefined to start with */
sv_setpvn(ST(0), (const char*)s->master_key, s->master_key_length);
#endif
#if OPENSSL_VERSION_NUMBER < 0x10100000L
void
SSL_SESSION_set_master_key(s,key)
SSL_SESSION * s
PREINIT:
STRLEN len;
INPUT:
char * key = SvPV(ST(1), len);
CODE:
memcpy(s->master_key, key, len);
s->master_key_length = len;
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
void
SSL_get_client_random(s)
SSL * s
PREINIT:
size_t random_length;
unsigned char* random_data;
CODE:
ST(0) = sv_newmortal(); /* Undefined to start with */
random_length = SSL_get_client_random(s, 0, 0); /* get the length */
New(0, random_data, random_length, unsigned char);
SSL_get_client_random(s, random_data, random_length);
sv_setpvn(ST(0), (const char*)random_data, random_length);
Safefree(random_data);
#else
void
SSL_get_client_random(s)
SSL * s
CODE:
ST(0) = sv_newmortal(); /* Undefined to start with */
sv_setpvn(ST(0), (const char*)s->s3->client_random, SSL3_RANDOM_SIZE);
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
void
SSL_get_server_random(s)
SSL * s
PREINIT:
size_t random_length;
unsigned char* random_data;
CODE:
ST(0) = sv_newmortal(); /* Undefined to start with */
random_length = SSL_get_server_random(s, 0, 0); /* get the length */
New(0, random_data, random_length, unsigned char);
SSL_get_server_random(s, random_data, random_length);
sv_setpvn(ST(0), (const char*)random_data, random_length);
Safefree(random_data);
#else
void
SSL_get_server_random(s)
SSL * s
CODE:
ST(0) = sv_newmortal(); /* Undefined to start with */
sv_setpvn(ST(0), (const char*)s->s3->server_random, SSL3_RANDOM_SIZE);
#endif
int
SSL_get_keyblock_size(s)
SSL * s
CODE:
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
const SSL_CIPHER *ssl_cipher;
int cipher = NID_undef, digest = NID_undef, mac_secret_size = 0;
const EVP_CIPHER *c = NULL;
const EVP_MD *h = NULL;
ssl_cipher = SSL_get_current_cipher(s);
if (ssl_cipher)
cipher = SSL_CIPHER_get_cipher_nid(ssl_cipher);
if (cipher != NID_undef)
c = EVP_get_cipherbynid(cipher);
if (ssl_cipher)
digest = SSL_CIPHER_get_digest_nid(ssl_cipher);
if (digest != NID_undef) /* No digest if e.g., AEAD cipher */
h = EVP_get_digestbynid(digest);
if (h)
mac_secret_size = EVP_MD_size(h);
RETVAL = -1;
if (c)
RETVAL = 2 * (EVP_CIPHER_key_length(c) + mac_secret_size +
EVP_CIPHER_iv_length(c));
#else
if (s == NULL ||
s->enc_read_ctx == NULL ||
s->enc_read_ctx->cipher == NULL ||
s->read_hash == NULL)
{
RETVAL = -1;
}
else
{
const EVP_CIPHER *c;
const EVP_MD *h;
int md_size = -1;
c = s->enc_read_ctx->cipher;
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
if (s->s3)
md_size = s->s3->tmp.new_mac_secret_size;
#elif OPENSSL_VERSION_NUMBER >= 0x00909000L
h = EVP_MD_CTX_md(s->read_hash);
md_size = EVP_MD_size(h);
#else
h = s->read_hash;
md_size = EVP_MD_size(h);
#endif
/* No digest if e.g., AEAD cipher */
RETVAL = (md_size >= 0) ? (2 * (EVP_CIPHER_key_length(c) +
md_size +
EVP_CIPHER_iv_length(c)))
: -1;
}
#endif
OUTPUT:
RETVAL
#if defined(SSL_F_SSL_SET_HELLO_EXTENSION)
int
SSL_set_hello_extension(s, type, data)
SSL * s
int type
PREINIT:
STRLEN len;
INPUT:
char * data = SvPV( ST(2), len);
CODE:
RETVAL = SSL_set_hello_extension(s, type, data, len);
OUTPUT:
RETVAL
#endif
#if defined(SSL_F_SSL_SET_HELLO_EXTENSION) || defined(SSL_F_SSL_SET_SESSION_TICKET_EXT)
void
SSL_set_session_secret_cb(s,callback=&PL_sv_undef,data=&PL_sv_undef)
SSL * s
SV * callback
SV * data
CODE:
if (callback==NULL || !SvOK(callback)) {
SSL_set_session_secret_cb(s, NULL, NULL);
cb_data_advanced_put(s, "ssleay_session_secret_cb!!func", NULL);
cb_data_advanced_put(s, "ssleay_session_secret_cb!!data", NULL);
}
else {
cb_data_advanced_put(s, "ssleay_session_secret_cb!!func", newSVsv(callback));
cb_data_advanced_put(s, "ssleay_session_secret_cb!!data", newSVsv(data));
SSL_set_session_secret_cb(s, (tls_session_secret_cb_fn)&ssleay_session_secret_cb_invoke, s);
}
#endif
#ifdef NET_SSLEAY_CAN_PSK_CLIENT_CALLBACK
void
SSL_set_psk_client_callback(s,callback=&PL_sv_undef)
SSL * s
SV * callback
CODE:
if (callback==NULL || !SvOK(callback)) {
SSL_set_psk_client_callback(s, NULL);
cb_data_advanced_put(s, "ssleay_set_psk_client_callback!!func", NULL);
}
else {
cb_data_advanced_put(s, "ssleay_set_psk_client_callback!!func", newSVsv(callback));
SSL_set_psk_client_callback(s, ssleay_set_psk_client_callback_invoke);
}
void
SSL_CTX_set_psk_client_callback(ctx,callback=&PL_sv_undef)
SSL_CTX * ctx
SV * callback
CODE:
if (callback==NULL || !SvOK(callback)) {
SSL_CTX_set_psk_client_callback(ctx, NULL);
cb_data_advanced_put(ctx, "ssleay_ctx_set_psk_client_callback!!func", NULL);
}
else {
cb_data_advanced_put(ctx, "ssleay_ctx_set_psk_client_callback!!func", newSVsv(callback));
SSL_CTX_set_psk_client_callback(ctx, ssleay_ctx_set_psk_client_callback_invoke);
}
#endif
#ifdef NET_SSLEAY_CAN_TICKET_KEY_CB
void
SSL_CTX_set_tlsext_ticket_getkey_cb(ctx,callback=&PL_sv_undef,data=&PL_sv_undef)
SSL_CTX * ctx
SV * callback
SV * data
CODE:
if (callback==NULL || !SvOK(callback)) {
SSL_CTX_set_tlsext_ticket_key_cb(ctx, NULL);
cb_data_advanced_put(ctx, "tlsext_ticket_key_cb!!func", NULL);
cb_data_advanced_put(ctx, "tlsext_ticket_key_cb!!data", NULL);
}
else {
cb_data_advanced_put(ctx, "tlsext_ticket_key_cb!!func", newSVsv(callback));
cb_data_advanced_put(ctx, "tlsext_ticket_key_cb!!data", newSVsv(data));
SSL_CTX_set_tlsext_ticket_key_cb(ctx, &tlsext_ticket_key_cb_invoke);
}
#endif
#if OPENSSL_VERSION_NUMBER < 0x0090700fL
#define REM11 "NOTE: before 0.9.7"
int EVP_add_digest(EVP_MD *digest)
#else
int EVP_add_digest(const EVP_MD *digest)
#endif
#ifndef OPENSSL_NO_SHA
const EVP_MD *EVP_sha1()
#endif
#if !defined(OPENSSL_NO_SHA256) && OPENSSL_VERSION_NUMBER >= 0x0090800fL
const EVP_MD *EVP_sha256()
#endif
#if !defined(OPENSSL_NO_SHA512) && OPENSSL_VERSION_NUMBER >= 0x0090800fL
const EVP_MD *EVP_sha512()
#endif
void OpenSSL_add_all_digests()
const EVP_MD * EVP_get_digestbyname(const char *name)
int EVP_MD_type(const EVP_MD *md)
int EVP_MD_size(const EVP_MD *md)
#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
SV*
P_EVP_MD_list_all()
INIT:
AV * results;
CODE:
results = (AV *)sv_2mortal((SV *)newAV());
EVP_MD_do_all_sorted(handler_list_md_fn, results);
RETVAL = newRV((SV *)results);
OUTPUT:
RETVAL
#endif
#if OPENSSL_VERSION_NUMBER >= 0x0090700fL
#define REM16 "NOTE: requires 0.9.7+"
const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx)
EVP_MD_CTX *EVP_MD_CTX_create()
int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type)
int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx)
void
EVP_DigestUpdate(ctx,data)
PREINIT:
STRLEN len;
INPUT:
EVP_MD_CTX *ctx = INT2PTR(EVP_MD_CTX *, SvIV(ST(0)));
unsigned char *data = (unsigned char *) SvPV(ST(1), len);
CODE:
XSRETURN_IV(EVP_DigestUpdate(ctx,data,len));
void
EVP_DigestFinal(ctx)
EVP_MD_CTX *ctx
INIT:
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int md_size;
CODE:
if (EVP_DigestFinal(ctx,md,&md_size))
XSRETURN_PVN((char *)md, md_size);
else
XSRETURN_UNDEF;
void
EVP_DigestFinal_ex(ctx)
EVP_MD_CTX *ctx
INIT:
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int md_size;
CODE:
if (EVP_DigestFinal_ex(ctx,md,&md_size))
XSRETURN_PVN((char *)md, md_size);
else
XSRETURN_UNDEF;
void
EVP_Digest(...)
PREINIT:
STRLEN len;
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int md_size;
INPUT:
unsigned char *data = (unsigned char *) SvPV(ST(0), len);
EVP_MD *type = INT2PTR(EVP_MD *, SvIV(ST(1)));
ENGINE *impl = (items>2 && SvOK(ST(2))) ? INT2PTR(ENGINE *, SvIV(ST(2))) : NULL;
CODE:
if (EVP_Digest(data,len,md,&md_size,type,impl))
XSRETURN_PVN((char *)md, md_size);
else
XSRETURN_UNDEF;
#endif
const EVP_CIPHER *
EVP_get_cipherbyname(const char *name)
void
OpenSSL_add_all_algorithms()
#if OPENSSL_VERSION_NUMBER >= 0x0090700fL
void
OPENSSL_add_all_algorithms_noconf()
void
OPENSSL_add_all_algorithms_conf()
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
int
SSL_CTX_set1_param(ctx, vpm)
SSL_CTX * ctx
X509_VERIFY_PARAM *vpm
int
SSL_set1_param(ctx, vpm)
SSL * ctx
X509_VERIFY_PARAM *vpm
#endif
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
X509_VERIFY_PARAM *
X509_VERIFY_PARAM_new()
void
X509_VERIFY_PARAM_free(param)
X509_VERIFY_PARAM *param
int
X509_VERIFY_PARAM_inherit(to, from)
X509_VERIFY_PARAM *to
X509_VERIFY_PARAM *from
int
X509_VERIFY_PARAM_set1(to, from)
X509_VERIFY_PARAM *to
X509_VERIFY_PARAM *from
int
X509_VERIFY_PARAM_set1_name(param, name)
X509_VERIFY_PARAM *param
const char *name
int
X509_VERIFY_PARAM_set_flags(param, flags)
X509_VERIFY_PARAM *param
unsigned long flags
#if OPENSSL_VERSION_NUMBER >= 0x0090801fL
#define REM13 "NOTE: requires 0.9.8a+"
int
X509_VERIFY_PARAM_clear_flags(param, flags)
X509_VERIFY_PARAM *param
unsigned long flags
unsigned long
X509_VERIFY_PARAM_get_flags(param)
X509_VERIFY_PARAM *param
#endif
int
X509_VERIFY_PARAM_set_purpose(param, purpose)
X509_VERIFY_PARAM *param
int purpose
int
X509_VERIFY_PARAM_set_trust(param, trust)
X509_VERIFY_PARAM *param
int trust
void
X509_VERIFY_PARAM_set_depth(param, depth)
X509_VERIFY_PARAM *param
int depth
void
X509_VERIFY_PARAM_set_time(param, t)
X509_VERIFY_PARAM *param
time_t t
int
X509_VERIFY_PARAM_add0_policy(param, policy)
X509_VERIFY_PARAM *param
ASN1_OBJECT *policy
int
X509_VERIFY_PARAM_set1_policies(param, policies)
X509_VERIFY_PARAM *param
STACK_OF(ASN1_OBJECT) *policies
int
X509_VERIFY_PARAM_get_depth(param)
X509_VERIFY_PARAM *param
int
X509_VERIFY_PARAM_add0_table(param)
X509_VERIFY_PARAM *param
const X509_VERIFY_PARAM *
X509_VERIFY_PARAM_lookup(name)
const char *name
void
X509_VERIFY_PARAM_table_cleanup()
#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER) /* OpenSSL 1.0.2 */
X509_VERIFY_PARAM *
SSL_CTX_get0_param(ctx)
SSL_CTX * ctx
X509_VERIFY_PARAM *
SSL_get0_param(ssl)
SSL * ssl
int
X509_VERIFY_PARAM_set1_host(param, name)
X509_VERIFY_PARAM *param
PREINIT:
STRLEN namelen;
INPUT:
const char * name = SvPV(ST(1), namelen);
CODE:
RETVAL = X509_VERIFY_PARAM_set1_host(param, name, namelen);
OUTPUT:
RETVAL
int
X509_VERIFY_PARAM_add1_host(param, name)
X509_VERIFY_PARAM *param
PREINIT:
STRLEN namelen;
INPUT:
const char * name = SvPV(ST(1), namelen);
CODE:
RETVAL = X509_VERIFY_PARAM_add1_host(param, name, namelen);
OUTPUT:
RETVAL
void
X509_VERIFY_PARAM_set_hostflags(param, flags)
X509_VERIFY_PARAM *param
unsigned int flags
char *
X509_VERIFY_PARAM_get0_peername(param)
X509_VERIFY_PARAM *param
int
X509_VERIFY_PARAM_set1_email(param, email)
X509_VERIFY_PARAM *param
PREINIT:
STRLEN emaillen;
INPUT:
const char * email = SvPV(ST(1), emaillen);
CODE:
RETVAL = X509_VERIFY_PARAM_set1_email(param, email, emaillen);
OUTPUT:
RETVAL
int
X509_VERIFY_PARAM_set1_ip(param, ip)
X509_VERIFY_PARAM *param
PREINIT:
STRLEN iplen;
INPUT:
const unsigned char * ip = (const unsigned char *)SvPV(ST(1), iplen);
CODE:
RETVAL = X509_VERIFY_PARAM_set1_ip(param, ip, iplen);
OUTPUT:
RETVAL
int
X509_VERIFY_PARAM_set1_ip_asc(param, ipasc)
X509_VERIFY_PARAM *param
const char *ipasc
#endif /* OpenSSL 1.0.2 */
void
X509_policy_tree_free(tree)
X509_POLICY_TREE *tree
int
X509_policy_tree_level_count(tree)
X509_POLICY_TREE *tree
X509_POLICY_LEVEL *
X509_policy_tree_get0_level(tree, i)
X509_POLICY_TREE *tree
int i
STACK_OF(X509_POLICY_NODE) *
X509_policy_tree_get0_policies(tree)
X509_POLICY_TREE *tree
STACK_OF(X509_POLICY_NODE) *
X509_policy_tree_get0_user_policies(tree)
X509_POLICY_TREE *tree
int
X509_policy_level_node_count(level)
X509_POLICY_LEVEL *level
X509_POLICY_NODE *
X509_policy_level_get0_node(level, i)
X509_POLICY_LEVEL *level
int i
const ASN1_OBJECT *
X509_policy_node_get0_policy(node)
const X509_POLICY_NODE *node
STACK_OF(POLICYQUALINFO) *
X509_policy_node_get0_qualifiers(node)
X509_POLICY_NODE *node
const X509_POLICY_NODE *
X509_policy_node_get0_parent(node)
const X509_POLICY_NODE *node
#endif
ASN1_OBJECT *
OBJ_dup(o)
ASN1_OBJECT *o
ASN1_OBJECT *
OBJ_nid2obj(n)
int n
const char *
OBJ_nid2ln(n)
int n
const char *
OBJ_nid2sn(n)
int n
int
OBJ_obj2nid(o)
ASN1_OBJECT *o
ASN1_OBJECT *
OBJ_txt2obj(s, no_name=0)
const char *s
int no_name
void
OBJ_obj2txt(a, no_name=0)
ASN1_OBJECT *a
int no_name
PREINIT:
char buf[100]; /* openssl doc: a buffer length of 80 should be more than enough to handle any OID encountered in practice */
int len;
CODE:
len = OBJ_obj2txt(buf, sizeof(buf), a, no_name);
ST(0) = sv_newmortal();
sv_setpvn(ST(0), buf, len);
#if OPENSSL_VERSION_NUMBER < 0x0090700fL
#define REM14 "NOTE: before 0.9.7"
int
OBJ_txt2nid(s)
char *s
#else
int
OBJ_txt2nid(s)
const char *s
#endif
int
OBJ_ln2nid(s)
const char *s
int
OBJ_sn2nid(s)
const char *s
int
OBJ_cmp(a, b)
ASN1_OBJECT *a
ASN1_OBJECT *b
#if OPENSSL_VERSION_NUMBER >= 0x0090700fL
void
X509_pubkey_digest(data,type)
const X509 *data
const EVP_MD *type
PREINIT:
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int md_size;
PPCODE:
if (X509_pubkey_digest(data,type,md,&md_size))
XSRETURN_PVN((char *)md, md_size);
else
XSRETURN_UNDEF;
#endif
void
X509_digest(data,type)
const X509 *data
const EVP_MD *type
PREINIT:
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int md_size;
PPCODE:
if (X509_digest(data,type,md,&md_size))
XSRETURN_PVN((char *)md, md_size);
XSRETURN_UNDEF;
void
X509_CRL_digest(data,type)
const X509_CRL *data
const EVP_MD *type
PREINIT:
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int md_size;
PPCODE:
if (X509_CRL_digest(data,type,md,&md_size))
XSRETURN_PVN((char *)md, md_size);
XSRETURN_UNDEF;
void
X509_REQ_digest(data,type)
const X509_REQ *data
const EVP_MD *type
PREINIT:
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int md_size;
PPCODE:
if (X509_REQ_digest(data,type,md,&md_size))
XSRETURN_PVN((char *)md, md_size);
XSRETURN_UNDEF;
void
X509_NAME_digest(data,type)
const X509_NAME *data
const EVP_MD *type
PREINIT:
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int md_size;
PPCODE:
if (X509_NAME_digest(data,type,md,&md_size))
XSRETURN_PVN((char *)md, md_size);
XSRETURN_UNDEF;
unsigned long
X509_subject_name_hash(X509 *x)
unsigned long
X509_issuer_name_hash(X509 *a)
unsigned long
X509_issuer_and_serial_hash(X509 *a)
ASN1_OBJECT *
P_X509_get_signature_alg(x)
X509 * x
CODE:
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
RETVAL = (X509_get0_tbs_sigalg(x)->algorithm);
#else
RETVAL = (x->cert_info->signature->algorithm);
#endif
OUTPUT:
RETVAL
ASN1_OBJECT *
P_X509_get_pubkey_alg(x)
X509 * x
PREINIT:
CODE:
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
{
X509_ALGOR * algor;
X509_PUBKEY_get0_param(0, 0, 0, &algor, X509_get_X509_PUBKEY(x));
RETVAL = (algor->algorithm);
}
#else
RETVAL = (x->cert_info->key->algor->algorithm);
#endif
OUTPUT:
RETVAL
void
X509_get_X509_PUBKEY(x)
const X509 *x
PPCODE:
X509_PUBKEY *pkey;
STRLEN len;
unsigned char *pc, *pi;
if (!(pkey = X509_get_X509_PUBKEY(x))) croak("invalid certificate");
if (!(len = i2d_X509_PUBKEY(pkey, NULL))) croak("invalid certificate public key");
Newx(pc,len,unsigned char);
if (!pc) croak("out of memory");
pi = pc;
i2d_X509_PUBKEY(pkey, &pi);
if (pi-pc != len) croak("invalid encoded length");
XPUSHs(sv_2mortal(newSVpv((char*)pc,len)));
Safefree(pc);
#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_NEXTPROTONEG) && !defined(LIBRESSL_VERSION_NUMBER)
int
SSL_CTX_set_next_protos_advertised_cb(ctx,callback,data=&PL_sv_undef)
SSL_CTX * ctx
SV * callback
SV * data
CODE:
RETVAL = 1;
if (callback==NULL || !SvOK(callback)) {
SSL_CTX_set_next_protos_advertised_cb(ctx, NULL, NULL);
cb_data_advanced_put(ctx, "next_protos_advertised_cb!!func", NULL);
cb_data_advanced_put(ctx, "next_protos_advertised_cb!!data", NULL);
PR1("SSL_CTX_set_next_protos_advertised_cb - undef\n");
}
else if (SvROK(callback) && (SvTYPE(SvRV(callback)) == SVt_PVAV)) {
/* callback param array ref like ['proto1','proto2'] */
cb_data_advanced_put(ctx, "next_protos_advertised_cb!!func", NULL);
cb_data_advanced_put(ctx, "next_protos_advertised_cb!!data", newSVsv(callback));
SSL_CTX_set_next_protos_advertised_cb(ctx, next_protos_advertised_cb_invoke, ctx);
PR2("SSL_CTX_set_next_protos_advertised_cb - simple ctx=%p\n",ctx);
}
else if (SvROK(callback) && (SvTYPE(SvRV(callback)) == SVt_PVCV)) {
cb_data_advanced_put(ctx, "next_protos_advertised_cb!!func", newSVsv(callback));
cb_data_advanced_put(ctx, "next_protos_advertised_cb!!data", newSVsv(data));
SSL_CTX_set_next_protos_advertised_cb(ctx, next_protos_advertised_cb_invoke, ctx);
PR2("SSL_CTX_set_next_protos_advertised_cb - advanced ctx=%p\n",ctx);
}
else {
RETVAL = 0;
}
OUTPUT:
RETVAL
int
SSL_CTX_set_next_proto_select_cb(ctx,callback,data=&PL_sv_undef)
SSL_CTX * ctx
SV * callback
SV * data
CODE:
RETVAL = 1;
if (callback==NULL || !SvOK(callback)) {
SSL_CTX_set_next_proto_select_cb(ctx, NULL, NULL);
cb_data_advanced_put(ctx, "next_proto_select_cb!!func", NULL);
cb_data_advanced_put(ctx, "next_proto_select_cb!!data", NULL);
PR1("SSL_CTX_set_next_proto_select_cb - undef\n");
}
else if (SvROK(callback) && (SvTYPE(SvRV(callback)) == SVt_PVAV)) {
/* callback param array ref like ['proto1','proto2'] */
cb_data_advanced_put(ctx, "next_proto_select_cb!!func", NULL);
cb_data_advanced_put(ctx, "next_proto_select_cb!!data", newSVsv(callback));
SSL_CTX_set_next_proto_select_cb(ctx, next_proto_select_cb_invoke, ctx);
PR2("SSL_CTX_set_next_proto_select_cb - simple ctx=%p\n",ctx);
}
else if (SvROK(callback) && (SvTYPE(SvRV(callback)) == SVt_PVCV)) {
cb_data_advanced_put(ctx, "next_proto_select_cb!!func", newSVsv(callback));
cb_data_advanced_put(ctx, "next_proto_select_cb!!data", newSVsv(data));
SSL_CTX_set_next_proto_select_cb(ctx, next_proto_select_cb_invoke, ctx);
PR2("SSL_CTX_set_next_proto_select_cb - advanced ctx=%p\n",ctx);
}
else {
RETVAL = 0;
}
OUTPUT:
RETVAL
void
P_next_proto_negotiated(s)
const SSL *s
PREINIT:
const unsigned char *data;
unsigned int len;
PPCODE:
SSL_get0_next_proto_negotiated(s, &data, &len);
XPUSHs(sv_2mortal(newSVpv((char *)data, len)));
void
P_next_proto_last_status(s)
const SSL *s
PPCODE:
XPUSHs(sv_2mortal(newSVsv(cb_data_advanced_get((void*)s, "next_proto_select_cb!!last_status"))));
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
#if !defined(OPENSSL_NO_TLSEXT)
int
SSL_set_tlsext_status_type(SSL *ssl,int cmd)
long
SSL_set_tlsext_status_ocsp_resp(ssl,staple)
SSL * ssl
PREINIT:
char * p;
STRLEN staplelen;
INPUT:
char * staple = SvPV( ST(1), staplelen);
CODE:
/* OpenSSL will free the memory */
New(0, p, staplelen, char);
memcpy(p, staple, staplelen);
RETVAL = SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP,staplelen,(void *)p);
OUTPUT:
RETVAL
int
SSL_CTX_set_tlsext_status_cb(ctx,callback,data=&PL_sv_undef)
SSL_CTX * ctx
SV * callback
SV * data
CODE:
RETVAL = 1;
if (callback==NULL || !SvOK(callback)) {
cb_data_advanced_put(ctx, "tlsext_status_cb!!func", NULL);
cb_data_advanced_put(ctx, "tlsext_status_cb!!data", NULL);
SSL_CTX_set_tlsext_status_cb(ctx, NULL);
} else if (SvROK(callback) && (SvTYPE(SvRV(callback)) == SVt_PVCV)) {
cb_data_advanced_put(ctx, "tlsext_status_cb!!func", newSVsv(callback));
cb_data_advanced_put(ctx, "tlsext_status_cb!!data", newSVsv(data));
SSL_CTX_set_tlsext_status_cb(ctx, tlsext_status_cb_invoke);
} else {
croak("argument must be code reference");
}
OUTPUT:
RETVAL
int
SSL_set_session_ticket_ext_cb(ssl,callback,data=&PL_sv_undef)
SSL * ssl
SV * callback
SV * data
CODE:
RETVAL = 1;
if (callback==NULL || !SvOK(callback)) {
cb_data_advanced_put(ssl, "session_ticket_ext_cb!!func", NULL);
cb_data_advanced_put(ssl, "session_ticket_ext_cb!!data", NULL);
SSL_set_session_ticket_ext_cb(ssl, NULL, NULL);
} else if (SvROK(callback) && (SvTYPE(SvRV(callback)) == SVt_PVCV)) {
cb_data_advanced_put(ssl, "session_ticket_ext_cb!!func", newSVsv(callback));
cb_data_advanced_put(ssl, "session_ticket_ext_cb!!data", newSVsv(data));
SSL_set_session_ticket_ext_cb(ssl, (tls_session_ticket_ext_cb_fn)&session_ticket_ext_cb_invoke, ssl);
} else {
croak("argument must be code reference");
}
OUTPUT:
RETVAL
int
SSL_set_session_ticket_ext(ssl,ticket)
SSL *ssl
PREINIT:
unsigned char * p;
STRLEN ticketlen;
INPUT:
unsigned char * ticket = (unsigned char *)SvPV( ST(1), ticketlen);
CODE:
RETVAL = 0;
if (ticketlen > 0) {
Newx(p, ticketlen, unsigned char);
if (!p)
croak("Net::SSLeay: set_session_ticket_ext could not allocate memory.\n");
memcpy(p, ticket, ticketlen);
RETVAL = SSL_set_session_ticket_ext(ssl, p, ticketlen);
Safefree(p);
}
OUTPUT:
RETVAL
#endif
OCSP_RESPONSE *
d2i_OCSP_RESPONSE(pv)
SV *pv
CODE:
RETVAL = NULL;
if (SvPOK(pv)) {
const unsigned char *p;
STRLEN len;
p = (unsigned char*)SvPV(pv,len);
RETVAL = d2i_OCSP_RESPONSE(NULL,&p,len);
}
OUTPUT:
RETVAL
void
i2d_OCSP_RESPONSE(r)
OCSP_RESPONSE * r
PPCODE:
STRLEN len;
unsigned char *pc,*pi;
if (!(len = i2d_OCSP_RESPONSE(r,NULL))) croak("invalid OCSP response");
Newx(pc,len,unsigned char);
if (!pc) croak("out of memory");
pi = pc;
i2d_OCSP_RESPONSE(r,&pi);
XPUSHs(sv_2mortal(newSVpv((char*)pc,len)));
Safefree(pc);
void
OCSP_RESPONSE_free(r)
OCSP_RESPONSE * r
OCSP_REQUEST *
d2i_OCSP_REQUEST(pv)
SV *pv
CODE:
RETVAL = NULL;
if (SvPOK(pv)) {
const unsigned char *p;
STRLEN len;
p = (unsigned char*)SvPV(pv,len);
RETVAL = d2i_OCSP_REQUEST(NULL,&p,len);
}
OUTPUT:
RETVAL
void
i2d_OCSP_REQUEST(r)
OCSP_REQUEST * r
PPCODE:
STRLEN len;
unsigned char *pc,*pi;
if (!(len = i2d_OCSP_REQUEST(r,NULL))) croak("invalid OCSP request");
Newx(pc,len,unsigned char);
if (!pc) croak("out of memory");
pi = pc;
i2d_OCSP_REQUEST(r,&pi);
XPUSHs(sv_2mortal(newSVpv((char*)pc,len)));
Safefree(pc);
void
OCSP_REQUEST_free(r)
OCSP_REQUEST * r
const char *
OCSP_response_status_str(long status)
long
OCSP_response_status(OCSP_RESPONSE *r)
void
SSL_OCSP_cert2ids(ssl,...)
SSL *ssl
PPCODE:
SSL_CTX *ctx;
X509_STORE *store;
STACK_OF(X509) *chain;
X509 *cert,*issuer;
OCSP_CERTID *id;
int i;
STRLEN len;
unsigned char *pi;
if (!ssl) croak("not a SSL object");
ctx = SSL_get_SSL_CTX(ssl);
if (!ctx) croak("invalid SSL object - no context");
store = SSL_CTX_get_cert_store(ctx);
chain = SSL_get_peer_cert_chain(ssl);
for(i=0;i<items-1;i++) {
cert = INT2PTR(X509*,SvIV(ST(i+1)));
if (X509_check_issued(cert,cert) == X509_V_OK)
croak("no OCSP request for self-signed certificate");
if (!(issuer = find_issuer(cert,store,chain)))
croak("cannot find issuer certificate");
if (!(id = OCSP_cert_to_id(EVP_sha1(),cert,issuer)))
croak("out of memory for generating OCSP certid");
pi = NULL;
if (!(len = i2d_OCSP_CERTID(id,&pi)))
croak("OCSP certid has no length");
XPUSHs(sv_2mortal(newSVpvn((char *)pi, len)));
free(pi);
OCSP_CERTID_free(id);
}
OCSP_REQUEST *
OCSP_ids2req(...)
CODE:
OCSP_REQUEST *req;
OCSP_CERTID *id;
int i;
req = OCSP_REQUEST_new();
if (!req) croak("out of memory");
OCSP_request_add1_nonce(req,NULL,-1);
for(i=0;i<items;i++) {
STRLEN len;
const unsigned char *p = (unsigned char*)SvPV(ST(i),len);
id = d2i_OCSP_CERTID(NULL,&p,len);
if (!id) {
OCSP_REQUEST_free(req);
croak("failed to get OCSP certid from string");
}
OCSP_request_add0_id(req,id);
}
RETVAL = req;
OUTPUT:
RETVAL
int
SSL_OCSP_response_verify(ssl,rsp,svreq=NULL,flags=0)
SSL *ssl
OCSP_RESPONSE *rsp
SV *svreq
unsigned long flags
PREINIT:
SSL_CTX *ctx;
X509_STORE *store;
OCSP_BASICRESP *bsr;
OCSP_REQUEST *req = NULL;
int i;
CODE:
if (!ssl) croak("not a SSL object");
ctx = SSL_get_SSL_CTX(ssl);
if (!ctx) croak("invalid SSL object - no context");
bsr = OCSP_response_get1_basic(rsp);
if (!bsr) croak("invalid OCSP response");
/* if we get a nonce it should match our nonce, if we get no nonce
* it was probably pre-signed */
if (svreq && SvOK(svreq) &&
(req = INT2PTR(OCSP_REQUEST*,SvIV(svreq)))) {
i = OCSP_check_nonce(req,bsr);
if ( i <= 0 ) {
if (i == -1) {
TRACE(2,"SSL_OCSP_response_verify: no nonce in response");
} else {
OCSP_BASICRESP_free(bsr);
croak("nonce in OCSP response does not match request");
}
}
}
RETVAL = 0;
if ((store = SSL_CTX_get_cert_store(ctx))) {
/* add the SSL uchain to the uchain of the OCSP basic response, this
* looks like the easiest way to handle the case where the OCSP
* response does not contain the chain up to the trusted root */
STACK_OF(X509) *chain = SSL_get_peer_cert_chain(ssl);
for(i=0;i<sk_X509_num(chain);i++) {
OCSP_basic_add1_cert(bsr, sk_X509_value(chain,i));
}
TRACE(1,"run basic verify");
RETVAL = OCSP_basic_verify(bsr, NULL, store, flags);
if (chain && !RETVAL) {
/* some CAs don't add a certificate to their OCSP responses and
* openssl does not include the trusted CA which signed the
* lowest chain certificate when looking for the signer.
* So find this CA ourself and retry verification. */
X509 *issuer;
X509 *last = sk_X509_value(chain,sk_X509_num(chain)-1);
ERR_clear_error(); /* clear error from last OCSP_basic_verify */
if (last && (issuer = find_issuer(last,store,chain))) {
OCSP_basic_add1_cert(bsr, issuer);
TRACE(1,"run OCSP_basic_verify with issuer for last chain element");
RETVAL = OCSP_basic_verify(bsr, NULL, store, flags);
}
}
}
OCSP_BASICRESP_free(bsr);
OUTPUT:
RETVAL
void
OCSP_response_results(rsp,...)
OCSP_RESPONSE *rsp
PPCODE:
OCSP_BASICRESP *bsr;
int i,want_array;
time_t nextupd = 0;
int getall,sksn;
bsr = OCSP_response_get1_basic(rsp);
if (!bsr) croak("invalid OCSP response");
want_array = (GIMME == G_ARRAY);
getall = (items <= 1);
sksn = OCSP_resp_count(bsr);
for(i=0; i < (getall ? sksn : items-1); i++) {
const char *error = NULL;
OCSP_SINGLERESP *sir = NULL;
OCSP_CERTID *certid = NULL;
SV *idsv = NULL;
int first, status, revocationReason;
ASN1_GENERALIZEDTIME *revocationTime, *thisupdate, *nextupdate;
if(getall) {
sir = OCSP_resp_get0(bsr,i);
} else {
STRLEN len;
const unsigned char *p;
idsv = ST(i+1);
if (!SvOK(idsv)) croak("undefined certid in arguments");
p = (unsigned char*)SvPV(idsv,len);
if (!(certid = d2i_OCSP_CERTID(NULL,&p,len))) {
error = "failed to get OCSP certid from string";
goto end;
}
first = OCSP_resp_find(bsr, certid, -1); /* Find the first matching */
if (first >= 0)
sir = OCSP_resp_get0(bsr,first);
}
if (sir)
{
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
status = OCSP_single_get0_status(sir, &revocationReason, &revocationTime, &thisupdate, &nextupdate);
#else
status = sir->certStatus->type;
if (status == V_OCSP_CERTSTATUS_REVOKED)
revocationTime = sir->certStatus->value.revoked->revocationTime;
thisupdate = sir->thisUpdate;
nextupdate = sir->nextUpdate;
#endif
if (status == V_OCSP_CERTSTATUS_REVOKED) {
error = "certificate status is revoked";
} else if (status != V_OCSP_CERTSTATUS_GOOD) {
error = "certificate status is unknown";
}
else if (!OCSP_check_validity(thisupdate, nextupdate, 0, -1)) {
error = "response not yet valid or expired";
}
} else {
error = "cannot find entry for certificate in OCSP response";
}
end:
if (want_array) {
AV *idav = newAV();
if (!idsv) {
/* getall: create new SV with OCSP_CERTID */
unsigned char *pi,*pc;
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
int len = i2d_OCSP_CERTID(OCSP_SINGLERESP_get0_id(sir),NULL);
#else
int len = i2d_OCSP_CERTID(sir->certId,NULL);
#endif
if(!len) continue;
Newx(pc,len,unsigned char);
if (!pc) croak("out of memory");
pi = pc;
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
i2d_OCSP_CERTID(OCSP_SINGLERESP_get0_id(sir),&pi);
#else
i2d_OCSP_CERTID(sir->certId,&pi);
#endif
idsv = newSVpv((char*)pc,len);
Safefree(pc);
} else {
/* reuse idsv from ST(..), but increment refcount */
idsv = SvREFCNT_inc(idsv);
}
av_push(idav, idsv);
av_push(idav, error ? newSVpv(error,0) : newSV(0));
if (sir) {
HV *details = newHV();
av_push(idav,newRV_noinc((SV*)details));
hv_store(details,"statusType",10,
newSViv(status),0);
if (nextupdate) hv_store(details,"nextUpdate",10,
newSViv(ASN1_TIME_timet(nextupdate)),0);
if (thisupdate) hv_store(details,"thisUpdate",10,
newSViv(ASN1_TIME_timet(thisupdate)),0);
if (status == V_OCSP_CERTSTATUS_REVOKED) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
OCSP_REVOKEDINFO *rev = sir->certStatus->value.revoked;
revocationReason = ASN1_ENUMERATED_get(rev->revocationReason);
#endif
hv_store(details,"revocationTime",14,newSViv(ASN1_TIME_timet(revocationTime)),0);
hv_store(details,"revocationReason",16,newSViv(revocationReason),0);
hv_store(details,"revocationReason_str",20,newSVpv(
OCSP_crl_reason_str(revocationReason),0),0);
}
}
XPUSHs(sv_2mortal(newRV_noinc((SV*)idav)));
} else if (!error) {
/* compute lowest nextUpdate */
time_t nu = ASN1_TIME_timet(nextupdate);
if (!nextupd || nextupd>nu) nextupd = nu;
}
if (certid) OCSP_CERTID_free(certid);
if (error && !want_array) {
OCSP_BASICRESP_free(bsr);
croak("%s", error);
}
}
OCSP_BASICRESP_free(bsr);
if (!want_array)
XPUSHs(sv_2mortal(newSViv(nextupd)));
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_TLSEXT)
int
SSL_CTX_set_alpn_select_cb(ctx,callback,data=&PL_sv_undef)
SSL_CTX * ctx
SV * callback
SV * data
CODE:
RETVAL = 1;
if (callback==NULL || !SvOK(callback)) {
SSL_CTX_set_alpn_select_cb(ctx, NULL, NULL);
cb_data_advanced_put(ctx, "alpn_select_cb!!func", NULL);
cb_data_advanced_put(ctx, "alpn_select_cb!!data", NULL);
PR1("SSL_CTX_set_alpn_select_cb - undef\n");
}
else if (SvROK(callback) && (SvTYPE(SvRV(callback)) == SVt_PVAV)) {
/* callback param array ref like ['proto1','proto2'] */
cb_data_advanced_put(ctx, "alpn_select_cb!!func", NULL);
cb_data_advanced_put(ctx, "alpn_select_cb!!data", newSVsv(callback));
SSL_CTX_set_alpn_select_cb(ctx, alpn_select_cb_invoke, ctx);
PR2("SSL_CTX_set_alpn_select_cb - simple ctx=%p\n",ctx);
}
else if (SvROK(callback) && (SvTYPE(SvRV(callback)) == SVt_PVCV)) {
cb_data_advanced_put(ctx, "alpn_select_cb!!func", newSVsv(callback));
cb_data_advanced_put(ctx, "alpn_select_cb!!data", newSVsv(data));
SSL_CTX_set_alpn_select_cb(ctx, alpn_select_cb_invoke, ctx);
PR2("SSL_CTX_set_alpn_select_cb - advanced ctx=%p\n",ctx);
}
else {
RETVAL = 0;
}
OUTPUT:
RETVAL
int
SSL_CTX_set_alpn_protos(ctx,data=&PL_sv_undef)
SSL_CTX * ctx
SV * data
PREINIT:
unsigned char *alpn_data;
unsigned char alpn_len;
CODE:
RETVAL = -1;
if (!SvROK(data) || (SvTYPE(SvRV(data)) != SVt_PVAV))
croak("Net::SSLeay: CTX_set_alpn_protos needs a single array reference.\n");
alpn_len = next_proto_helper_AV2protodata((AV*)SvRV(data), NULL);
Newx(alpn_data, alpn_len, unsigned char);
if (!alpn_data)
croak("Net::SSLeay: CTX_set_alpn_protos could not allocate memory.\n");
alpn_len = next_proto_helper_AV2protodata((AV*)SvRV(data), alpn_data);
RETVAL = SSL_CTX_set_alpn_protos(ctx, alpn_data, alpn_len);
Safefree(alpn_data);
OUTPUT:
RETVAL
int
SSL_set_alpn_protos(ssl,data=&PL_sv_undef)
SSL * ssl
SV * data
PREINIT:
unsigned char *alpn_data;
unsigned char alpn_len;
CODE:
RETVAL = -1;
if (!SvROK(data) || (SvTYPE(SvRV(data)) != SVt_PVAV))
croak("Net::SSLeay: set_alpn_protos needs a single array reference.\n");
alpn_len = next_proto_helper_AV2protodata((AV*)SvRV(data), NULL);
Newx(alpn_data, alpn_len, unsigned char);
if (!alpn_data)
croak("Net::SSLeay: set_alpn_protos could not allocate memory.\n");
alpn_len = next_proto_helper_AV2protodata((AV*)SvRV(data), alpn_data);
RETVAL = SSL_set_alpn_protos(ssl, alpn_data, alpn_len);
Safefree(alpn_data);
OUTPUT:
RETVAL
void
P_alpn_selected(s)
const SSL *s
PREINIT:
const unsigned char *data;
unsigned int len;
PPCODE:
SSL_get0_alpn_selected(s, &data, &len);
XPUSHs(sv_2mortal(newSVpv((char *)data, len)));
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
void
SSL_export_keying_material(ssl, outlen, label, p)
SSL * ssl
int outlen
PREINIT:
char * out;
STRLEN labellen;
STRLEN plen;
int ret;
INPUT:
char * label = SvPV( ST(2), labellen);
char * p = SvPV( ST(3), plen);
PPCODE:
New(0, out, outlen, char);
ret = SSL_export_keying_material(ssl, (unsigned char*)out, outlen, label, labellen, (unsigned char*)p, plen, plen ? 1 : 0);
PUSHs(sv_2mortal(ret>=0 ? newSVpvn(out, outlen) : newSV(0)));
EXTEND(SP, 1);
Safefree(out);
#endif
#define REM_EOF "/* EOF - SSLeay.xs */"