Ruby  2.4.2p198(2017-09-14revision59899)
ossl_x509name.c
Go to the documentation of this file.
1 /*
2  * 'OpenSSL for Ruby' project
3  * Copyright (C) 2001 Michal Rokos <m.rokos@sh.cvut.cz>
4  * All rights reserved.
5  */
6 /*
7  * This program is licensed under the same licence as Ruby.
8  * (See the file 'LICENCE'.)
9  */
10 #include "ossl.h"
11 
12 #define NewX509Name(klass) \
13  TypedData_Wrap_Struct((klass), &ossl_x509name_type, 0)
14 #define SetX509Name(obj, name) do { \
15  if (!(name)) { \
16  ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \
17  } \
18  RTYPEDDATA_DATA(obj) = (name); \
19 } while (0)
20 #define GetX509Name(obj, name) do { \
21  TypedData_Get_Struct((obj), X509_NAME, &ossl_x509name_type, (name)); \
22  if (!(name)) { \
23  ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \
24  } \
25 } while (0)
26 #define SafeGetX509Name(obj, name) do { \
27  OSSL_Check_Kind((obj), cX509Name); \
28  GetX509Name((obj), (name)); \
29 } while (0)
30 
31 #define OBJECT_TYPE_TEMPLATE \
32  rb_const_get(cX509Name, rb_intern("OBJECT_TYPE_TEMPLATE"))
33 #define DEFAULT_OBJECT_TYPE \
34  rb_const_get(cX509Name, rb_intern("DEFAULT_OBJECT_TYPE"))
35 
36 /*
37  * Classes
38  */
41 
42 static void
44 {
45  X509_NAME_free(ptr);
46 }
47 
49  "OpenSSL/X509/NAME",
50  {
52  },
54 };
55 
56 /*
57  * Public
58  */
59 VALUE
61 {
62  X509_NAME *new;
63  VALUE obj;
64 
65  obj = NewX509Name(cX509Name);
66  if (!name) {
67  new = X509_NAME_new();
68  } else {
69  new = X509_NAME_dup(name);
70  }
71  if (!new) {
73  }
74  SetX509Name(obj, new);
75 
76  return obj;
77 }
78 
79 X509_NAME *
81 {
82  X509_NAME *name;
83 
84  SafeGetX509Name(obj, name);
85 
86  return name;
87 }
88 
89 /*
90  * Private
91  */
92 static VALUE
94 {
95  X509_NAME *name;
96  VALUE obj;
97 
98  obj = NewX509Name(klass);
99  if (!(name = X509_NAME_new())) {
101  }
102  SetX509Name(obj, name);
103 
104  return obj;
105 }
106 
107 static ID id_aref;
109 #define rb_aref(obj, key) rb_funcall((obj), id_aref, 1, (key))
110 
111 static VALUE
113 {
114  VALUE self = rb_ary_entry(args, 0);
115  VALUE template = rb_ary_entry(args, 1);
116  VALUE entry[3];
117 
118  Check_Type(i, T_ARRAY);
119  entry[0] = rb_ary_entry(i, 0);
120  entry[1] = rb_ary_entry(i, 1);
121  entry[2] = rb_ary_entry(i, 2);
122  if(NIL_P(entry[2])) entry[2] = rb_aref(template, entry[0]);
123  if(NIL_P(entry[2])) entry[2] = DEFAULT_OBJECT_TYPE;
124  ossl_x509name_add_entry(3, entry, self);
125 
126  return Qnil;
127 }
128 
129 /*
130  * call-seq:
131  * X509::Name.new => name
132  * X509::Name.new(der) => name
133  * X509::Name.new(distinguished_name) => name
134  * X509::Name.new(distinguished_name, template) => name
135  *
136  * Creates a new Name.
137  *
138  * A name may be created from a DER encoded string +der+, an Array
139  * representing a +distinguished_name+ or a +distinguished_name+ along with a
140  * +template+.
141  *
142  * name = OpenSSL::X509::Name.new [['CN', 'nobody'], ['DC', 'example']]
143  *
144  * name = OpenSSL::X509::Name.new name.to_der
145  *
146  * See add_entry for a description of the +distinguished_name+ Array's
147  * contents
148  */
149 static VALUE
151 {
152  X509_NAME *name;
153  VALUE arg, template;
154 
155  GetX509Name(self, name);
156  if (rb_scan_args(argc, argv, "02", &arg, &template) == 0) {
157  return self;
158  }
159  else {
160  VALUE tmp = rb_check_array_type(arg);
161  if (!NIL_P(tmp)) {
162  VALUE args;
163  if(NIL_P(template)) template = OBJECT_TYPE_TEMPLATE;
164  args = rb_ary_new3(2, self, template);
165  rb_block_call(tmp, rb_intern("each"), 0, 0, ossl_x509name_init_i, args);
166  }
167  else{
168  const unsigned char *p;
169  VALUE str = ossl_to_der_if_possible(arg);
170  X509_NAME *x;
171  StringValue(str);
172  p = (unsigned char *)RSTRING_PTR(str);
173  x = d2i_X509_NAME(&name, &p, RSTRING_LEN(str));
174  DATA_PTR(self) = name;
175  if(!x){
177  }
178  }
179  }
180 
181  return self;
182 }
183 
184 static VALUE
186 {
187  X509_NAME *name, *name_other, *name_new;
188 
189  rb_check_frozen(self);
190  GetX509Name(self, name);
191  SafeGetX509Name(other, name_other);
192 
193  name_new = X509_NAME_dup(name_other);
194  if (!name_new)
195  ossl_raise(eX509NameError, "X509_NAME_dup");
196 
197  SetX509Name(self, name_new);
198  X509_NAME_free(name);
199 
200  return self;
201 }
202 
203 /*
204  * call-seq:
205  * name.add_entry(oid, value [, type]) => self
206  *
207  * Adds a new entry with the given +oid+ and +value+ to this name. The +oid+
208  * is an object identifier defined in ASN.1. Some common OIDs are:
209  *
210  * C:: Country Name
211  * CN:: Common Name
212  * DC:: Domain Component
213  * O:: Organization Name
214  * OU:: Organizational Unit Name
215  * ST:: State or Province Name
216  */
217 static
219 {
220  X509_NAME *name;
221  VALUE oid, value, type;
222  const char *oid_name;
223 
224  rb_scan_args(argc, argv, "21", &oid, &value, &type);
225  oid_name = StringValueCStr(oid);
226  StringValue(value);
227  if(NIL_P(type)) type = rb_aref(OBJECT_TYPE_TEMPLATE, oid);
228  GetX509Name(self, name);
229  if (!X509_NAME_add_entry_by_txt(name, oid_name, NUM2INT(type),
230  (const unsigned char *)RSTRING_PTR(value), RSTRING_LENINT(value), -1, 0)) {
232  }
233 
234  return self;
235 }
236 
237 static VALUE
239 {
240  X509_NAME *name;
241  char *buf;
242  VALUE str;
243 
244  GetX509Name(self, name);
245  buf = X509_NAME_oneline(name, NULL, 0);
246  str = rb_str_new2(buf);
247  OPENSSL_free(buf);
248 
249  return str;
250 }
251 
252 /*
253  * call-seq:
254  * name.to_s => string
255  * name.to_s(flags) => string
256  *
257  * Returns this name as a Distinguished Name string. +flags+ may be one of:
258  *
259  * * OpenSSL::X509::Name::COMPAT
260  * * OpenSSL::X509::Name::RFC2253
261  * * OpenSSL::X509::Name::ONELINE
262  * * OpenSSL::X509::Name::MULTILINE
263  */
264 static VALUE
266 {
267  X509_NAME *name;
268  VALUE flag, str;
269  BIO *out;
270  unsigned long iflag;
271 
272  rb_scan_args(argc, argv, "01", &flag);
273  if (NIL_P(flag))
274  return ossl_x509name_to_s_old(self);
275  else iflag = NUM2ULONG(flag);
276  if (!(out = BIO_new(BIO_s_mem())))
278  GetX509Name(self, name);
279  if (!X509_NAME_print_ex(out, name, 0, iflag)){
280  BIO_free(out);
282  }
283  str = ossl_membio2str(out);
284 
285  return str;
286 }
287 
288 /*
289  * call-seq:
290  * name.to_a => [[name, data, type], ...]
291  *
292  * Returns an Array representation of the distinguished name suitable for
293  * passing to ::new
294  */
295 static VALUE
297 {
298  X509_NAME *name;
299  X509_NAME_ENTRY *entry;
300  int i,entries,nid;
301  char long_name[512];
302  const char *short_name;
303  VALUE ary, vname, ret;
304  ASN1_STRING *value;
305 
306  GetX509Name(self, name);
307  entries = X509_NAME_entry_count(name);
308  if (entries < 0) {
309  OSSL_Debug("name entries < 0!");
310  return rb_ary_new();
311  }
312  ret = rb_ary_new2(entries);
313  for (i=0; i<entries; i++) {
314  if (!(entry = X509_NAME_get_entry(name, i))) {
316  }
317  if (!i2t_ASN1_OBJECT(long_name, sizeof(long_name),
318  X509_NAME_ENTRY_get_object(entry))) {
320  }
321  nid = OBJ_ln2nid(long_name);
322  if (nid == NID_undef) {
323  vname = rb_str_new2((const char *) &long_name);
324  } else {
325  short_name = OBJ_nid2sn(nid);
326  vname = rb_str_new2(short_name); /*do not free*/
327  }
328  value = X509_NAME_ENTRY_get_data(entry);
329  ary = rb_ary_new3(3, vname, asn1str_to_str(value), INT2NUM(value->type));
330  rb_ary_push(ret, ary);
331  }
332  return ret;
333 }
334 
335 static int
337 {
338  X509_NAME *name1, *name2;
339 
340  GetX509Name(self, name1);
341  SafeGetX509Name(other, name2);
342 
343  return X509_NAME_cmp(name1, name2);
344 }
345 
346 /*
347  * call-seq:
348  * name.cmp other => integer
349  * name.<=> other => integer
350  *
351  * Compares this Name with +other+ and returns 0 if they are the same and -1 or
352  * +1 if they are greater or less than each other respectively.
353  */
354 static VALUE
356 {
357  int result;
358 
359  result = ossl_x509name_cmp0(self, other);
360  if (result < 0) return INT2FIX(-1);
361  if (result > 1) return INT2FIX(1);
362 
363  return INT2FIX(0);
364 }
365 
366 /*
367  * call-seq:
368  * name.eql? other => boolean
369  *
370  * Returns true if +name+ and +other+ refer to the same hash key.
371  */
372 static VALUE
374 {
375  if (!rb_obj_is_kind_of(other, cX509Name))
376  return Qfalse;
377 
378  return ossl_x509name_cmp0(self, other) == 0 ? Qtrue : Qfalse;
379 }
380 
381 /*
382  * call-seq:
383  * name.hash => integer
384  *
385  * The hash value returned is suitable for use as a certificate's filename in
386  * a CA path.
387  */
388 static VALUE
390 {
391  X509_NAME *name;
392  unsigned long hash;
393 
394  GetX509Name(self, name);
395 
396  hash = X509_NAME_hash(name);
397 
398  return ULONG2NUM(hash);
399 }
400 
401 #ifdef HAVE_X509_NAME_HASH_OLD
402 /*
403  * call-seq:
404  * name.hash_old => integer
405  *
406  * Returns an MD5 based hash used in OpenSSL 0.9.X.
407  */
408 static VALUE
409 ossl_x509name_hash_old(VALUE self)
410 {
411  X509_NAME *name;
412  unsigned long hash;
413 
414  GetX509Name(self, name);
415 
416  hash = X509_NAME_hash_old(name);
417 
418  return ULONG2NUM(hash);
419 }
420 #endif
421 
422 /*
423  * call-seq:
424  * name.to_der => string
425  *
426  * Converts the name to DER encoding
427  */
428 static VALUE
430 {
431  X509_NAME *name;
432  VALUE str;
433  long len;
434  unsigned char *p;
435 
436  GetX509Name(self, name);
437  if((len = i2d_X509_NAME(name, NULL)) <= 0)
439  str = rb_str_new(0, len);
440  p = (unsigned char *)RSTRING_PTR(str);
441  if(i2d_X509_NAME(name, &p) <= 0)
443  ossl_str_adjust(str, p);
444 
445  return str;
446 }
447 
448 /*
449  * Document-class: OpenSSL::X509::Name
450  *
451  * An X.509 name represents a hostname, email address or other entity
452  * associated with a public key.
453  *
454  * You can create a Name by parsing a distinguished name String or by
455  * supplying the distinguished name as an Array.
456  *
457  * name = OpenSSL::X509::Name.parse 'CN=nobody/DC=example'
458  *
459  * name = OpenSSL::X509::Name.new [['CN', 'nobody'], ['DC', 'example']]
460  */
461 
462 void
464 {
465  VALUE utf8str, ptrstr, ia5str, hash;
466 
467 #if 0
468  mOSSL = rb_define_module("OpenSSL");
471 #endif
472 
473  id_aref = rb_intern("[]");
476 
478 
486  rb_define_alias(cX509Name, "<=>", "cmp");
489 #ifdef HAVE_X509_NAME_HASH_OLD
490  rb_define_method(cX509Name, "hash_old", ossl_x509name_hash_old, 0);
491 #endif
493 
494  utf8str = INT2NUM(V_ASN1_UTF8STRING);
495  ptrstr = INT2NUM(V_ASN1_PRINTABLESTRING);
496  ia5str = INT2NUM(V_ASN1_IA5STRING);
497 
498  /*
499  * The default object type for name entries.
500  */
501  rb_define_const(cX509Name, "DEFAULT_OBJECT_TYPE", utf8str);
502  hash = rb_hash_new();
503  RHASH_SET_IFNONE(hash, utf8str);
504  rb_hash_aset(hash, rb_str_new2("C"), ptrstr);
505  rb_hash_aset(hash, rb_str_new2("countryName"), ptrstr);
506  rb_hash_aset(hash, rb_str_new2("serialNumber"), ptrstr);
507  rb_hash_aset(hash, rb_str_new2("dnQualifier"), ptrstr);
508  rb_hash_aset(hash, rb_str_new2("DC"), ia5str);
509  rb_hash_aset(hash, rb_str_new2("domainComponent"), ia5str);
510  rb_hash_aset(hash, rb_str_new2("emailAddress"), ia5str);
511 
512  /*
513  * The default object type template for name entries.
514  */
515  rb_define_const(cX509Name, "OBJECT_TYPE_TEMPLATE", hash);
516 
517  /*
518  * A flag for #to_s.
519  *
520  * Breaks the name returned into multiple lines if longer than 80
521  * characters.
522  */
523  rb_define_const(cX509Name, "COMPAT", ULONG2NUM(XN_FLAG_COMPAT));
524 
525  /*
526  * A flag for #to_s.
527  *
528  * Returns an RFC2253 format name.
529  */
530  rb_define_const(cX509Name, "RFC2253", ULONG2NUM(XN_FLAG_RFC2253));
531 
532  /*
533  * A flag for #to_s.
534  *
535  * Returns a more readable format than RFC2253.
536  */
537  rb_define_const(cX509Name, "ONELINE", ULONG2NUM(XN_FLAG_ONELINE));
538 
539  /*
540  * A flag for #to_s.
541  *
542  * Returns a multiline format.
543  */
544  rb_define_const(cX509Name, "MULTILINE", ULONG2NUM(XN_FLAG_MULTILINE));
545 }
VALUE rb_eStandardError
Definition: error.c:760
VALUE mOSSL
Definition: ossl.c:213
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1196
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1145
#define GetX509Name(obj, name)
Definition: ossl_x509name.c:20
#define INT2NUM(x)
Definition: ruby.h:1538
#define NUM2INT(x)
Definition: ruby.h:684
static unsigned int hash(str, len) register const char *str
static VALUE ossl_x509name_initialize_copy(VALUE self, VALUE other)
#define Qtrue
Definition: ruby.h:437
#define ossl_str_adjust(str, p)
Definition: ossl.h:82
static VALUE ossl_x509name_alloc(VALUE klass)
Definition: ossl_x509name.c:93
static const rb_data_type_t ossl_x509name_type
Definition: ossl_x509name.c:48
#define ULONG2NUM(x)
Definition: ruby.h:1574
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:905
#define DEFAULT_OBJECT_TYPE
Definition: ossl_x509name.c:33
static int ossl_x509name_cmp0(VALUE self, VALUE other)
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:693
#define Check_Type(v, t)
Definition: ruby.h:562
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:690
static VALUE ossl_x509name_to_s_old(VALUE self)
#define DATA_PTR(dta)
Definition: ruby.h:1113
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:864
VALUE rb_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE)
VALUE cX509Name
Definition: ossl_x509name.c:39
#define SafeGetX509Name(obj, name)
Definition: ossl_x509name.c:26
#define T_ARRAY
Definition: ruby.h:498
VALUE ossl_membio2str(BIO *bio)
Definition: ossl_bio.c:47
#define rb_ary_new2
Definition: intern.h:90
#define RHASH_SET_IFNONE(h, ifnone)
Definition: ruby.h:1068
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Definition: ruby.h:1830
static VALUE ossl_x509name_to_s(int argc, VALUE *argv, VALUE self)
#define rb_define_copy_func(klass, func)
Definition: ruby_missing.h:13
VALUE rb_mComparable
Definition: compar.c:15
VALUE ossl_to_der_if_possible(VALUE obj)
Definition: ossl.c:237
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:1576
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1872
static void ossl_x509name_free(void *ptr)
Definition: ossl_x509name.c:43
VALUE rb_ary_new(void)
Definition: array.c:493
#define NIL_P(v)
Definition: ruby.h:451
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2734
VALUE eOSSLError
Definition: ossl.c:218
static VALUE ossl_x509name_to_a(VALUE self)
int argc
Definition: ruby.c:183
#define Qfalse
Definition: ruby.h:436
#define rb_str_new2
Definition: intern.h:857
static VALUE ossl_x509name_initialize(int argc, VALUE *argv, VALUE self)
static ID id_aref
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1758
#define RSTRING_LEN(str)
Definition: ruby.h:978
#define NewX509Name(klass)
Definition: ossl_x509name.c:12
static VALUE ossl_x509name_eql(VALUE self, VALUE other)
VALUE rb_hash_new(void)
Definition: hash.c:441
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1919
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4309
unsigned long ID
Definition: ruby.h:86
#define Qnil
Definition: ruby.h:438
VALUE ossl_x509name_new(X509_NAME *name)
Definition: ossl_x509name.c:60
unsigned long VALUE
Definition: ruby.h:85
#define OBJECT_TYPE_TEMPLATE
Definition: ossl_x509name.c:31
static VALUE result
Definition: nkf.c:40
#define rb_ary_new3
Definition: intern.h:91
VALUE mX509
Definition: ossl_x509.c:12
static VALUE ossl_x509name_to_der(VALUE self)
#define OSSL_Debug
Definition: ossl.h:155
static VALUE ossl_x509name_hash(VALUE self)
register unsigned int len
Definition: zonetab.h:51
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:790
#define StringValueCStr(v)
Definition: ruby.h:571
#define RSTRING_PTR(str)
Definition: ruby.h:982
#define rb_aref(obj, key)
VALUE asn1str_to_str(const ASN1_STRING *str)
Definition: ossl_asn1.c:103
#define INT2FIX(i)
Definition: ruby.h:232
static VALUE ossl_x509name_cmp(VALUE self, VALUE other)
#define NUM2ULONG(x)
Definition: ruby.h:658
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:635
#define SetX509Name(obj, name)
Definition: ossl_x509name.c:14
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:278
const char * name
Definition: nkf.c:208
int nid
#define RSTRING_LENINT(str)
Definition: ruby.h:990
#define rb_check_frozen(obj)
Definition: intern.h:276
VALUE rb_define_module(const char *name)
Definition: class.c:768
X509_NAME * GetX509NamePtr(VALUE obj)
Definition: ossl_x509name.c:80
static VALUE ossl_x509name_init_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
#define rb_intern(str)
static VALUE ossl_x509name_add_entry(int, VALUE *, VALUE)
#define NULL
Definition: _sdbm.c:102
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1515
VALUE eX509NameError
Definition: ossl_x509name.c:40
void Init_ossl_x509name(void)
char ** argv
Definition: ruby.c:184
#define StringValue(v)
Definition: ruby.h:569
VALUE rb_str_new(const char *, long)
Definition: string.c:736