openssl 2.1.0.beta2 → 2.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -653,15 +653,15 @@ static VALUE ossl_ec_key_dsa_verify_asn1(VALUE self, VALUE data, VALUE sig)
653
653
  StringValue(data);
654
654
  StringValue(sig);
655
655
 
656
- switch (ECDSA_verify(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(sig), (int)RSTRING_LEN(sig), ec)) {
657
- case 1: return Qtrue;
658
- case 0: return Qfalse;
659
- default: break;
656
+ switch (ECDSA_verify(0, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data),
657
+ (unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), ec)) {
658
+ case 1:
659
+ return Qtrue;
660
+ case 0:
661
+ return Qfalse;
662
+ default:
663
+ ossl_raise(eECError, "ECDSA_verify");
660
664
  }
661
-
662
- ossl_raise(eECError, "ECDSA_verify");
663
-
664
- UNREACHABLE;
665
665
  }
666
666
 
667
667
  /*
@@ -1319,76 +1319,61 @@ ec_point_new(const EC_POINT *point, const EC_GROUP *group)
1319
1319
  return obj;
1320
1320
  }
1321
1321
 
1322
+ static VALUE ossl_ec_point_initialize_copy(VALUE, VALUE);
1322
1323
  /*
1323
1324
  * call-seq:
1324
1325
  * OpenSSL::PKey::EC::Point.new(point)
1325
- * OpenSSL::PKey::EC::Point.new(group)
1326
- * OpenSSL::PKey::EC::Point.new(group, bn)
1326
+ * OpenSSL::PKey::EC::Point.new(group [, encoded_point])
1327
+ *
1328
+ * Creates a new instance of OpenSSL::PKey::EC::Point. If the only argument is
1329
+ * an instance of EC::Point, a copy is returned. Otherwise, creates a point
1330
+ * that belongs to _group_.
1327
1331
  *
1328
- * See the OpenSSL documentation for EC_POINT_*
1332
+ * _encoded_point_ is the octet string representation of the point. This
1333
+ * must be either a String or an OpenSSL::BN.
1329
1334
  */
1330
1335
  static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self)
