openssl 2.2.0 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +33 -45
  3. data/History.md +260 -0
  4. data/ext/openssl/extconf.rb +85 -72
  5. data/ext/openssl/openssl_missing.c +0 -66
  6. data/ext/openssl/openssl_missing.h +26 -45
  7. data/ext/openssl/ossl.c +67 -47
  8. data/ext/openssl/ossl.h +26 -6
  9. data/ext/openssl/ossl_asn1.c +26 -13
  10. data/ext/openssl/ossl_bn.c +278 -142
  11. data/ext/openssl/ossl_bn.h +2 -1
  12. data/ext/openssl/ossl_cipher.c +12 -13
  13. data/ext/openssl/ossl_config.c +412 -41
  14. data/ext/openssl/ossl_config.h +4 -7
  15. data/ext/openssl/ossl_digest.c +15 -11
  16. data/ext/openssl/ossl_engine.c +16 -15
  17. data/ext/openssl/ossl_hmac.c +56 -135
  18. data/ext/openssl/ossl_kdf.c +11 -3
  19. data/ext/openssl/ossl_ocsp.c +5 -53
  20. data/ext/openssl/ossl_pkcs12.c +21 -3
  21. data/ext/openssl/ossl_pkcs7.c +42 -59
  22. data/ext/openssl/ossl_pkey.c +1142 -191
  23. data/ext/openssl/ossl_pkey.h +36 -73
  24. data/ext/openssl/ossl_pkey_dh.c +130 -340
  25. data/ext/openssl/ossl_pkey_dsa.c +100 -405
  26. data/ext/openssl/ossl_pkey_ec.c +163 -335
  27. data/ext/openssl/ossl_pkey_rsa.c +106 -493
  28. data/ext/openssl/ossl_ssl.c +529 -421
  29. data/ext/openssl/ossl_ssl_session.c +28 -29
  30. data/ext/openssl/ossl_ts.c +64 -39
  31. data/ext/openssl/ossl_x509.c +0 -6
  32. data/ext/openssl/ossl_x509cert.c +167 -11
  33. data/ext/openssl/ossl_x509crl.c +13 -10
  34. data/ext/openssl/ossl_x509ext.c +1 -2
  35. data/ext/openssl/ossl_x509name.c +9 -2
  36. data/ext/openssl/ossl_x509req.c +13 -10
  37. data/ext/openssl/ossl_x509revoked.c +3 -3
  38. data/ext/openssl/ossl_x509store.c +193 -90
  39. data/lib/openssl/buffering.rb +10 -1
  40. data/lib/openssl/hmac.rb +65 -0
  41. data/lib/openssl/pkey.rb +429 -0
  42. data/lib/openssl/ssl.rb +13 -8
  43. data/lib/openssl/version.rb +1 -1
  44. data/lib/openssl/x509.rb +22 -0
  45. data/lib/openssl.rb +0 -1
  46. metadata +8 -66
  47. data/ext/openssl/ruby_missing.h +0 -24
  48. data/lib/openssl/config.rb +0 -501
@@ -4,6 +4,7 @@
4
4
 
5
5
  #include "ossl.h"
6
6
 
7
+ #ifndef OPENSSL_NO_SOCK
7
8
  VALUE cSSLSession;
8
9
  static VALUE eSSLSession;
9
10
 
@@ -34,43 +35,38 @@ static VALUE ossl_ssl_session_alloc(VALUE klass)
34
35
  * Creates a new Session object from an instance of SSLSocket or DER/PEM encoded
35
36
  * String.
36
37
  */
37
- static VALUE ossl_ssl_session_initialize(VALUE self, VALUE arg1)
38
+ static VALUE
39
+ ossl_ssl_session_initialize(VALUE self, VALUE arg1)
38
40
  {
39
- SSL_SESSION *ctx = NULL;
40
-
41
- if (RDATA(self)->data)
42
- ossl_raise(eSSLSession, "SSL Session already initialized");
43
-
44
- if (rb_obj_is_instance_of(arg1, cSSLSocket)) {
45
- SSL *ssl;
46
-
47
- GetSSL(arg1, ssl);
48
-
49
- if ((ctx = SSL_get1_session(ssl)) == NULL)
50
- ossl_raise(eSSLSession, "no session available");
51
- } else {
52
- BIO *in = ossl_obj2bio(&arg1);
41
+ SSL_SESSION *ctx;
53
42
 
54
- ctx = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL);
43
+ if (RTYPEDDATA_DATA(self))
44
+ ossl_raise(eSSLSession, "SSL Session already initialized");
55
45
 
56
- if (!ctx) {
57
- OSSL_BIO_reset(in);
58
- ctx = d2i_SSL_SESSION_bio(in, NULL);
59
- }
46
+ if (rb_obj_is_instance_of(arg1, cSSLSocket)) {
47
+ SSL *ssl;
60
48
 
61
- BIO_free(in);
49
+ GetSSL(arg1, ssl);
62
50
 
63
- if (!ctx)
64
- ossl_raise(rb_eArgError, "unknown type");
65
- }
51
+ if ((ctx = SSL_get1_session(ssl)) == NULL)
52
+ ossl_raise(eSSLSession, "no session available");
53
+ }
54
+ else {
55
+ BIO *in = ossl_obj2bio(&arg1);
66
56
 
67
- /* should not happen */
68
- if (ctx == NULL)
69
- ossl_raise(eSSLSession, "ctx not set - internal error");
57
+ ctx = d2i_SSL_SESSION_bio(in, NULL);
58
+ if (!ctx) {
59
+ OSSL_BIO_reset(in);
60
+ ctx = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL);
61
+ }
62
+ BIO_free(in);
63
+ if (!ctx)
64
+ ossl_raise(rb_eArgError, "unknown type");
65
+ }
70
66
 
