Ruby  2.0.0p594(2014-10-27revision48167)
ossl_x509name.c
Go to the documentation of this file.
1 /*
2  * $Id: ossl_x509name.c 38268 2012-12-08 00:26:56Z drbrain $
3  * 'OpenSSL for Ruby' project
4  * Copyright (C) 2001 Michal Rokos <m.rokos@sh.cvut.cz>
5  * All rights reserved.
6  */
7 /*
8  * This program is licenced under the same licence as Ruby.
9  * (See the file 'LICENCE'.)
10  */
11 #include "ossl.h"
12 
13 #define WrapX509Name(klass, obj, name) do { \
14  if (!(name)) { \
15  ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \
16  } \
17  (obj) = Data_Wrap_Struct((klass), 0, X509_NAME_free, (name)); \
18 } while (0)
19 #define GetX509Name(obj, name) do { \
20  Data_Get_Struct((obj), X509_NAME, (name)); \
21  if (!(name)) { \
22  ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \
23  } \
24 } while (0)
25 #define SafeGetX509Name(obj, name) do { \
26  OSSL_Check_Kind((obj), cX509Name); \
27  GetX509Name((obj), (name)); \
28 } while (0)
29 
30 #define OBJECT_TYPE_TEMPLATE \
31  rb_const_get(cX509Name, rb_intern("OBJECT_TYPE_TEMPLATE"))
32 #define DEFAULT_OBJECT_TYPE \
33  rb_const_get(cX509Name, rb_intern("DEFAULT_OBJECT_TYPE"))
34 
35 /*
36  * Classes
37  */
40 
41 /*
42  * Public
43  */
44 VALUE
46 {
47  X509_NAME *new;
48  VALUE obj;
49 
50  if (!name) {
51  new = X509_NAME_new();
52  } else {
53  new = X509_NAME_dup(name);
54  }
55  if (!new) {
57  }
58  WrapX509Name(cX509Name, obj, new);
59 
60  return obj;
61 }
62 
63 X509_NAME *
65 {
66  X509_NAME *name;
67 
68  SafeGetX509Name(obj, name);
69 
70  return name;
71 }
72 
73 /*
74  * Private
75  */
76 static VALUE
78 {
79  X509_NAME *name;
80  VALUE obj;
81 
82  if (!(name = X509_NAME_new())) {
84  }
85  WrapX509Name(klass, obj, name);
86 
87  return obj;
88 }
89 
90 static ID id_aref;
92 #define rb_aref(obj, key) rb_funcall((obj), id_aref, 1, (key))
93 
94 static VALUE
96 {
97  VALUE self = rb_ary_entry(args, 0);
98  VALUE template = rb_ary_entry(args, 1);
99  VALUE entry[3];
100 
101  Check_Type(i, T_ARRAY);
102  entry[0] = rb_ary_entry(i, 0);
103  entry[1] = rb_ary_entry(i, 1);
104  entry[2] = rb_ary_entry(i, 2);
105  if(NIL_P(entry[2])) entry[2] = rb_aref(template, entry[0]);
106  if(NIL_P(entry[2])) entry[2] = DEFAULT_OBJECT_TYPE;
107  ossl_x509name_add_entry(3, entry, self);
108 
109  return Qnil;
110 }
111 
112 /*
113  * call-seq:
114  * X509::Name.new => name
115  * X509::Name.new(der) => name
116  * X509::Name.new(distinguished_name) => name
117  * X509::Name.new(distinguished_name, template) => name
118  *
119  * Creates a new Name.
120  *
121  * A name may be created from a DER encoded string +der+, an Array
122  * representing a +distinguished_name+ or a +distinguished_name+ along with a
123  * +template+.
124  *
125  * name = OpenSSL::X509::Name.new [['CN', 'nobody'], ['DC', 'example']]
126  *
127  * name = OpenSSL::X509::Name.new name.to_der
128  *
129  * See add_entry for a description of the +distinguished_name+ Array's
130  * contents
131  */
132 static VALUE
134 {
135  X509_NAME *name;
136  VALUE arg, template;
137 
138  GetX509Name(self, name);
139  if (rb_scan_args(argc, argv, "02", &arg, &template) == 0) {
140  return self;
141  }
142  else {
144  if (!NIL_P(tmp)) {
145  VALUE args;
146  if(NIL_P(template)) template = OBJECT_TYPE_TEMPLATE;
147  args = rb_ary_new3(2, self, template);
148  rb_block_call(tmp, rb_intern("each"), 0, 0, ossl_x509name_init_i, args);
149  }
150  else{
151  const unsigned char *p;
153  X509_NAME *x;
154  StringValue(str);
155  p = (unsigned char *)RSTRING_PTR(str);
156  x = d2i_X509_NAME(&name, &p, RSTRING_LEN(str));
157  DATA_PTR(self) = name;
158  if(!x){
160  }
161  }
162  }
163 
164  return self;
165 }
166 
167 /*
168  * call-seq:
169  * name.add_entry(oid, value [, type]) => self
170  *
171  * Adds a new entry with the given +oid+ and +value+ to this name. The +oid+
172  * is an object identifier defined in ASN.1. Some common OIDs are:
173  *
174  * C:: Country Name
175  * CN:: Common Name
176  * DC:: Domain Component
177  * O:: Organization Name
178  * OU:: Organizational Unit Name
179  * ST:: State or Province Name
180  */
181 static
183 {
184  X509_NAME *name;
185  VALUE oid, value, type;
186 
187  rb_scan_args(argc, argv, "21", &oid, &value, &type);
188  StringValue(oid);
189  StringValue(value);
190  if(NIL_P(type)) type = rb_aref(OBJECT_TYPE_TEMPLATE, oid);
191  GetX509Name(self, name);
192  if (!X509_NAME_add_entry_by_txt(name, RSTRING_PTR(oid), NUM2INT(type),
193  (const unsigned char *)RSTRING_PTR(value), RSTRING_LENINT(value), -1, 0)) {
195  }
196 
197  return self;
198 }
199 
200 static VALUE
202 {
203  X509_NAME *name;
204  char *buf;
205  VALUE str;
206 
207  GetX509Name(self, name);
208  buf = X509_NAME_oneline(name, NULL, 0);
209  str = rb_str_new2(buf);
210  OPENSSL_free(buf);
211 
212  return str;
213 }
214 
215 /*
216  * call-seq:
217  * name.to_s => string
218  * name.to_s(flags) => string
219  *
220  * Returns this name as a Distinguished Name string. +flags+ may be one of:
221  *
222  * * OpenSSL::X509::Name::COMPAT
223  * * OpenSSL::X509::Name::RFC2253
224  * * OpenSSL::X509::Name::ONELINE
225  * * OpenSSL::X509::Name::MULTILINE
226  */
227 static VALUE
229 {
230  X509_NAME *name;
231  VALUE flag, str;
232  BIO *out;
233  unsigned long iflag;
234 
235  rb_scan_args(argc, argv, "01", &flag);
236  if (NIL_P(flag))
237  return ossl_x509name_to_s_old(self);
238  else iflag = NUM2ULONG(flag);
239  if (!(out = BIO_new(BIO_s_mem())))
241  GetX509Name(self, name);
242  if (!X509_NAME_print_ex(out, name, 0, iflag)){
243  BIO_free(out);
245  }
246  str = ossl_membio2str(out);
247 
248  return str;
249 }
250 
251 /*
252  * call-seq:
253  * name.to_a => [[name, data, type], ...]
254  *
255  * Returns an Array representation of the distinguished name suitable for
256  * passing to ::new
257  */
258 static VALUE
260 {
261  X509_NAME *name;
262  X509_NAME_ENTRY *entry;
263  int i,entries,nid;
264  char long_name[512];
265  const char *short_name;
266  VALUE ary, vname, ret;
267 
268  GetX509Name(self, name);
269  entries = X509_NAME_entry_count(name);
270  if (entries < 0) {
271  OSSL_Debug("name entries < 0!");
272  return rb_ary_new();
273  }
274  ret = rb_ary_new2(entries);
275  for (i=0; i<entries; i++) {
276  if (!(entry = X509_NAME_get_entry(name, i))) {
278  }
279  if (!i2t_ASN1_OBJECT(long_name, sizeof(long_name), entry->object)) {
281  }
282  nid = OBJ_ln2nid(long_name);
283  if (nid == NID_undef) {
284  vname = rb_str_new2((const char *) &long_name);
285  } else {
286  short_name = OBJ_nid2sn(nid);
287  vname = rb_str_new2(short_name); /*do not free*/
288  }
289  ary = rb_ary_new3(3,
290  vname,
291  rb_str_new((const char *)entry->value->data, entry->value->length),
292  INT2FIX(entry->value->type));
293  rb_ary_push(ret, ary);
294  }
295  return ret;
296 }
297 
298 static int
300 {
301  X509_NAME *name1, *name2;
302 
303  GetX509Name(self, name1);
304  SafeGetX509Name(other, name2);
305 
306  return X509_NAME_cmp(name1, name2);
307 }
308 
309 /*
310  * call-seq:
311  * name.cmp other => integer
312  * name.<=> other => integer
313  *
314  * Compares this Name with +other+ and returns 0 if they are the same and -1 or
315  * +1 if they are greater or less than each other respectively.
316  */
317 static VALUE
319 {
320  int result;
321 
322  result = ossl_x509name_cmp0(self, other);
323  if (result < 0) return INT2FIX(-1);
324  if (result > 1) return INT2FIX(1);
325 
326  return INT2FIX(0);
327 }
328 
329 /*
330  * call-seq:
331  * name.eql? other => boolean
332  *
333  * Returns true if +name+ and +other+ refer to the same hash key.
334  */
335 static VALUE
337 {
338  int result;
339 
340  if(CLASS_OF(other) != cX509Name) return Qfalse;
341  result = ossl_x509name_cmp0(self, other);
342 
343  return (result == 0) ? Qtrue : Qfalse;
344 }
345 
346 /*
347  * call-seq:
348  * name.hash => integer
349  *
350  * The hash value returned is suitable for use as a certificate's filename in
351  * a CA path.
352  */
353 static VALUE
355 {
356  X509_NAME *name;
357  unsigned long hash;
358 
359  GetX509Name(self, name);
360 
361  hash = X509_NAME_hash(name);
362 
363  return ULONG2NUM(hash);
364 }
365 
366 #ifdef HAVE_X509_NAME_HASH_OLD
367 /*
368  * call-seq:
369  * name.hash_old => integer
370  *
371  * Returns an MD5 based hash used in OpenSSL 0.9.X.
372  */
373 static VALUE
374 ossl_x509name_hash_old(VALUE self)
375 {
376  X509_NAME *name;
377  unsigned long hash;
378 
379  GetX509Name(self, name);
380 
381  hash = X509_NAME_hash_old(name);
382 
383  return ULONG2NUM(hash);
384 }
385 #endif
386 
387 /*
388  * call-seq:
389  * name.to_der => string
390  *
391  * Converts the name to DER encoding
392  */
393 static VALUE
395 {
396  X509_NAME *name;
397  VALUE str;
398  long len;
399  unsigned char *p;
400 
401  GetX509Name(self, name);
402  if((len = i2d_X509_NAME(name, NULL)) <= 0)
404  str = rb_str_new(0, len);
405  p = (unsigned char *)RSTRING_PTR(str);
406  if(i2d_X509_NAME(name, &p) <= 0)
408  ossl_str_adjust(str, p);
409 
410  return str;
411 }
412 
413 /*
414  * Document-class: OpenSSL::X509::Name
415  *
416  * An X.509 name represents a hostname, email address or other entity
417  * associated with a public key.
418  *
419  * You can create a Name by parsing a distinguished name String or by
420  * supplying the distinguished name as an Array.
421  *
422  * name = OpenSSL::X509::Name.parse 'CN=nobody/DC=example'
423  *
424  * name = OpenSSL::X509::Name.new [['CN', 'nobody'], ['DC', 'example']]
425  */
426 
427 void
429 {
430  VALUE utf8str, ptrstr, ia5str, hash;
431 
432  id_aref = rb_intern("[]");
435 
437 
444  rb_define_alias(cX509Name, "<=>", "cmp");
447 #ifdef HAVE_X509_NAME_HASH_OLD
448  rb_define_method(cX509Name, "hash_old", ossl_x509name_hash_old, 0);
449 #endif
451 
452  utf8str = INT2NUM(V_ASN1_UTF8STRING);
453  ptrstr = INT2NUM(V_ASN1_PRINTABLESTRING);
454  ia5str = INT2NUM(V_ASN1_IA5STRING);
455 
456  /* Document-const: DEFAULT_OBJECT_TYPE
457  *
458  * The default object type for name entries.
459  */
460  rb_define_const(cX509Name, "DEFAULT_OBJECT_TYPE", utf8str);
461  hash = rb_hash_new();
462  RHASH(hash)->ifnone = utf8str;
463  rb_hash_aset(hash, rb_str_new2("C"), ptrstr);
464  rb_hash_aset(hash, rb_str_new2("countryName"), ptrstr);
465  rb_hash_aset(hash, rb_str_new2("serialNumber"), ptrstr);
466  rb_hash_aset(hash, rb_str_new2("dnQualifier"), ptrstr);
467  rb_hash_aset(hash, rb_str_new2("DC"), ia5str);
468  rb_hash_aset(hash, rb_str_new2("domainComponent"), ia5str);
469  rb_hash_aset(hash, rb_str_new2("emailAddress"), ia5str);
470 
471  /* Document-const: OBJECT_TYPE_TEMPLATE
472  *
473  * The default object type template for name entries.
474  */
475  rb_define_const(cX509Name, "OBJECT_TYPE_TEMPLATE", hash);
476 
477  /* Document-const: COMPAT
478  *
479  * A flag for #to_s.
480  *
481  * Breaks the name returned into multiple lines if longer than 80
482  * characters.
483  */
484  rb_define_const(cX509Name, "COMPAT", ULONG2NUM(XN_FLAG_COMPAT));
485 
486  /* Document-const: RFC2253
487  *
488  * A flag for #to_s.
489  *
490  * Returns an RFC2253 format name.
491  */
492  rb_define_const(cX509Name, "RFC2253", ULONG2NUM(XN_FLAG_RFC2253));
493 
494  /* Document-const: ONELINE
495  *
496  * A flag for #to_s.
497  *
498  * Returns a more readable format than RFC2253.
499  */
500  rb_define_const(cX509Name, "ONELINE", ULONG2NUM(XN_FLAG_ONELINE));
501 
502  /* Document-const: MULTILINE
503  *
504  * A flag for #to_s.
505  *
506  * Returns a multiline format.
507  */
508  rb_define_const(cX509Name, "MULTILINE", ULONG2NUM(XN_FLAG_MULTILINE));
509 }
volatile VALUE tmp
Definition: tcltklib.c:10208
volatile VALUE ary
Definition: tcltklib.c:9712
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1088
#define GetX509Name(obj, name)
Definition: ossl_x509name.c:19
Win32OLEIDispatch * p
Definition: win32ole.c:786
C_block * out
Definition: crypt.c:308
#define ossl_str_adjust(str, p)
Definition: ossl.h:138
ssize_t i
Definition: bigdecimal.c:5676
static VALUE ossl_x509name_alloc(VALUE klass)
Definition: ossl_x509name.c:77
static VALUE ossl_x509name_init_i(VALUE i, VALUE args)
Definition: ossl_x509name.c:95
int ret
Definition: tcltklib.c:280
#define RHASH(obj)
VALUE eX509NameError
Definition: ossl_x509name.c:39
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:822
#define DEFAULT_OBJECT_TYPE
Definition: ossl_x509name.c:32
static int ossl_x509name_cmp0(VALUE self, VALUE other)
#define NUM2ULONG(x)
#define RSTRING_PTR(str)
#define CLASS_OF(v)
NIL_P(eventloop_thread)
Definition: tcltklib.c:4067
#define T_ARRAY
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:549
return Qtrue
Definition: tcltklib.c:9609
VALUE rb_ary_new3(long n,...)
Definition: array.c:432
static VALUE ossl_x509name_to_s_old(VALUE self)
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:699
#define SafeGetX509Name(obj, name)
Definition: ossl_x509name.c:25
#define rb_str_new2
VALUE ossl_membio2str(BIO *bio)
Definition: ossl_bio.c:77
X509_NAME * GetX509NamePtr(VALUE)
Definition: ossl_x509name.c:64
VALUE VALUE args
Definition: tcltklib.c:2560
flag
Definition: tcltklib.c:2047
char * name2
Definition: tcltklib.c:4205
static VALUE ossl_x509name_to_s(int argc, VALUE *argv, VALUE self)
VALUE hash
Definition: tkutil.c:267
VALUE rb_mComparable
Definition: compar.c:14
VALUE ossl_to_der_if_possible(VALUE obj)
Definition: ossl.c:283
return Qfalse
Definition: tcltklib.c:6778
#define Qnil
Definition: tcltklib.c:1895
void Init_ossl_x509name(void)
static VALUE char * str
Definition: tcltklib.c:3546
VALUE rb_ary_new(void)
Definition: array.c:424
#define Check_Type(v, t)
unsigned long ID
Definition: ripper.y:105
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2204
static VALUE VALUE obj
Definition: tcltklib.c:3157
#define RSTRING_LEN(str)
#define INT2FIX(i)
VALUE eOSSLError
Definition: ossl.c:264
static VALUE ossl_x509name_to_a(VALUE self)
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
static VALUE ossl_x509name_initialize(int argc, VALUE *argv, VALUE self)
static ID id_aref
Definition: ossl_x509name.c:90
#define WrapX509Name(klass, obj, name)
Definition: ossl_x509name.c:13
VALUE * argv
Definition: tcltklib.c:1970
VALUE rb_hash_aset(VALUE, VALUE, VALUE)
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1543
q result
Definition: tcltklib.c:7069
volatile VALUE value
Definition: tcltklib.c:9441
#define StringValue(v)
char * name1
Definition: tcltklib.c:4204
static VALUE ossl_x509name_eql(VALUE self, VALUE other)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1574
VALUE rb_block_call(VALUE, ID, int, VALUE *, VALUE(*)(ANYARGS), VALUE)
Definition: vm_eval.c:1119
int type
Definition: tcltklib.c:111
#define OBJECT_TYPE_TEMPLATE
Definition: ossl_x509name.c:30
int argc
Definition: tcltklib.c:1969
VALUE mX509
Definition: ossl_x509.c:13
static VALUE ossl_x509name_to_der(VALUE self)
#define OSSL_Debug
Definition: ossl.h:211
static VALUE ossl_x509name_hash(VALUE self)
arg
Definition: ripper.y:1317
#define rb_aref(obj, key)
Definition: ossl_x509name.c:92
static VALUE ossl_x509name_cmp(VALUE self, VALUE other)
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:557
DATA_PTR(self)
RUBY_EXTERN VALUE rb_cObject
Definition: ripper.y:1426
klass
Definition: tcltklib.c:3503
#define INT2NUM(x)
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:333
#define RSTRING_LENINT(str)
VALUE rb_ary_new2(long capa)
Definition: array.c:417
VALUE rb_str_new(const char *, long)
Definition: string.c:425
#define NUM2INT(x)
VALUE rb_hash_new(void)
Definition: hash.c:234
unsigned long VALUE
Definition: ripper.y:104
VALUE ossl_x509name_new(X509_NAME *)
Definition: ossl_x509name.c:45
VALUE cX509Name
Definition: ossl_x509name.c:38
#define rb_intern(str)
static VALUE ossl_x509name_add_entry(int, VALUE *, VALUE)
#define NULL
Definition: _sdbm.c:103
const char * name
Definition: nkf.c:208
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1348
#define ULONG2NUM(x)
size_t len
Definition: tcltklib.c:3567