Ruby
2.0.0p247(2013-06-27revision41674)
|
00001 /* 00002 * $Id: ossl_x509ext.c 31166 2011-03-24 07:29:21Z naruse $ 00003 * 'OpenSSL for Ruby' project 00004 * Copyright (C) 2001-2002 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 WrapX509Ext(klass, obj, ext) do { \ 00014 if (!(ext)) { \ 00015 ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \ 00016 } \ 00017 (obj) = Data_Wrap_Struct((klass), 0, X509_EXTENSION_free, (ext)); \ 00018 } while (0) 00019 #define GetX509Ext(obj, ext) do { \ 00020 Data_Get_Struct((obj), X509_EXTENSION, (ext)); \ 00021 if (!(ext)) { \ 00022 ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \ 00023 } \ 00024 } while (0) 00025 #define SafeGetX509Ext(obj, ext) do { \ 00026 OSSL_Check_Kind((obj), cX509Ext); \ 00027 GetX509Ext((obj), (ext)); \ 00028 } while (0) 00029 #define MakeX509ExtFactory(klass, obj, ctx) do { \ 00030 if (!((ctx) = OPENSSL_malloc(sizeof(X509V3_CTX)))) \ 00031 ossl_raise(rb_eRuntimeError, "CTX wasn't allocated!"); \ 00032 X509V3_set_ctx((ctx), NULL, NULL, NULL, NULL, 0); \ 00033 (obj) = Data_Wrap_Struct((klass), 0, ossl_x509extfactory_free, (ctx)); \ 00034 } while (0) 00035 #define GetX509ExtFactory(obj, ctx) do { \ 00036 Data_Get_Struct((obj), X509V3_CTX, (ctx)); \ 00037 if (!(ctx)) { \ 00038 ossl_raise(rb_eRuntimeError, "CTX wasn't initialized!"); \ 00039 } \ 00040 } while (0) 00041 00042 /* 00043 * Classes 00044 */ 00045 VALUE cX509Ext; 00046 VALUE cX509ExtFactory; 00047 VALUE eX509ExtError; 00048 00049 /* 00050 * Public 00051 */ 00052 VALUE 00053 ossl_x509ext_new(X509_EXTENSION *ext) 00054 { 00055 X509_EXTENSION *new; 00056 VALUE obj; 00057 00058 if (!ext) { 00059 new = X509_EXTENSION_new(); 00060 } else { 00061 new = X509_EXTENSION_dup(ext); 00062 } 00063 if (!new) { 00064 ossl_raise(eX509ExtError, NULL); 00065 } 00066 WrapX509Ext(cX509Ext, obj, new); 00067 00068 return obj; 00069 } 00070 00071 X509_EXTENSION * 00072 GetX509ExtPtr(VALUE obj) 00073 { 00074 X509_EXTENSION *ext; 00075 00076 SafeGetX509Ext(obj, ext); 00077 00078 return ext; 00079 } 00080 00081 X509_EXTENSION * 00082 DupX509ExtPtr(VALUE obj) 00083 { 00084 X509_EXTENSION *ext, *new; 00085 00086 SafeGetX509Ext(obj, ext); 00087 if (!(new = X509_EXTENSION_dup(ext))) { 00088 ossl_raise(eX509ExtError, NULL); 00089 } 00090 00091 return new; 00092 } 00093 00094 /* 00095 * Private 00096 */ 00097 /* 00098 * Ext factory 00099 */ 00100 static void 00101 ossl_x509extfactory_free(X509V3_CTX *ctx) 00102 { 00103 OPENSSL_free(ctx); 00104 } 00105 00106 static VALUE 00107 ossl_x509extfactory_alloc(VALUE klass) 00108 { 00109 X509V3_CTX *ctx; 00110 VALUE obj; 00111 00112 MakeX509ExtFactory(klass, obj, ctx); 00113 rb_iv_set(obj, "@config", Qnil); 00114 00115 return obj; 00116 } 00117 00118 static VALUE 00119 ossl_x509extfactory_set_issuer_cert(VALUE self, VALUE cert) 00120 { 00121 X509V3_CTX *ctx; 00122 00123 GetX509ExtFactory(self, ctx); 00124 rb_iv_set(self, "@issuer_certificate", cert); 00125 ctx->issuer_cert = GetX509CertPtr(cert); /* NO DUP NEEDED */ 00126 00127 return cert; 00128 } 00129 00130 static VALUE 00131 ossl_x509extfactory_set_subject_cert(VALUE self, VALUE cert) 00132 { 00133 X509V3_CTX *ctx; 00134 00135 GetX509ExtFactory(self, ctx); 00136 rb_iv_set(self, "@subject_certificate", cert); 00137 ctx->subject_cert = GetX509CertPtr(cert); /* NO DUP NEEDED */ 00138 00139 return cert; 00140 } 00141 00142 static VALUE 00143 ossl_x509extfactory_set_subject_req(VALUE self, VALUE req) 00144 { 00145 X509V3_CTX *ctx; 00146 00147 GetX509ExtFactory(self, ctx); 00148 rb_iv_set(self, "@subject_request", req); 00149 ctx->subject_req = GetX509ReqPtr(req); /* NO DUP NEEDED */ 00150 00151 return req; 00152 } 00153 00154 static VALUE 00155 ossl_x509extfactory_set_crl(VALUE self, VALUE crl) 00156 { 00157 X509V3_CTX *ctx; 00158 00159 GetX509ExtFactory(self, ctx); 00160 rb_iv_set(self, "@crl", crl); 00161 ctx->crl = GetX509CRLPtr(crl); /* NO DUP NEEDED */ 00162 00163 return crl; 00164 } 00165 00166 #ifdef HAVE_X509V3_SET_NCONF 00167 static VALUE 00168 ossl_x509extfactory_set_config(VALUE self, VALUE config) 00169 { 00170 X509V3_CTX *ctx; 00171 CONF *conf; 00172 00173 GetX509ExtFactory(self, ctx); 00174 rb_iv_set(self, "@config", config); 00175 conf = GetConfigPtr(config); /* NO DUP NEEDED */ 00176 X509V3_set_nconf(ctx, conf); 00177 00178 return config; 00179 } 00180 #else 00181 #define ossl_x509extfactory_set_config rb_f_notimplement 00182 #endif 00183 00184 static VALUE 00185 ossl_x509extfactory_initialize(int argc, VALUE *argv, VALUE self) 00186 { 00187 /*X509V3_CTX *ctx;*/ 00188 VALUE issuer_cert, subject_cert, subject_req, crl; 00189 00190 /*GetX509ExtFactory(self, ctx);*/ 00191 00192 rb_scan_args(argc, argv, "04", 00193 &issuer_cert, &subject_cert, &subject_req, &crl); 00194 if (!NIL_P(issuer_cert)) 00195 ossl_x509extfactory_set_issuer_cert(self, issuer_cert); 00196 if (!NIL_P(subject_cert)) 00197 ossl_x509extfactory_set_subject_cert(self, subject_cert); 00198 if (!NIL_P(subject_req)) 00199 ossl_x509extfactory_set_subject_req(self, subject_req); 00200 if (!NIL_P(crl)) 00201 ossl_x509extfactory_set_crl(self, crl); 00202 00203 return self; 00204 } 00205 00206 /* 00207 * Array to X509_EXTENSION 00208 * Structure: 00209 * ["ln", "value", bool_critical] or 00210 * ["sn", "value", bool_critical] or 00211 * ["ln", "critical,value"] or the same for sn 00212 * ["ln", "value"] => not critical 00213 */ 00214 static VALUE 00215 ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self) 00216 { 00217 X509V3_CTX *ctx; 00218 X509_EXTENSION *ext; 00219 VALUE oid, value, critical, valstr, obj; 00220 int nid; 00221 #ifdef HAVE_X509V3_EXT_NCONF_NID 00222 VALUE rconf; 00223 CONF *conf; 00224 #else 00225 static LHASH *empty_lhash; 00226 #endif 00227 00228 rb_scan_args(argc, argv, "21", &oid, &value, &critical); 00229 StringValue(oid); 00230 StringValue(value); 00231 if(NIL_P(critical)) critical = Qfalse; 00232 00233 nid = OBJ_ln2nid(RSTRING_PTR(oid)); 00234 if(!nid) nid = OBJ_sn2nid(RSTRING_PTR(oid)); 00235 if(!nid) ossl_raise(eX509ExtError, "unknown OID `%s'", RSTRING_PTR(oid)); 00236 valstr = rb_str_new2(RTEST(critical) ? "critical," : ""); 00237 rb_str_append(valstr, value); 00238 GetX509ExtFactory(self, ctx); 00239 #ifdef HAVE_X509V3_EXT_NCONF_NID 00240 rconf = rb_iv_get(self, "@config"); 00241 conf = NIL_P(rconf) ? NULL : GetConfigPtr(rconf); 00242 ext = X509V3_EXT_nconf_nid(conf, ctx, nid, RSTRING_PTR(valstr)); 00243 #else 00244 if (!empty_lhash) empty_lhash = lh_new(NULL, NULL); 00245 ext = X509V3_EXT_conf_nid(empty_lhash, ctx, nid, RSTRING_PTR(valstr)); 00246 #endif 00247 if (!ext){ 00248 ossl_raise(eX509ExtError, "%s = %s", 00249 RSTRING_PTR(oid), RSTRING_PTR(value)); 00250 } 00251 WrapX509Ext(cX509Ext, obj, ext); 00252 00253 return obj; 00254 } 00255 00256 /* 00257 * Ext 00258 */ 00259 static VALUE 00260 ossl_x509ext_alloc(VALUE klass) 00261 { 00262 X509_EXTENSION *ext; 00263 VALUE obj; 00264 00265 if(!(ext = X509_EXTENSION_new())){ 00266 ossl_raise(eX509ExtError, NULL); 00267 } 00268 WrapX509Ext(klass, obj, ext); 00269 00270 return obj; 00271 } 00272 00273 /* 00274 * call-seq: 00275 * OpenSSL::X509::Extension.new asn1 00276 * OpenSSL::X509::Extension.new name, value 00277 * OpenSSL::X509::Extension.new name, value, critical 00278 * 00279 * Creates an X509 extension. 00280 * 00281 * The extension may be created from +asn1+ data or from an extension +name+ 00282 * and +value+. The +name+ may be either an OID or an extension name. If 00283 * +critical+ is true the extension is marked critical. 00284 */ 00285 static VALUE 00286 ossl_x509ext_initialize(int argc, VALUE *argv, VALUE self) 00287 { 00288 VALUE oid, value, critical; 00289 const unsigned char *p; 00290 X509_EXTENSION *ext, *x; 00291 00292 GetX509Ext(self, ext); 00293 if(rb_scan_args(argc, argv, "12", &oid, &value, &critical) == 1){ 00294 oid = ossl_to_der_if_possible(oid); 00295 StringValue(oid); 00296 p = (unsigned char *)RSTRING_PTR(oid); 00297 x = d2i_X509_EXTENSION(&ext, &p, RSTRING_LEN(oid)); 00298 DATA_PTR(self) = ext; 00299 if(!x) 00300 ossl_raise(eX509ExtError, NULL); 00301 return self; 00302 } 00303 rb_funcall(self, rb_intern("oid="), 1, oid); 00304 rb_funcall(self, rb_intern("value="), 1, value); 00305 if(argc > 2) rb_funcall(self, rb_intern("critical="), 1, critical); 00306 00307 return self; 00308 } 00309 00310 static VALUE 00311 ossl_x509ext_set_oid(VALUE self, VALUE oid) 00312 { 00313 X509_EXTENSION *ext; 00314 ASN1_OBJECT *obj; 00315 char *s; 00316 00317 s = StringValuePtr(oid); 00318 obj = OBJ_txt2obj(s, 0); 00319 if(!obj) obj = OBJ_txt2obj(s, 1); 00320 if(!obj) ossl_raise(eX509ExtError, NULL); 00321 GetX509Ext(self, ext); 00322 X509_EXTENSION_set_object(ext, obj); 00323 00324 return oid; 00325 } 00326 00327 static VALUE 00328 ossl_x509ext_set_value(VALUE self, VALUE data) 00329 { 00330 X509_EXTENSION *ext; 00331 ASN1_OCTET_STRING *asn1s; 00332 char *s; 00333 00334 data = ossl_to_der_if_possible(data); 00335 StringValue(data); 00336 if(!(s = OPENSSL_malloc(RSTRING_LEN(data)))) 00337 ossl_raise(eX509ExtError, "malloc error"); 00338 memcpy(s, RSTRING_PTR(data), RSTRING_LEN(data)); 00339 if(!(asn1s = ASN1_OCTET_STRING_new())){ 00340 OPENSSL_free(s); 00341 ossl_raise(eX509ExtError, NULL); 00342 } 00343 if(!M_ASN1_OCTET_STRING_set(asn1s, s, RSTRING_LENINT(data))){ 00344 OPENSSL_free(s); 00345 ASN1_OCTET_STRING_free(asn1s); 00346 ossl_raise(eX509ExtError, NULL); 00347 } 00348 OPENSSL_free(s); 00349 GetX509Ext(self, ext); 00350 X509_EXTENSION_set_data(ext, asn1s); 00351 00352 return data; 00353 } 00354 00355 static VALUE 00356 ossl_x509ext_set_critical(VALUE self, VALUE flag) 00357 { 00358 X509_EXTENSION *ext; 00359 00360 GetX509Ext(self, ext); 00361 X509_EXTENSION_set_critical(ext, RTEST(flag) ? 1 : 0); 00362 00363 return flag; 00364 } 00365 00366 static VALUE 00367 ossl_x509ext_get_oid(VALUE obj) 00368 { 00369 X509_EXTENSION *ext; 00370 ASN1_OBJECT *extobj; 00371 BIO *out; 00372 VALUE ret; 00373 int nid; 00374 00375 GetX509Ext(obj, ext); 00376 extobj = X509_EXTENSION_get_object(ext); 00377 if ((nid = OBJ_obj2nid(extobj)) != NID_undef) 00378 ret = rb_str_new2(OBJ_nid2sn(nid)); 00379 else{ 00380 if (!(out = BIO_new(BIO_s_mem()))) 00381 ossl_raise(eX509ExtError, NULL); 00382 i2a_ASN1_OBJECT(out, extobj); 00383 ret = ossl_membio2str(out); 00384 } 00385 00386 return ret; 00387 } 00388 00389 static VALUE 00390 ossl_x509ext_get_value(VALUE obj) 00391 { 00392 X509_EXTENSION *ext; 00393 BIO *out; 00394 VALUE ret; 00395 00396 GetX509Ext(obj, ext); 00397 if (!(out = BIO_new(BIO_s_mem()))) 00398 ossl_raise(eX509ExtError, NULL); 00399 if (!X509V3_EXT_print(out, ext, 0, 0)) 00400 M_ASN1_OCTET_STRING_print(out, ext->value); 00401 ret = ossl_membio2str(out); 00402 00403 return ret; 00404 } 00405 00406 static VALUE 00407 ossl_x509ext_get_critical(VALUE obj) 00408 { 00409 X509_EXTENSION *ext; 00410 00411 GetX509Ext(obj, ext); 00412 return X509_EXTENSION_get_critical(ext) ? Qtrue : Qfalse; 00413 } 00414 00415 static VALUE 00416 ossl_x509ext_to_der(VALUE obj) 00417 { 00418 X509_EXTENSION *ext; 00419 unsigned char *p; 00420 long len; 00421 VALUE str; 00422 00423 GetX509Ext(obj, ext); 00424 if((len = i2d_X509_EXTENSION(ext, NULL)) <= 0) 00425 ossl_raise(eX509ExtError, NULL); 00426 str = rb_str_new(0, len); 00427 p = (unsigned char *)RSTRING_PTR(str); 00428 if(i2d_X509_EXTENSION(ext, &p) < 0) 00429 ossl_raise(eX509ExtError, NULL); 00430 ossl_str_adjust(str, p); 00431 00432 return str; 00433 } 00434 00435 /* 00436 * INIT 00437 */ 00438 void 00439 Init_ossl_x509ext() 00440 { 00441 eX509ExtError = rb_define_class_under(mX509, "ExtensionError", eOSSLError); 00442 00443 cX509ExtFactory = rb_define_class_under(mX509, "ExtensionFactory", rb_cObject); 00444 00445 rb_define_alloc_func(cX509ExtFactory, ossl_x509extfactory_alloc); 00446 rb_define_method(cX509ExtFactory, "initialize", ossl_x509extfactory_initialize, -1); 00447 00448 rb_attr(cX509ExtFactory, rb_intern("issuer_certificate"), 1, 0, Qfalse); 00449 rb_attr(cX509ExtFactory, rb_intern("subject_certificate"), 1, 0, Qfalse); 00450 rb_attr(cX509ExtFactory, rb_intern("subject_request"), 1, 0, Qfalse); 00451 rb_attr(cX509ExtFactory, rb_intern("crl"), 1, 0, Qfalse); 00452 rb_attr(cX509ExtFactory, rb_intern("config"), 1, 0, Qfalse); 00453 00454 rb_define_method(cX509ExtFactory, "issuer_certificate=", ossl_x509extfactory_set_issuer_cert, 1); 00455 rb_define_method(cX509ExtFactory, "subject_certificate=", ossl_x509extfactory_set_subject_cert, 1); 00456 rb_define_method(cX509ExtFactory, "subject_request=", ossl_x509extfactory_set_subject_req, 1); 00457 rb_define_method(cX509ExtFactory, "crl=", ossl_x509extfactory_set_crl, 1); 00458 rb_define_method(cX509ExtFactory, "config=", ossl_x509extfactory_set_config, 1); 00459 rb_define_method(cX509ExtFactory, "create_ext", ossl_x509extfactory_create_ext, -1); 00460 00461 cX509Ext = rb_define_class_under(mX509, "Extension", rb_cObject); 00462 rb_define_alloc_func(cX509Ext, ossl_x509ext_alloc); 00463 rb_define_method(cX509Ext, "initialize", ossl_x509ext_initialize, -1); 00464 rb_define_method(cX509Ext, "oid=", ossl_x509ext_set_oid, 1); 00465 rb_define_method(cX509Ext, "value=", ossl_x509ext_set_value, 1); 00466 rb_define_method(cX509Ext, "critical=", ossl_x509ext_set_critical, 1); 00467 rb_define_method(cX509Ext, "oid", ossl_x509ext_get_oid, 0); 00468 rb_define_method(cX509Ext, "value", ossl_x509ext_get_value, 0); 00469 rb_define_method(cX509Ext, "critical?", ossl_x509ext_get_critical, 0); 00470 rb_define_method(cX509Ext, "to_der", ossl_x509ext_to_der, 0); 00471 } 00472