00001
00002
00003
00004
00005
00006
00007
00008
00009
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
00032
00033 VALUE cX509Req;
00034 VALUE eX509ReqError;
00035
00036
00037
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
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 (void)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(eX509CertError, 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
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))) {
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
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))) {
00315 ossl_raise(eX509ReqError, NULL);
00316 }
00317
00318 return ossl_pkey_new(pkey);
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);
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);
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
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);
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
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