1/* 2 * $Id: ossl_x509crl.c 32199 2011-06-22 08:41:08Z emboss $ 3 * 'OpenSSL for Ruby' project 4 * Copyright (C) 2001-2002 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 WrapX509CRL(klass, obj, crl) do { \ 14 if (!(crl)) { \ 15 ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \ 16 } \ 17 (obj) = Data_Wrap_Struct((klass), 0, X509_CRL_free, (crl)); \ 18} while (0) 19#define GetX509CRL(obj, crl) do { \ 20 Data_Get_Struct((obj), X509_CRL, (crl)); \ 21 if (!(crl)) { \ 22 ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \ 23 } \ 24} while (0) 25#define SafeGetX509CRL(obj, crl) do { \ 26 OSSL_Check_Kind((obj), cX509CRL); \ 27 GetX509CRL((obj), (crl)); \ 28} while (0) 29 30/* 31 * Classes 32 */ 33VALUE cX509CRL; 34VALUE eX509CRLError; 35 36/* 37 * PUBLIC 38 */ 39X509_CRL * 40GetX509CRLPtr(VALUE obj) 41{ 42 X509_CRL *crl; 43 44 SafeGetX509CRL(obj, crl); 45 46 return crl; 47} 48 49X509_CRL * 50DupX509CRLPtr(VALUE obj) 51{ 52 X509_CRL *crl; 53 54 SafeGetX509CRL(obj, crl); 55 CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509_CRL); 56 57 return crl; 58} 59 60VALUE 61ossl_x509crl_new(X509_CRL *crl) 62{ 63 X509_CRL *tmp; 64 VALUE obj; 65 66 tmp = crl ? X509_CRL_dup(crl) : X509_CRL_new(); 67 if(!tmp) ossl_raise(eX509CRLError, NULL); 68 WrapX509CRL(cX509CRL, obj, tmp); 69 70 return obj; 71} 72 73/* 74 * PRIVATE 75 */ 76static VALUE 77ossl_x509crl_alloc(VALUE klass) 78{ 79 X509_CRL *crl; 80 VALUE obj; 81 82 if (!(crl = X509_CRL_new())) { 83 ossl_raise(eX509CRLError, NULL); 84 } 85 WrapX509CRL(klass, obj, crl); 86 87 return obj; 88} 89 90static VALUE 91ossl_x509crl_initialize(int argc, VALUE *argv, VALUE self) 92{ 93 BIO *in; 94 X509_CRL *crl, *x = DATA_PTR(self); 95 VALUE arg; 96 97 if (rb_scan_args(argc, argv, "01", &arg) == 0) { 98 return self; 99 } 100 arg = ossl_to_der_if_possible(arg); 101 in = ossl_obj2bio(arg); 102 crl = PEM_read_bio_X509_CRL(in, &x, NULL, NULL); 103 DATA_PTR(self) = x; 104 if (!crl) { 105 OSSL_BIO_reset(in); 106 crl = d2i_X509_CRL_bio(in, &x); 107 DATA_PTR(self) = x; 108 } 109 BIO_free(in); 110 if (!crl) ossl_raise(eX509CRLError, NULL); 111 112 return self; 113} 114 115static VALUE 116ossl_x509crl_copy(VALUE self, VALUE other) 117{ 118 X509_CRL *a, *b, *crl; 119 120 rb_check_frozen(self); 121 if (self == other) return self; 122 GetX509CRL(self, a); 123 SafeGetX509CRL(other, b); 124 if (!(crl = X509_CRL_dup(b))) { 125 ossl_raise(eX509CRLError, NULL); 126 } 127 X509_CRL_free(a); 128 DATA_PTR(self) = crl; 129 130 return self; 131} 132 133static VALUE 134ossl_x509crl_get_version(VALUE self) 135{ 136 X509_CRL *crl; 137 long ver; 138 139 GetX509CRL(self, crl); 140 ver = X509_CRL_get_version(crl); 141 142 return LONG2NUM(ver); 143} 144 145static VALUE 146ossl_x509crl_set_version(VALUE self, VALUE version) 147{ 148 X509_CRL *crl; 149 long ver; 150 151 if ((ver = NUM2LONG(version)) < 0) { 152 ossl_raise(eX509CRLError, "version must be >= 0!"); 153 } 154 GetX509CRL(self, crl); 155 if (!X509_CRL_set_version(crl, ver)) { 156 ossl_raise(eX509CRLError, NULL); 157 } 158 159 return version; 160} 161 162static VALUE 163ossl_x509crl_get_signature_algorithm(VALUE self) 164{ 165 X509_CRL *crl; 166 BIO *out; 167 BUF_MEM *buf; 168 VALUE str; 169 170 GetX509CRL(self, crl); 171 if (!(out = BIO_new(BIO_s_mem()))) { 172 ossl_raise(eX509CRLError, NULL); 173 } 174 if (!i2a_ASN1_OBJECT(out, crl->sig_alg->algorithm)) { 175 BIO_free(out); 176 ossl_raise(eX509CRLError, NULL); 177 } 178 BIO_get_mem_ptr(out, &buf); 179 str = rb_str_new(buf->data, buf->length); 180 BIO_free(out); 181 return str; 182} 183 184static VALUE 185ossl_x509crl_get_issuer(VALUE self) 186{ 187 X509_CRL *crl; 188 189 GetX509CRL(self, crl); 190 191 return ossl_x509name_new(X509_CRL_get_issuer(crl)); /* NO DUP - don't free */ 192} 193 194static VALUE 195ossl_x509crl_set_issuer(VALUE self, VALUE issuer) 196{ 197 X509_CRL *crl; 198 199 GetX509CRL(self, crl); 200 201 if (!X509_CRL_set_issuer_name(crl, GetX509NamePtr(issuer))) { /* DUPs name */ 202 ossl_raise(eX509CRLError, NULL); 203 } 204 return issuer; 205} 206 207static VALUE 208ossl_x509crl_get_last_update(VALUE self) 209{ 210 X509_CRL *crl; 211 212 GetX509CRL(self, crl); 213 214 return asn1time_to_time(X509_CRL_get_lastUpdate(crl)); 215} 216 217static VALUE 218ossl_x509crl_set_last_update(VALUE self, VALUE time) 219{ 220 X509_CRL *crl; 221 time_t sec; 222 223 sec = time_to_time_t(time); 224 GetX509CRL(self, crl); 225 if (!X509_time_adj(crl->crl->lastUpdate, 0, &sec)) { 226 ossl_raise(eX509CRLError, NULL); 227 } 228 229 return time; 230} 231 232static VALUE 233ossl_x509crl_get_next_update(VALUE self) 234{ 235 X509_CRL *crl; 236 237 GetX509CRL(self, crl); 238 239 return asn1time_to_time(X509_CRL_get_nextUpdate(crl)); 240} 241 242static VALUE 243ossl_x509crl_set_next_update(VALUE self, VALUE time) 244{ 245 X509_CRL *crl; 246 time_t sec; 247 248 sec = time_to_time_t(time); 249 GetX509CRL(self, crl); 250 /* This must be some thinko in OpenSSL */ 251 if (!(crl->crl->nextUpdate = X509_time_adj(crl->crl->nextUpdate, 0, &sec))){ 252 ossl_raise(eX509CRLError, NULL); 253 } 254 255 return time; 256} 257 258static VALUE 259ossl_x509crl_get_revoked(VALUE self) 260{ 261 X509_CRL *crl; 262 int i, num; 263 X509_REVOKED *rev; 264 VALUE ary, revoked; 265 266 GetX509CRL(self, crl); 267 num = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl)); 268 if (num < 0) { 269 OSSL_Debug("num < 0???"); 270 return rb_ary_new(); 271 } 272 ary = rb_ary_new2(num); 273 for(i=0; i<num; i++) { 274 /* NO DUP - don't free! */ 275 rev = sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i); 276 revoked = ossl_x509revoked_new(rev); 277 rb_ary_push(ary, revoked); 278 } 279 280 return ary; 281} 282 283static VALUE 284ossl_x509crl_set_revoked(VALUE self, VALUE ary) 285{ 286 X509_CRL *crl; 287 X509_REVOKED *rev; 288 int i; 289 290 Check_Type(ary, T_ARRAY); 291 /* All ary members should be X509 Revoked */ 292 for (i=0; i<RARRAY_LEN(ary); i++) { 293 OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Rev); 294 } 295 GetX509CRL(self, crl); 296 sk_X509_REVOKED_pop_free(crl->crl->revoked, X509_REVOKED_free); 297 crl->crl->revoked = NULL; 298 for (i=0; i<RARRAY_LEN(ary); i++) { 299 rev = DupX509RevokedPtr(RARRAY_PTR(ary)[i]); 300 if (!X509_CRL_add0_revoked(crl, rev)) { /* NO DUP - don't free! */ 301 ossl_raise(eX509CRLError, NULL); 302 } 303 } 304 X509_CRL_sort(crl); 305 306 return ary; 307} 308 309static VALUE 310ossl_x509crl_add_revoked(VALUE self, VALUE revoked) 311{ 312 X509_CRL *crl; 313 X509_REVOKED *rev; 314 315 GetX509CRL(self, crl); 316 rev = DupX509RevokedPtr(revoked); 317 if (!X509_CRL_add0_revoked(crl, rev)) { /* NO DUP - don't free! */ 318 ossl_raise(eX509CRLError, NULL); 319 } 320 X509_CRL_sort(crl); 321 322 return revoked; 323} 324 325static VALUE 326ossl_x509crl_sign(VALUE self, VALUE key, VALUE digest) 327{ 328 X509_CRL *crl; 329 EVP_PKEY *pkey; 330 const EVP_MD *md; 331 332 GetX509CRL(self, crl); 333 pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ 334 md = GetDigestPtr(digest); 335 if (!X509_CRL_sign(crl, pkey, md)) { 336 ossl_raise(eX509CRLError, NULL); 337 } 338 339 return self; 340} 341 342static VALUE 343ossl_x509crl_verify(VALUE self, VALUE key) 344{ 345 X509_CRL *crl; 346 int ret; 347 348 GetX509CRL(self, crl); 349 if ((ret = X509_CRL_verify(crl, GetPKeyPtr(key))) < 0) { 350 ossl_raise(eX509CRLError, NULL); 351 } 352 if (ret == 1) { 353 return Qtrue; 354 } 355 356 return Qfalse; 357} 358 359static VALUE 360ossl_x509crl_to_der(VALUE self) 361{ 362 X509_CRL *crl; 363 BIO *out; 364 BUF_MEM *buf; 365 VALUE str; 366 367 GetX509CRL(self, crl); 368 if (!(out = BIO_new(BIO_s_mem()))) { 369 ossl_raise(eX509CRLError, NULL); 370 } 371 if (!i2d_X509_CRL_bio(out, crl)) { 372 BIO_free(out); 373 ossl_raise(eX509CRLError, NULL); 374 } 375 BIO_get_mem_ptr(out, &buf); 376 str = rb_str_new(buf->data, buf->length); 377 BIO_free(out); 378 379 return str; 380} 381 382static VALUE 383ossl_x509crl_to_pem(VALUE self) 384{ 385 X509_CRL *crl; 386 BIO *out; 387 BUF_MEM *buf; 388 VALUE str; 389 390 GetX509CRL(self, crl); 391 if (!(out = BIO_new(BIO_s_mem()))) { 392 ossl_raise(eX509CRLError, NULL); 393 } 394 if (!PEM_write_bio_X509_CRL(out, crl)) { 395 BIO_free(out); 396 ossl_raise(eX509CRLError, NULL); 397 } 398 BIO_get_mem_ptr(out, &buf); 399 str = rb_str_new(buf->data, buf->length); 400 BIO_free(out); 401 402 return str; 403} 404 405static VALUE 406ossl_x509crl_to_text(VALUE self) 407{ 408 X509_CRL *crl; 409 BIO *out; 410 BUF_MEM *buf; 411 VALUE str; 412 413 GetX509CRL(self, crl); 414 if (!(out = BIO_new(BIO_s_mem()))) { 415 ossl_raise(eX509CRLError, NULL); 416 } 417 if (!X509_CRL_print(out, crl)) { 418 BIO_free(out); 419 ossl_raise(eX509CRLError, NULL); 420 } 421 BIO_get_mem_ptr(out, &buf); 422 str = rb_str_new(buf->data, buf->length); 423 BIO_free(out); 424 425 return str; 426} 427 428/* 429 * Gets X509v3 extensions as array of X509Ext objects 430 */ 431static VALUE 432ossl_x509crl_get_extensions(VALUE self) 433{ 434 X509_CRL *crl; 435 int count, i; 436 X509_EXTENSION *ext; 437 VALUE ary; 438 439 GetX509CRL(self, crl); 440 count = X509_CRL_get_ext_count(crl); 441 if (count < 0) { 442 OSSL_Debug("count < 0???"); 443 return rb_ary_new(); 444 } 445 ary = rb_ary_new2(count); 446 for (i=0; i<count; i++) { 447 ext = X509_CRL_get_ext(crl, i); /* NO DUP - don't free! */ 448 rb_ary_push(ary, ossl_x509ext_new(ext)); 449 } 450 451 return ary; 452} 453 454/* 455 * Sets X509_EXTENSIONs 456 */ 457static VALUE 458ossl_x509crl_set_extensions(VALUE self, VALUE ary) 459{ 460 X509_CRL *crl; 461 X509_EXTENSION *ext; 462 int i; 463 464 Check_Type(ary, T_ARRAY); 465 /* All ary members should be X509 Extensions */ 466 for (i=0; i<RARRAY_LEN(ary); i++) { 467 OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Ext); 468 } 469 GetX509CRL(self, crl); 470 sk_X509_EXTENSION_pop_free(crl->crl->extensions, X509_EXTENSION_free); 471 crl->crl->extensions = NULL; 472 for (i=0; i<RARRAY_LEN(ary); i++) { 473 ext = DupX509ExtPtr(RARRAY_PTR(ary)[i]); 474 if(!X509_CRL_add_ext(crl, ext, -1)) { /* DUPs ext - FREE it */ 475 X509_EXTENSION_free(ext); 476 ossl_raise(eX509CRLError, NULL); 477 } 478 X509_EXTENSION_free(ext); 479 } 480 481 return ary; 482} 483 484static VALUE 485ossl_x509crl_add_extension(VALUE self, VALUE extension) 486{ 487 X509_CRL *crl; 488 X509_EXTENSION *ext; 489 490 GetX509CRL(self, crl); 491 ext = DupX509ExtPtr(extension); 492 if (!X509_CRL_add_ext(crl, ext, -1)) { /* DUPs ext - FREE it */ 493 X509_EXTENSION_free(ext); 494 ossl_raise(eX509CRLError, NULL); 495 } 496 X509_EXTENSION_free(ext); 497 498 return extension; 499} 500 501/* 502 * INIT 503 */ 504void 505Init_ossl_x509crl() 506{ 507 eX509CRLError = rb_define_class_under(mX509, "CRLError", eOSSLError); 508 509 cX509CRL = rb_define_class_under(mX509, "CRL", rb_cObject); 510 511 rb_define_alloc_func(cX509CRL, ossl_x509crl_alloc); 512 rb_define_method(cX509CRL, "initialize", ossl_x509crl_initialize, -1); 513 rb_define_copy_func(cX509CRL, ossl_x509crl_copy); 514 515 rb_define_method(cX509CRL, "version", ossl_x509crl_get_version, 0); 516 rb_define_method(cX509CRL, "version=", ossl_x509crl_set_version, 1); 517 rb_define_method(cX509CRL, "signature_algorithm", ossl_x509crl_get_signature_algorithm, 0); 518 rb_define_method(cX509CRL, "issuer", ossl_x509crl_get_issuer, 0); 519 rb_define_method(cX509CRL, "issuer=", ossl_x509crl_set_issuer, 1); 520 rb_define_method(cX509CRL, "last_update", ossl_x509crl_get_last_update, 0); 521 rb_define_method(cX509CRL, "last_update=", ossl_x509crl_set_last_update, 1); 522 rb_define_method(cX509CRL, "next_update", ossl_x509crl_get_next_update, 0); 523 rb_define_method(cX509CRL, "next_update=", ossl_x509crl_set_next_update, 1); 524 rb_define_method(cX509CRL, "revoked", ossl_x509crl_get_revoked, 0); 525 rb_define_method(cX509CRL, "revoked=", ossl_x509crl_set_revoked, 1); 526 rb_define_method(cX509CRL, "add_revoked", ossl_x509crl_add_revoked, 1); 527 rb_define_method(cX509CRL, "sign", ossl_x509crl_sign, 2); 528 rb_define_method(cX509CRL, "verify", ossl_x509crl_verify, 1); 529 rb_define_method(cX509CRL, "to_der", ossl_x509crl_to_der, 0); 530 rb_define_method(cX509CRL, "to_pem", ossl_x509crl_to_pem, 0); 531 rb_define_alias(cX509CRL, "to_s", "to_pem"); 532 rb_define_method(cX509CRL, "to_text", ossl_x509crl_to_text, 0); 533 rb_define_method(cX509CRL, "extensions", ossl_x509crl_get_extensions, 0); 534 rb_define_method(cX509CRL, "extensions=", ossl_x509crl_set_extensions, 1); 535 rb_define_method(cX509CRL, "add_extension", ossl_x509crl_add_extension, 1); 536} 537 538