-
Notifications
You must be signed in to change notification settings - Fork 182
Open
Description
#724 reminded me of this issue.
Due to an insufficient error check with sscanf() in asn1time_to_time(), OpenSSL::ASN1.decode ignores any fractional seconds or time zone information in DER/BER.
$ ruby -ropenssl -e'p OpenSSL::ASN1.decode("\x18\x13" + "20161208193439.123Z").value'
2016-12-08 19:34:39 UTC # <- The fractional seconds is lost
$ ruby -ropenssl -e'p OpenSSL::ASN1.decode("\x18\x13" + "20161208193439+0900").value'
2016-12-08 19:34:39 UTC # <- Timezone is lost
openssl/ext/openssl/ossl_asn1.c
Lines 19 to 70 in 1e8e246
| VALUE | |
| asn1time_to_time(const ASN1_TIME *time) | |
| { | |
| struct tm tm; | |
| VALUE argv[6]; | |
| int count; | |
| memset(&tm, 0, sizeof(struct tm)); | |
| switch (time->type) { | |
| case V_ASN1_UTCTIME: | |
| count = sscanf((const char *)time->data, "%2d%2d%2d%2d%2d%2dZ", | |
| &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, | |
| &tm.tm_sec); | |
| if (count == 5) { | |
| tm.tm_sec = 0; | |
| } else if (count != 6) { | |
| ossl_raise(rb_eTypeError, "bad UTCTIME format: \"%s\"", | |
| time->data); | |
| } | |
| if (tm.tm_year < 69) { | |
| tm.tm_year += 2000; | |
| } else { | |
| tm.tm_year += 1900; | |
| } | |
| break; | |
| case V_ASN1_GENERALIZEDTIME: | |
| count = sscanf((const char *)time->data, "%4d%2d%2d%2d%2d%2dZ", | |
| &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, | |
| &tm.tm_sec); | |
| if (count == 5) { | |
| tm.tm_sec = 0; | |
| } | |
| else if (count != 6) { | |
| ossl_raise(rb_eTypeError, "bad GENERALIZEDTIME format: \"%s\"", | |
| time->data); | |
| } | |
| break; | |
| default: | |
| rb_warning("unknown time format"); | |
| return Qnil; | |
| } | |
| argv[0] = INT2NUM(tm.tm_year); | |
| argv[1] = INT2NUM(tm.tm_mon); | |
| argv[2] = INT2NUM(tm.tm_mday); | |
| argv[3] = INT2NUM(tm.tm_hour); | |
| argv[4] = INT2NUM(tm.tm_min); | |
| argv[5] = INT2NUM(tm.tm_sec); | |
| return rb_funcall2(rb_cTime, rb_intern("utc"), 6, argv); | |
| } |
openssl/test/openssl/test_asn1.rb
Lines 435 to 452 in 1e8e246
| # not implemented | |
| # decode_test B(%w{ 18 13 }) + "20161208193439+0930".b, | |
| # OpenSSL::ASN1::GeneralizedTime.new(Time.new(2016, 12, 8, 19, 34, 39, "+09:30")) | |
| # decode_test B(%w{ 18 11 }) + "201612081934-0930".b, | |
| # OpenSSL::ASN1::GeneralizedTime.new(Time.new(2016, 12, 8, 19, 34, 0, "-09:30")) | |
| # decode_test B(%w{ 18 11 }) + "201612081934-09".b, | |
| # OpenSSL::ASN1::GeneralizedTime.new(Time.new(2016, 12, 8, 19, 34, 0, "-09:00")) | |
| # decode_test B(%w{ 18 0D }) + "2016120819.5Z".b, | |
| # OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 30, 0)) | |
| # decode_test B(%w{ 18 0D }) + "2016120819,5Z".b, | |
| # OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 30, 0)) | |
| # decode_test B(%w{ 18 0F }) + "201612081934.5Z".b, | |
| # OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 30)) | |
| # decode_test B(%w{ 18 11 }) + "20161208193439.5Z".b, | |
| # OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 39.5)) | |
| # assert_raise(OpenSSL::ASN1::ASN1Error) { | |
| # OpenSSL::ASN1.decode(B(%w{ 18 0D }) + "201612081934Y".b) | |
| # } |
Metadata
Metadata
Assignees
Labels
No labels