71
- RDATA(self)->data = ctx;
67
+ RTYPEDDATA_DATA(self) = ctx;
72
68
 
73
- return self;
69
+ return self;
74
70
  }
75
71
 
76
72
  static VALUE
@@ -304,6 +300,7 @@ static VALUE ossl_ssl_session_to_text(VALUE self)
304
300
  return ossl_membio2str(out);
305
301
  }
306
302
 
303
+ #endif /* !defined(OPENSSL_NO_SOCK) */
307
304
 
308
305
  void Init_ossl_ssl_session(void)
309
306
  {
@@ -312,6 +309,7 @@ void Init_ossl_ssl_session(void)
312
309
  mSSL = rb_define_module_under(mOSSL, "SSL");
313
310
  eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
314
311
  #endif
312
+ #ifndef OPENSSL_NO_SOCK
315
313
  cSSLSession = rb_define_class_under(mSSL, "Session", rb_cObject);
316
314
  eSSLSession = rb_define_class_under(cSSLSession, "SessionError", eOSSLError);
317
315
 
@@ -329,4 +327,5 @@ void Init_ossl_ssl_session(void)
329
327
  rb_define_method(cSSLSession, "to_der", ossl_ssl_session_to_der, 0);
330
328
  rb_define_method(cSSLSession, "to_pem", ossl_ssl_session_to_pem, 0);
331
329
  rb_define_method(cSSLSession, "to_text", ossl_ssl_session_to_text, 0);
330
+ #endif /* !defined(OPENSSL_NO_SOCK) */
332
331
  }
@@ -68,9 +68,9 @@ static VALUE cTimestampRequest;
68
68
  static VALUE cTimestampResponse;
69
69
  static VALUE cTimestampTokenInfo;
70
70
  static VALUE cTimestampFactory;
71
- static ID sBAD_ALG, sBAD_REQUEST, sBAD_DATA_FORMAT, sTIME_NOT_AVAILABLE;
72
- static ID sUNACCEPTED_POLICY, sUNACCEPTED_EXTENSION, sADD_INFO_NOT_AVAILABLE;
73
- static ID sSYSTEM_FAILURE;
71
+ static VALUE sBAD_ALG, sBAD_REQUEST, sBAD_DATA_FORMAT, sTIME_NOT_AVAILABLE;
72
+ static VALUE sUNACCEPTED_POLICY, sUNACCEPTED_EXTENSION, sADD_INFO_NOT_AVAILABLE;
73
+ static VALUE sSYSTEM_FAILURE;
74
74
 
75
75
  static void
76
76
  ossl_ts_req_free(void *ptr)
@@ -145,6 +145,12 @@ obj_to_asn1obj(VALUE obj)
145
145
  return a1obj;
146
146
  }
147
147
 
148
+ static VALUE
149
+ obj_to_asn1obj_i(VALUE obj)
150
+ {
151
+ return (VALUE)obj_to_asn1obj(obj);
152
+ }
153
+
148
154
  static VALUE
149
155
  get_asn1obj(ASN1_OBJECT *obj)
150
156
  {
@@ -205,8 +211,10 @@ ossl_ts_req_initialize(int argc, VALUE *argv, VALUE self)
205
211
  in = ossl_obj2bio(&arg);
206
212
  ts_req = d2i_TS_REQ_bio(in, &ts_req);
207
213
  BIO_free(in);
208
- if (!ts_req)
214
+ if (!ts_req) {
215
+ DATA_PTR(self) = NULL;
209
216
  ossl_raise(eTimestampError, "Error when decoding the timestamp request");
217
+ }
210
218
  DATA_PTR(self) = ts_req;
211
219
 
212
220
  return self;
@@ -529,8 +537,10 @@ ossl_ts_resp_initialize(VALUE self, VALUE der)
529
537
  in = ossl_obj2bio(&der);
530
538
  ts_resp = d2i_TS_RESP_bio(in, &ts_resp);
531
539
  BIO_free(in);
532
- if (!ts_resp)
540
+ if (!ts_resp) {
541
+ DATA_PTR(self) = NULL;
533
542
  ossl_raise(eTimestampError, "Error when decoding the timestamp response");
543
+ }
534
544
  DATA_PTR(self) = ts_resp;
535
545
 
536
546
  return self;
@@ -816,17 +826,14 @@ ossl_ts_resp_verify(int argc, VALUE *argv, VALUE self)
816
826
  X509_up_ref(cert);
817
827
  }
