Ruby 1.9.3p327(2012-11-10revision37606)
|
00001 /* 00002 * $Id: ossl_x509req.c 32199 2011-06-22 08:41:08Z emboss $ 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 WrapX509Req(klass, obj, req) do { \ 00014 if (!(req)) { \ 00015 ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \ 00016 } \ 00017 (obj) = Data_Wrap_Struct((klass), 0, X509_REQ_free, (req)); \ 00018 } while (0) 00019 #define GetX509Req(obj, req) do { \ 00020 Data_Get_Struct((obj), X509_REQ, (req)); \ 00021 if (!(req)) { \ 00022 ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \ 00023 } \ 00024 } while (0) 00025 #define SafeGetX509Req(obj, req) do { \ 00026 OSSL_Check_Kind((obj), cX509Req); \ 00027 GetX509Req((obj), (req)); \ 00028 } while (0) 00029 00030 /* 00031 * Classes 00032 */ 00033 VALUE cX509Req; 00034 VALUE eX509ReqError; 00035 00036 /* 00037 * Public functions 00038 */ 00039 VALUE 00040 ossl_x509req_new(X509_REQ *req) 00041 { 00042 X509_REQ *new; 00043 VALUE obj; 00044 00045 if (!req) { 00046 new = X509_REQ_new(); 00047 } else { 00048 new = X509_REQ_dup(req); 00049 } 00050 if (!new) { 00051 ossl_raise(eX509ReqError, NULL); 00052 } 00053 WrapX509Req(cX509Req, obj, new); 00054 00055 return obj; 00056 } 00057 00058 X509_REQ * 00059 GetX509ReqPtr(VALUE obj) 00060 { 00061 X509_REQ *req; 00062 00063 SafeGetX509Req(obj, req); 00064 00065 return req; 00066 } 00067 00068 X509_REQ * 00069 DupX509ReqPtr(VALUE obj) 00070 { 00071 X509_REQ *req, *new; 00072 00073 SafeGetX509Req(obj, req); 00074 if (!(new = X509_REQ_dup(req))) { 00075 ossl_raise(eX509ReqError, NULL); 00076 } 00077 00078 return new; 00079 } 00080 00081 /* 00082 * Private functions 00083 */ 00084 static VALUE 00085 ossl_x509req_alloc(VALUE klass) 00086 { 00087 X509_REQ *req; 00088 VALUE obj; 00089 00090 if (!(req = X509_REQ_new())) { 00091 ossl_raise(eX509ReqError, NULL); 00092 } 00093 WrapX509Req(klass, obj, req); 00094 00095 return obj; 00096 } 00097 00098 static VALUE 00099 ossl_x509req_initialize(int argc, VALUE *argv, VALUE self) 00100 { 00101 BIO *in; 00102 X509_REQ *req, *x = DATA_PTR(self); 00103 VALUE arg; 00104 00105 if (rb_scan_args(argc, argv, "01", &arg) == 0) { 00106 return self; 00107 } 00108 arg = ossl_to_der_if_possible(arg); 00109 in = ossl_obj2bio(arg); 00110 req = PEM_read_bio_X509_REQ(in, &x, NULL, NULL); 00111 DATA_PTR(self) = x; 00112 if (!req) { 00113 OSSL_BIO_reset(in); 00114 req = d2i_X509_REQ_bio(in, &x); 00115 DATA_PTR(self) = x; 00116 } 00117 BIO_free(in); 00118 if (!req) ossl_raise(eX509ReqError, NULL); 00119 00120 return self; 00121 } 00122 00123 static VALUE 00124 ossl_x509req_copy(VALUE self, VALUE other) 00125 { 00126 X509_REQ *a, *b, *req; 00127 00128 rb_check_frozen(self); 00129 if (self == other) return self; 00130 GetX509Req(self, a); 00131 SafeGetX509Req(other, b); 00132 if (!(req = X509_REQ_dup(b))) { 00133 ossl_raise(eX509ReqError, NULL); 00134 } 00135 X509_REQ_free(a); 00136 DATA_PTR(self) = req; 00137 00138 return self; 00139 } 00140 00141 static VALUE 00142 ossl_x509req_to_pem(VALUE self) 00143 { 00144 X509_REQ *req; 00145 BIO *out; 00146 BUF_MEM *buf; 00147 VALUE str; 00148 00149 GetX509Req(self, req); 00150 if (!(out = BIO_new(BIO_s_mem()))) { 00151 ossl_raise(eX509ReqError, NULL); 00152 } 00153 if (!PEM_write_bio_X509_REQ(out, req)) { 00154 BIO_free(out); 00155 ossl_raise(eX509ReqError, NULL); 00156 } 00157 BIO_get_mem_ptr(out, &buf); 00158 str = rb_str_new(buf->data, buf->length); 00159 BIO_free(out); 00160 00161 return str; 00162 } 00163 00164 static VALUE 00165 ossl_x509req_to_der(VALUE self) 00166 { 00167 X509_REQ *req; 00168 VALUE str; 00169 long len; 00170 unsigned char *p; 00171 00172 GetX509Req(self, req); 00173 if ((len = i2d_X509_REQ(req, NULL)) <= 0) 00174 ossl_raise(eX509ReqError, NULL); 00175 str = rb_str_new(0, len); 00176 p = (unsigned char *)RSTRING_PTR(str); 00177 if (i2d_X509_REQ(req, &p) <= 0) 00178 ossl_raise(eX509ReqError, NULL); 00179 ossl_str_adjust(str, p); 00180 00181 return str; 00182 } 00183 00184 static VALUE 00185 ossl_x509req_to_text(VALUE self) 00186 { 00187 X509_REQ *req; 00188 BIO *out; 00189 BUF_MEM *buf; 00190 VALUE str; 00191 00192 GetX509Req(self, req); 00193 if (!(out = BIO_new(BIO_s_mem()))) { 00194 ossl_raise(eX509ReqError, NULL); 00195 } 00196 if (!X509_REQ_print(out, req)) { 00197 BIO_free(out); 00198 ossl_raise(eX509ReqError, NULL); 00199 } 00200 BIO_get_mem_ptr(out, &buf); 00201 str = rb_str_new(buf->data, buf->length); 00202 BIO_free(out); 00203 00204 return str; 00205 } 00206 00207 #if 0 00208 /* 00209 * Makes X509 from X509_REQuest 00210 */ 00211 static VALUE 00212 ossl_x509req_to_x509(VALUE self, VALUE days, VALUE key) 00213 { 00214 X509_REQ *req; 00215 X509 *x509; 00216 00217 GetX509Req(self, req); 00218 ... 00219 if (!(x509 = X509_REQ_to_X509(req, d, pkey))) { 00220 ossl_raise(eX509ReqError, NULL); 00221 } 00222 00223 return ossl_x509_new(x509); 00224 } 00225 #endif 00226 00227 static VALUE 00228 ossl_x509req_get_version(VALUE self) 00229 { 00230 X509_REQ *req; 00231 long version; 00232 00233 GetX509Req(self, req); 00234 version = X509_REQ_get_version(req); 00235 00236 return LONG2FIX(version); 00237 } 00238 00239 static VALUE 00240 ossl_x509req_set_version(VALUE self, VALUE version) 00241 { 00242 X509_REQ *req; 00243 long ver; 00244 00245 if ((ver = FIX2LONG(version)) < 0) { 00246 ossl_raise(eX509ReqError, "version must be >= 0!"); 00247 } 00248 GetX509Req(self, req); 00249 if (!X509_REQ_set_version(req, ver)) { 00250 ossl_raise(eX509ReqError, NULL); 00251 } 00252 00253 return version; 00254 } 00255 00256 static VALUE 00257 ossl_x509req_get_subject(VALUE self) 00258 { 00259 X509_REQ *req; 00260 X509_NAME *name; 00261 00262 GetX509Req(self, req); 00263 if (!(name = X509_REQ_get_subject_name(req))) { /* NO DUP - don't free */ 00264 ossl_raise(eX509ReqError, NULL); 00265 } 00266 00267 return ossl_x509name_new(name); 00268 } 00269 00270 static VALUE 00271 ossl_x509req_set_subject(VALUE self, VALUE subject) 00272 { 00273 X509_REQ *req; 00274 00275 GetX509Req(self, req); 00276 /* DUPs name */ 00277 if (!X509_REQ_set_subject_name(req, GetX509NamePtr(subject))) { 00278 ossl_raise(eX509ReqError, NULL); 00279 } 00280 00281 return subject; 00282 } 00283 00284 static VALUE 00285 ossl_x509req_get_signature_algorithm(VALUE self) 00286 { 00287 X509_REQ *req; 00288 BIO *out; 00289 BUF_MEM *buf; 00290 VALUE str; 00291 00292 GetX509Req(self, req); 00293 00294 if (!(out = BIO_new(BIO_s_mem()))) { 00295 ossl_raise(eX509ReqError, NULL); 00296 } 00297 if (!i2a_ASN1_OBJECT(out, req->sig_alg->algorithm)) { 00298 BIO_free(out); 00299 ossl_raise(eX509ReqError, NULL); 00300 } 00301 BIO_get_mem_ptr(out, &buf); 00302 str = rb_str_new(buf->data, buf->length); 00303 BIO_free(out); 00304 return str; 00305 } 00306 00307 static VALUE 00308 ossl_x509req_get_public_key(VALUE self) 00309 { 00310 X509_REQ *req; 00311 EVP_PKEY *pkey; 00312 00313 GetX509Req(self, req); 00314 if (!(pkey = X509_REQ_get_pubkey(req))) { /* adds reference */ 00315 ossl_raise(eX509ReqError, NULL); 00316 } 00317 00318 return ossl_pkey_new(pkey); /* NO DUP - OK */ 00319 } 00320 00321 static VALUE 00322 ossl_x509req_set_public_key(VALUE self, VALUE key) 00323 { 00324 X509_REQ *req; 00325 EVP_PKEY *pkey; 00326 00327 GetX509Req(self, req); 00328 pkey = GetPKeyPtr(key); /* NO NEED TO DUP */ 00329 if (!X509_REQ_set_pubkey(req, pkey)) { 00330 ossl_raise(eX509ReqError, NULL); 00331 } 00332 00333 return key; 00334 } 00335 00336 static VALUE 00337 ossl_x509req_sign(VALUE self, VALUE key, VALUE digest) 00338 { 00339 X509_REQ *req; 00340 EVP_PKEY *pkey; 00341 const EVP_MD *md; 00342 00343 GetX509Req(self, req); 00344 pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ 00345 md = GetDigestPtr(digest); 00346 if (!X509_REQ_sign(req, pkey, md)) { 00347 ossl_raise(eX509ReqError, NULL); 00348 } 00349 00350 return self; 00351 } 00352 00353 /* 00354 * Checks that cert signature is made with PRIVversion of this PUBLIC 'key' 00355 */ 00356 static VALUE 00357 ossl_x509req_verify(VALUE self, VALUE key) 00358 { 00359 X509_REQ *req; 00360 EVP_PKEY *pkey; 00361 int i; 00362 00363 GetX509Req(self, req); 00364 pkey = GetPKeyPtr(key); /* NO NEED TO DUP */ 00365 if ((i = X509_REQ_verify(req, pkey)) < 0) { 00366 ossl_raise(eX509ReqError, NULL); 00367 } 00368 if (i > 0) { 00369 return Qtrue; 00370 } 00371 00372 return Qfalse; 00373 } 00374 00375 static VALUE 00376 ossl_x509req_get_attributes(VALUE self) 00377 { 00378 X509_REQ *req; 00379 int count, i; 00380 X509_ATTRIBUTE *attr; 00381 VALUE ary; 00382 00383 GetX509Req(self, req); 00384 00385 count = X509_REQ_get_attr_count(req); 00386 if (count < 0) { 00387 OSSL_Debug("count < 0???"); 00388 return rb_ary_new(); 00389 } 00390 ary = rb_ary_new2(count); 00391 for (i=0; i<count; i++) { 00392 attr = X509_REQ_get_attr(req, i); 00393 rb_ary_push(ary, ossl_x509attr_new(attr)); 00394 } 00395 00396 return ary; 00397 } 00398 00399 static VALUE 00400 ossl_x509req_set_attributes(VALUE self, VALUE ary) 00401 { 00402 X509_REQ *req; 00403 X509_ATTRIBUTE *attr; 00404 int i; 00405 VALUE item; 00406 00407 Check_Type(ary, T_ARRAY); 00408 for (i=0;i<RARRAY_LEN(ary); i++) { 00409 OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Attr); 00410 } 00411 GetX509Req(self, req); 00412 sk_X509_ATTRIBUTE_pop_free(req->req_info->attributes, X509_ATTRIBUTE_free); 00413 req->req_info->attributes = NULL; 00414 for (i=0;i<RARRAY_LEN(ary); i++) { 00415 item = RARRAY_PTR(ary)[i]; 00416 attr = DupX509AttrPtr(item); 00417 if (!X509_REQ_add1_attr(req, attr)) { 00418 ossl_raise(eX509ReqError, NULL); 00419 } 00420 } 00421 return ary; 00422 } 00423 00424 static VALUE 00425 ossl_x509req_add_attribute(VALUE self, VALUE attr) 00426 { 00427 X509_REQ *req; 00428 00429 GetX509Req(self, req); 00430 if (!X509_REQ_add1_attr(req, DupX509AttrPtr(attr))) { 00431 ossl_raise(eX509ReqError, NULL); 00432 } 00433 00434 return attr; 00435 } 00436 00437 /* 00438 * X509_REQUEST init 00439 */ 00440 void 00441 Init_ossl_x509req() 00442 { 00443 eX509ReqError = rb_define_class_under(mX509, "RequestError", eOSSLError); 00444 00445 cX509Req = rb_define_class_under(mX509, "Request", rb_cObject); 00446 00447 rb_define_alloc_func(cX509Req, ossl_x509req_alloc); 00448 rb_define_method(cX509Req, "initialize", ossl_x509req_initialize, -1); 00449 rb_define_copy_func(cX509Req, ossl_x509req_copy); 00450 00451 rb_define_method(cX509Req, "to_pem", ossl_x509req_to_pem, 0); 00452 rb_define_method(cX509Req, "to_der", ossl_x509req_to_der, 0); 00453 rb_define_alias(cX509Req, "to_s", "to_pem"); 00454 rb_define_method(cX509Req, "to_text", ossl_x509req_to_text, 0); 00455 rb_define_method(cX509Req, "version", ossl_x509req_get_version, 0); 00456 rb_define_method(cX509Req, "version=", ossl_x509req_set_version, 1); 00457 rb_define_method(cX509Req, "subject", ossl_x509req_get_subject, 0); 00458 rb_define_method(cX509Req, "subject=", ossl_x509req_set_subject, 1); 00459 rb_define_method(cX509Req, "signature_algorithm", ossl_x509req_get_signature_algorithm, 0); 00460 rb_define_method(cX509Req, "public_key", ossl_x509req_get_public_key, 0); 00461 rb_define_method(cX509Req, "public_key=", ossl_x509req_set_public_key, 1); 00462 rb_define_method(cX509Req, "sign", ossl_x509req_sign, 2); 00463 rb_define_method(cX509Req, "verify", ossl_x509req_verify, 1); 00464 rb_define_method(cX509Req, "attributes", ossl_x509req_get_attributes, 0); 00465 rb_define_method(cX509Req, "attributes=", ossl_x509req_set_attributes, 1); 00466 rb_define_method(cX509Req, "add_attribute", ossl_x509req_add_attribute, 1); 00467 } 00468 00469