1331
1336
  {
1332
1337
  EC_POINT *point;
1333
- VALUE arg1, arg2;
1334
- VALUE group_v = Qnil;
1335
- const EC_GROUP *group = NULL;
1338
+ VALUE group_v, arg2;
1339
+ const EC_GROUP *group;
1336
1340
 
1337
1341
  TypedData_Get_Struct(self, EC_POINT, &ossl_ec_point_type, point);
1338
1342
  if (point)
1339
- ossl_raise(eEC_POINT, "EC_POINT already initialized");
1340
-
1341
- switch (rb_scan_args(argc, argv, "11", &arg1, &arg2)) {
1342
- case 1:
1343
- if (rb_obj_is_kind_of(arg1, cEC_POINT)) {
1344
- const EC_POINT *arg_point;
1345
-
1346
- group_v = rb_attr_get(arg1, id_i_group);
1347
- GetECGroup(group_v, group);
1348
- GetECPoint(arg1, arg_point);
1349
-
1350
- point = EC_POINT_dup(arg_point, group);
1351
- } else if (rb_obj_is_kind_of(arg1, cEC_GROUP)) {
1352
- group_v = arg1;
1353
- GetECGroup(group_v, group);
1354
-
1355
- point = EC_POINT_new(group);
1356
- } else {
1357
- ossl_raise(eEC_POINT, "wrong argument type: must be OpenSSL::PKey::EC::Point or OpenSSL::Pkey::EC::Group");
1358
- }
1359
-
1360
- break;
1361
- case 2:
1362
- if (!rb_obj_is_kind_of(arg1, cEC_GROUP))
1363
- ossl_raise(rb_eArgError, "1st argument must be OpenSSL::PKey::EC::Group");
1364
- group_v = arg1;
1365
- GetECGroup(group_v, group);
1366
-
1367
- if (rb_obj_is_kind_of(arg2, cBN)) {
1368
- const BIGNUM *bn = GetBNPtr(arg2);
1369
-
1370
- point = EC_POINT_bn2point(group, bn, NULL, ossl_bn_ctx);
1371
- } else {
1372
- BIO *in = ossl_obj2bio(&arg1);
1373
-
1374
- /* BUG: finish me */
1375
-
1376
- BIO_free(in);
1343
+ rb_raise(eEC_POINT, "EC_POINT already initialized");
1377
1344
 
1378
- if (point == NULL) {
1379
- ossl_raise(eEC_POINT, "unknown type for 2nd arg");
1380
- }
1381
- }
1382
- break;
1383
- default:
1384
- ossl_raise(rb_eArgError, "wrong number of arguments");
1345
+ rb_scan_args(argc, argv, "11", &group_v, &arg2);
1346
+ if (rb_obj_is_kind_of(group_v, cEC_POINT)) {
1347
+ if (argc != 1)
1348
+ rb_raise(rb_eArgError, "invalid second argument");
1349
+ return ossl_ec_point_initialize_copy(self, group_v);
1385
1350
  }
1386
1351
 
1387
- if (point == NULL)
1388
- ossl_raise(eEC_POINT, NULL);
1389
-
1390
- if (NIL_P(group_v))
1391
- ossl_raise(rb_eRuntimeError, "missing group (internal error)");
1352
+ GetECGroup(group_v, group);
1353
+ if (argc == 1) {
1354
+ point = EC_POINT_new(group);
1355
+ if (!point)
1356
+ ossl_raise(eEC_POINT, "EC_POINT_new");
1357
+ }
1358
+ else {
1359
+ if (rb_obj_is_kind_of(arg2, cBN)) {
1360
+ point = EC_POINT_bn2point(group, GetBNPtr(arg2), NULL, ossl_bn_ctx);
1361
+ if (!point)
1362
+ ossl_raise(eEC_POINT, "EC_POINT_bn2point");
1363
+ }
1364
+ else {
1365
+ StringValue(arg2);
1366
+ point = EC_POINT_new(group);
1367
+ if (!point)
1368
+ ossl_raise(eEC_POINT, "EC_POINT_new");
1369
+ if (!EC_POINT_oct2point(group, point,
1370
+ (unsigned char *)RSTRING_PTR(arg2),
1371
+ RSTRING_LEN(arg2), ossl_bn_ctx)) {
1372
+ EC_POINT_free(point);
1373
+ ossl_raise(eEC_POINT, "EC_POINT_oct2point");
1374
+ }
1375
+ }
1376
+ }
1392
1377
 
1393
1378
  RTYPEDDATA_DATA(self) = point;
1394
1379
  rb_ivar_set(self, id_i_group, group_v);
@@ -1543,38 +1528,38 @@ static VALUE ossl_ec_point_set_to_infinity(VALUE self)
1543
1528
 
1544
1529
  /*
1545
1530
  * call-seq:
1546
- * point.to_bn(conversion_form = nil) => OpenSSL::BN
1531
+ * point.to_octet_string(conversion_form) -> String
1532
+ *
1533
+ * Returns the octet string representation of the elliptic curve point.
1547
1534
  *
1548
- * Convert the EC point into an octet string and store in an OpenSSL::BN. If
1549
- * _conversion_form_ is given, the point data is converted using the specified
1550
- * form. If not given, the default form set in the EC::Group object is used.
1535
+ * _conversion_form_ specifies how the point is converted. Possible values are:
1551
1536
  *
1552
- * See also EC::Point#point_conversion_form=.
1537
+ * - +:compressed+
1538
+ * - +:uncompressed+
1539
+ * - +:hybrid+
1553
1540
  */
1554
1541
  static VALUE
1555
- ossl_ec_point_to_bn(int argc, VALUE *argv, VALUE self)
1542
+ ossl_ec_point_to_octet_string(VALUE self, VALUE conversion_form)
1556
1543
  {
1557
1544
  EC_POINT *point;
1558
- VALUE form_obj, bn_obj;
1559
1545
  const EC_GROUP *group;
1560
1546
  point_conversion_form_t form;
1561
- BIGNUM *bn;
1547
+ VALUE str;
1548
+ size_t len;
1562
1549
 
1563
1550
  GetECPoint(self, point);
1564
1551
  GetECPointGroup(self, group);
1565
- rb_scan_args(argc, argv, "01", &form_obj);
1566
- if (NIL_P(form_obj))
1567
- form = EC_GROUP_get_point_conversion_form(group);
1568
- else
1569
- form = parse_point_conversion_form_symbol(form_obj);
1570
-
1571
- bn_obj = rb_obj_alloc(cBN);
1572
- bn = GetBNPtr(bn_obj);
1573
-
1574
- if (EC_POINT_point2bn(group, point, form, bn, ossl_bn_ctx) == NULL)
1575
- ossl_raise(eEC_POINT, "EC_POINT_point2bn");
1576
-
1577
- return bn_obj;
1552
+ form = parse_point_conversion_form_symbol(conversion_form);
1553
+
1554
+ len = EC_POINT_point2oct(group, point, form, NULL, 0, ossl_bn_ctx);
1555
+ if (!len)
1556
+ ossl_raise(eEC_POINT, "EC_POINT_point2oct");
1557
+ str = rb_str_new(NULL, (long)len);
1558
+ if (!EC_POINT_point2oct(group, point, form,
1559
+ (unsigned char *)RSTRING_PTR(str), len,
1560
+ ossl_bn_ctx))
1561
+ ossl_raise(eEC_POINT, "EC_POINT_point2oct");
1562
+ return str;
1578
1563
  }
1579
1564
 
1580
1565
  /*
@@ -1664,6 +1649,7 @@ static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self)
1664
1649
 
1665
1650
  void Init_ossl_ec(void)
1666
1651
  {
1652
+ #undef rb_intern
1667
1653
  #if 0
1668
1654
  mPKey = rb_define_module_under(mOSSL, "PKey");
1669
1655
  cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
@@ -1799,7 +1785,7 @@ void Init_ossl_ec(void)
1799
1785
  rb_define_method(cEC_POINT, "set_to_infinity!", ossl_ec_point_set_to_infinity, 0);
1800
1786
  /* all the other methods */
1801
1787
 
1802
- rb_define_method(cEC_POINT, "to_bn", ossl_ec_point_to_bn, -1);
1788
+ rb_define_method(cEC_POINT, "to_octet_string", ossl_ec_point_to_octet_string, 1);
1803
1789
  rb_define_method(cEC_POINT, "mul", ossl_ec_point_mul, -1);
1804
1790
 
1805
1791
  id_i_group = rb_intern("@group");
@@ -67,8 +67,6 @@ ossl_rand_add(VALUE self, VALUE str, VALUE entropy)
67
67
  static VALUE
68
68
  ossl_rand_load_file(VALUE self, VALUE filename)
69
69
  {
70
- rb_check_safe_obj(filename);
71
-
72
70
  if(!RAND_load_file(StringValueCStr(filename), -1)) {
73
71
  ossl_raise(eRandomError, NULL);
74
72
  }
@@ -86,8 +84,6 @@ ossl_rand_load_file(VALUE self, VALUE filename)
86
84
  static VALUE
87
85
  ossl_rand_write_file(VALUE self, VALUE filename)
88
86
  {
89
- rb_check_safe_obj(filename);
90
-
91
87
  if (RAND_write_file(StringValueCStr(filename)) == -1) {
92
88
  ossl_raise(eRandomError, NULL);
93
89
  }
@@ -164,8 +160,6 @@ ossl_rand_pseudo_bytes(VALUE self, VALUE len)
164
160
  static VALUE
165
161
  ossl_rand_egd(VALUE self, VALUE filename)
166
162
  {
167
- rb_check_safe_obj(filename);
168
-
169
163
  if (RAND_egd(StringValueCStr(filename)) == -1) {
170
164
  ossl_raise(eRandomError, NULL);
171
165
  }
@@ -186,8 +180,6 @@ ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len)
186
180
  {
187
181
  int n = NUM2INT(len);
188
182
 
189
- rb_check_safe_obj(filename);
190
-
191
183
  if (RAND_egd_bytes(StringValueCStr(filename), n) == -1) {
192
184
  ossl_raise(eRandomError, NULL);
193
185
  }
@@ -13,6 +13,12 @@
13
13
 
14
14
  #define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0]))
15
15
 
16
+ #if !defined(TLS1_3_VERSION) && \
17
+ defined(LIBRESSL_VERSION_NUMBER) && \
18
+ LIBRESSL_VERSION_NUMBER >= 0x3020000fL
19
+ # define TLS1_3_VERSION 0x0304
20
+ #endif
21
+
16
22
  #ifdef _WIN32
17
23
  # define TO_SOCKET(s) _get_osfhandle(s)
18
24
  #else
@@ -33,7 +39,7 @@ static VALUE eSSLErrorWaitReadable;
33
39
  static VALUE eSSLErrorWaitWritable;
34
40
 
35
41
  static ID id_call, ID_callback_state, id_tmp_dh_callback, id_tmp_ecdh_callback,
36
- id_npn_protocols_encoded;
42
+ id_npn_protocols_encoded, id_each;
37
43
  static VALUE sym_exception, sym_wait_readable, sym_wait_writable;
38
44
 
39
45
  static ID id_i_cert_store, id_i_ca_file, id_i_ca_path, id_i_verify_mode,
@@ -53,6 +59,13 @@ static int ossl_sslctx_ex_ptr_idx;
53
59
  static int ossl_sslctx_ex_store_p;
54
60
  #endif
55
61
 
62
+ static void
63
+ ossl_sslctx_mark(void *ptr)
64
+ {
65
+ SSL_CTX *ctx = ptr;
66
+ rb_gc_mark((VALUE)SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_ptr_idx));
67
+ }
68
+
56
69
  static void
57
70
  ossl_sslctx_free(void *ptr)
58
71
  {
@@ -67,7 +80,7 @@ ossl_sslctx_free(void *ptr)
67
80
  static const rb_data_type_t ossl_sslctx_type = {
68
81
  "OpenSSL/SSL/CTX",
69
82
  {
70
- 0, ossl_sslctx_free,
83
+ ossl_sslctx_mark, ossl_sslctx_free,
71
84
  },
72
85
  0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
73
86
  };
@@ -184,8 +197,10 @@ ossl_sslctx_set_minmax_proto_version(VALUE self, VALUE min_v, VALUE max_v)
184
197
 
185
198
  for (i = 0; i < numberof(options_map); i++) {
186
199
  sum |= options_map[i].opts;
187
- if (min && min > options_map[i].ver || max && max < options_map[i].ver)
200
+ if ((min && min > options_map[i].ver) ||
201
+ (max && max < options_map[i].ver)) {
188
202
  opts |= options_map[i].opts;
203
+ }
189
204
  }
190
205
  SSL_CTX_clear_options(ctx, sum);
191
206
  SSL_CTX_set_options(ctx, opts);
@@ -357,7 +372,14 @@ ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
357
372
  rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(status));
358
373
  return 0;
359
374
  }
360
- preverify_ok = ret == Qtrue;
375
+ if (ret != Qtrue) {
376
+ preverify_ok = 0;
377
+ #if defined(X509_V_ERR_HOSTNAME_MISMATCH)
378
+ X509_STORE_CTX_set_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH);
379
+ #else
380
+ X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
381
+ #endif
382
+ }
361
383
  }
362
384
 
363
385
  return ossl_verify_cb_call(cb, preverify_ok, ctx);
@@ -377,9 +399,8 @@ ossl_call_session_get_cb(VALUE ary)
377
399
  return rb_funcallv(cb, id_call, 1, &ary);
378
400
  }
