diff options
author | Michal Rokos <m.rokos@sh.cvut.cz> | 2001-11-16 11:20:13 +0000 |
---|---|---|
committer | Michal Rokos <m.rokos@sh.cvut.cz> | 2001-11-16 11:20:13 +0000 |
commit | 8903e757c052d3a99aada758bb628ec135360e60 (patch) | |
tree | 5f0e99803c1fc5c6909fd7d325d0f279265b97cf /ossl_x509ext.c | |
download | ruby-openssl-history-8903e757c052d3a99aada758bb628ec135360e60.tar.gz |
Initial revision
Diffstat (limited to 'ossl_x509ext.c')
-rw-r--r-- | ossl_x509ext.c | 374 |
1 files changed, 374 insertions, 0 deletions
diff --git a/ossl_x509ext.c b/ossl_x509ext.c new file mode 100644 index 0000000..b5a7ddc --- /dev/null +++ b/ossl_x509ext.c @@ -0,0 +1,374 @@ +/* + * $Id$ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001 Michal Rokos <m.rokos@sh.cvut.cz> + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" + +#define MakeX509Ext(obj, extp) {\ + obj = Data_Make_Struct(cX509Extension, ossl_x509ext, 0, ossl_x509ext_free, extp);\ +} + +#define GetX509Ext(obj, extp) {\ + Data_Get_Struct(obj, ossl_x509ext, extp);\ +} + +#define MakeX509ExtFactory(obj, extfactoryp) {\ + obj = Data_Make_Struct(cX509ExtensionFactory, ossl_x509extfactory, 0, ossl_x509extfactory_free, extfactoryp);\ +} + +#define GetX509ExtFactory(obj, extfactoryp) {\ + Data_Get_Struct(obj, ossl_x509extfactory, extfactoryp);\ +} + +/* + * Classes + */ +VALUE cX509Extension; +VALUE cX509ExtensionFactory; +VALUE eX509ExtensionError; + +/* + * Structs + */ +typedef struct ossl_x509ext_st { + X509_EXTENSION *extension; +} ossl_x509ext; + +typedef struct ossl_x509extfactory_st { + X509V3_CTX ctx; +} ossl_x509extfactory; + + +static void ossl_x509ext_free(ossl_x509ext *extp) +{ + if (extp) { + if (extp->extension) X509_EXTENSION_free(extp->extension); + free(extp); + } +} + +static void ossl_x509extfactory_free(ossl_x509extfactory *extfactoryp) +{ + if (extfactoryp) { + free(extfactoryp); + } +} + +/* + * public + */ +VALUE ossl_x509ext_new2(X509_EXTENSION *ext) +{ + ossl_x509ext *extp = NULL; + X509_EXTENSION *new = NULL; + VALUE obj; + + MakeX509Ext(obj, extp); + if (!(new = X509_EXTENSION_dup(ext))) { + rb_raise(eX509ExtensionError, "%s", ossl_error()); + } + extp->extension = new; + + return obj; +} + +X509_EXTENSION *ossl_x509ext_get_X509_EXTENSION(VALUE obj) +{ + ossl_x509ext *extp = NULL; + + GetX509Ext(obj, extp); + return X509_EXTENSION_dup(extp->extension); +} + +/* + * private + */ +static VALUE ossl_x509extfactory_s_new(int argc, VALUE *argv, VALUE klass) +{ + ossl_x509extfactory *extfactoryp = NULL; + VALUE obj; + + MakeX509ExtFactory(obj, extfactoryp); + rb_obj_call_init(obj, argc, argv); + return obj; +} + +static VALUE ossl_x509extfactory_set_issuer_cert(VALUE self, VALUE cert) +{ + ossl_x509extfactory *extfactoryp = NULL; + + GetX509ExtFactory(self, extfactoryp); + + OSSL_Check_Type(cert, cX509Certificate); + (extfactoryp->ctx).issuer_cert = ossl_x509_get_X509(cert); + + return cert; +} + +static VALUE ossl_x509extfactory_set_subject_cert(VALUE self, VALUE cert) +{ + ossl_x509extfactory *extfactoryp = NULL; + + GetX509ExtFactory(self, extfactoryp); + + OSSL_Check_Type(cert, cX509Certificate); + (extfactoryp->ctx).subject_cert = ossl_x509_get_X509(cert); + + return cert; +} + +static VALUE ossl_x509extfactory_set_subject_req(VALUE self, VALUE req) +{ + ossl_x509extfactory *extfactoryp = NULL; + + GetX509ExtFactory(self, extfactoryp); + + OSSL_Check_Type(req, cX509Request); + (extfactoryp->ctx).subject_req = ossl_x509req_get_X509_REQ(req); + + return req; +} + +static VALUE ossl_x509extfactory_set_crl(VALUE self, VALUE crl) +{ + ossl_x509extfactory *extfactoryp = NULL; + + GetX509ExtFactory(self, extfactoryp); + + OSSL_Check_Type(crl, cX509CRL); + (extfactoryp->ctx).crl = ossl_x509crl_get_X509_CRL(crl); + + return crl; +} + +static VALUE ossl_x509extfactory_initialize(int argc, VALUE *argv, VALUE self) +{ + ossl_x509extfactory *extfactoryp = NULL; + VALUE issuer_cert, subject_cert, subject_req, crl; + + GetX509ExtFactory(self, extfactoryp); + + rb_scan_args(argc, argv, "04", &issuer_cert, &subject_cert, &subject_req, &crl); + + if (!NIL_P(issuer_cert)) { + ossl_x509extfactory_set_issuer_cert(self, issuer_cert); + } + if (!NIL_P(subject_cert)) { + ossl_x509extfactory_set_subject_cert(self, subject_cert); + } + if (!NIL_P(subject_req)) { + ossl_x509extfactory_set_subject_req(self, subject_req); + } + if (!NIL_P(crl)) { + ossl_x509extfactory_set_crl(self, crl); + } + + return self; +} + +/* +X509_NAME *str_to_x509ext(VALUE str) +{ + X509_NAME *name = NULL; + + rb_raise(eX509ExtensionError, "TODO!"); + + Check_Type(str, T_STRING); + if (!(name = X509_NAME_new())) { + rb_raise(eX509ExtensionError, "%s", ossl_error()); + } +} + */ + +/* + * Array to X509_EXTENSION + * Structure: + * ["ln", "value", bool_critical] or + * ["sn", "value", bool_critical] or + * ["ln", "critical,value"] or the same for sn + * ["ln", "value"] => not critical + */ +X509_EXTENSION *ary_to_x509ext(VALUE ary, X509V3_CTX *ctx) +{ + X509_EXTENSION *ext = NULL; + int nid = NID_undef; + char *value = NULL; + VALUE item; + + Check_Type(ary, T_ARRAY); + + if ((RARRAY(ary)->len) < 2 || (RARRAY(ary)->len > 3)) { /*2 or 3 allowed*/ + rb_raise(eX509ExtensionError, "unsupported structure"); + } + if (!(ext = X509_EXTENSION_new())) { + rb_raise(eX509ExtensionError, "%s", ossl_error()); + } + /* key [0] */ + item = RARRAY(ary)->ptr[0]; + Check_Type(item, T_STRING); + if (!(nid = OBJ_ln2nid(RSTRING(item)->ptr))) + if (!(nid = OBJ_sn2nid(RSTRING(item)->ptr))) + rb_raise(eX509ExtensionError, "%s", ossl_error()); + /* data [1] */ + item = RARRAY(ary)->ptr[1]; + Check_Type(item, T_STRING); + + /* (optional) critical [2] */ + if (RARRAY(ary)->len == 3 && RARRAY(ary)->ptr[2] == Qtrue) { + if (!(value = malloc((RSTRING(item)->len)+strlen("critical,")+1))) { + rb_raise(eX509ExtensionError, "malloc error"); + } + strcpy(value, "critical,"); + strncat(value, RSTRING(item)->ptr, RSTRING(item)->len); + } else + value = strdup(RSTRING(item)->ptr); + + if (!(ext = X509V3_EXT_conf_nid(NULL, ctx, nid, value))) { + free(value); + rb_raise(eX509ExtensionError, "%s", ossl_error()); + } + free(value); + + return ext; +} + +static VALUE ossl_x509extfactory_create_extension(int argc, VALUE *argv, VALUE self) +{ + ossl_x509extfactory *extfactoryp = NULL; + ossl_x509ext *extp = NULL; + X509_EXTENSION *ext = NULL; + VALUE obj,ary,arg1,arg2,arg3; + + GetX509ExtFactory(self, extfactoryp); + + switch (rb_scan_args(argc, argv, "12", &arg1, &arg2, &arg3)) { + case 1: + ary = arg1; + break; + case 2: + arg3 = Qnil; + case 3: + ary = rb_ary_new2(3); + rb_ary_push(ary, arg1); + rb_ary_push(ary, arg2); + rb_ary_push(ary, arg3); + break; + default: + rb_raise(rb_eTypeError, "unsupported type"); + } + + switch (TYPE(ary)) { + /* + case T_STRING: + ext = str_to_x509ext(ary); + break; + */ + case T_ARRAY: + ext = ary_to_x509ext(ary, &(extfactoryp->ctx)); + break; + default: + rb_raise(rb_eTypeError, "unsupported type"); + } + + MakeX509Ext(obj, extp); + extp->extension = ext; + + return obj; +} + +static VALUE ossl_x509ext_to_str(VALUE obj) +{ + ossl_x509ext *extp = NULL; + BIO *out = NULL; + BUF_MEM *buf = NULL; + int nid = NID_undef, critical; + VALUE str; + + GetX509Ext(obj, extp); + + if (!(out = BIO_new(BIO_s_mem()))) { + rb_raise(eX509ExtensionError, "%s", ossl_error()); + } + + /* + * TODO: + * User defined user format + */ + nid = OBJ_obj2nid(X509_EXTENSION_get_object(extp->extension)); + BIO_printf(out, "OID=%s, VALUE=", (nid == NID_undef)?"UNKNOWN":OBJ_nid2sn(nid)); /*OBJ_nid2ln(nid)*/ + if (!X509V3_EXT_print(out, extp->extension, 0, 0)) { + rb_raise(eX509ExtensionError, "%s", ossl_error()); + } + critical = X509_EXTENSION_get_critical(extp->extension); + BIO_printf(out,", critical = %s\n", (critical)?"yes":"no"); + BIO_get_mem_ptr(out, &buf); + str = rb_str_new(buf->data, buf->length); + BIO_free(out); + + return str; +} + +static VALUE ossl_x509ext_to_a(VALUE obj) +{ + ossl_x509ext *extp = NULL; + BIO *out = NULL; + BUF_MEM *buf = NULL; + int nid = NID_undef, critical; + VALUE ary, value; + + GetX509Ext(obj, extp); + + ary = rb_ary_new2(3); + + nid = OBJ_obj2nid(X509_EXTENSION_get_object(extp->extension)); + rb_ary_push(ary, rb_str_new2((nid == NID_undef)?"UNKNOWN":OBJ_nid2sn(nid))); + + if (!(out = BIO_new(BIO_s_mem()))) { + rb_raise(eX509ExtensionError, "%s", ossl_error()); + } + if (!X509V3_EXT_print(out, extp->extension, 0, 0)) { + rb_raise(eX509ExtensionError, "%s", ossl_error()); + } + BIO_get_mem_ptr(out, &buf); + value = rb_str_new(buf->data, buf->length); + BIO_free(out); + + rb_funcall(value, rb_intern("tr!"), 2, rb_str_new2("\n"), rb_str_new2(",")); + rb_ary_push(ary, value); + + critical = X509_EXTENSION_get_critical(extp->extension); + rb_ary_push(ary, (critical)?Qtrue:Qfalse); + + return ary; +} + +void Init_ossl_x509ext(VALUE mX509) +{ + + eX509ExtensionError = rb_define_class_under(mX509, "ExtensionError", rb_eStandardError); + + cX509ExtensionFactory = rb_define_class_under(mX509, "ExtensionFactory", rb_cObject); + rb_define_singleton_method(cX509ExtensionFactory, "new", ossl_x509extfactory_s_new, -1); + rb_define_method(cX509ExtensionFactory, "initialize", ossl_x509extfactory_initialize, -1); + rb_define_method(cX509ExtensionFactory, "issuer_certificate=", ossl_x509extfactory_set_issuer_cert, 1); + rb_define_method(cX509ExtensionFactory, "subject_certificate=", ossl_x509extfactory_set_subject_cert, 1); + rb_define_method(cX509ExtensionFactory, "subject_request=", ossl_x509extfactory_set_subject_req, 1); + rb_define_method(cX509ExtensionFactory, "crl=", ossl_x509extfactory_set_crl, 1); + rb_define_method(cX509ExtensionFactory, "create_extension", ossl_x509extfactory_create_extension, -1); + + cX509Extension = rb_define_class_under(mX509, "Extension", rb_cObject); + rb_undef_method(CLASS_OF(cX509Extension), "new"); +/* + rb_define_singleton_method(cX509Extension, "new", ossl_x509ext_s_new, -1); + rb_define_method(cX509Extension, "initialize", ossl_x509ext_initialize, -1); + */ + rb_define_method(cX509Extension, "to_str", ossl_x509ext_to_str, 0); + rb_define_method(cX509Extension, "to_a", ossl_x509ext_to_a, 0); +} + |