From 3930d3b36bfbe7b380595ed835dbd6b36847aab9 Mon Sep 17 00:00:00 2001 From: technorama Date: Mon, 2 Apr 2007 19:00:23 +0000 Subject: [PATCH] * ext/openssl/{ossl.[ch],ossl_pkey.c} Add documentation. * ext/openssl/ossl_hmac.c Add reset method. * ext/openssl/ossl_cipher.c (Cipher#update) Take additional buffer argument. * ext/openssl/{ossl_bio.c,ossl_ssl.c,ruby_missing.h} compatibility with 1.8. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12133 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 11 +++++++++ ext/openssl/ossl.c | 23 ++++++++++++++++-- ext/openssl/ossl.h | 5 ++++ ext/openssl/ossl_bio.c | 2 +- ext/openssl/ossl_cipher.c | 50 ++++++++++++++++++++++++++++++++------ ext/openssl/ossl_hmac.c | 17 +++++++++++++ ext/openssl/ossl_pkey.h | 8 ++++++ ext/openssl/ossl_pkey_dh.c | 6 ++--- ext/openssl/ossl_ssl.c | 16 ++++++------ ext/openssl/ruby_missing.h | 21 ++++++++++++++++ 10 files changed, 138 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4e01fdf0f8..9c3fdd71f7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +Mon Apr 2 14:55:58 2007 Technorama + * ext/openssl/{ossl.[ch],ossl_pkey.c} Add documentation. + + * ext/openssl/ossl_hmac.c Add reset method. + + * ext/openssl/ossl_cipher.c (Cipher#update) Take additional + buffer argument. + + * ext/openssl/{ossl_bio.c,ossl_ssl.c,ruby_missing.h} + compatibility with 1.8. + Mon Apr 2 21:55:12 2007 Nobuyoshi Nakada * insns.def (throw), thread.c, yarvcore.h (throwed_errinfo): fixed diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index 16e93bc939..dda3832268 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -310,6 +310,14 @@ ossl_raise(VALUE exc, const char *fmt, ...) rb_exc_raise(rb_exc_new(exc, buf, len)); } +/* + * call-seq: + * OpenSSL.errors -> [String...] + * + * See any remaining errors held in queue. + * + * Any errors you see here are probably due to a bug in ruby's OpenSSL implementation. + */ VALUE ossl_get_errors() { @@ -345,12 +353,23 @@ ossl_debug(const char *fmt, ...) } #endif +/* + * call-seq: + * OpenSSL.debug -> true | false + */ static VALUE ossl_debug_get(VALUE self) { return dOSSL; } +/* + * call-seq: + * OpenSSL.debug = boolean -> boolean + * + * Turns on or off CRYPTO_MEM_CHECK. + * Also shows some debugging message on stderr. + */ static VALUE ossl_debug_set(VALUE self, VALUE val) { @@ -427,8 +446,8 @@ Init_openssl() /* * Verify callback Proc index for ext-data */ - ossl_verify_cb_idx = - X509_STORE_CTX_get_ex_new_index(0, "ossl_verify_cb_idx", 0, 0, 0); + if ((ossl_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, "ossl_verify_cb_idx", 0, 0, 0)) < 0) + ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index"); /* * Init debug core diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h index f8d2514a61..b11614560e 100644 --- a/ext/openssl/ossl.h +++ b/ext/openssl/ossl.h @@ -17,6 +17,11 @@ extern "C" { #endif +#if 0 + mOSSL = rb_define_module("OpenSSL"); + mX509 = rb_define_module_under(mOSSL, "X509"); +#endif + /* * OpenSSL has defined RFILE and Ruby has defined RFILE - so undef it! */ diff --git a/ext/openssl/ossl_bio.c b/ext/openssl/ossl_bio.c index 1358478acb..6db1fb9a62 100644 --- a/ext/openssl/ossl_bio.c +++ b/ext/openssl/ossl_bio.c @@ -25,7 +25,7 @@ ossl_obj2bio(VALUE obj) GetOpenFile(obj, fptr); rb_io_check_readable(fptr); - if ((fd = dup(fptr->fd)) < 0){ + if ((fd = dup(FPTR_TO_FD(fptr))) < 0){ rb_sys_fail(0); } if (!(fp = fdopen(fd, "r"))){ diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c index e260a4b04f..e91b15461e 100644 --- a/ext/openssl/ossl_cipher.c +++ b/ext/openssl/ossl_cipher.c @@ -295,25 +295,59 @@ ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self) return Qnil; } + /* * call-seq: - * cipher.update(string) -> aString + * cipher << data -> string * + * === Parameters + * +data+ is a nonempty string. + * + * This method is deprecated and not available in 1.9.x or later. + */ +static VALUE +ossl_cipher_update_deprecated(VALUE self, VALUE data) +{ + char *cname; + + cname = rb_class2name(rb_obj_class(self)); + rb_warning("%s#<< is deprecated; use %s#update instead", cname, cname); + return rb_funcall(self, rb_intern("update"), 1, data); +} + + +/* + * call-seq: + * cipher.update(data [, buffer]) -> string or buffer + * + * === Parameters + * +data+ is a nonempty string. + * +buffer+ is an optional string to store the result. */ static VALUE -ossl_cipher_update(VALUE self, VALUE data) +ossl_cipher_update(int argc, VALUE *argv, VALUE self) { EVP_CIPHER_CTX *ctx; char *in; int in_len, out_len; - VALUE str; + VALUE data, str; + + rb_scan_args(argc, argv, "11", &data, &str); StringValue(data); in = RSTRING_PTR(data); if ((in_len = RSTRING_LEN(data)) == 0) rb_raise(rb_eArgError, "data must not be empty"); GetCipher(self, ctx); - str = rb_str_new(0, in_len+EVP_CIPHER_CTX_block_size(ctx)); + out_len = in_len+EVP_CIPHER_CTX_block_size(ctx); + + if (NIL_P(str)) { + str = rb_str_new(0, out_len); + } else { + StringValue(str); + rb_str_resize(str, out_len); + } + if (!EVP_CipherUpdate(ctx, RSTRING_PTR(str), &out_len, in, in_len)) ossl_raise(eCipherError, NULL); assert(out_len < RSTRING_LEN(str)); @@ -518,7 +552,10 @@ Init_ossl_cipher(void) rb_define_method(cCipher, "encrypt", ossl_cipher_encrypt, -1); rb_define_method(cCipher, "decrypt", ossl_cipher_decrypt, -1); rb_define_method(cCipher, "pkcs5_keyivgen", ossl_cipher_pkcs5_keyivgen, -1); - rb_define_method(cCipher, "update", ossl_cipher_update, 1); + rb_define_method(cCipher, "update", ossl_cipher_update, -1); +#if RUBY_VERSION_CODE < 190 + rb_define_method(cCipher, "<<", ossl_cipher_update_deprecated, 1); +#endif rb_define_method(cCipher, "final", ossl_cipher_final, 0); rb_define_method(cCipher, "name", ossl_cipher_name, 0); rb_define_method(cCipher, "key=", ossl_cipher_set_key, 1); @@ -528,6 +565,5 @@ Init_ossl_cipher(void) rb_define_method(cCipher, "iv_len", ossl_cipher_iv_length, 0); rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0); rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1); - - rb_define_const(mCipher, "PKCS5_SALT_LEN", PKCS5_SALT_LEN); } + diff --git a/ext/openssl/ossl_hmac.c b/ext/openssl/ossl_hmac.c index 84d378f732..ba85f521f7 100644 --- a/ext/openssl/ossl_hmac.c +++ b/ext/openssl/ossl_hmac.c @@ -172,6 +172,22 @@ ossl_hmac_hexdigest(VALUE self) return hexdigest; } +/* + * call-seq: + * hmac.reset -> self + * + */ +static VALUE +ossl_hmac_reset(VALUE self) +{ + HMAC_CTX *ctx; + + GetHMAC(self, ctx); + HMAC_Init_ex(ctx, NULL, 0, NULL, NULL); + + return self; +} + /* * call-seq: * HMAC.digest(digest, key, data) -> aString @@ -237,6 +253,7 @@ Init_ossl_hmac() rb_define_method(cHMAC, "initialize", ossl_hmac_initialize, 2); rb_define_copy_func(cHMAC, ossl_hmac_copy); + rb_define_method(cHMAC, "reset", ossl_hmac_reset, 0); rb_define_method(cHMAC, "update", ossl_hmac_update, 1); rb_define_alias(cHMAC, "<<", "update"); rb_define_method(cHMAC, "digest", ossl_hmac_digest, 0); diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h index 880a104675..5057843fd1 100644 --- a/ext/openssl/ossl_pkey.h +++ b/ext/openssl/ossl_pkey.h @@ -78,6 +78,10 @@ VALUE ossl_dh_new(EVP_PKEY *); void Init_ossl_dh(void); #define OSSL_PKEY_BN(keytype, name) \ +/* \ + * call-seq: \ + * key.##name -> aBN \ + */ \ static VALUE ossl_##keytype##_get_##name(VALUE self) \ { \ EVP_PKEY *pkey; \ @@ -89,6 +93,10 @@ static VALUE ossl_##keytype##_get_##name(VALUE self) \ return Qnil; \ return ossl_bn_new(bn); \ } \ +/* \ + * call-seq: \ + * key.##name = bn -> bn \ + */ \ static VALUE ossl_##keytype##_set_##name(VALUE self, VALUE bignum) \ { \ EVP_PKEY *pkey; \ diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c index 3614914680..a6924a6bb8 100644 --- a/ext/openssl/ossl_pkey_dh.c +++ b/ext/openssl/ossl_pkey_dh.c @@ -483,9 +483,9 @@ ossl_create_dh(unsigned char *p, size_t plen, unsigned char *g, size_t glen) return dh; } - /* - * TEST - */ +/* + * INIT + */ void Init_ossl_dh() { diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 93bb709451..8f32630ed7 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -550,7 +550,7 @@ ossl_ssl_setup(VALUE self) GetOpenFile(io, fptr); rb_io_check_readable(fptr); rb_io_check_writable(fptr); - SSL_set_fd(ssl, TO_SOCKET(fptr->fd)); + SSL_set_fd(ssl, TO_SOCKET(FPTR_TO_FD(fptr))); SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void*)self); cb = ossl_sslctx_get_verify_cb(v_ctx); SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void*)cb); @@ -582,10 +582,10 @@ ossl_start_ssl(VALUE self, int (*func)()) if((ret = func(ssl)) > 0) break; switch(ssl_get_error(ssl, ret)){ case SSL_ERROR_WANT_WRITE: - rb_io_wait_writable(fptr->fd); + rb_io_wait_writable(FPTR_TO_FD(fptr)); continue; case SSL_ERROR_WANT_READ: - rb_io_wait_readable(fptr->fd); + rb_io_wait_readable(FPTR_TO_FD(fptr)); continue; case SSL_ERROR_SYSCALL: if (errno) rb_sys_fail(0); @@ -633,7 +633,7 @@ ossl_ssl_read(int argc, VALUE *argv, VALUE self) GetOpenFile(ossl_ssl_get_io(self), fptr); if (ssl) { if(SSL_pending(ssl) <= 0) - rb_thread_wait_fd(fptr->fd); + rb_thread_wait_fd(FPTR_TO_FD(fptr)); for (;;){ nread = SSL_read(ssl, RSTRING_PTR(str), RSTRING_LEN(str)); switch(ssl_get_error(ssl, nread)){ @@ -642,10 +642,10 @@ ossl_ssl_read(int argc, VALUE *argv, VALUE self) case SSL_ERROR_ZERO_RETURN: rb_eof_error(); case SSL_ERROR_WANT_WRITE: - rb_io_wait_writable(fptr->fd); + rb_io_wait_writable(FPTR_TO_FD(fptr)); continue; case SSL_ERROR_WANT_READ: - rb_io_wait_readable(fptr->fd); + rb_io_wait_readable(FPTR_TO_FD(fptr)); continue; case SSL_ERROR_SYSCALL: if(ERR_peek_error() == 0 && nread == 0) rb_eof_error(); @@ -686,10 +686,10 @@ ossl_ssl_write(VALUE self, VALUE str) case SSL_ERROR_NONE: goto end; case SSL_ERROR_WANT_WRITE: - rb_io_wait_writable(fptr->fd); + rb_io_wait_writable(FPTR_TO_FD(fptr)); continue; case SSL_ERROR_WANT_READ: - rb_io_wait_readable(fptr->fd); + rb_io_wait_readable(FPTR_TO_FD(fptr)); continue; case SSL_ERROR_SYSCALL: if (errno) rb_sys_fail(0); diff --git a/ext/openssl/ruby_missing.h b/ext/openssl/ruby_missing.h index 4bd08890f8..2eaa77e691 100644 --- a/ext/openssl/ruby_missing.h +++ b/ext/openssl/ruby_missing.h @@ -14,5 +14,26 @@ #define rb_define_copy_func(klass, func) \ rb_define_method(klass, "initialize_copy", func, 1) + +#if RUBY_VERSION_CODE > 190 +#define FPTR_TO_FD(fptr) (fptr->fd) +#else + +#define rb_io_t OpenFile +#define FPTR_TO_FD(fptr) (fileno(fptr->f)) + + +/* these methods should probably be backported to 1.8 */ +#define rb_str_set_len(str, length) do { \ + RSTRING(str)->ptr[length] = 0; \ + RSTRING(str)->len = length; \ +} while(0) + +/* the openssl module doesn't use arg[3-4] and arg2 is always rb_each */ +#define rb_block_call(arg1, arg2, arg3, arg4, arg5, arg6) rb_iterate(rb_each, arg1, arg5, arg6) + +#endif /* RUBY_VERSION_CODE > 190 */ + + #endif /* _OSS_RUBY_MISSING_H_ */