00001
00002
00003
00004
00005
00006
00007
00008
00009
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
00037
00038 VALUE cX509Name;
00039 VALUE eX509NameError;
00040
00041
00042
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
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
00114
00115
00116
00117
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
00156
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
00194
00195
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
00223
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
00294
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
00311
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
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