ruby-changes:20289
From: emboss <ko1@a...>
Date: Thu, 30 Jun 2011 23:49:01 +0900 (JST)
Subject: [ruby-changes:20289] emboss:r32337 (trunk): * ext/openssl/ossl.c/.h: Added ossl_x509_name_sk2ary.
emboss 2011-06-30 23:48:52 +0900 (Thu, 30 Jun 2011) New Revision: 32337 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=32337 Log: * ext/openssl/ossl.c/.h: Added ossl_x509_name_sk2ary. * ext/openssl/ossl.c: Replaced ossl_x509_ary2k by generic macro to simplify future conversions. * ext/openssl/ossl_ssl.c: Implement SSLSocket#client_ca. * test/openssl/test_ssl.rb: Add test for SSLSocket#client_ca. Thanks to Ippei Obayashi for providing the patch! [ Ruby 1.9 - Feature #4481 ] [ruby-core:35461] Modified files: trunk/ChangeLog trunk/ext/openssl/ossl.c trunk/ext/openssl/ossl.h trunk/ext/openssl/ossl_ssl.c trunk/test/openssl/test_ssl.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 32336) +++ ChangeLog (revision 32337) @@ -1,3 +1,13 @@ +Thu Jun 30 23:43:30 2011 Martin Bosslet <Martin.Bosslet@g...> + + * ext/openssl/ossl.c/.h: Added ossl_x509_name_sk2ary. + * ext/openssl/ossl.c: Replaced ossl_x509_ary2k by generic macro to + simplify future conversions. + * ext/openssl/ossl_ssl.c: Implement SSLSocket#client_ca. + * test/openssl/test_ssl.rb: Add test for SSLSocket#client_ca. + Thanks to Ippei Obayashi for providing the patch! + [ Ruby 1.9 - Feature #4481 ] [ruby-core:35461] + Thu Jun 30 22:38:58 2011 Koichi Sasada <ko1@a...> * benchmark/bm_vm2_defined_method.rb: added to measure performance of Index: ext/openssl/ossl_ssl.c =================================================================== --- ext/openssl/ossl_ssl.c (revision 32336) +++ ext/openssl/ossl_ssl.c (revision 32337) @@ -1643,6 +1643,33 @@ return INT2FIX(SSL_get_verify_result(ssl)); } +/* + * call-seq: + * ssl.client_ca => [x509name, ...] + * + * Returns the list of client CAs. Please note that in contrast to + * SSLContext#client_ca= no array of X509::Certificate is returned but + * X509::Name instances of the CA's subject distinguished name. + * + * In server mode, returns the list set by SSLContext#client_ca=. + * In client mode, returns the list of client CAs sent from the server. + */ +static VALUE +ossl_ssl_get_client_ca_list(VALUE self) +{ + SSL *ssl; + STACK_OF(X509_NAME) *ca; + + Data_Get_Struct(self, SSL, ssl); + if (!ssl) { + rb_warning("SSL session is not started yet."); + return Qnil; + } + + ca = SSL_get_client_CA_list(ssl); + return ossl_x509name_sk2ary(ca); +} + void Init_ossl_ssl() { @@ -1930,6 +1957,7 @@ rb_define_method(cSSLSocket, "session_reused?", ossl_ssl_session_reused, 0); rb_define_method(cSSLSocket, "session=", ossl_ssl_set_session, 1); rb_define_method(cSSLSocket, "verify_result", ossl_ssl_get_verify_result, 0); + rb_define_method(cSSLSocket, "client_ca", ossl_ssl_get_client_ca_list, 0); #define ossl_ssl_def_const(x) rb_define_const(mSSL, #x, INT2NUM(SSL_##x)) Index: ext/openssl/ossl.c =================================================================== --- ext/openssl/ossl.c (revision 32336) +++ ext/openssl/ossl.c (revision 32337) @@ -47,49 +47,54 @@ /* * Data Conversion */ -STACK_OF(X509) * -ossl_x509_ary2sk0(VALUE ary) -{ - STACK_OF(X509) *sk; - VALUE val; - X509 *x509; - int i; - - Check_Type(ary, T_ARRAY); - sk = sk_X509_new_null(); - if (!sk) ossl_raise(eOSSLError, NULL); - - for (i = 0; i < RARRAY_LEN(ary); i++) { - val = rb_ary_entry(ary, i); - if (!rb_obj_is_kind_of(val, cX509Cert)) { - sk_X509_pop_free(sk, X509_free); - ossl_raise(eOSSLError, "object not X509 cert in array"); - } - x509 = DupX509CertPtr(val); /* NEED TO DUP */ - sk_X509_push(sk, x509); - } - return sk; +#define OSSL_IMPL_ARY2SK(name, type, expected_class, dup) \ +STACK_OF(type) * \ +ossl_##name##_ary2sk0(VALUE ary) \ +{ \ + STACK_OF(type) *sk; \ + VALUE val; \ + type *x; \ + int i; \ + \ + Check_Type(ary, T_ARRAY); \ + sk = sk_##type##_new_null(); \ + if (!sk) ossl_raise(eOSSLError, NULL); \ + \ + for (i = 0; i < RARRAY_LEN(ary); i++) { \ + val = rb_ary_entry(ary, i); \ + if (!rb_obj_is_kind_of(val, expected_class)) { \ + sk_##type##_pop_free(sk, type##_free); \ + ossl_raise(eOSSLError, "object in array not" \ + " of class ##type##"); \ + } \ + x = dup(val); /* NEED TO DUP */ \ + sk_##type##_push(sk, x); \ + } \ + return sk; \ +} \ + \ +STACK_OF(type) * \ +ossl_protect_##name##_ary2sk(VALUE ary, int *status) \ +{ \ + return (STACK_OF(type)*)rb_protect( \ + (VALUE(*)_((VALUE)))ossl_##name##_ary2sk0, \ + ary, \ + status); \ +} \ + \ +STACK_OF(type) * \ +ossl_##name##_ary2sk(VALUE ary) \ +{ \ + STACK_OF(type) *sk; \ + int status = 0; \ + \ + sk = ossl_protect_##name##_ary2sk(ary, &status); \ + if (status) rb_jump_tag(status); \ + \ + return sk; \ } +OSSL_IMPL_ARY2SK(x509, X509, cX509Cert, DupX509CertPtr) -STACK_OF(X509) * -ossl_protect_x509_ary2sk(VALUE ary, int *status) -{ - return (STACK_OF(X509)*)rb_protect((VALUE(*)_((VALUE)))ossl_x509_ary2sk0, - ary, status); -} - -STACK_OF(X509) * -ossl_x509_ary2sk(VALUE ary) -{ - STACK_OF(X509) *sk; - int status = 0; - - sk = ossl_protect_x509_ary2sk(ary, &status); - if(status) rb_jump_tag(status); - - return sk; -} - #define OSSL_IMPL_SK2ARY(name, type) \ VALUE \ ossl_##name##_sk2ary(STACK_OF(type) *sk) \ @@ -117,6 +122,7 @@ } OSSL_IMPL_SK2ARY(x509, X509) OSSL_IMPL_SK2ARY(x509crl, X509_CRL) +OSSL_IMPL_SK2ARY(x509name, X509_NAME) static VALUE ossl_str_new(int size) Index: ext/openssl/ossl.h =================================================================== --- ext/openssl/ossl.h (revision 32336) +++ ext/openssl/ossl.h (revision 32337) @@ -126,6 +126,7 @@ STACK_OF(X509) *ossl_protect_x509_ary2sk(VALUE,int*); VALUE ossl_x509_sk2ary(STACK_OF(X509) *certs); VALUE ossl_x509crl_sk2ary(STACK_OF(X509_CRL) *crl); +VALUE ossl_x509name_sk2ary(STACK_OF(X509_NAME) *names); VALUE ossl_buf2str(char *buf, int len); #define ossl_str_adjust(str, p) \ do{\ Index: test/openssl/test_ssl.rb =================================================================== --- test/openssl/test_ssl.rb (revision 32336) +++ test/openssl/test_ssl.rb (revision 32337) @@ -135,6 +135,28 @@ } end + def test_client_ca + ctx_proc = Proc.new do |ctx| + ctx.client_ca = [@ca_cert] + end + + vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT + start_server(PORT, vflag, true, :ctx_proc => ctx_proc){|server, port| + ctx = OpenSSL::SSL::SSLContext.new + client_ca_from_server = nil + ctx.client_cert_cb = Proc.new do |sslconn| + client_ca_from_server = sslconn.client_ca + [@cli_cert, @cli_key] + end + sock = TCPSocket.new("127.0.0.1", port) + ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) + ssl.sync_close = true + ssl.connect + assert_equal([@ca], client_ca_from_server) + ssl.close + } + end + def test_starttls start_server(PORT, OpenSSL::SSL::VERIFY_NONE, false){|server, port| sock = TCPSocket.new("127.0.0.1", port) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/