|
Ruby 1.9.2p290(2011-07-09revision32553)
|
00001 /* 00002 * $Id: ossl_x509ext.c 30320 2010-12-23 12:45:44Z yugui $ 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 static VALUE 00274 ossl_x509ext_initialize(int argc, VALUE *argv, VALUE self) 00275 { 00276 VALUE oid, value, critical; 00277 const unsigned char *p; 00278 X509_EXTENSION *ext, *x; 00279 00280 GetX509Ext(self, ext); 00281 if(rb_scan_args(argc, argv, "12", &oid, &value, &critical) == 1){ 00282 oid = ossl_to_der_if_possible(oid); 00283 StringValue(oid); 00284 p = (unsigned char *)RSTRING_PTR(oid); 00285 x = d2i_X509_EXTENSION(&ext, &p, RSTRING_LEN(oid)); 00286 DATA_PTR(self) = ext; 00287 if(!x) 00288 ossl_raise(eX509ExtError, NULL); 00289 return self; 00290 } 00291 rb_funcall(self, rb_intern("oid="), 1, oid); 00292 rb_funcall(self, rb_intern("value="), 1, value); 00293 if(argc > 2) rb_funcall(self, rb_intern("critical="), 1, critical); 00294 00295 return self; 00296 } 00297 00298 static VALUE 00299 ossl_x509ext_set_oid(VALUE self, VALUE oid) 00300 { 00301 X509_EXTENSION *ext; 00302 ASN1_OBJECT *obj; 00303 char *s; 00304 00305 s = StringValuePtr(oid); 00306 obj = OBJ_txt2obj(s, 0); 00307 if(!obj) obj = OBJ_txt2obj(s, 1); 00308 if(!obj) ossl_raise(eX509ExtError, NULL); 00309 GetX509Ext(self, ext); 00310 X509_EXTENSION_set_object(ext, obj); 00311 00312 return oid; 00313 } 00314 00315 static VALUE 00316 ossl_x509ext_set_value(VALUE self, VALUE data) 00317 { 00318 X509_EXTENSION *ext; 00319 ASN1_OCTET_STRING *asn1s; 00320 char *s; 00321 00322 data = ossl_to_der_if_possible(data); 00323 StringValue(data); 00324 if(!(s = OPENSSL_malloc(RSTRING_LEN(data)))) 00325 ossl_raise(eX509ExtError, "malloc error"); 00326 memcpy(s, RSTRING_PTR(data), RSTRING_LEN(data)); 00327 if(!(asn1s = ASN1_OCTET_STRING_new())){ 00328 OPENSSL_free(s); 00329 ossl_raise(eX509ExtError, NULL); 00330 } 00331 if(!M_ASN1_OCTET_STRING_set(asn1s, s, RSTRING_LEN(data))){ 00332 OPENSSL_free(s); 00333 ASN1_OCTET_STRING_free(asn1s); 00334 ossl_raise(eX509ExtError, NULL); 00335 } 00336 OPENSSL_free(s); 00337 GetX509Ext(self, ext); 00338 X509_EXTENSION_set_data(ext, asn1s); 00339 00340 return data; 00341 } 00342 00343 static VALUE 00344 ossl_x509ext_set_critical(VALUE self, VALUE flag) 00345 { 00346 X509_EXTENSION *ext; 00347 00348 GetX509Ext(self, ext); 00349 X509_EXTENSION_set_critical(ext, RTEST(flag) ? 1 : 0); 00350 00351 return flag; 00352 } 00353 00354 static VALUE 00355 ossl_x509ext_get_oid(VALUE obj) 00356 { 00357 X509_EXTENSION *ext; 00358 ASN1_OBJECT *extobj; 00359 BIO *out; 00360 VALUE ret; 00361 int nid; 00362 00363 GetX509Ext(obj, ext); 00364 extobj = X509_EXTENSION_get_object(ext); 00365 if ((nid = OBJ_obj2nid(extobj)) != NID_undef) 00366 ret = rb_str_new2(OBJ_nid2sn(nid)); 00367 else{ 00368 if (!(out = BIO_new(BIO_s_mem()))) 00369 ossl_raise(eX509ExtError, NULL); 00370 i2a_ASN1_OBJECT(out, extobj); 00371 ret = ossl_membio2str(out); 00372 } 00373 00374 return ret; 00375 } 00376 00377 static VALUE 00378 ossl_x509ext_get_value(VALUE obj) 00379 { 00380 X509_EXTENSION *ext; 00381 BIO *out; 00382 VALUE ret; 00383 00384 GetX509Ext(obj, ext); 00385 if (!(out = BIO_new(BIO_s_mem()))) 00386 ossl_raise(eX509ExtError, NULL); 00387 if (!X509V3_EXT_print(out, ext, 0, 0)) 00388 M_ASN1_OCTET_STRING_print(out, ext->value); 00389 ret = ossl_membio2str(out); 00390 00391 return ret; 00392 } 00393 00394 static VALUE 00395 ossl_x509ext_get_critical(VALUE obj) 00396 { 00397 X509_EXTENSION *ext; 00398 00399 GetX509Ext(obj, ext); 00400 return X509_EXTENSION_get_critical(ext) ? Qtrue : Qfalse; 00401 } 00402 00403 static VALUE 00404 ossl_x509ext_to_der(VALUE obj) 00405 { 00406 X509_EXTENSION *ext; 00407 unsigned char *p; 00408 long len; 00409 VALUE str; 00410 00411 GetX509Ext(obj, ext); 00412 if((len = i2d_X509_EXTENSION(ext, NULL)) <= 0) 00413 ossl_raise(eX509ExtError, NULL); 00414 str = rb_str_new(0, len); 00415 p = (unsigned char *)RSTRING_PTR(str); 00416 if(i2d_X509_EXTENSION(ext, &p) < 0) 00417 ossl_raise(eX509ExtError, NULL); 00418 ossl_str_adjust(str, p); 00419 00420 return str; 00421 } 00422 00423 /* 00424 * INIT 00425 */ 00426 void 00427 Init_ossl_x509ext() 00428 { 00429 eX509ExtError = rb_define_class_under(mX509, "ExtensionError", eOSSLError); 00430 00431 cX509ExtFactory = rb_define_class_under(mX509, "ExtensionFactory", rb_cObject); 00432 00433 rb_define_alloc_func(cX509ExtFactory, ossl_x509extfactory_alloc); 00434 rb_define_method(cX509ExtFactory, "initialize", ossl_x509extfactory_initialize, -1); 00435 00436 rb_attr(cX509ExtFactory, rb_intern("issuer_certificate"), 1, 0, Qfalse); 00437 rb_attr(cX509ExtFactory, rb_intern("subject_certificate"), 1, 0, Qfalse); 00438 rb_attr(cX509ExtFactory, rb_intern("subject_request"), 1, 0, Qfalse); 00439 rb_attr(cX509ExtFactory, rb_intern("crl"), 1, 0, Qfalse); 00440 rb_attr(cX509ExtFactory, rb_intern("config"), 1, 0, Qfalse); 00441 00442 rb_define_method(cX509ExtFactory, "issuer_certificate=", ossl_x509extfactory_set_issuer_cert, 1); 00443 rb_define_method(cX509ExtFactory, "subject_certificate=", ossl_x509extfactory_set_subject_cert, 1); 00444 rb_define_method(cX509ExtFactory, "subject_request=", ossl_x509extfactory_set_subject_req, 1); 00445 rb_define_method(cX509ExtFactory, "crl=", ossl_x509extfactory_set_crl, 1); 00446 rb_define_method(cX509ExtFactory, "config=", ossl_x509extfactory_set_config, 1); 00447 rb_define_method(cX509ExtFactory, "create_ext", ossl_x509extfactory_create_ext, -1); 00448 00449 cX509Ext = rb_define_class_under(mX509, "Extension", rb_cObject); 00450 rb_define_alloc_func(cX509Ext, ossl_x509ext_alloc); 00451 rb_define_method(cX509Ext, "initialize", ossl_x509ext_initialize, -1); 00452 rb_define_method(cX509Ext, "oid=", ossl_x509ext_set_oid, 1); 00453 rb_define_method(cX509Ext, "value=", ossl_x509ext_set_value, 1); 00454 rb_define_method(cX509Ext, "critical=", ossl_x509ext_set_critical, 1); 00455 rb_define_method(cX509Ext, "oid", ossl_x509ext_get_oid, 0); 00456 rb_define_method(cX509Ext, "value", ossl_x509ext_get_value, 0); 00457 rb_define_method(cX509Ext, "critical?", ossl_x509ext_get_critical, 0); 00458 rb_define_method(cX509Ext, "to_der", ossl_x509ext_to_der, 0); 00459 } 00460
1.7.3