818
828
 
819
- TS_VERIFY_CTS_set_certs(ctx, x509inter);
829
+ TS_VERIFY_CTX_set_certs(ctx, x509inter);
820
830
  TS_VERIFY_CTX_add_flags(ctx, TS_VFY_SIGNATURE);
821
831
  TS_VERIFY_CTX_set_store(ctx, x509st);
822
832
 
823
833
  ok = TS_RESP_verify_response(ctx, resp);
824
-
825
- /* WORKAROUND:
826
- * X509_STORE can count references, but X509_STORE_free() doesn't check
827
- * this. To prevent our X509_STORE from being freed with our
828
- * TS_VERIFY_CTX we set the store to NULL first.
829
- * Fixed in OpenSSL 1.0.2; bff9ce4db38b (master), 5b4b9ce976fc (1.0.2)
834
+ /*
835
+ * TS_VERIFY_CTX_set_store() call above does not increment the reference
836
+ * counter, so it must be unset before TS_VERIFY_CTX_free() is called.
830
837
  */
831
838
  TS_VERIFY_CTX_set_store(ctx, NULL);
832
839
  TS_VERIFY_CTX_free(ctx);
@@ -871,8 +878,10 @@ ossl_ts_token_info_initialize(VALUE self, VALUE der)
871
878
  in = ossl_obj2bio(&der);
872
879
  info = d2i_TS_TST_INFO_bio(in, &info);
873
880
  BIO_free(in);
874
- if (!info)
881
+ if (!info) {
882
+ DATA_PTR(self) = NULL;
875
883
  ossl_raise(eTimestampError, "Error when decoding the timestamp token info");
884
+ }
876
885
  DATA_PTR(self) = info;
877
886
 
878
887
  return self;
@@ -1074,13 +1083,29 @@ ossl_tsfac_serial_cb(struct TS_resp_ctx *ctx, void *data)
1074
1083
  }
1075
1084
 
1076
1085
  static int
1086
+ #if !defined(LIBRESSL_VERSION_NUMBER)
1077
1087
  ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, long *sec, long *usec)
1088
+ #else
1089
+ ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, time_t *sec, long *usec)
1090
+ #endif
1078
1091
  {
1079
1092
  *sec = *((long *)data);
1080
1093
  *usec = 0;
1081
1094
  return 1;
1082
1095
  }
1083
1096
 
1097
+ static VALUE
1098
+ ossl_evp_get_digestbyname_i(VALUE arg)
1099
+ {
1100
+ return (VALUE)ossl_evp_get_digestbyname(arg);
1101
+ }
1102
+
1103
+ static VALUE
1104
+ ossl_obj2bio_i(VALUE arg)
1105
+ {
1106
+ return (VALUE)ossl_obj2bio((VALUE *)arg);
1107
+ }
1108
+
1084
1109
  /*
1085
1110
  * Creates a Response with the help of an OpenSSL::PKey, an
1086
1111
  * OpenSSL::X509::Certificate and a Request.
@@ -1149,7 +1174,7 @@ ossl_tsfac_create_ts(VALUE self, VALUE key, VALUE certificate, VALUE request)
1149
1174
  goto end;
1150
1175
  }
1151
1176
  if (!NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req)) {
1152
- def_policy_id_obj = (ASN1_OBJECT*)rb_protect((VALUE (*)(VALUE))obj_to_asn1obj, (VALUE)def_policy_id, &status);
1177
+ def_policy_id_obj = (ASN1_OBJECT*)rb_protect(obj_to_asn1obj_i, (VALUE)def_policy_id, &status);
1153
1178
  if (status)
1154
1179
  goto end;
1155
1180
  }
@@ -1191,7 +1216,7 @@ ossl_tsfac_create_ts(VALUE self, VALUE key, VALUE certificate, VALUE request)
1191
1216
 
1192
1217
  for (i = 0; i < RARRAY_LEN(allowed_digests); i++) {
1193
1218
  rbmd = rb_ary_entry(allowed_digests, i);
1194
- md = (const EVP_MD *)rb_protect((VALUE (*)(VALUE))ossl_evp_get_digestbyname, rbmd, &status);
1219
+ md = (const EVP_MD *)rb_protect(ossl_evp_get_digestbyname_i, rbmd, &status);
1195
1220
  if (status)
1196
1221
  goto end;
1197
1222
  TS_RESP_CTX_add_md(ctx, md);
@@ -1202,7 +1227,7 @@ ossl_tsfac_create_ts(VALUE self, VALUE key, VALUE certificate, VALUE request)
1202
1227
  if (status)
1203
1228
  goto end;
1204
1229
 
1205
- req_bio = (BIO*)rb_protect((VALUE (*)(VALUE))ossl_obj2bio, (VALUE)&str, &status);
1230
+ req_bio = (BIO*)rb_protect(ossl_obj2bio_i, (VALUE)&str, &status);
1206
1231
  if (status)
1207
1232
  goto end;
1208
1233
 
@@ -1226,7 +1251,7 @@ end:
1226
1251
  ASN1_OBJECT_free(def_policy_id_obj);
1227
1252
  TS_RESP_CTX_free(ctx);
1228
1253
  if (err_msg)
1229
- ossl_raise(eTimestampError, err_msg);
1254
+ rb_exc_raise(ossl_make_error(eTimestampError, rb_str_new_cstr(err_msg)));
1230
1255
  if (status)
1231
1256
  rb_jump_tag(status);
1232
1257
  return ret;
@@ -1247,24 +1272,24 @@ Init_ossl_ts(void)
1247
1272
  * timestamp server rejects the message imprint algorithm used in the
1248
1273
  * +Request+
1249
1274
  */
