From af895bc5596b1521e13a3c6ab65aacdb6913e128 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Thu, 15 Dec 2016 14:50:23 +0900 Subject: asn1: avoid truncating OID in OpenSSL::ASN1::ObjectId#oid OpenSSL::ASN1::ObjectId#oid, which returns the dotted representation of the OID, is silently truncating the result if it overflows the 128-bytes buffer. Although it normally won't be more than 127-characters, it'd be better to avoid. This can be done by checking the return value of OBJ_obj2txt(). Previous releases of LibreSSL (< 2.5.1) have a bug in OBJ_obj2txt() and it does not work if the resulting string would be larger than the buffer. A workaround is added to the test. It should be removed when we deprecate support for LibreSSL 2.4. --- ext/openssl/ossl_asn1.c | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) (limited to 'ext/openssl/ossl_asn1.c') diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c index 00d598ef..50fcb5b1 100644 --- a/ext/openssl/ossl_asn1.c +++ b/ext/openssl/ossl_asn1.c @@ -1347,6 +1347,28 @@ ossl_asn1obj_get_ln(VALUE self) return ret; } +static VALUE +asn1obj_get_oid_i(VALUE vobj) +{ + ASN1_OBJECT *a1obj = (void *)vobj; + VALUE str; + int len; + + str = rb_usascii_str_new(NULL, 127); + len = OBJ_obj2txt(RSTRING_PTR(str), RSTRING_LENINT(str), a1obj, 1); + if (len <= 0 || len == INT_MAX) + ossl_raise(eASN1Error, "OBJ_obj2txt"); + if (len > RSTRING_LEN(str)) { + /* +1 is for the \0 terminator added by OBJ_obj2txt() */ + rb_str_resize(str, len + 1); + len = OBJ_obj2txt(RSTRING_PTR(str), len + 1, a1obj, 1); + if (len <= 0) + ossl_raise(eASN1Error, "OBJ_obj2txt"); + } + rb_str_set_len(str, len); + return str; +} + /* * call-seq: * oid.oid -> string @@ -1357,16 +1379,16 @@ ossl_asn1obj_get_ln(VALUE self) static VALUE ossl_asn1obj_get_oid(VALUE self) { - VALUE val; + VALUE str; ASN1_OBJECT *a1obj; - char buf[128]; + int state; - val = ossl_asn1_get_value(self); - a1obj = obj_to_asn1obj(val); - OBJ_obj2txt(buf, sizeof(buf), a1obj, 1); + a1obj = obj_to_asn1obj(ossl_asn1_get_value(self)); + str = rb_protect(asn1obj_get_oid_i, (VALUE)a1obj, &state); ASN1_OBJECT_free(a1obj); - - return rb_str_new2(buf); + if (state) + rb_jump_tag(state); + return str; } #define OSSL_ASN1_IMPL_FACTORY_METHOD(klass) \ -- cgit v1.2.3