379
401
 
380
- /* this method is currently only called for servers (in OpenSSL <= 0.9.8e) */
381
402
  static SSL_SESSION *
382
- #if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER)
403
+ #if (!defined(LIBRESSL_VERSION_NUMBER) ? OPENSSL_VERSION_NUMBER >= 0x10100000 : LIBRESSL_VERSION_NUMBER >= 0x2080000f)
383
404
  ossl_sslctx_session_get_cb(SSL *ssl, const unsigned char *buf, int len, int *copy)
384
405
  #else
385
406
  ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy)
@@ -591,7 +612,7 @@ ssl_renegotiation_cb(const SSL *ssl)
591
612
  #if !defined(OPENSSL_NO_NEXTPROTONEG) || \
592
613
  defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB)
593
614
  static VALUE
594
- ssl_npn_encode_protocol_i(VALUE cur, VALUE encoded)
615
+ ssl_npn_encode_protocol_i(RB_BLOCK_CALL_FUNC_ARGLIST(cur, encoded))
595
616
  {
596
617
  int len = RSTRING_LENINT(cur);
597
618
  char len_byte;
@@ -608,7 +629,7 @@ static VALUE
608
629
  ssl_encode_npn_protocols(VALUE protocols)
609
630
  {
610
631
  VALUE encoded = rb_str_new(NULL, 0);
611
- rb_iterate(rb_each, protocols, ssl_npn_encode_protocol_i, encoded);
632
+ rb_block_call(protocols, id_each, 0, 0, ssl_npn_encode_protocol_i, encoded);
612
633
  return encoded;
613
634
  }
614
635
 
@@ -678,7 +699,7 @@ static int
678
699
  ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen,
679
700
  void *arg)
