From 4b95ee660ba6b2ed952859382faac8f31cea9002 Mon Sep 17 00:00:00 2001 From: "@rubynerd" Date: Mon, 22 Mar 2021 21:35:31 +0000 Subject: [PATCH] replace add_signed_attribute with set_signed_attributes --- ext/openssl/ossl.c | 1 + ext/openssl/ossl.h | 1 + ext/openssl/ossl_pkcs7.c | 93 +++++++------------------------------ ext/openssl/ossl_x509.h | 1 + ext/openssl/ossl_x509attr.c | 15 ++++++ 5 files changed, 34 insertions(+), 77 deletions(-) diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index 70b6a6a80..cf838c7cb 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -61,6 +61,7 @@ ossl_##name##_ary2sk(VALUE ary) \ return sk; \ } OSSL_IMPL_ARY2SK(x509, X509, cX509Cert, DupX509CertPtr) +OSSL_IMPL_ARY2SK(x509_attr, X509_ATTRIBUTE, cX509Attr, DupX509AttrPtr) #define OSSL_IMPL_SK2ARY(name, type) \ VALUE \ diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h index 577eb6d6b..214404174 100644 --- a/ext/openssl/ossl.h +++ b/ext/openssl/ossl.h @@ -80,6 +80,7 @@ extern VALUE eOSSLError; */ STACK_OF(X509) *ossl_x509_ary2sk(VALUE); STACK_OF(X509) *ossl_protect_x509_ary2sk(VALUE,int*); +STACK_OF(X509_ATTRIBUTE) *ossl_protect_x509_attr_ary2sk(VALUE,int*); VALUE ossl_x509_sk2ary(const STACK_OF(X509) *certs); VALUE ossl_x509crl_sk2ary(const STACK_OF(X509_CRL) *crl); VALUE ossl_x509name_sk2ary(const STACK_OF(X509_NAME) *names); diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c index 9e362b07e..ba01a6308 100644 --- a/ext/openssl/ossl_pkcs7.c +++ b/ext/openssl/ossl_pkcs7.c @@ -973,87 +973,26 @@ ossl_pkcs7si_get_signed_time(VALUE self) } static VALUE -ossl_pkcs7si_add_signed_attribute(VALUE self, VALUE oid, VALUE value) { - // PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *si, int nid, int attrtype, void *value) - // - // argument sources: - // si - signer_info from OpenSSL, OpenSSL::PKCS7#signers.first, then rubyobj -> OpenSSL struct - // nid - "numerical id" of OID, how to pivot from OpenSSL::ASN1::ObjectId??? - // - nightmare - // - ObjectId has little connection with reality, it's a subclass of Primitive - // attrtype - "and it adds a new ASN.1 ANY object of type attrtype with the given value to the new attribute." - // - what is this? - // value - void PTR, ossl_asn1_get_asn1type has a case statement that produces a correct value - +ossl_pkcs7si_set_signed_attributes(VALUE self, VALUE ary) +{ PKCS7_SIGNER_INFO *p7si; - ASN1_OBJECT *a1obj; - ASN1_TYPE *value_as_type; // hacks to use ossl_asn1_get_asn1type's case statement - int nid, tag = 0; + STACK_OF(X509_ATTRIBUTE) *sk; + int status, result; GetPKCS7si(self, p7si); + Check_Type(ary, T_ARRAY); - // convert OpenSSL::ASN1::ObjectId to a nid - a1obj = obj_to_asn1obj(ossl_asn1_get_value(oid)); // TODO: error check - nid = OBJ_obj2nid(a1obj); // TODO: error check (NID_undef) - // it's completely possible someone's using an unknown NID here - // we should raise an informative error if this happens - - // so about attrtype... - // i'm assuming this would be something like "OpenSSL::ASN1::Sequence" in Ruby - // we can determine attrtype from the "value", as essentially the "value" is an attrtype plus value - // so attrtype is eventually passed into ASN1_TYPE_set - // ASN1_type_set docs makes explicit references to "V_ASN1_SEQUENCE"/"V_ASN1_BOOLEAN"/"V_ASN1_OTHER" - // so i'm now pretty convinced i should be able to get this from a1obj - - // though should we use ossl_asn1_get_tag? - // ossl_asn1_tag takes VALUE obj -> int - tag = ossl_asn1_tag(value); // TODO: error check - - // how tf do we go from value -> ruby -> openssl somehow? -> "value pointer" - // maybe this: - // value = ossl_asn1_get_value(obj); // no, becaue value is a ruby — ossl_asn1_get_asn1type might have something useful - - // struct asn1_object_st { - // const char *sn, *ln; - // int nid; - // int length; - // const unsigned char *data; - // int flags; - // } - - - // "void *value" goes PKCS7_signed_attribute -> add_attribute -> X509_ATTRIBUTE_create (x_attrib.c) - // -> ASN1_TYPE_set(val, atrtype, value) - // -> a->value.ptr = value; - // a is an ASN1_TYPE struct (asn1_type_st) - // include/openssl/asn1.h.in as: - // - // struct asn1_type_st { - // int type; - // union { - // char *ptr; - // // a bunch of other specifically typed attributes like: - // ASN1_BOOLEAN boolean; - // ASN1_UNIVERSALSTRING *universalstring; - // } - // very unclear on if this matters though? - // - // so what do we need? i'm still no closer to actually answering that question - // i can get an ASN1_OBJECT but that's still not much use to me - // - // i can actually get an ASN1_TYPE from ossl_asn1_get_asn1type, which calls - // ASN1_TYPE_set under the hood via a crazy case statement. - value_as_type = ossl_asn1_get_asn1type(value); - - // method sig would be .add_signed_attribute(oid/type, value) - // where ObjectId is actually a Primitive (???) so how do I handle that? - // both oid and value are ultimately primitives tbh - PKCS7_add_signed_attribute(p7si, nid, tag, value_as_type.value); - - // return the value of the attribute we've just stuck in - return value; -} + // TODO: reset attributes + + // build list of x509 attrs of length RARRAY_LEN(ary) + sk = ossl_protect_x509_attr_ary2sk(ary, &status); + result = PKCS7_set_signed_attributes(p7si, sk); + + fprintf(stderr, "set signed attributes result is: '%d'\n", result); + + return Qtrue; +} /* * RECIPIENT INFO @@ -1173,7 +1112,7 @@ Init_ossl_pkcs7(void) rb_define_method(cPKCS7Signer, "issuer", ossl_pkcs7si_get_issuer, 0); rb_define_method(cPKCS7Signer, "serial", ossl_pkcs7si_get_serial,0); rb_define_method(cPKCS7Signer,"signed_time",ossl_pkcs7si_get_signed_time,0); - rb_define_method(cPKCS7Signer, "add_signed_attribute", ossl_pkcs7si_add_signed_attribute, 2); + rb_define_method(cPKCS7Signer, "signed_attributes=", ossl_pkcs7si_set_signed_attributes, 1); cPKCS7Recipient = rb_define_class_under(cPKCS7,"RecipientInfo",rb_cObject); rb_define_alloc_func(cPKCS7Recipient, ossl_pkcs7ri_alloc); diff --git a/ext/openssl/ossl_x509.h b/ext/openssl/ossl_x509.h index 4fadfa6b8..40252ce73 100644 --- a/ext/openssl/ossl_x509.h +++ b/ext/openssl/ossl_x509.h @@ -32,6 +32,7 @@ extern VALUE eX509AttrError; VALUE ossl_x509attr_new(X509_ATTRIBUTE *); X509_ATTRIBUTE *GetX509AttrPtr(VALUE); +X509_ATTRIBUTE *DupX509AttrPtr(VALUE); void Init_ossl_x509attr(void); /* diff --git a/ext/openssl/ossl_x509attr.c b/ext/openssl/ossl_x509attr.c index 60846cfe9..184ca2a1e 100644 --- a/ext/openssl/ossl_x509attr.c +++ b/ext/openssl/ossl_x509attr.c @@ -77,6 +77,21 @@ GetX509AttrPtr(VALUE obj) return attr; } +X509_ATTRIBUTE * +DupX509AttrPtr(VALUE obj) +{ + X509_ATTRIBUTE *attr, *new; + + GetX509Attr(obj, attr); + + // XXX: maybe missing an up_ref here? + if (!(new = X509_ATTRIBUTE_dup(attr))) { + fprintf(stderr, "dup failed unlucky\n"); + } + + return new; +} + /* * Private */