1250
- sBAD_ALG = rb_intern("BAD_ALG");
1275
+ sBAD_ALG = ID2SYM(rb_intern_const("BAD_ALG"));
1251
1276
 
1252
1277
  /*
1253
1278
  * Possible return value for +Response#failure_info+. Indicates that the
1254
1279
  * timestamp server was not able to process the +Request+ properly.
1255
1280
  */
1256
- sBAD_REQUEST = rb_intern("BAD_REQUEST");
1281
+ sBAD_REQUEST = ID2SYM(rb_intern_const("BAD_REQUEST"));
1257
1282
  /*
1258
1283
  * Possible return value for +Response#failure_info+. Indicates that the
1259
1284
  * timestamp server was not able to parse certain data in the +Request+.
1260
1285
  */
1261
- sBAD_DATA_FORMAT = rb_intern("BAD_DATA_FORMAT");
1286
+ sBAD_DATA_FORMAT = ID2SYM(rb_intern_const("BAD_DATA_FORMAT"));
1262
1287
 
1263
- sTIME_NOT_AVAILABLE = rb_intern("TIME_NOT_AVAILABLE");
1264
- sUNACCEPTED_POLICY = rb_intern("UNACCEPTED_POLICY");
1265
- sUNACCEPTED_EXTENSION = rb_intern("UNACCEPTED_EXTENSION");
1266
- sADD_INFO_NOT_AVAILABLE = rb_intern("ADD_INFO_NOT_AVAILABLE");
1267
- sSYSTEM_FAILURE = rb_intern("SYSTEM_FAILURE");
1288
+ sTIME_NOT_AVAILABLE = ID2SYM(rb_intern_const("TIME_NOT_AVAILABLE"));
1289
+ sUNACCEPTED_POLICY = ID2SYM(rb_intern_const("UNACCEPTED_POLICY"));
1290
+ sUNACCEPTED_EXTENSION = ID2SYM(rb_intern_const("UNACCEPTED_EXTENSION"));
1291
+ sADD_INFO_NOT_AVAILABLE = ID2SYM(rb_intern_const("ADD_INFO_NOT_AVAILABLE"));
1292
+ sSYSTEM_FAILURE = ID2SYM(rb_intern_const("SYSTEM_FAILURE"));
1268
1293
 
