From ab2e1c141fa996348d836b4e1537aace5e4d4463 Mon Sep 17 00:00:00 2001 From: gotoyuzo Date: Thu, 11 Dec 2003 12:29:08 +0000 Subject: * ext/openssl/ossl_pkcs12.[ch]: new files. add OpenSSL::PKCS12. * ext/openssl/ossl_ossl.[ch]: ditto. * ext/openssl/MANIFEST: add ossl_pkcs12.[ch]. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5172 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 8 +++ ext/openssl/MANIFEST | 2 + ext/openssl/ossl.c | 1 + ext/openssl/ossl.h | 3 + ext/openssl/ossl_pkcs12.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++ ext/openssl/ossl_pkcs12.h | 16 +++++ 6 files changed, 182 insertions(+) create mode 100644 ext/openssl/ossl_pkcs12.c create mode 100644 ext/openssl/ossl_pkcs12.h diff --git a/ChangeLog b/ChangeLog index 24d1d4602f..74eac81606 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +Thu Dec 11 21:24:43 2003 GOTOU Yuuzou + + * ext/openssl/ossl_pkcs12.[ch]: new files. add OpenSSL::PKCS12. + + * ext/openssl/ossl_ossl.[ch]: ditto. + + * ext/openssl/MANIFEST: add ossl_pkcs12.[ch]. + Thu Dec 11 20:54:28 2003 Minero Aoki * lib/fileutils.rb (mkdir_p): remove trailing `/' befere mkdir(2). diff --git a/ext/openssl/MANIFEST b/ext/openssl/MANIFEST index cdaf55c926..75768b7814 100644 --- a/ext/openssl/MANIFEST +++ b/ext/openssl/MANIFEST @@ -35,6 +35,8 @@ ossl_ns_spki.c ossl_ns_spki.h ossl_ocsp.c ossl_ocsp.h +ossl_pkcs12.c +ossl_pkcs12.h ossl_pkcs7.c ossl_pkcs7.h ossl_pkey.c diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index 6646bafc2e..ac98d6f0a6 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -425,6 +425,7 @@ Init_openssl() Init_ossl_digest(); Init_ossl_hmac(); Init_ossl_ns_spki(); + Init_ossl_pkcs12(); Init_ossl_pkcs7(); Init_ossl_pkey(); Init_ossl_rand(); diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h index b0e26bee91..c5054beba2 100644 --- a/ext/openssl/ossl.h +++ b/ext/openssl/ossl.h @@ -37,6 +37,8 @@ extern "C" { #include #include #include +#include +#include #include #include #include @@ -196,6 +198,7 @@ void ossl_debug(const char *, ...); #include "ossl_hmac.h" #include "ossl_ns_spki.h" #include "ossl_ocsp.h" +#include "ossl_pkcs12.h" #include "ossl_pkcs7.h" #include "ossl_pkey.h" #include "ossl_rand.h" diff --git a/ext/openssl/ossl_pkcs12.c b/ext/openssl/ossl_pkcs12.c new file mode 100644 index 0000000000..801f765d95 --- /dev/null +++ b/ext/openssl/ossl_pkcs12.c @@ -0,0 +1,152 @@ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + * $Id$ + */ +#include "ossl.h" + +#define WrapPKCS12(klass, obj, p12) do { \ + if(!p12) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \ + obj = Data_Wrap_Struct(klass, 0, PKCS12_free, p12); \ +} while (0) + +#define GetPKCS12(obj, p12) do { \ + Data_Get_Struct(obj, PKCS12, p12); \ + if(!p12) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \ +} while (0) + +#define SafeGetPKCS12(obj, p12) do { \ + OSSL_Check_Kind(obj, cPKCS12); \ + GetPKCS12(obj, p12); \ +} while (0) + +#define ossl_pkcs12_set_key(o,v) rb_iv_set((o), "@key", (v)) +#define ossl_pkcs12_set_cert(o,v) rb_iv_set((o), "@certificate", (v)) +#define ossl_pkcs12_set_ca_certs(o,v) rb_iv_set((o), "@ca_certs", (v)) +#define ossl_pkcs12_get_key(o) rb_iv_get((o), "@key") +#define ossl_pkcs12_get_cert(o) rb_iv_get((o), "@certificate") +#define ossl_pkcs12_get_ca_certs(o) rb_iv_get((o), "@ca_certs") + +/* + * Classes + */ +VALUE mPKCS12; +VALUE cPKCS12; +VALUE ePKCS12Error; + +/* + * Private + */ +static VALUE +ossl_pkcs12_s_allocate(VALUE klass) +{ + PKCS12 *p12; + VALUE obj; + + if(!(p12 = PKCS12_new())) ossl_raise(ePKCS12Error, NULL); + WrapPKCS12(klass, obj, p12); + + return obj; +} + +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; +} + +static VALUE +ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self) +{ + BIO *in; + VALUE arg, pass, pkey, cert, ca; + char *passphrase; + EVP_PKEY *key; + X509 *x509; + STACK_OF(X509) *x509s = NULL; + int st = 0; + + if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) return self; + passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass); + in = ossl_obj2bio(arg); + d2i_PKCS12_bio(in, (PKCS12 **)&DATA_PTR(self)); + BIO_free(in); + + pkey = cert = ca = Qnil; + if(!PKCS12_parse((PKCS12*)DATA_PTR(self), passphrase, &key, &x509, &x509s)) + ossl_raise(ePKCS12Error, NULL); + pkey = rb_protect((VALUE(*)())ossl_pkey_new, (VALUE)key, &st); /* NO DUP */ + if(st) goto err; + cert = rb_protect((VALUE(*)())ossl_x509_new, (VALUE)x509, &st); + if(st) goto err; + if(x509s){ + ca = rb_protect((VALUE(*)())ossl_x509_sk2ary, (VALUE)x509s, &st); + if(st) goto err; + } + + err: + X509_free(x509); + sk_X509_pop_free(x509s, X509_free); + ossl_pkcs12_set_key(self, pkey); + ossl_pkcs12_set_cert(self, cert); + ossl_pkcs12_set_ca_certs(self, ca); + if(st) rb_jump_tag(st); + + return self; +} + +static VALUE +ossl_pkcs12_to_der(VALUE self) +{ + PKCS12 *p12; + VALUE str; + long len; + unsigned char *p; + + GetPKCS12(self, p12); + if((len = i2d_PKCS12(p12, NULL)) <= 0) + ossl_raise(ePKCS12Error, NULL); + str = rb_str_new(0, len); + p = RSTRING(str)->ptr; + if(i2d_PKCS12(p12, &p) <= 0) + ossl_raise(ePKCS12Error, NULL); + ossl_str_adjust(str, p); + + return str; +} + +void +Init_ossl_pkcs12() +{ + mPKCS12 = rb_define_module_under(mOSSL, "PKCS12"); + cPKCS12 = rb_define_class_under(mPKCS12, "PKCS12", rb_cObject); + ePKCS12Error = rb_define_class_under(mPKCS12, "PKCS12Error", eOSSLError); + rb_define_module_function(mPKCS12, "create", ossl_pkcs12_s_create, -1); + + rb_define_alloc_func(cPKCS12, ossl_pkcs12_s_allocate); + rb_attr(cPKCS12, rb_intern("key"), 1, 0, Qfalse); + rb_attr(cPKCS12, rb_intern("certificate"), 1, 0, Qfalse); + rb_attr(cPKCS12, rb_intern("ca_certs"), 1, 0, Qfalse); + rb_define_method(cPKCS12, "initialize", ossl_pkcs12_initialize, -1); + rb_define_method(cPKCS12, "to_der", ossl_pkcs12_to_der, 0); +} diff --git a/ext/openssl/ossl_pkcs12.h b/ext/openssl/ossl_pkcs12.h new file mode 100644 index 0000000000..fa73c4bec5 --- /dev/null +++ b/ext/openssl/ossl_pkcs12.h @@ -0,0 +1,16 @@ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + * $Id$ + */ +#if !defined(_OSSL_PKCS12_H_) +#define _OSSL_PKCS7_H_ + +extern VALUE mPKCS12; +extern VALUE cPKCS12; +extern VALUE ePKCS12Error; + +void Init_ossl_pkcs12(void); + +#endif /* _OSSL_PKCS12_H_ */ + -- cgit v1.2.3