#include "openssl.h" static int p5_ssl_ex_ssl_ptr=0; static int p5_ssl_ex_ssl_info_callback=0; static int p5_ssl_ex_ssl_ctx_ptr=0; static int p5_ssl_ctx_ex_ssl_info_callback=0; typedef struct ssl_ic_args_st { SV *cb; SV *arg; } SSL_IC_ARGS; static void p5_ssl_info_callback(ssl,mode,ret) SSL *ssl; int mode; int ret; { int i; SV *me,*cb; me=(SV *)SSL_get_ex_data(ssl,p5_ssl_ex_ssl_ptr); cb=(SV *)SSL_get_ex_data(ssl,p5_ssl_ex_ssl_info_callback); if (cb == NULL) cb=(SV *)SSL_CTX_get_ex_data( SSL_get_SSL_CTX(ssl),p5_ssl_ctx_ex_ssl_info_callback); if (cb != NULL) { dSP; PUSHMARK(sp); XPUSHs(me); XPUSHs(sv_2mortal(newSViv(mode))); XPUSHs(sv_2mortal(newSViv(ret))); PUTBACK; i=perl_call_sv(cb,G_DISCARD); } else { croak("Internal error in SSL p5_ssl_info_callback"); } } int boot_ssl() { p5_ssl_ex_ssl_ptr= SSL_get_ex_new_index(0,"OpenSSL::SSL",ex_new,NULL,ex_cleanup); p5_ssl_ex_ssl_info_callback= SSL_get_ex_new_index(0,"ssl_info_callback",NULL,NULL, ex_cleanup); p5_ssl_ex_ssl_ctx_ptr= SSL_get_ex_new_index(0,"ssl_ctx_ptr",NULL,NULL, ex_cleanup); p5_ssl_ctx_ex_ssl_info_callback= SSL_CTX_get_ex_new_index(0,"ssl_ctx_info_callback",NULL,NULL, ex_cleanup); return(1); } MODULE = OpenSSL::SSL PACKAGE = OpenSSL::SSL::CTX PREFIX = p5_SSL_CTX_ PROTOTYPES: ENABLE VERSIONCHECK: DISABLE void p5_SSL_CTX_new(...) PREINIT: SSL_METHOD *meth; SSL_CTX *ctx; char *method; PPCODE: pr_name("p5_SSL_CTX_new"); if ((items == 1) && SvPOK(ST(0))) method=SvPV(ST(0),na); else if ((items == 2) && SvPOK(ST(1))) method=SvPV(ST(1),na); else croak("Usage: OpenSSL::SSL::CTX::new(type)"); if (strcmp(method,"SSLv3") == 0) meth=SSLv3_method(); else if (strcmp(method,"SSLv3_client") == 0) meth=SSLv3_client_method(); else if (strcmp(method,"SSLv3_server") == 0) meth=SSLv3_server_method(); else if (strcmp(method,"SSLv23") == 0) meth=SSLv23_method(); else if (strcmp(method,"SSLv23_client") == 0) meth=SSLv23_client_method(); else if (strcmp(method,"SSLv23_server") == 0) meth=SSLv23_server_method(); else if (strcmp(method,"SSLv2") == 0) meth=SSLv2_method(); else if (strcmp(method,"SSLv2_client") == 0) meth=SSLv2_client_method(); else if (strcmp(method,"SSLv2_server") == 0) meth=SSLv2_server_method(); else if (strcmp(method,"TLSv1") == 0) meth=TLSv1_method(); else if (strcmp(method,"TLSv1_client") == 0) meth=TLSv1_client_method(); else if (strcmp(method,"TLSv1_server") == 0) meth=TLSv1_server_method(); else { croak("Not a valid SSL method name, should be 'SSLv[23] [client|server]'"); } EXTEND(sp,1); PUSHs(sv_newmortal()); ctx=SSL_CTX_new(meth); sv_setref_pv(ST(0), "OpenSSL::SSL::CTX", (void*)ctx); int p5_SSL_CTX_use_PrivateKey_file(ctx,file,...) SSL_CTX *ctx; char *file; PREINIT: int i=SSL_FILETYPE_PEM; char *ptr; CODE: pr_name("p5_SSL_CTX_use_PrivateKey_file"); if (items > 3) croak("OpenSSL::SSL::CTX::use_PrivateKey_file(ssl_ctx,file[,type])"); if (items == 3) { ptr=SvPV(ST(2),na); if (strcmp(ptr,"der") == 0) i=SSL_FILETYPE_ASN1; else i=SSL_FILETYPE_PEM; } RETVAL=SSL_CTX_use_RSAPrivateKey_file(ctx,file,i); OUTPUT: RETVAL int p5_SSL_CTX_set_options(ctx,...) SSL_CTX *ctx; PREINIT: int i; char *ptr; SV *sv; CODE: pr_name("p5_SSL_CTX_set_options"); for (i=1; ireferences); SSL_CTX_free(ctx); MODULE = OpenSSL::SSL PACKAGE = OpenSSL::SSL PREFIX = p5_SSL_ void p5_SSL_new(...) PREINIT: SV *sv_ctx; SSL_CTX *ctx; SSL *ssl; SV *arg; PPCODE: pr_name("p5_SSL_new"); if ((items != 1) && (items != 2)) croak("Usage: OpenSSL::SSL::new(ssl_ctx)"); if (sv_derived_from(ST(items-1),"OpenSSL::SSL::CTX")) { IV tmp = SvIV((SV*)SvRV(ST(items-1))); ctx=(SSL_CTX *)tmp; sv_ctx=ST(items-1); } else croak("ssl_ctx is not of type OpenSSL::SSL::CTX"); EXTEND(sp,1); PUSHs(sv_newmortal()); ssl=SSL_new(ctx); sv_setref_pv(ST(0), "OpenSSL::SSL", (void*)ssl); /* Now this is being a little hairy, we keep a pointer to * our perl reference. We need to do a different one * to the one we return because it will have its reference * count dropped to 0 upon return and if we up its reference * count, it will never be DESTROYED */ arg=newSVsv(ST(0)); SSL_set_ex_data(ssl,p5_ssl_ex_ssl_ptr,(char *)arg); SvREFCNT_inc(sv_ctx); SSL_set_ex_data(ssl,p5_ssl_ex_ssl_ctx_ptr,(char *)sv_ctx); int p5_SSL_connect(ssl) SSL *ssl; CODE: RETVAL=SSL_connect(ssl); OUTPUT: RETVAL int p5_SSL_accept(ssl) SSL *ssl; CODE: RETVAL=SSL_connect(ssl); OUTPUT: RETVAL int p5_SSL_sysread(ssl,in,num, ...) SSL *ssl; SV *in; int num; PREINIT: int i,n,olen; int offset; char *p; CODE: offset=0; if (!SvPOK(in)) sv_setpvn(in,"",0); SvPV(in,olen); if (items > 3) { offset=SvIV(ST(3)); if (offset < 0) { if (-offset > olen) croak("Offset outside string"); offset+=olen; } } if ((num+offset) > olen) { SvGROW(in,num+offset+1); p=SvPV(in,i); memset(&(p[olen]),0,(num+offset)-olen+1); } p=SvPV(in,n); i=SSL_read(ssl,p+offset,num); RETVAL=i; if (i <= 0) i=0; SvCUR_set(in,offset+i); OUTPUT: RETVAL int p5_SSL_syswrite(ssl,in, ...) SSL *ssl; SV *in; PREINIT: char *ptr; int len,in_len; int offset=0; int n; CODE: ptr=SvPV(in,in_len); if (items > 2) { len=SvOK(ST(2))?SvIV(ST(2)):in_len; if (items > 3) { offset=SvIV(ST(3)); if (offset < 0) { if (-offset > in_len) croak("Offset outside string"); offset+=in_len; } else if ((offset >= in_len) && (in_len > 0)) croak("Offset outside string"); } if (len >= (in_len-offset)) len=in_len-offset; } else len=in_len; RETVAL=SSL_write(ssl,ptr+offset,len); OUTPUT: RETVAL void p5_SSL_set_bio(ssl,bio) SSL *ssl; BIO *bio; CODE: bio->references++; SSL_set_bio(ssl,bio,bio); int p5_SSL_set_options(ssl,...) SSL *ssl; PREINIT: int i; char *ptr; SV *sv; CODE: pr_name("p5_SSL_set_options"); for (i=1; ireferences,ssl->ctx->references); #ifdef DEBUG fprintf(stderr,"SSL_DESTROY %d\n",ssl->references); #endif SSL_free(ssl); int p5_SSL_references(ssl) SSL *ssl; CODE: RETVAL=ssl->references; OUTPUT: RETVAL int p5_SSL_do_handshake(ssl) SSL *ssl; CODE: RETVAL=SSL_do_handshake(ssl); OUTPUT: RETVAL int p5_SSL_renegotiate(ssl) SSL *ssl; CODE: RETVAL=SSL_renegotiate(ssl); OUTPUT: RETVAL int p5_SSL_shutdown(ssl) SSL *ssl; CODE: RETVAL=SSL_shutdown(ssl); OUTPUT: RETVAL char * p5_SSL_get_version(ssl) SSL *ssl; CODE: RETVAL=SSL_get_version(ssl); OUTPUT: RETVAL SSL_CIPHER * p5_SSL_get_current_cipher(ssl) SSL *ssl; CODE: RETVAL=SSL_get_current_cipher(ssl); OUTPUT: RETVAL X509 * p5_SSL_get_peer_certificate(ssl) SSL *ssl CODE: RETVAL=SSL_get_peer_certificate(ssl); OUTPUT: RETVAL MODULE = OpenSSL::SSL PACKAGE = OpenSSL::SSL::CIPHER PREFIX = p5_SSL_CIPHER_ int p5_SSL_CIPHER_get_bits(sc) SSL_CIPHER *sc PREINIT: int i,ret; PPCODE: EXTEND(sp,2); PUSHs(sv_newmortal()); PUSHs(sv_newmortal()); ret=SSL_CIPHER_get_bits(sc,&i); sv_setiv(ST(0),(IV)ret); sv_setiv(ST(1),(IV)i); char * p5_SSL_CIPHER_get_version(sc) SSL_CIPHER *sc CODE: RETVAL=SSL_CIPHER_get_version(sc); OUTPUT: RETVAL char * p5_SSL_CIPHER_get_name(sc) SSL_CIPHER *sc CODE: RETVAL=SSL_CIPHER_get_name(sc); OUTPUT: RETVAL MODULE = OpenSSL::SSL PACKAGE = OpenSSL::BIO PREFIX = p5_BIO_ void p5_BIO_get_ssl(bio) BIO *bio; PREINIT: SSL *ssl; SV *ret; int i; PPCODE: if ((i=BIO_get_ssl(bio,&ssl)) > 0) { ret=(SV *)SSL_get_ex_data(ssl,p5_ssl_ex_ssl_ptr); ret=sv_mortalcopy(ret); } else ret= &sv_undef; EXTEND(sp,1); PUSHs(ret);