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 ID 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
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 static VALUE
00133 ossl_x509name_initialize(int argc, VALUE *argv, VALUE self)
00134 {
00135 X509_NAME *name;
00136 VALUE arg, template;
00137
00138 GetX509Name(self, name);
00139 if (rb_scan_args(argc, argv, "02", &arg, &template) == 0) {
00140 return self;
00141 }
00142 else {
00143 VALUE tmp = rb_check_array_type(arg);
00144 if (!NIL_P(tmp)) {
00145 VALUE args;
00146 if(NIL_P(template)) template = OBJECT_TYPE_TEMPLATE;
00147 args = rb_ary_new3(2, self, template);
00148 rb_block_call(tmp, rb_intern("each"), 0, 0, ossl_x509name_init_i, args);
00149 }
00150 else{
00151 const unsigned char *p;
00152 VALUE str = ossl_to_der_if_possible(arg);
00153 X509_NAME *x;
00154 StringValue(str);
00155 p = (unsigned char *)RSTRING_PTR(str);
00156 x = d2i_X509_NAME(&name, &p, RSTRING_LEN(str));
00157 DATA_PTR(self) = name;
00158 if(!x){
00159 ossl_raise(eX509NameError, NULL);
00160 }
00161 }
00162 }
00163
00164 return self;
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 static
00182 VALUE ossl_x509name_add_entry(int argc, VALUE *argv, VALUE self)
00183 {
00184 X509_NAME *name;
00185 VALUE oid, value, type;
00186
00187 rb_scan_args(argc, argv, "21", &oid, &value, &type);
00188 StringValue(oid);
00189 StringValue(value);
00190 if(NIL_P(type)) type = rb_aref(OBJECT_TYPE_TEMPLATE, oid);
00191 GetX509Name(self, name);
00192 if (!X509_NAME_add_entry_by_txt(name, RSTRING_PTR(oid), NUM2INT(type),
00193 (const unsigned char *)RSTRING_PTR(value), RSTRING_LENINT(value), -1, 0)) {
00194 ossl_raise(eX509NameError, NULL);
00195 }
00196
00197 return self;
00198 }
00199
00200 static VALUE
00201 ossl_x509name_to_s_old(VALUE self)
00202 {
00203 X509_NAME *name;
00204 char *buf;
00205 VALUE str;
00206
00207 GetX509Name(self, name);
00208 buf = X509_NAME_oneline(name, NULL, 0);
00209 str = rb_str_new2(buf);
00210 OPENSSL_free(buf);
00211
00212 return str;
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 static VALUE
00228 ossl_x509name_to_s(int argc, VALUE *argv, VALUE self)
00229 {
00230 X509_NAME *name;
00231 VALUE flag, str;
00232 BIO *out;
00233 unsigned long iflag;
00234
00235 rb_scan_args(argc, argv, "01", &flag);
00236 if (NIL_P(flag))
00237 return ossl_x509name_to_s_old(self);
00238 else iflag = NUM2ULONG(flag);
00239 if (!(out = BIO_new(BIO_s_mem())))
00240 ossl_raise(eX509NameError, NULL);
00241 GetX509Name(self, name);
00242 if (!X509_NAME_print_ex(out, name, 0, iflag)){
00243 BIO_free(out);
00244 ossl_raise(eX509NameError, NULL);
00245 }
00246 str = ossl_membio2str(out);
00247
00248 return str;
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00258 static VALUE
00259 ossl_x509name_to_a(VALUE self)
00260 {
00261 X509_NAME *name;
00262 X509_NAME_ENTRY *entry;
00263 int i,entries,nid;
00264 char long_name[512];
00265 const char *short_name;
00266 VALUE ary, vname, ret;
00267
00268 GetX509Name(self, name);
00269 entries = X509_NAME_entry_count(name);
00270 if (entries < 0) {
00271 OSSL_Debug("name entries < 0!");
00272 return rb_ary_new();
00273 }
00274 ret = rb_ary_new2(entries);
00275 for (i=0; i<entries; i++) {
00276 if (!(entry = X509_NAME_get_entry(name, i))) {
00277 ossl_raise(eX509NameError, NULL);
00278 }
00279 if (!i2t_ASN1_OBJECT(long_name, sizeof(long_name), entry->object)) {
00280 ossl_raise(eX509NameError, NULL);
00281 }
00282 nid = OBJ_ln2nid(long_name);
00283 if (nid == NID_undef) {
00284 vname = rb_str_new2((const char *) &long_name);
00285 } else {
00286 short_name = OBJ_nid2sn(nid);
00287 vname = rb_str_new2(short_name);
00288 }
00289 ary = rb_ary_new3(3,
00290 vname,
00291 rb_str_new((const char *)entry->value->data, entry->value->length),
00292 INT2FIX(entry->value->type));
00293 rb_ary_push(ret, ary);
00294 }
00295 return ret;
00296 }
00297
00298 static int
00299 ossl_x509name_cmp0(VALUE self, VALUE other)
00300 {
00301 X509_NAME *name1, *name2;
00302
00303 GetX509Name(self, name1);
00304 SafeGetX509Name(other, name2);
00305
00306 return X509_NAME_cmp(name1, name2);
00307 }
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 static VALUE
00318 ossl_x509name_cmp(VALUE self, VALUE other)
00319 {
00320 int result;
00321
00322 result = ossl_x509name_cmp0(self, other);
00323 if (result < 0) return INT2FIX(-1);
00324 if (result > 1) return INT2FIX(1);
00325
00326 return INT2FIX(0);
00327 }
00328
00329
00330
00331
00332
00333
00334
00335 static VALUE
00336 ossl_x509name_eql(VALUE self, VALUE other)
00337 {
00338 int result;
00339
00340 if(CLASS_OF(other) != cX509Name) return Qfalse;
00341 result = ossl_x509name_cmp0(self, other);
00342
00343 return (result == 0) ? Qtrue : Qfalse;
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353 static VALUE
00354 ossl_x509name_hash(VALUE self)
00355 {
00356 X509_NAME *name;
00357 unsigned long hash;
00358
00359 GetX509Name(self, name);
00360
00361 hash = X509_NAME_hash(name);
00362
00363 return ULONG2NUM(hash);
00364 }
00365
00366 #ifdef HAVE_X509_NAME_HASH_OLD
00367
00368
00369
00370
00371
00372
00373 static VALUE
00374 ossl_x509name_hash_old(VALUE self)
00375 {
00376 X509_NAME *name;
00377 unsigned long hash;
00378
00379 GetX509Name(self, name);
00380
00381 hash = X509_NAME_hash_old(name);
00382
00383 return ULONG2NUM(hash);
00384 }
00385 #endif
00386
00387
00388
00389
00390
00391
00392
00393 static VALUE
00394 ossl_x509name_to_der(VALUE self)
00395 {
00396 X509_NAME *name;
00397 VALUE str;
00398 long len;
00399 unsigned char *p;
00400
00401 GetX509Name(self, name);
00402 if((len = i2d_X509_NAME(name, NULL)) <= 0)
00403 ossl_raise(eX509NameError, NULL);
00404 str = rb_str_new(0, len);
00405 p = (unsigned char *)RSTRING_PTR(str);
00406 if(i2d_X509_NAME(name, &p) <= 0)
00407 ossl_raise(eX509NameError, NULL);
00408 ossl_str_adjust(str, p);
00409
00410 return str;
00411 }
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427 void
00428 Init_ossl_x509name()
00429 {
00430 VALUE utf8str, ptrstr, ia5str, hash;
00431
00432 id_aref = rb_intern("[]");
00433 eX509NameError = rb_define_class_under(mX509, "NameError", eOSSLError);
00434 cX509Name = rb_define_class_under(mX509, "Name", rb_cObject);
00435
00436 rb_include_module(cX509Name, rb_mComparable);
00437
00438 rb_define_alloc_func(cX509Name, ossl_x509name_alloc);
00439 rb_define_method(cX509Name, "initialize", ossl_x509name_initialize, -1);
00440 rb_define_method(cX509Name, "add_entry", ossl_x509name_add_entry, -1);
00441 rb_define_method(cX509Name, "to_s", ossl_x509name_to_s, -1);
00442 rb_define_method(cX509Name, "to_a", ossl_x509name_to_a, 0);
00443 rb_define_method(cX509Name, "cmp", ossl_x509name_cmp, 1);
00444 rb_define_alias(cX509Name, "<=>", "cmp");
00445 rb_define_method(cX509Name, "eql?", ossl_x509name_eql, 1);
00446 rb_define_method(cX509Name, "hash", ossl_x509name_hash, 0);
00447 #ifdef HAVE_X509_NAME_HASH_OLD
00448 rb_define_method(cX509Name, "hash_old", ossl_x509name_hash_old, 0);
00449 #endif
00450 rb_define_method(cX509Name, "to_der", ossl_x509name_to_der, 0);
00451
00452 utf8str = INT2NUM(V_ASN1_UTF8STRING);
00453 ptrstr = INT2NUM(V_ASN1_PRINTABLESTRING);
00454 ia5str = INT2NUM(V_ASN1_IA5STRING);
00455
00456
00457
00458
00459
00460 rb_define_const(cX509Name, "DEFAULT_OBJECT_TYPE", utf8str);
00461 hash = rb_hash_new();
00462 RHASH(hash)->ifnone = utf8str;
00463 rb_hash_aset(hash, rb_str_new2("C"), ptrstr);
00464 rb_hash_aset(hash, rb_str_new2("countryName"), ptrstr);
00465 rb_hash_aset(hash, rb_str_new2("serialNumber"), ptrstr);
00466 rb_hash_aset(hash, rb_str_new2("dnQualifier"), ptrstr);
00467 rb_hash_aset(hash, rb_str_new2("DC"), ia5str);
00468 rb_hash_aset(hash, rb_str_new2("domainComponent"), ia5str);
00469 rb_hash_aset(hash, rb_str_new2("emailAddress"), ia5str);
00470
00471
00472
00473
00474
00475 rb_define_const(cX509Name, "OBJECT_TYPE_TEMPLATE", hash);
00476
00477
00478
00479
00480
00481
00482
00483
00484 rb_define_const(cX509Name, "COMPAT", ULONG2NUM(XN_FLAG_COMPAT));
00485
00486
00487
00488
00489
00490
00491
00492 rb_define_const(cX509Name, "RFC2253", ULONG2NUM(XN_FLAG_RFC2253));
00493
00494
00495
00496
00497
00498
00499
00500 rb_define_const(cX509Name, "ONELINE", ULONG2NUM(XN_FLAG_ONELINE));
00501
00502
00503
00504
00505
00506
00507
00508 rb_define_const(cX509Name, "MULTILINE", ULONG2NUM(XN_FLAG_MULTILINE));
00509 }
00510