680
701
  {
681
- VALUE protocols = (VALUE)arg;
702
+ VALUE protocols = rb_attr_get((VALUE)arg, id_npn_protocols_encoded);
682
703
 
683
704
  *out = (const unsigned char *) RSTRING_PTR(protocols);
684
705
  *outlen = RSTRING_LENINT(protocols);
@@ -896,7 +917,7 @@ ossl_sslctx_setup(VALUE self)
896
917
  if (!NIL_P(val)) {
897
918
  VALUE encoded = ssl_encode_npn_protocols(val);
898
919
  rb_ivar_set(self, id_npn_protocols_encoded, encoded);
899
- SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)encoded);
920
+ SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)self);
900
921
  OSSL_Debug("SSL NPN advertise callback added");
901
922
  }
902
923
  if (RTEST(rb_attr_get(self, id_i_npn_select_cb))) {
@@ -1035,10 +1056,6 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
1035
1056
  }
1036
1057
 
1037
1058
  GetSSLCTX(self, ctx);
1038
- if(!ctx){
1039
- ossl_raise(eSSLError, "SSL_CTX is not initialized.");
1040
- return Qnil;
1041
- }
1042
1059
  if (!SSL_CTX_set_cipher_list(ctx, StringValueCStr(str))) {
1043
1060
  ossl_raise(eSSLError, "SSL_CTX_set_cipher_list");
1044
1061
  }