1269
1294
  /* Document-class: OpenSSL::Timestamp
1270
1295
  * Provides classes and methods to request, create and validate
@@ -1280,7 +1305,7 @@ Init_ossl_ts(void)
1280
1305
  * ===Create a Response:
1281
1306
  * #Assumes ts.p12 is a PKCS#12-compatible file with a private key
1282
1307
  * #and a certificate that has an extended key usage of 'timeStamping'
1283
- * p12 = OpenSSL::PKCS12.new(File.open('ts.p12', 'rb'), 'pwd')
1308
+ * p12 = OpenSSL::PKCS12.new(File.binread('ts.p12'), 'pwd')
1284
1309
  * md = OpenSSL::Digest.new('SHA1')
1285
1310
  * hash = md.digest(data) #some binary data to be timestamped
1286
1311
  * req = OpenSSL::Timestamp::Request.new
@@ -1295,16 +1320,16 @@ Init_ossl_ts(void)
1295
1320
  *
1296
1321
  * ===Verify a timestamp response:
1297
1322
  * #Assume we have a timestamp token in a file called ts.der
1298
- * ts = OpenSSL::Timestamp::Response.new(File.open('ts.der', 'rb')
1323
+ * ts = OpenSSL::Timestamp::Response.new(File.binread('ts.der'))
1299
1324
  * #Assume we have the Request for this token in a file called req.der
1300
- * req = OpenSSL::Timestamp::Request.new(File.open('req.der', 'rb')
1325
+ * req = OpenSSL::Timestamp::Request.new(File.binread('req.der'))
1301
1326
  * # Assume the associated root CA certificate is contained in a
1302
1327
  * # DER-encoded file named root.cer
1303
- * root = OpenSSL::X509::Certificate.new(File.open('root.cer', 'rb')
1328
+ * root = OpenSSL::X509::Certificate.new(File.binread('root.cer'))
1304
1329
  * # get the necessary intermediate certificates, available in
1305
1330
  * # DER-encoded form in inter1.cer and inter2.cer
1306
- * inter1 = OpenSSL::X509::Certificate.new(File.open('inter1.cer', 'rb')
1307
- * inter2 = OpenSSL::X509::Certificate.new(File.open('inter2.cer', 'rb')
1331
+ * inter1 = OpenSSL::X509::Certificate.new(File.binread('inter1.cer'))
1332
+ * inter2 = OpenSSL::X509::Certificate.new(File.binread('inter2.cer'))
1308
1333
  * ts.verify(req, root, inter1, inter2) -> ts or raises an exception if validation fails
1309
1334
  *
1310
1335
  */
@@ -1437,9 +1462,9 @@ Init_ossl_ts(void)
1437
1462
  * timestamping certificate.
1438
1463
  *
1439
1464
  * req = OpenSSL::Timestamp::Request.new(raw_bytes)
