• 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 

Generated on Wed Sep 8 2010 21:54:12 for Ruby by  doxygen 1.7.1