@@ -1518,6 +1535,14 @@ ssl_started(SSL *ssl)
1518
1535
  return SSL_get_fd(ssl) >= 0;
1519
1536
  }
1520
1537
 
1538
+ static void
1539
+ ossl_ssl_mark(void *ptr)
1540
+ {
1541
+ SSL *ssl = ptr;
1542
+ rb_gc_mark((VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx));
1543
+ rb_gc_mark((VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_vcb_idx));
1544
+ }
1545
+
1521
1546
  static void
1522
1547
  ossl_ssl_free(void *ssl)
1523
1548
  {
@@ -1527,7 +1552,7 @@ ossl_ssl_free(void *ssl)
1527
1552
  const rb_data_type_t ossl_ssl_type = {
1528
1553
  "OpenSSL/SSL",
1529
1554
  {
1530
- 0, ossl_ssl_free,
1555
+ ossl_ssl_mark, ossl_ssl_free,
1531
1556
  },
1532
1557
  0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
1533
1558
  };
@@ -1683,6 +1708,11 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts)
1683
1708
  rb_io_wait_readable(fptr->fd);
1684
1709
  continue;
1685
1710
  case SSL_ERROR_SYSCALL:
1711
+ #ifdef __APPLE__
1712
+ /* See ossl_ssl_write_internal() */
1713
+ if (errno == EPROTOTYPE)
1714
+ continue;
1715
+ #endif
1686
1716
  if (errno) rb_sys_fail(funcname);
1687
1717
  ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
1688
1718
  #if defined(SSL_R_CERTIFICATE_VERIFY_FAILED)