1440
- * p12 = OpenSSL::PKCS12.new(File.open('ts.p12', 'rb'), 'pwd')
1441
- * inter1 = OpenSSL::X509::Certificate.new(File.open('inter1.cer', 'rb')
1442
- * inter2 = OpenSSL::X509::Certificate.new(File.open('inter2.cer', 'rb')
1465
+ * p12 = OpenSSL::PKCS12.new(File.binread('ts.p12'), 'pwd')
1466
+ * inter1 = OpenSSL::X509::Certificate.new(File.binread('inter1.cer'))
1467
+ * inter2 = OpenSSL::X509::Certificate.new(File.binread('inter2.cer'))
1443
1468
  * fac = OpenSSL::Timestamp::Factory.new
1444
1469
  * fac.gen_time = Time.now
1445
1470
  * fac.serial_number = 1
@@ -1503,11 +1528,11 @@ Init_ossl_ts(void)
1503
1528
  *
1504
1529
  */
1505
1530
  cTimestampFactory = rb_define_class_under(mTimestamp, "Factory", rb_cObject);
1506
- rb_attr(cTimestampFactory, rb_intern("allowed_digests"), 1, 1, 0);
1507
- rb_attr(cTimestampFactory, rb_intern("default_policy_id"), 1, 1, 0);
1508
- rb_attr(cTimestampFactory, rb_intern("serial_number"), 1, 1, 0);
1509
- rb_attr(cTimestampFactory, rb_intern("gen_time"), 1, 1, 0);
1510
- rb_attr(cTimestampFactory, rb_intern("additional_certs"), 1, 1, 0);
1531
+ rb_attr(cTimestampFactory, rb_intern_const("allowed_digests"), 1, 1, 0);
1532
+ rb_attr(cTimestampFactory, rb_intern_const("default_policy_id"), 1, 1, 0);
1533
+ rb_attr(cTimestampFactory, rb_intern_const("serial_number"), 1, 1, 0);
1534
+ rb_attr(cTimestampFactory, rb_intern_const("gen_time"), 1, 1, 0);
1535
+ rb_attr(cTimestampFactory, rb_intern_const("additional_certs"), 1, 1, 0);
1511
1536
  rb_define_method(cTimestampFactory, "create_timestamp", ossl_tsfac_create_ts, 3);
1512
1537
  }
1513
1538
 
@@ -115,11 +115,9 @@ Init_ossl_x509(void)
115
115
  DefX509Const(V_ERR_SUITE_B_LOS_NOT_ALLOWED);
116
116
  DefX509Const(V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256);
117
117
  #endif
118
- #if defined(X509_V_ERR_HOSTNAME_MISMATCH)
119
118
  DefX509Const(V_ERR_HOSTNAME_MISMATCH);
120
119
  DefX509Const(V_ERR_EMAIL_MISMATCH);
121
120
  DefX509Const(V_ERR_IP_ADDRESS_MISMATCH);
122
- #endif
123
121
  #if defined(X509_V_ERR_DANE_NO_MATCH)
124
122
  DefX509Const(V_ERR_DANE_NO_MATCH);
125
123
  #endif
@@ -187,12 +185,10 @@ Init_ossl_x509(void)
187
185
  /* Set by Store#flags= and StoreContext#flags=. Enables checking of the
188
186
  * signature of the root self-signed CA. */
189
187
  DefX509Const(V_FLAG_CHECK_SS_SIGNATURE);
190
- #if defined(X509_V_FLAG_TRUSTED_FIRST)
191
188
  /* Set by Store#flags= and StoreContext#flags=. When constructing a
192
189
  * certificate chain, search the Store first for the issuer certificate.
193
190
  * Enabled by default in OpenSSL >= 1.1.0. */
194
191
  DefX509Const(V_FLAG_TRUSTED_FIRST);
195
- #endif
196
192
  #if defined(X509_V_FLAG_SUITEB_128_LOS_ONLY)
197
193
  /* Set by Store#flags= and StoreContext#flags=.
198
194
  * Enables Suite B 128 bit only mode. */
@@ -208,11 +204,9 @@ Init_ossl_x509(void)
208
204
  * Enables Suite B 128 bit mode allowing 192 bit algorithms. */
209
205
  DefX509Const(V_FLAG_SUITEB_128_LOS);
210
206
  #endif
211
- #if defined(X509_V_FLAG_PARTIAL_CHAIN)
212
207
  /* Set by Store#flags= and StoreContext#flags=.
213
208
  * Allows partial chains if at least one certificate is in trusted store. */
214
209
  DefX509Const(V_FLAG_PARTIAL_CHAIN);
215
- #endif
216
210
  #if defined(X509_V_FLAG_NO_ALT_CHAINS)
217
211
  /* Set by Store#flags= and StoreContext#flags=. Suppresses searching for
218
212
  * a alternative chain. No effect in OpenSSL >= 1.1.0. */
@@ -115,24 +115,27 @@ static VALUE
115
115
  ossl_x509_initialize(int argc, VALUE *argv, VALUE self)
116
116
  {
117
117
  BIO *in;
118
- X509 *x509, *x = DATA_PTR(self);
118
+ X509 *x509, *x509_orig = RTYPEDDATA_DATA(self);
119
119
  VALUE arg;
120
120
 
121
+ rb_check_frozen(self);
121
122
  if (rb_scan_args(argc, argv, "01", &arg) == 0) {
122
123
  /* create just empty X509Cert */
123
124
  return self;
124
125
  }
125
126
  arg = ossl_to_der_if_possible(arg);
126
127
  in = ossl_obj2bio(&arg);
127
- x509 = PEM_read_bio_X509(in, &x, NULL, NULL);
128
- DATA_PTR(self) = x;
128
+ x509 = d2i_X509_bio(in, NULL);
129
129
  if (!x509) {
130
- OSSL_BIO_reset(in);
131
- x509 = d2i_X509_bio(in, &x);
132
- DATA_PTR(self) = x;
130
+ OSSL_BIO_reset(in);
131
+ x509 = PEM_read_bio_X509(in, NULL, NULL, NULL);
133
132
  }
134
133
  BIO_free(in);
135
- if (!x509) ossl_raise(eX509CertError, NULL);
134
+ if (!x509)
135
+ ossl_raise(eX509CertError, "PEM_read_bio_X509");
136
+
137
+ RTYPEDDATA_DATA(self) = x509;
138
+ X509_free(x509_orig);
136
139
 
137
140
  return self;
138
141
  }
@@ -639,12 +642,12 @@ ossl_x509_set_extensions(VALUE self, VALUE ary)
639
642
  OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext);
640
643
  }
641
644
  GetX509(self, x509);
642
- while ((ext = X509_delete_ext(x509, 0)))
643
- X509_EXTENSION_free(ext);
645
+ for (i = X509_get_ext_count(x509); i > 0; i--)
646
+ X509_EXTENSION_free(X509_delete_ext(x509, 0));
644
647
  for (i=0; i<RARRAY_LEN(ary); i++) {
645
648
  ext = GetX509ExtPtr(RARRAY_AREF(ary, i));
646
649
  if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext */
647
- ossl_raise(eX509CertError, NULL);
650
+ ossl_raise(eX509CertError, "X509_add_ext");
648
651
  }
649
652
  }
650
653
 
@@ -704,6 +707,157 @@ ossl_x509_eq(VALUE self, VALUE other)
704
707
  return !X509_cmp(a, b) ? Qtrue : Qfalse;
705
708
  }
706
709
 
