summaryrefslogtreecommitdiff
path: root/ext/openssl
diff options
context:
space:
mode:
Diffstat (limited to 'ext/openssl')
-rw-r--r--ext/openssl/History.md2
-rw-r--r--ext/openssl/lib/openssl/x509.rb18
-rw-r--r--ext/openssl/ossl_ocsp.c2
-rw-r--r--ext/openssl/ossl_ssl.c231
-rw-r--r--ext/openssl/ossl_x509name.c11
5 files changed, 121 insertions, 143 deletions
diff --git a/ext/openssl/History.md b/ext/openssl/History.md
index 46435f9be61..255c0fc50bd 100644
--- a/ext/openssl/History.md
+++ b/ext/openssl/History.md
@@ -113,7 +113,7 @@ Bug fixes
[[GitHub #453]](https://github.com/ruby/openssl/pull/453)
* Fix misuse of input record separator in `OpenSSL::Buffering` where it was
for output.
-* Fix wrong interger casting in `OpenSSL::PKey::EC#dsa_verify_asn1`.
+* Fix wrong integer casting in `OpenSSL::PKey::EC#dsa_verify_asn1`.
[[GitHub #460]](https://github.com/ruby/openssl/pull/460)
* `extconf.rb` explicitly checks that OpenSSL's version number is 1.0.1 or
newer but also less than 3.0. Ruby/OpenSSL v2.1.x and v2.2.x will not support
diff --git a/ext/openssl/lib/openssl/x509.rb b/ext/openssl/lib/openssl/x509.rb
index 448941f75e3..f973f4f4dc6 100644
--- a/ext/openssl/lib/openssl/x509.rb
+++ b/ext/openssl/lib/openssl/x509.rb
@@ -279,11 +279,29 @@ module OpenSSL
end
class << self
+ # Parses the UTF-8 string representation of a distinguished name,
+ # according to RFC 2253.
+ #
+ # See also #to_utf8 for the opposite operation.
def parse_rfc2253(str, template=OBJECT_TYPE_TEMPLATE)
ary = OpenSSL::X509::Name::RFC2253DN.scan(str)
self.new(ary, template)
end
+ # Parses the string representation of a distinguished name. Two
+ # different forms are supported:
+ #
+ # - \OpenSSL format (<tt>X509_NAME_oneline()</tt>) used by
+ # <tt>#to_s</tt>. For example: <tt>/DC=com/DC=example/CN=nobody</tt>
+ # - \OpenSSL format (<tt>X509_NAME_print()</tt>)
+ # used by <tt>#to_s(OpenSSL::X509::Name::COMPAT)</tt>. For example:
+ # <tt>DC=com, DC=example, CN=nobody</tt>
+ #
+ # Neither of them is standardized and has quirks and inconsistencies
+ # in handling of escaped characters or multi-valued RDNs.
+ #
+ # Use of this method is discouraged in new applications. See
+ # Name.parse_rfc2253 and #to_utf8 for the alternative.
def parse_openssl(str, template=OBJECT_TYPE_TEMPLATE)
if str.start_with?("/")
# /A=B/C=D format
diff --git a/ext/openssl/ossl_ocsp.c b/ext/openssl/ossl_ocsp.c
index d4ca958a586..1e87484afc8 100644
--- a/ext/openssl/ossl_ocsp.c
+++ b/ext/openssl/ossl_ocsp.c
@@ -803,7 +803,7 @@ add_status_convert_time(VALUE obj)
* revocation, and must be one of OpenSSL::OCSP::REVOKED_STATUS_* constants.
* _revocation_time_ is the time when the certificate is revoked.
*
- * _this_update_ and _next_update_ indicate the time at which ths status is
+ * _this_update_ and _next_update_ indicate the time at which the status is
* verified to be correct and the time at or before which newer information
* will be available, respectively. _next_update_ is optional.
*
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index 28286574574..3b425ca7596 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -1704,8 +1704,7 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts)
* call-seq:
* ssl.connect => self
*
- * Initiates an SSL/TLS handshake with a server. The handshake may be started
- * after unencrypted data has been sent over the socket.
+ * Initiates an SSL/TLS handshake with a server.
*/
static VALUE
ossl_ssl_connect(VALUE self)
@@ -1752,8 +1751,7 @@ ossl_ssl_connect_nonblock(int argc, VALUE *argv, VALUE self)
* call-seq:
* ssl.accept => self
*
- * Waits for a SSL/TLS client to initiate a handshake. The handshake may be
- * started after unencrypted data has been sent over the socket.
+ * Waits for a SSL/TLS client to initiate a handshake.
*/
static VALUE
ossl_ssl_accept(VALUE self)
@@ -1800,7 +1798,7 @@ static VALUE
ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
{
SSL *ssl;
- int ilen, nread = 0;
+ int ilen;
VALUE len, str;
rb_io_t *fptr;
VALUE io, opts = Qnil;
@@ -1810,6 +1808,9 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
} else {
rb_scan_args(argc, argv, "11", &len, &str);
}
+ GetSSL(self, ssl);
+ if (!ssl_started(ssl))
+ rb_raise(eSSLError, "SSL session is not started yet");
ilen = NUM2INT(len);
if (NIL_P(str))
@@ -1825,85 +1826,60 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
if (ilen == 0)
return str;
- GetSSL(self, ssl);
io = rb_attr_get(self, id_i_io);
GetOpenFile(io, fptr);
- if (ssl_started(ssl)) {
- rb_str_locktmp(str);
- for (;;) {
- nread = SSL_read(ssl, RSTRING_PTR(str), ilen);
- switch(ssl_get_error(ssl, nread)){
- case SSL_ERROR_NONE:
+
+ rb_str_locktmp(str);
+ for (;;) {
+ int nread = SSL_read(ssl, RSTRING_PTR(str), ilen);
+ switch (ssl_get_error(ssl, nread)) {
+ case SSL_ERROR_NONE:
+ rb_str_unlocktmp(str);
+ rb_str_set_len(str, nread);
+ return str;
+ case SSL_ERROR_ZERO_RETURN:
+ rb_str_unlocktmp(str);
+ if (no_exception_p(opts)) { return Qnil; }
+ rb_eof_error();
+ case SSL_ERROR_WANT_WRITE:
+ if (nonblock) {
rb_str_unlocktmp(str);
- goto end;
- case SSL_ERROR_ZERO_RETURN:
+ if (no_exception_p(opts)) { return sym_wait_writable; }
+ write_would_block(nonblock);
+ }
+ io_wait_writable(fptr);
+ continue;
+ case SSL_ERROR_WANT_READ:
+ if (nonblock) {
rb_str_unlocktmp(str);
- if (no_exception_p(opts)) { return Qnil; }
- rb_eof_error();
- case SSL_ERROR_WANT_WRITE:
- if (nonblock) {
- rb_str_unlocktmp(str);
- if (no_exception_p(opts)) { return sym_wait_writable; }
- write_would_block(nonblock);
- }
- io_wait_writable(fptr);
- continue;
- case SSL_ERROR_WANT_READ:
- if (nonblock) {
- rb_str_unlocktmp(str);
- if (no_exception_p(opts)) { return sym_wait_readable; }
- read_would_block(nonblock);
- }
- io_wait_readable(fptr);
- continue;
- case SSL_ERROR_SYSCALL:
- if (!ERR_peek_error()) {
- rb_str_unlocktmp(str);
- if (errno)
- rb_sys_fail(0);
- else {
- /*
- * The underlying BIO returned 0. This is actually a
- * protocol error. But unfortunately, not all
- * implementations cleanly shutdown the TLS connection
- * but just shutdown/close the TCP connection. So report
- * EOF for now...
- */
- if (no_exception_p(opts)) { return Qnil; }
- rb_eof_error();
- }
- }
- /* fall through */
- default:
+ if (no_exception_p(opts)) { return sym_wait_readable; }
+ read_would_block(nonblock);
+ }
+ io_wait_readable(fptr);
+ continue;
+ case SSL_ERROR_SYSCALL:
+ if (!ERR_peek_error()) {
rb_str_unlocktmp(str);
- ossl_raise(eSSLError, "SSL_read");
- }
- }
- }
- else {
- ID meth = nonblock ? rb_intern("read_nonblock") : rb_intern("sysread");
-
- rb_warning("SSL session is not started yet.");
-#if defined(RB_PASS_KEYWORDS)
- if (nonblock) {
- VALUE argv[3];
- argv[0] = len;
- argv[1] = str;
- argv[2] = opts;
- return rb_funcallv_kw(io, meth, 3, argv, RB_PASS_KEYWORDS);
- }
-#else
- if (nonblock) {
- return rb_funcall(io, meth, 3, len, str, opts);
+ if (errno)
+ rb_sys_fail(0);
+ else {
+ /*
+ * The underlying BIO returned 0. This is actually a
+ * protocol error. But unfortunately, not all
+ * implementations cleanly shutdown the TLS connection
+ * but just shutdown/close the TCP connection. So report
+ * EOF for now...
+ */
+ if (no_exception_p(opts)) { return Qnil; }
+ rb_eof_error();
+ }
+ }
+ /* fall through */
+ default:
+ rb_str_unlocktmp(str);
+ ossl_raise(eSSLError, "SSL_read");
}
-#endif
- else
- return rb_funcall(io, meth, 2, len, str);
}
-
- end:
- rb_str_set_len(str, nread);
- return str;
}
/*
@@ -1943,78 +1919,55 @@ static VALUE
ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
{
SSL *ssl;
- int nwrite = 0;
rb_io_t *fptr;
- int nonblock = opts != Qfalse;
+ int num, nonblock = opts != Qfalse;
VALUE tmp, io;
- tmp = rb_str_new_frozen(StringValue(str));
GetSSL(self, ssl);
+ if (!ssl_started(ssl))
+ rb_raise(eSSLError, "SSL session is not started yet");
+
+ tmp = rb_str_new_frozen(StringValue(str));
io = rb_attr_get(self, id_i_io);
GetOpenFile(io, fptr);
- if (ssl_started(ssl)) {
- for (;;) {
- int num = RSTRING_LENINT(tmp);
-
- /* SSL_write(3ssl) manpage states num == 0 is undefined */
- if (num == 0)
- goto end;
-
- nwrite = SSL_write(ssl, RSTRING_PTR(tmp), num);
- switch(ssl_get_error(ssl, nwrite)){
- case SSL_ERROR_NONE:
- goto end;
- case SSL_ERROR_WANT_WRITE:
- if (no_exception_p(opts)) { return sym_wait_writable; }
- write_would_block(nonblock);
- io_wait_writable(fptr);
- continue;
- case SSL_ERROR_WANT_READ:
- if (no_exception_p(opts)) { return sym_wait_readable; }
- read_would_block(nonblock);
- io_wait_readable(fptr);
- continue;
- case SSL_ERROR_SYSCALL:
+
+ /* SSL_write(3ssl) manpage states num == 0 is undefined */
+ num = RSTRING_LENINT(tmp);
+ if (num == 0)
+ return INT2FIX(0);
+
+ for (;;) {
+ int nwritten = SSL_write(ssl, RSTRING_PTR(tmp), num);
+ switch (ssl_get_error(ssl, nwritten)) {
+ case SSL_ERROR_NONE:
+ return INT2NUM(nwritten);
+ case SSL_ERROR_WANT_WRITE:
+ if (no_exception_p(opts)) { return sym_wait_writable; }
+ write_would_block(nonblock);
+ io_wait_writable(fptr);
+ continue;
+ case SSL_ERROR_WANT_READ:
+ if (no_exception_p(opts)) { return sym_wait_readable; }
+ read_would_block(nonblock);
+ io_wait_readable(fptr);
+ continue;
+ case SSL_ERROR_SYSCALL:
#ifdef __APPLE__
- /*
- * It appears that send syscall can return EPROTOTYPE if the
- * socket is being torn down. Retry to get a proper errno to
- * make the error handling in line with the socket library.
- * [Bug #14713] https://bugs.ruby-lang.org/issues/14713
- */
- if (errno == EPROTOTYPE)
- continue;
+ /*
+ * It appears that send syscall can return EPROTOTYPE if the
+ * socket is being torn down. Retry to get a proper errno to
+ * make the error handling in line with the socket library.
+ * [Bug #14713] https://bugs.ruby-lang.org/issues/14713
+ */
+ if (errno == EPROTOTYPE)
+ continue;
#endif
- if (errno) rb_sys_fail(0);
- /* fallthrough */
- default:
- ossl_raise(eSSLError, "SSL_write");
- }
+ if (errno) rb_sys_fail(0);
+ /* fallthrough */
+ default:
+ ossl_raise(eSSLError, "SSL_write");
}
}
- else {
- ID meth = nonblock ?
- rb_intern("write_nonblock") : rb_intern("syswrite");
-
- rb_warning("SSL session is not started yet.");
-#if defined(RB_PASS_KEYWORDS)
- if (nonblock) {
- VALUE argv[2];
- argv[0] = str;
- argv[1] = opts;
- return rb_funcallv_kw(io, meth, 2, argv, RB_PASS_KEYWORDS);
- }
-#else
- if (nonblock) {
- return rb_funcall(io, meth, 2, str, opts);
- }
-#endif
- else
- return rb_funcall(io, meth, 1, str);
- }
-
- end:
- return INT2NUM(nwrite);
}
/*
diff --git a/ext/openssl/ossl_x509name.c b/ext/openssl/ossl_x509name.c
index 1522c3d897c..13a2b2c030f 100644
--- a/ext/openssl/ossl_x509name.c
+++ b/ext/openssl/ossl_x509name.c
@@ -291,7 +291,14 @@ x509name_print(VALUE self, unsigned long iflag)
* * OpenSSL::X509::Name::MULTILINE
*
* If _format_ is omitted, the largely broken and traditional OpenSSL format
- * is used.
+ * (<tt>X509_NAME_oneline()</tt> format) is chosen.
+ *
+ * <b>Use of this method is discouraged.</b> None of the formats other than
+ * OpenSSL::X509::Name::RFC2253 is standardized and may show an inconsistent
+ * behavior through \OpenSSL versions.
+ *
+ * It is recommended to use #to_utf8 instead, which is equivalent to calling
+ * <tt>name.to_s(OpenSSL::X509::Name::RFC2253).force_encoding("UTF-8")</tt>.
*/
static VALUE
ossl_x509name_to_s(int argc, VALUE *argv, VALUE self)
@@ -498,7 +505,7 @@ ossl_x509name_to_der(VALUE self)
* You can create a Name by parsing a distinguished name String or by
* supplying the distinguished name as an Array.
*
- * name = OpenSSL::X509::Name.parse '/CN=nobody/DC=example'
+ * name = OpenSSL::X509::Name.parse_rfc2253 'DC=example,CN=nobody'
*
* name = OpenSSL::X509::Name.new [['CN', 'nobody'], ['DC', 'example']]
*/