static VALUE ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self) { VALUE pass, name, pkey, cert, ca; VALUE obj; char *passphrase, *friendlyname; EVP_PKEY *key; X509 *x509; STACK_OF(X509) *x509s; PKCS12 *p12; rb_scan_args(argc, argv, "41", &pass, &name, &pkey, &cert, &ca); passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass); friendlyname = NIL_P(name) ? NULL : StringValuePtr(name); key = GetPKeyPtr(pkey); x509 = GetX509CertPtr(cert); x509s = NIL_P(ca) ? NULL : ossl_x509_ary2sk(ca); p12 = PKCS12_create(passphrase, friendlyname, key, x509, x509s, 0, 0, 0, 0, 0); sk_X509_pop_free(x509s, X509_free); if(!p12) ossl_raise(ePKCS12Error, NULL); WrapPKCS12(cPKCS12, obj, p12); return obj; }
/* * call-seq: * spki.public_key = pub => pkey * * === Parameters * * +pub+ - the public key to be set for this instance * * Sets the public key to be associated with the SPKI, an instance of * OpenSSL::PKey. This should be the public key corresponding to the * private key used for signing the SPKI. */ static VALUE ossl_spki_set_public_key(VALUE self, VALUE key) { NETSCAPE_SPKI *spki; GetSPKI(self, spki); if (!NETSCAPE_SPKI_set_pubkey(spki, GetPKeyPtr(key))) { /* NO NEED TO DUP */ ossl_raise(eSPKIError, NULL); } return key; }
static DH* ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength) { VALUE args[3]; int status, success; args[0] = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); args[1] = INT2FIX(is_export); args[2] = INT2FIX(keylength); success = rb_protect((VALUE(*)_((VALUE)))ossl_call_tmp_dh_callback, (VALUE)args, &status); if (status || !success) return NULL; return GetPKeyPtr(ossl_ssl_get_tmp_dh(args[0]))->pkey.dh; }
static VALUE ossl_x509crl_verify(VALUE self, VALUE key) { X509_CRL *crl; int ret; GetX509CRL(self, crl); if ((ret = X509_CRL_verify(crl, GetPKeyPtr(key))) < 0) { ossl_raise(eX509CRLError, NULL); } if (ret == 1) { return Qtrue; } return Qfalse; }
static VALUE ossl_x509crl_verify(VALUE self, VALUE key) { X509_CRL *crl; GetX509CRL(self, crl); switch (X509_CRL_verify(crl, GetPKeyPtr(key))) { case 1: return Qtrue; case 0: ossl_clear_error(); return Qfalse; default: ossl_raise(eX509CRLError, NULL); } }
/* * call-seq: * spki.verify(key) => boolean * * === Parameters * * +key+ - the public key to be used for verifying the SPKI signature * * Returns +true+ if the signature is valid, +false+ otherwise. To verify an * SPKI, the public key contained within the SPKI should be used. */ static VALUE ossl_spki_verify(VALUE self, VALUE key) { NETSCAPE_SPKI *spki; GetSPKI(self, spki); switch (NETSCAPE_SPKI_verify(spki, GetPKeyPtr(key))) { /* NO NEED TO DUP */ case 0: return Qfalse; case 1: return Qtrue; default: ossl_raise(eSPKIError, NULL); } return Qnil; /* dummy */ }
/* * call-seq: * PKCS12.create(pass, name, key, cert [, ca, [, key_pbe [, cert_pbe [, key_iter [, mac_iter [, keytype]]]]]]) * * === Parameters * * +pass+ - string * * +name+ - A string describing the key. * * +key+ - Any PKey. * * +cert+ - A X509::Certificate. * * * The public_key portion of the certificate must contain a valid public key. * * * The not_before and not_after fields must be filled in. * * +ca+ - An optional array of X509::Certificate's. * * +key_pbe+ - string * * +cert_pbe+ - string * * +key_iter+ - integer * * +mac_iter+ - integer * * +keytype+ - An integer representing an MSIE specific extension. * * Any optional arguments may be supplied as nil to preserve the OpenSSL defaults. * * See the OpenSSL documentation for PKCS12_create(). */ static VALUE ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self) { VALUE pass, name, pkey, cert, ca, key_nid, cert_nid, key_iter, mac_iter, keytype; VALUE obj; char *passphrase, *friendlyname; EVP_PKEY *key; X509 *x509; STACK_OF(X509) *x509s; int nkey = 0, ncert = 0, kiter = 0, miter = 0, ktype = 0; PKCS12 *p12; rb_scan_args(argc, argv, "46", &pass, &name, &pkey, &cert, &ca, &key_nid, &cert_nid, &key_iter, &mac_iter, &keytype); passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass); friendlyname = NIL_P(name) ? NULL : StringValuePtr(name); key = GetPKeyPtr(pkey); x509 = GetX509CertPtr(cert); x509s = NIL_P(ca) ? NULL : ossl_x509_ary2sk(ca); /* TODO: make a VALUE to nid function */ if (!NIL_P(key_nid)) { if ((nkey = OBJ_txt2nid(StringValuePtr(key_nid))) == NID_undef) rb_raise(rb_eArgError, "Unknown PBE algorithm %s", StringValuePtr(key_nid)); } if (!NIL_P(cert_nid)) { if ((ncert = OBJ_txt2nid(StringValuePtr(cert_nid))) == NID_undef) rb_raise(rb_eArgError, "Unknown PBE algorithm %s", StringValuePtr(cert_nid)); } if (!NIL_P(key_iter)) kiter = NUM2INT(key_iter); if (!NIL_P(mac_iter)) miter = NUM2INT(mac_iter); if (!NIL_P(keytype)) ktype = NUM2INT(keytype); p12 = PKCS12_create(passphrase, friendlyname, key, x509, x509s, nkey, ncert, kiter, miter, ktype); sk_X509_pop_free(x509s, X509_free); if(!p12) ossl_raise(ePKCS12Error, NULL); WrapPKCS12(cPKCS12, obj, p12); ossl_pkcs12_set_key(obj, pkey); ossl_pkcs12_set_cert(obj, cert); ossl_pkcs12_set_ca_certs(obj, ca); return obj; }
static VALUE ossl_call_tmp_dh_callback(VALUE *args) { SSL *ssl; VALUE cb, dh; EVP_PKEY *pkey; Data_Get_Struct(args[0], SSL, ssl); cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx); if (NIL_P(cb)) return Qfalse; dh = rb_funcall(cb, rb_intern("call"), 3, args[0], args[1], args[2]); pkey = GetPKeyPtr(dh); if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) return Qfalse; ossl_ssl_set_tmp_dh(args[0], dh); return Qtrue; }
static VALUE ossl_call_client_cert_cb(VALUE obj) { VALUE cb, ary, cert, key; SSL *ssl; Data_Get_Struct(obj, SSL, ssl); cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx); if (NIL_P(cb)) return Qfalse; ary = rb_funcall(cb, rb_intern("call"), 1, obj); Check_Type(ary, T_ARRAY); GetX509CertPtr(cert = rb_ary_entry(ary, 0)); GetPKeyPtr(key = rb_ary_entry(ary, 1)); ossl_ssl_set_x509(obj, cert); ossl_ssl_set_key(obj, key); return Qtrue; }
/* * call-seq: * ctx.setup => Qtrue # first time * ctx.setup => nil # thereafter * * This method is called automatically when a new SSLSocket is created. * Normally you do not need to call this method (unless you are writing an extension in C). */ static VALUE ossl_sslctx_setup(VALUE self) { SSL_CTX *ctx; X509 *cert = NULL, *client_ca = NULL; X509_STORE *store; EVP_PKEY *key = NULL; char *ca_path = NULL, *ca_file = NULL; int i, verify_mode; VALUE val; if(OBJ_FROZEN(self)) return Qnil; Data_Get_Struct(self, SSL_CTX, ctx); #if !defined(OPENSSL_NO_DH) if (RTEST(ossl_sslctx_get_tmp_dh_cb(self))){ SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback); } else{ SSL_CTX_set_tmp_dh_callback(ctx, ossl_default_tmp_dh_callback); } #endif SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_ptr_idx, (void*)self); val = ossl_sslctx_get_cert_store(self); if(!NIL_P(val)){ /* * WORKAROUND: * X509_STORE can count references, but * X509_STORE_free() doesn't care it. * So we won't increment it but mark it by ex_data. */ store = GetX509StorePtr(val); /* NO NEED TO DUP */ SSL_CTX_set_cert_store(ctx, store); SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_store_p, (void*)1); } val = ossl_sslctx_get_extra_cert(self); if(!NIL_P(val)){ rb_block_call(val, rb_intern("each"), 0, 0, ossl_sslctx_add_extra_chain_cert_i, self); } /* private key may be bundled in certificate file. */ val = ossl_sslctx_get_cert(self); cert = NIL_P(val) ? NULL : GetX509CertPtr(val); /* NO DUP NEEDED */ val = ossl_sslctx_get_key(self); key = NIL_P(val) ? NULL : GetPKeyPtr(val); /* NO DUP NEEDED */ if (cert && key) { if (!SSL_CTX_use_certificate(ctx, cert)) { /* Adds a ref => Safe to FREE */ ossl_raise(eSSLError, "SSL_CTX_use_certificate:"); } if (!SSL_CTX_use_PrivateKey(ctx, key)) { /* Adds a ref => Safe to FREE */ ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey:"); } if (!SSL_CTX_check_private_key(ctx)) { ossl_raise(eSSLError, "SSL_CTX_check_private_key:"); } } val = ossl_sslctx_get_client_ca(self); if(!NIL_P(val)){ if(TYPE(val) == T_ARRAY){ for(i = 0; i < RARRAY_LEN(val); i++){ client_ca = GetX509CertPtr(RARRAY_PTR(val)[i]); if (!SSL_CTX_add_client_CA(ctx, client_ca)){ /* Copies X509_NAME => FREE it. */ ossl_raise(eSSLError, "SSL_CTX_add_client_CA"); } } } else{ client_ca = GetX509CertPtr(val); /* NO DUP NEEDED. */ if (!SSL_CTX_add_client_CA(ctx, client_ca)){ /* Copies X509_NAME => FREE it. */ ossl_raise(eSSLError, "SSL_CTX_add_client_CA"); } } } val = ossl_sslctx_get_ca_file(self); ca_file = NIL_P(val) ? NULL : StringValuePtr(val); val = ossl_sslctx_get_ca_path(self); ca_path = NIL_P(val) ? NULL : StringValuePtr(val); if(ca_file || ca_path){ if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path)) rb_warning("can't set verify locations"); } val = ossl_sslctx_get_verify_mode(self); verify_mode = NIL_P(val) ? SSL_VERIFY_NONE : NUM2INT(val); SSL_CTX_set_verify(ctx, verify_mode, ossl_ssl_verify_callback); if (RTEST(ossl_sslctx_get_client_cert_cb(self))) SSL_CTX_set_client_cert_cb(ctx, ossl_client_cert_cb); val = ossl_sslctx_get_timeout(self); if(!NIL_P(val)) SSL_CTX_set_timeout(ctx, NUM2LONG(val)); val = ossl_sslctx_get_verify_dep(self); if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx, NUM2LONG(val)); val = ossl_sslctx_get_options(self); if(!NIL_P(val)) SSL_CTX_set_options(ctx, NUM2LONG(val)); rb_obj_freeze(self); val = ossl_sslctx_get_sess_id_ctx(self); if (!NIL_P(val)){ StringValue(val); if (!SSL_CTX_set_session_id_context(ctx, (unsigned char *)RSTRING_PTR(val), RSTRING_LEN(val))){ ossl_raise(eSSLError, "SSL_CTX_set_session_id_context:"); } } if (RTEST(rb_iv_get(self, "@session_get_cb"))) { SSL_CTX_sess_set_get_cb(ctx, ossl_sslctx_session_get_cb); OSSL_Debug("SSL SESSION get callback added"); } if (RTEST(rb_iv_get(self, "@session_new_cb"))) { SSL_CTX_sess_set_new_cb(ctx, ossl_sslctx_session_new_cb); OSSL_Debug("SSL SESSION new callback added"); } if (RTEST(rb_iv_get(self, "@session_remove_cb"))) { SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb); OSSL_Debug("SSL SESSION remove callback added"); } #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME val = rb_iv_get(self, "@servername_cb"); if (!NIL_P(val)) { SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); OSSL_Debug("SSL TLSEXT servername callback added"); } #endif return Qtrue; }