710
+ struct load_chained_certificates_arguments {
711
+ VALUE certificates;
712
+ X509 *certificate;
713
+ };
714
+
715
+ static VALUE
716
+ load_chained_certificates_append_push(VALUE _arguments) {
717
+ struct load_chained_certificates_arguments *arguments = (struct load_chained_certificates_arguments*)_arguments;
718
+
719
+ if (arguments->certificates == Qnil) {
720
+ arguments->certificates = rb_ary_new();
721
+ }
722
+
723
+ rb_ary_push(arguments->certificates, ossl_x509_new(arguments->certificate));
724
+
725
+ return Qnil;
726
+ }
727
+
728
+ static VALUE
729
+ load_chained_certificate_append_ensure(VALUE _arguments) {
730
+ struct load_chained_certificates_arguments *arguments = (struct load_chained_certificates_arguments*)_arguments;
731
+
732
+ X509_free(arguments->certificate);
733
+
734
+ return Qnil;
735
+ }
736
+
737
+ inline static VALUE
738
+ load_chained_certificates_append(VALUE certificates, X509 *certificate) {
739
+ struct load_chained_certificates_arguments arguments;
740
+ arguments.certificates = certificates;
741
+ arguments.certificate = certificate;
742
+
743
+ rb_ensure(load_chained_certificates_append_push, (VALUE)&arguments, load_chained_certificate_append_ensure, (VALUE)&arguments);
744
+
745
+ return arguments.certificates;
746
+ }
747
+
748
+ static VALUE
749
+ load_chained_certificates_PEM(BIO *in) {
750
+ VALUE certificates = Qnil;
751
+ X509 *certificate = PEM_read_bio_X509(in, NULL, NULL, NULL);
752
+
753
+ /* If we cannot read even one certificate: */
754
+ if (certificate == NULL) {
755
+ /* If we cannot read one certificate because we could not read the PEM encoding: */
756
+ if (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE) {
757
+ ossl_clear_error();
758
+ }
759
+
760
+ if (ERR_peek_last_error())
761
+ ossl_raise(eX509CertError, NULL);
762
+ else
763
+ return Qnil;
764
+ }
765
+
766
+ certificates = load_chained_certificates_append(Qnil, certificate);
767
+
768
+ while ((certificate = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
769
+ load_chained_certificates_append(certificates, certificate);
770
+ }
771
+
772
+ /* We tried to read one more certificate but could not read start line: */
773
+ if (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE) {
774
+ /* This is not an error, it means we are finished: */
775
+ ossl_clear_error();
776
+
777
+ return certificates;
778
+ }
779
+
780
+ /* Alternatively, if we reached the end of the file and there was no error: */
781
+ if (BIO_eof(in) && !ERR_peek_last_error()) {
782
+ return certificates;
783
+ } else {
784
+ /* Otherwise, we tried to read a certificate but failed somewhere: */
785
+ ossl_raise(eX509CertError, NULL);
786
+ }
787
+ }
788
+
789
+ static VALUE
790
+ load_chained_certificates_DER(BIO *in) {
791
+ X509 *certificate = d2i_X509_bio(in, NULL);
792
+
793
+ /* If we cannot read one certificate: */
794
+ if (certificate == NULL) {
795
+ /* Ignore error. We could not load. */
796
+ ossl_clear_error();
797
+
798
+ return Qnil;
799
+ }
800
+
801
+ return load_chained_certificates_append(Qnil, certificate);
802
+ }
803
+
804
+ static VALUE
805
+ load_chained_certificates(VALUE _io) {
806
+ BIO *in = (BIO*)_io;
807
+ VALUE certificates = Qnil;
808
+
809
+ /*
810
+ DER is a binary format and it may contain octets within it that look like
811
+ PEM encoded certificates. So we need to check DER first.
812
+ */
813
+ certificates = load_chained_certificates_DER(in);
814
+
815
+ if (certificates != Qnil)
816
+ return certificates;
817
+
818
+ OSSL_BIO_reset(in);
819
+
820
+ certificates = load_chained_certificates_PEM(in);
821
+
822
+ if (certificates != Qnil)
823
+ return certificates;
824
+
825
+ /* Otherwise we couldn't read the output correctly so fail: */
826
+ ossl_raise(eX509CertError, "Could not detect format of certificate data!");
827
+ }
828
+
829
+ static VALUE
830
+ load_chained_certificates_ensure(VALUE _io) {
831
+ BIO *in = (BIO*)_io;
832
+
833
+ BIO_free(in);
834
+
835
+ return Qnil;
836
+ }
837
+
838
+ /*
839
+ * call-seq:
840
+ * OpenSSL::X509::Certificate.load(string) -> [certs...]
841
+ * OpenSSL::X509::Certificate.load(file) -> [certs...]
842
+ *
843
+ * Read the chained certificates from the given input. Supports both PEM
844
+ * and DER encoded certificates.
845
+ *
846
+ * PEM is a text format and supports more than one certificate.
847
+ *
848
+ * DER is a binary format and only supports one certificate.
849
+ *
850
+ * If the file is empty, or contains only unrelated data, an
851
+ * +OpenSSL::X509::CertificateError+ exception will be raised.
852
+ */
853
+ static VALUE
854
+ ossl_x509_load(VALUE klass, VALUE buffer)
855
+ {
856
+ BIO *in = ossl_obj2bio(&buffer);
857
+
858
+ return rb_ensure(load_chained_certificates, (VALUE)in, load_chained_certificates_ensure, (VALUE)in);
859
+ }
860
+
707
861
  /*
708
862
  * INIT
709
863
  */
@@ -730,7 +884,7 @@ Init_ossl_x509cert(void)
730
884
  * Certificate is capable of handling DER-encoded certificates and
731
885
  * certificates encoded in OpenSSL's PEM format.
732
886
  *
733
- * raw = File.read "cert.cer" # DER- or PEM-encoded
887
+ * raw = File.binread "cert.cer" # DER- or PEM-encoded
734
888
  * certificate = OpenSSL::X509::Certificate.new raw
735
889
  *
736
890
  * === Saving a certificate to a file
@@ -812,6 +966,8 @@ Init_ossl_x509cert(void)
812
966
  */
813
967
  cX509Cert = rb_define_class_under(mX509, "Certificate", rb_cObject);
814
968
 
969
+ rb_define_singleton_method(cX509Cert, "load", ossl_x509_load, 1);
970
+
815
971
  rb_define_alloc_func(cX509Cert, ossl_x509_alloc);
816
972
  rb_define_method(cX509Cert, "initialize", ossl_x509_initialize, -1);
817
973
  rb_define_method(cX509Cert, "initialize_copy", ossl_x509_copy, 1);
@@ -93,23 +93,26 @@ static VALUE
93
93
  ossl_x509crl_initialize(int argc, VALUE *argv, VALUE self)
94
94
  {
95
95
  BIO *in;
96
- X509_CRL *crl, *x = DATA_PTR(self);
96
+ X509_CRL *crl, *crl_orig = RTYPEDDATA_DATA(self);
97
97
  VALUE arg;
98
98
 
99
+ rb_check_frozen(self);
99
100
  if (rb_scan_args(argc, argv, "01", &arg) == 0) {
100
101
  return self;
101
102
  }
102
103
  arg = ossl_to_der_if_possible(arg);
103
104
  in = ossl_obj2bio(&arg);
104
- crl = PEM_read_bio_X509_CRL(in, &x, NULL, NULL);
105
- DATA_PTR(self) = x;
105
+ crl = d2i_X509_CRL_bio(in, NULL);
106
106
  if (!crl) {
107
- OSSL_BIO_reset(in);
108
- crl = d2i_X509_CRL_bio(in, &x);
109
- DATA_PTR(self) = x;
107
+ OSSL_BIO_reset(in);
108
+ crl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
110
109
  }
111
110
  BIO_free(in);
112
- if (!crl) ossl_raise(eX509CRLError, NULL);
111
+ if (!crl)
112
+ ossl_raise(eX509CRLError, "PEM_read_bio_X509_CRL");
113
+
114
+ RTYPEDDATA_DATA(self) = crl;
115
+ X509_CRL_free(crl_orig);
113
116
 
114
117
  return self;
115
118
  }
@@ -471,12 +474,12 @@ ossl_x509crl_set_extensions(VALUE self, VALUE ary)
471
474
  OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext);
