Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# ext/openssl/ossl_x509name.c

Go to the documentation of this file.

    00001 /*
    00002  * $Id: ossl_x509name.c 27440 2010-04-22 08:21:01Z nobu $
    00003  * 'OpenSSL for Ruby' project
    00004  * Copyright (C) 2001 Michal Rokos <m.rokos@sh.cvut.cz>
    00005  * All rights reserved.
    00006  */
    00007 /*
    00008  * This program is licenced under the same licence as Ruby.
    00009  * (See the file 'LICENCE'.)
    00010  */
    00011 #include "ossl.h"
    00012
    00013 #define WrapX509Name(klass, obj, name) do { \
    00014     if (!name) { \
    00015         ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \
    00016     } \
    00017     obj = Data_Wrap_Struct(klass, 0, X509_NAME_free, name); \
    00018 } while (0)
    00019 #define GetX509Name(obj, name) do { \
    00020     Data_Get_Struct(obj, X509_NAME, name); \
    00021     if (!name) { \
    00022         ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \
    00023     } \
    00024 } while (0)
    00025 #define SafeGetX509Name(obj, name) do { \
    00026     OSSL_Check_Kind(obj, cX509Name); \
    00027     GetX509Name(obj, name); \
    00028 } while (0)
    00029
    00030 #define OBJECT_TYPE_TEMPLATE \
    00031   rb_const_get(cX509Name, rb_intern("OBJECT_TYPE_TEMPLATE"))
    00032 #define DEFAULT_OBJECT_TYPE \
    00033   rb_const_get(cX509Name, rb_intern("DEFAULT_OBJECT_TYPE"))
    00034
    00035 /*
    00036  * Classes
    00037  */
    00038 VALUE cX509Name;
    00039 VALUE eX509NameError;
    00040
    00041 /*
    00042  * Public
    00043  */
    00044 VALUE
    00045 ossl_x509name_new(X509_NAME *name)
    00046 {
    00047     X509_NAME *new;
    00048     VALUE obj;
    00049
    00050     if (!name) {
    00051         new = X509_NAME_new();
    00052     } else {
    00053         new = X509_NAME_dup(name);
    00054     }
    00055     if (!new) {
    00056         ossl_raise(eX509NameError, NULL);
    00057     }
    00058     WrapX509Name(cX509Name, obj, new);
    00059
    00060     return obj;
    00061 }
    00062
    00063 X509_NAME *
    00064 GetX509NamePtr(VALUE obj)
    00065 {
    00066     X509_NAME *name;
    00067
    00068     SafeGetX509Name(obj, name);
    00069
    00070     return name;
    00071 }
    00072
    00073 /*
    00074  * Private
    00075  */
    00076 static VALUE
    00077 ossl_x509name_alloc(VALUE klass)
    00078 {
    00079     X509_NAME *name;
    00080     VALUE obj;
    00081
    00082     if (!(name = X509_NAME_new())) {
    00083         ossl_raise(eX509NameError, NULL);
    00084     }
    00085     WrapX509Name(klass, obj, name);
    00086
    00087     return obj;
    00088 }
    00089
    00090 static int id_aref;
    00091 static VALUE ossl_x509name_add_entry(int, VALUE*, VALUE);
    00092 #define rb_aref(obj, key) rb_funcall(obj, id_aref, 1, key)
    00093
    00094 static VALUE
    00095 ossl_x509name_init_i(VALUE i, VALUE args)
    00096 {
    00097     VALUE self = rb_ary_entry(args, 0);
    00098     VALUE template = rb_ary_entry(args, 1);
    00099     VALUE entry[3];
    00100
    00101     Check_Type(i, T_ARRAY);
    00102     entry[0] = rb_ary_entry(i, 0);
    00103     entry[1] = rb_ary_entry(i, 1);
    00104     entry[2] = rb_ary_entry(i, 2);
    00105     if(NIL_P(entry[2])) entry[2] = rb_aref(template, entry[0]);
    00106     if(NIL_P(entry[2])) entry[2] = DEFAULT_OBJECT_TYPE;
    00107     ossl_x509name_add_entry(3, entry, self);
    00108
    00109     return Qnil;
    00110 }
    00111
    00112 /*
    00113  * call-seq:
    00114  *    X509::Name.new => name
    00115  *    X509::Name.new(string) => name
    00116  *    X509::Name.new(dn) => name
    00117  *    X509::Name.new(dn, template) => name
    00118  */
    00119 static VALUE
    00120 ossl_x509name_initialize(int argc, VALUE *argv, VALUE self)
    00121 {
    00122     X509_NAME *name;
    00123     VALUE arg, template;
    00124
    00125     GetX509Name(self, name);
    00126     if (rb_scan_args(argc, argv, "02", &arg, &template) == 0) {
    00127         return self;
    00128     }
    00129     else {
    00130         VALUE tmp = rb_check_array_type(arg);
    00131         if (!NIL_P(tmp)) {
    00132             VALUE args;
    00133             if(NIL_P(template)) template = OBJECT_TYPE_TEMPLATE;
    00134             args = rb_ary_new3(2, self, template);
    00135             rb_block_call(tmp, rb_intern("each"), 0, 0, ossl_x509name_init_i, args);
    00136         }
    00137         else{
    00138             const unsigned char *p;
    00139             VALUE str = ossl_to_der_if_possible(arg);
    00140             X509_NAME *x;
    00141             StringValue(str);
    00142             p = (unsigned char *)RSTRING_PTR(str);
    00143             x = d2i_X509_NAME(&name, &p, RSTRING_LEN(str));
    00144             DATA_PTR(self) = name;
    00145             if(!x){
    00146                 ossl_raise(eX509NameError, NULL);
    00147             }
    00148         }
    00149     }
    00150
    00151     return self;
    00152 }
    00153
    00154 /*
    00155  * call-seq:
    00156  *    name.add_entry(oid, value [, type]) => self
    00157  */
    00158 static
    00159 VALUE ossl_x509name_add_entry(int argc, VALUE *argv, VALUE self)
    00160 {
    00161     X509_NAME *name;
    00162     VALUE oid, value, type;
    00163
    00164     rb_scan_args(argc, argv, "21", &oid, &value, &type);
    00165     StringValue(oid);
    00166     StringValue(value);
    00167     if(NIL_P(type)) type = rb_aref(OBJECT_TYPE_TEMPLATE, oid);
    00168     GetX509Name(self, name);
    00169     if (!X509_NAME_add_entry_by_txt(name, RSTRING_PTR(oid), NUM2INT(type),
    00170                 (const unsigned char *)RSTRING_PTR(value), RSTRING_LEN(value), -1, 0)) {
    00171         ossl_raise(eX509NameError, NULL);
    00172     }
    00173
    00174     return self;
    00175 }
    00176
    00177 static VALUE
    00178 ossl_x509name_to_s_old(VALUE self)
    00179 {
    00180     X509_NAME *name;
    00181     char *buf;
    00182     VALUE str;
    00183
    00184     GetX509Name(self, name);
    00185     buf = X509_NAME_oneline(name, NULL, 0);
    00186     str = rb_str_new2(buf);
    00187     OPENSSL_free(buf);
    00188
    00189     return str;
    00190 }
    00191
    00192 /*
    00193  * call-seq:
    00194  *    name.to_s => string
    00195  *    name.to_s(integer) => string
    00196  */
    00197 static VALUE
    00198 ossl_x509name_to_s(int argc, VALUE *argv, VALUE self)
    00199 {
    00200     X509_NAME *name;
    00201     VALUE flag, str;
    00202     BIO *out;
    00203     unsigned long iflag;
    00204
    00205     rb_scan_args(argc, argv, "01", &flag);
    00206     if (NIL_P(flag))
    00207         return ossl_x509name_to_s_old(self);
    00208     else iflag = NUM2ULONG(flag);
    00209     if (!(out = BIO_new(BIO_s_mem())))
    00210         ossl_raise(eX509NameError, NULL);
    00211     GetX509Name(self, name);
    00212     if (!X509_NAME_print_ex(out, name, 0, iflag)){
    00213         BIO_free(out);
    00214         ossl_raise(eX509NameError, NULL);
    00215     }
    00216     str = ossl_membio2str(out);
    00217
    00218     return str;
    00219 }
    00220
    00221 /*
    00222  * call-seq:
    00223  *    name.to_a => [[name, data, type], ...]
    00224  */
    00225 static VALUE
    00226 ossl_x509name_to_a(VALUE self)
    00227 {
    00228     X509_NAME *name;
    00229     X509_NAME_ENTRY *entry;
    00230     int i,entries;
    00231     char long_name[512];
    00232     const char *short_name;
    00233     VALUE ary, ret;
    00234
    00235     GetX509Name(self, name);
    00236     entries = X509_NAME_entry_count(name);
    00237     if (entries < 0) {
    00238         OSSL_Debug("name entries < 0!");
    00239         return rb_ary_new();
    00240     }
    00241     ret = rb_ary_new2(entries);
    00242     for (i=0; i<entries; i++) {
    00243         if (!(entry = X509_NAME_get_entry(name, i))) {
    00244             ossl_raise(eX509NameError, NULL);
    00245         }
    00246         if (!i2t_ASN1_OBJECT(long_name, sizeof(long_name), entry->object)) {
    00247             ossl_raise(eX509NameError, NULL);
    00248         }
    00249         short_name = OBJ_nid2sn(OBJ_ln2nid(long_name));
    00250         ary = rb_ary_new3(3, rb_str_new2(short_name),
    00251                           rb_str_new((const char *)entry->value->data, entry->value->length),
    00252                           INT2FIX(entry->value->type));
    00253         rb_ary_push(ret, ary);
    00254     }
    00255     return ret;
    00256 }
    00257
    00258 static int
    00259 ossl_x509name_cmp0(VALUE self, VALUE other)
    00260 {
    00261     X509_NAME *name1, *name2;
    00262
    00263     GetX509Name(self, name1);
    00264     SafeGetX509Name(other, name2);
    00265
    00266     return X509_NAME_cmp(name1, name2);
    00267 }
    00268
    00269 static VALUE
    00270 ossl_x509name_cmp(VALUE self, VALUE other)
    00271 {
    00272     int result;
    00273
    00274     result = ossl_x509name_cmp0(self, other);
    00275     if (result < 0) return INT2FIX(-1);
    00276     if (result > 1) return INT2FIX(1);
    00277
    00278     return INT2FIX(0);
    00279 }
    00280
    00281 static VALUE
    00282 ossl_x509name_eql(VALUE self, VALUE other)
    00283 {
    00284     int result;
    00285
    00286     if(CLASS_OF(other) != cX509Name) return Qfalse;
    00287     result = ossl_x509name_cmp0(self, other);
    00288
    00289     return (result == 0) ? Qtrue : Qfalse;
    00290 }
    00291
    00292 /*
    00293  * call-seq:
    00294  *    name.hash => integer
    00295  */
    00296 static VALUE
    00297 ossl_x509name_hash(VALUE self)
    00298 {
    00299     X509_NAME *name;
    00300     unsigned long hash;
    00301
    00302     GetX509Name(self, name);
    00303
    00304     hash = X509_NAME_hash(name);
    00305
    00306     return ULONG2NUM(hash);
    00307 }
    00308
    00309 /*
    00310  * call-seq:
    00311  *    name.to_der => string
    00312  */
    00313 static VALUE
    00314 ossl_x509name_to_der(VALUE self)
    00315 {
    00316     X509_NAME *name;
    00317     VALUE str;
    00318     long len;
    00319     unsigned char *p;
    00320
    00321     GetX509Name(self, name);
    00322     if((len = i2d_X509_NAME(name, NULL)) <= 0)
    00323         ossl_raise(eX509NameError, NULL);
    00324     str = rb_str_new(0, len);
    00325     p = (unsigned char *)RSTRING_PTR(str);
    00326     if(i2d_X509_NAME(name, &p) <= 0)
    00327         ossl_raise(eX509NameError, NULL);
    00328     ossl_str_adjust(str, p);
    00329
    00330     return str;
    00331 }
    00332
    00333 /*
    00334  * INIT
    00335  */
    00336 void
    00337 Init_ossl_x509name()
    00338 {
    00339     VALUE utf8str, ptrstr, ia5str, hash;
    00340
    00341     id_aref = rb_intern("[]");
    00342     eX509NameError = rb_define_class_under(mX509, "NameError", eOSSLError);
    00343     cX509Name = rb_define_class_under(mX509, "Name", rb_cObject);
    00344
    00345     rb_define_alloc_func(cX509Name, ossl_x509name_alloc);
    00346     rb_define_method(cX509Name, "initialize", ossl_x509name_initialize, -1);
    00347     rb_define_method(cX509Name, "add_entry", ossl_x509name_add_entry, -1);
    00348     rb_define_method(cX509Name, "to_s", ossl_x509name_to_s, -1);
    00349     rb_define_method(cX509Name, "to_a", ossl_x509name_to_a, 0);
    00350     rb_define_method(cX509Name, "cmp", ossl_x509name_cmp, 1);
    00351     rb_define_alias(cX509Name, "<=>", "cmp");
    00352     rb_define_method(cX509Name, "eql?", ossl_x509name_eql, 1);
    00353     rb_define_method(cX509Name, "hash", ossl_x509name_hash, 0);
    00354     rb_define_method(cX509Name, "to_der", ossl_x509name_to_der, 0);
    00355
    00356     utf8str = INT2NUM(V_ASN1_UTF8STRING);
    00357     ptrstr = INT2NUM(V_ASN1_PRINTABLESTRING);
    00358     ia5str = INT2NUM(V_ASN1_IA5STRING);
    00359     rb_define_const(cX509Name, "DEFAULT_OBJECT_TYPE", utf8str);
    00360     hash = rb_hash_new();
    00361     RHASH(hash)->ifnone = utf8str;
    00362     rb_hash_aset(hash, rb_str_new2("C"), ptrstr);
    00363     rb_hash_aset(hash, rb_str_new2("countryName"), ptrstr);
    00364     rb_hash_aset(hash, rb_str_new2("serialNumber"), ptrstr);
    00365     rb_hash_aset(hash, rb_str_new2("dnQualifier"), ptrstr);
    00366     rb_hash_aset(hash, rb_str_new2("DC"), ia5str);
    00367     rb_hash_aset(hash, rb_str_new2("domainComponent"), ia5str);
    00368     rb_hash_aset(hash, rb_str_new2("emailAddress"), ia5str);
    00369     rb_define_const(cX509Name, "OBJECT_TYPE_TEMPLATE", hash);
    00370
    00371     rb_define_const(cX509Name, "COMPAT", ULONG2NUM(XN_FLAG_COMPAT));
    00372     rb_define_const(cX509Name, "RFC2253", ULONG2NUM(XN_FLAG_RFC2253));
    00373     rb_define_const(cX509Name, "ONELINE", ULONG2NUM(XN_FLAG_ONELINE));
    00374     rb_define_const(cX509Name, "MULTILINE", ULONG2NUM(XN_FLAG_MULTILINE));
    00375 }
    00376