@@ -1831,7 +1861,6 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
1831
1861
  else
1832
1862
  rb_str_modify_expand(str, ilen - RSTRING_LEN(str));
1833
1863
  }
1834
- OBJ_TAINT(str);
1835
1864
  rb_str_set_len(str, 0);
1836
1865
  if (ilen == 0)
1837
1866
  return str;
@@ -1840,26 +1869,36 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
1840
1869
  io = rb_attr_get(self, id_i_io);
1841
1870
  GetOpenFile(io, fptr);
1842
1871
  if (ssl_started(ssl)) {
1843
- for (;;){
1872
+ rb_str_locktmp(str);
1873
+ for (;;) {
1844
1874
  nread = SSL_read(ssl, RSTRING_PTR(str), ilen);
1845
1875
  switch(ssl_get_error(ssl, nread)){
1846
1876
  case SSL_ERROR_NONE:
1877
+ rb_str_unlocktmp(str);
1847
1878
  goto end;
1848
1879
  case SSL_ERROR_ZERO_RETURN:
1880
+ rb_str_unlocktmp(str);
1849
1881
  if (no_exception_p(opts)) { return Qnil; }
1850
1882
  rb_eof_error();
1851
1883
  case SSL_ERROR_WANT_WRITE:
1852
- if (no_exception_p(opts)) { return sym_wait_writable; }
1853
- write_would_block(nonblock);
1884
+ if (nonblock) {
1885
+ rb_str_unlocktmp(str);
1886
+ if (no_exception_p(opts)) { return sym_wait_writable; }
1887
+ write_would_block(nonblock);
1888
+ }
1854
1889
  rb_io_wait_writable(fptr->fd);
1855
1890
  continue;
1856
1891
  case SSL_ERROR_WANT_READ:
1857
- if (no_exception_p(opts)) { return sym_wait_readable; }
1858
- read_would_block(nonblock);
1892
+ if (nonblock) {
1893
+ rb_str_unlocktmp(str);
1894
+ if (no_exception_p(opts)) { return sym_wait_readable; }
1895
+ read_would_block(nonblock);
1896
+ }
1859
1897
  rb_io_wait_readable(fptr->fd);
1860
1898
  continue;
1861
1899
  case SSL_ERROR_SYSCALL:
1862
1900
  if (!ERR_peek_error()) {
1901
+ rb_str_unlocktmp(str);
1863
1902
  if (errno)
1864
1903
  rb_sys_fail(0);
1865
1904
  else {
@@ -1874,19 +1913,32 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
1874
1913
  rb_eof_error();
1875
1914
  }
1876
1915
  }
1916
+ /* fall through */
1877
1917
  default:
1918
+ rb_str_unlocktmp(str);
1878
1919
  ossl_raise(eSSLError, "SSL_read");
1879
1920
  }
1880
1921
  }
1881
1922
  }
1882
1923
  else {
1883
- ID meth = nonblock ? rb_intern("read_nonblock") : rb_intern("sysread");
1884
-
1885
- rb_warning("SSL session is not started yet.");
1886
- if (nonblock)
1887
- return rb_funcall(io, meth, 3, len, str, opts);
1888
- else
1889
- return rb_funcall(io, meth, 2, len, str);
1924
+ ID meth = nonblock ? rb_intern("read_nonblock") : rb_intern("sysread");
1925
+
1926
+ rb_warning("SSL session is not started yet.");
1927
+ #if defined(RB_PASS_KEYWORDS)
1928
+ if (nonblock) {
1929
+ VALUE argv[3];
1930
+ argv[0] = len;
1931
+ argv[1] = str;
1932
+ argv[2] = opts;
1933
+ return rb_funcallv_kw(io, meth, 3, argv, RB_PASS_KEYWORDS);
1934
+ }
1935
+ #else
1936
+ if (nonblock) {
1937
+ return rb_funcall(io, meth, 3, len, str, opts);
1938
+ }
1939
+ #endif
1940
+ else
1941
+ return rb_funcall(io, meth, 2, len, str);
1890
1942
  }
1891
1943
 
1892
1944
  end:
@@ -1934,21 +1986,21 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
1934
1986
  int nwrite = 0;
1935
1987
  rb_io_t *fptr;
1936
1988
  int nonblock = opts != Qfalse;
1937
- VALUE io;
1989
+ VALUE tmp, io;
1938
1990
 
1939
- StringValue(str);
1991
+ tmp = rb_str_new_frozen(StringValue(str));
1940
1992
  GetSSL(self, ssl);
1941
1993
  io = rb_attr_get(self, id_i_io);
1942
1994
  GetOpenFile(io, fptr);
1943
1995
  if (ssl_started(ssl)) {
1944
- for (;;){
1945
- int num = RSTRING_LENINT(str);
1996
+ for (;;) {
1997
+ int num = RSTRING_LENINT(tmp);
1946
1998
 
1947
1999
  /* SSL_write(3ssl) manpage states num == 0 is undefined */
1948
2000
  if (num == 0)
1949
2001
  goto end;
1950
2002
 
1951
- nwrite = SSL_write(ssl, RSTRING_PTR(str), num);
2003
+ nwrite = SSL_write(ssl, RSTRING_PTR(tmp), num);
1952
2004
  switch(ssl_get_error(ssl, nwrite)){
1953
2005
  case SSL_ERROR_NONE:
1954
2006
  goto end;
@@ -1963,6 +2015,16 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
1963
2015
  rb_io_wait_readable(fptr->fd);
1964
2016
  continue;
1965
2017
  case SSL_ERROR_SYSCALL:
2018
+ #ifdef __APPLE__
2019
+ /*
2020
+ * It appears that send syscall can return EPROTOTYPE if the
2021
+ * socket is being torn down. Retry to get a proper errno to
2022
+ * make the error handling in line with the socket library.
2023
+ * [Bug #14713] https://bugs.ruby-lang.org/issues/14713
2024
+ */
2025
+ if (errno == EPROTOTYPE)
2026
+ continue;
2027
+ #endif
1966
2028
  if (errno) rb_sys_fail(0);
1967
2029
  default:
1968
2030
  ossl_raise(eSSLError, "SSL_write");
@@ -1973,11 +2035,21 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
1973
2035
  ID meth = nonblock ?
1974
2036
  rb_intern("write_nonblock") : rb_intern("syswrite");
1975
2037
 
1976
- rb_warning("SSL session is not started yet.");
1977
- if (nonblock)
1978
- return rb_funcall(io, meth, 2, str, opts);
1979
- else
1980
- return rb_funcall(io, meth, 1, str);
2038
+ rb_warning("SSL session is not started yet.");
2039
+ #if defined(RB_PASS_KEYWORDS)
2040
+ if (nonblock) {
2041
+ VALUE argv[2];
2042
+ argv[0] = str;
2043
+ argv[1] = opts;
2044
+ return rb_funcallv_kw(io, meth, 2, argv, RB_PASS_KEYWORDS);
2045
+ }
2046
+ #else
2047
+ if (nonblock) {
2048
+ return rb_funcall(io, meth, 2, str, opts);
2049
+ }
2050
+ #endif
2051
+ else
2052
+ return rb_funcall(io, meth, 1, str);
1981
2053
  }
1982
2054
 
1983
2055
  end:
@@ -2920,6 +2992,7 @@ Init_ossl_ssl(void)
2920
2992
  id_tmp_dh_callback = rb_intern("tmp_dh_callback");
2921
2993
  id_tmp_ecdh_callback = rb_intern("tmp_ecdh_callback");
2922
2994
  id_npn_protocols_encoded = rb_intern("npn_protocols_encoded");
2995
+ id_each = rb_intern_const("each");
2923
2996
 
2924
2997
  #define DefIVarID(name) do \
2925
2998
  id_i_##name = rb_intern("@"#name); while (0)
@@ -10,6 +10,6 @@
10
10
  #if !defined(_OSSL_VERSION_H_)
11
11
  #define _OSSL_VERSION_H_
12
12
 
13
- #define OSSL_VERSION "2.1.0"
13
+ #define OSSL_VERSION "2.1.3"
14
14
 
15
15
  #endif /* _OSSL_VERSION_H_ */