472
475
  }
473
476
  GetX509CRL(self, crl);
474
- while ((ext = X509_CRL_delete_ext(crl, 0)))
475
- X509_EXTENSION_free(ext);
477
+ for (i = X509_CRL_get_ext_count(crl); i > 0; i--)
478
+ X509_EXTENSION_free(X509_CRL_delete_ext(crl, 0));
476
479
  for (i=0; i<RARRAY_LEN(ary); i++) {
477
480
  ext = GetX509ExtPtr(RARRAY_AREF(ary, i)); /* NO NEED TO DUP */
478
481
  if (!X509_CRL_add_ext(crl, ext, -1)) {
479
- ossl_raise(eX509CRLError, NULL);
482
+ ossl_raise(eX509CRLError, "X509_CRL_add_ext");
480
483
  }
481
484
  }
482
485
 
@@ -226,11 +226,10 @@ ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self)
226
226
  GetX509ExtFactory(self, ctx);
227
227
  obj = NewX509Ext(cX509Ext);
228
228
  rconf = rb_iv_get(self, "@config");
229
- conf = NIL_P(rconf) ? NULL : DupConfigPtr(rconf);
229
+ conf = NIL_P(rconf) ? NULL : GetConfig(rconf);
230
230
  X509V3_set_nconf(ctx, conf);
231
231
  ext = X509V3_EXT_nconf_nid(conf, ctx, nid, RSTRING_PTR(valstr));
232
232
  X509V3_set_ctx_nodb(ctx);
233
- NCONF_free(conf);
234
233
  if (!ext){
235
234
  ossl_raise(eX509ExtError, "%"PRIsVALUE" = %"PRIsVALUE, oid, valstr);
236
235
  }