Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x509*: implement == #161

Merged
merged 6 commits into from
Oct 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions ext/openssl/ossl_x509cert.c
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,26 @@ ossl_x509_inspect(VALUE self)
ossl_x509_get_not_after(self));
}

/*
* call-seq:
* cert1 == cert2 -> true | false
*
* Compares the two certificates. Note that this takes into account all fields,
* not just the issuer name and the serial number.
*/
static VALUE
ossl_x509_eq(VALUE self, VALUE other)
{
X509 *a, *b;

GetX509(self, a);
if (!rb_obj_is_kind_of(other, cX509Cert))
return Qfalse;
GetX509(other, b);

return !X509_cmp(a, b) ? Qtrue : Qfalse;
}

/*
* INIT
*/
Expand Down Expand Up @@ -821,4 +841,5 @@ Init_ossl_x509cert(void)
rb_define_method(cX509Cert, "extensions=", ossl_x509_set_extensions, 1);
rb_define_method(cX509Cert, "add_extension", ossl_x509_add_extension, 1);
rb_define_method(cX509Cert, "inspect", ossl_x509_inspect, 0);
rb_define_method(cX509Cert, "==", ossl_x509_eq, 1);
}
21 changes: 21 additions & 0 deletions ext/openssl/ossl_x509revoked.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,26 @@ ossl_x509revoked_add_extension(VALUE self, VALUE ext)
return ext;
}

static VALUE
ossl_x509revoked_to_der(VALUE self)
{
X509_REVOKED *rev;
VALUE str;
int len;
unsigned char *p;

GetX509Rev(self, rev);
len = i2d_X509_REVOKED(rev, NULL);
if (len <= 0)
ossl_raise(eX509RevError, "i2d_X509_REVOKED");
str = rb_str_new(NULL, len);
p = (unsigned char *)RSTRING_PTR(str);
if (i2d_X509_REVOKED(rev, &p) <= 0)
ossl_raise(eX509RevError, "i2d_X509_REVOKED");
ossl_str_adjust(str, p);
return str;
}

/*
* INIT
*/
Expand Down Expand Up @@ -276,4 +296,5 @@ Init_ossl_x509revoked(void)
rb_define_method(cX509Rev, "extensions", ossl_x509revoked_get_extensions, 0);
rb_define_method(cX509Rev, "extensions=", ossl_x509revoked_set_extensions, 1);
rb_define_method(cX509Rev, "add_extension", ossl_x509revoked_add_extension, 1);
rb_define_method(cX509Rev, "to_der", ossl_x509revoked_to_der, 0);
}
33 changes: 33 additions & 0 deletions lib/openssl/x509.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ def create_ext_from_hash(hash)
end

class Extension
def ==(other)
return false unless Extension === other
to_der == other.to_der
end

def to_s # "oid = critical, value"
str = self.oid
str << " = "
Expand Down Expand Up @@ -160,6 +165,13 @@ def pretty_print(q)
end
end

class Attribute
def ==(other)
return false unless Attribute === other
to_der == other.to_der
end
end

class StoreContext
def cleanup
warn "(#{caller.first}) OpenSSL::X509::StoreContext#cleanup is deprecated with no replacement" if $VERBOSE
Expand All @@ -178,5 +190,26 @@ def pretty_print(q)
}
end
end

class CRL
def ==(other)
return false unless CRL === other
to_der == other.to_der
end
end

class Revoked
def ==(other)
return false unless Revoked === other
to_der == other.to_der
end
end

class Request
def ==(other)
return false unless Request === other
to_der == other.to_der
end
end
end
end
17 changes: 17 additions & 0 deletions test/test_x509attr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,23 @@ def test_dup
attr = OpenSSL::X509::Attribute.new("challengePassword", val)
assert_equal(attr.to_der, attr.dup.to_der)
end

def test_eq
val1 = OpenSSL::ASN1::Set([
OpenSSL::ASN1::UTF8String("abc123")
])
attr1 = OpenSSL::X509::Attribute.new("challengePassword", val1)
attr2 = OpenSSL::X509::Attribute.new("challengePassword", val1)
ef = OpenSSL::X509::ExtensionFactory.new
val2 = OpenSSL::ASN1::Set.new([OpenSSL::ASN1::Sequence.new([
ef.create_extension("keyUsage", "keyCertSign", true)
])])
attr3 = OpenSSL::X509::Attribute.new("extReq", val2)

assert_equal false, attr1 == 12345
assert_equal true, attr1 == attr2
assert_equal false, attr1 == attr3
end
end

end
14 changes: 14 additions & 0 deletions test/test_x509cert.rb
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,20 @@ def test_read_from_file
}
end

def test_eq
cacert = issue_cert(@ca, @rsa1024, 1, [], nil, nil)
cert1 = issue_cert(@ee1, @rsa2048, 2, [], cacert, @rsa1024)
cert2 = issue_cert(@ee1, @rsa2048, 2, [], cacert, @rsa1024)
cert3 = issue_cert(@ee1, @rsa2048, 3, [], cacert, @rsa1024)
cert4 = issue_cert(@ee1, @rsa2048, 2, [], cacert, @rsa1024, digest: "sha512")

assert_equal false, cert1 == 12345
assert_equal true, cert1 == cert2
assert_equal false, cert1 == cert3
assert_equal false, cert1 == cert4
assert_equal false, cert3 == cert4
end

private

def certificate_error_returns_false
Expand Down
50 changes: 50 additions & 0 deletions test/test_x509crl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,56 @@ def test_sign_and_verify
assert_equal(false, crl.verify(@dsa512))
end

def test_revoked_to_der
# revokedCertificates SEQUENCE OF SEQUENCE {
# userCertificate CertificateSerialNumber,
# revocationDate Time,
# crlEntryExtensions Extensions OPTIONAL
# -- if present, version MUST be v2
# } OPTIONAL,

now = Time.utc(2000, 1, 1)
rev1 = OpenSSL::X509::Revoked.new
rev1.serial = 123
rev1.time = now
ext = OpenSSL::X509::Extension.new("CRLReason", OpenSSL::ASN1::Enumerated(1))
rev1.extensions = [ext]
asn1 = OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Integer(123),
OpenSSL::ASN1::UTCTime(now),
OpenSSL::ASN1::Sequence([ext.to_der])
])

assert_equal asn1.to_der, rev1.to_der
end

def test_eq
cacert = issue_cert(@ca, @rsa1024, 1, [], nil, nil)
crl1 = issue_crl([], 1, Time.now, Time.now + 3600, [], cacert, @rsa1024, "sha256")
rev1 = OpenSSL::X509::Revoked.new.tap { |rev|
rev.serial = 1
rev.time = Time.now
}
crl1.add_revoked(rev1)
crl2 = OpenSSL::X509::CRL.new(crl1.to_der)

# CRL
assert_equal false, crl1 == 12345
assert_equal true, crl1 == crl2
rev2 = OpenSSL::X509::Revoked.new.tap { |rev|
rev.serial = 2
rev.time = Time.now
}
crl2.add_revoked(rev2)
assert_equal false, crl1 == crl2

# Revoked
assert_equal false, rev1 == 12345
assert_equal true, rev1 == crl2.revoked[0]
assert_equal false, rev1 == crl2.revoked[1]
assert_equal true, rev2 == crl2.revoked[1]
end

private

def crl_error_returns_false
Expand Down
11 changes: 11 additions & 0 deletions test/test_x509ext.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,17 @@ def test_dup
assert_equal(@basic_constraints.to_der, ext.to_der)
assert_equal(ext.to_der, ext.dup.to_der)
end

def test_eq
ext1 = OpenSSL::X509::Extension.new(@basic_constraints.to_der)
ef = OpenSSL::X509::ExtensionFactory.new
ext2 = ef.create_extension("basicConstraints", "critical, CA:TRUE, pathlen:2")
ext3 = ef.create_extension("basicConstraints", "critical, CA:TRUE")

assert_equal false, ext1 == 12345
assert_equal true, ext1 == ext2
assert_equal false, ext1 == ext3
end
end

end
10 changes: 10 additions & 0 deletions test/test_x509req.rb
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,16 @@ def test_dup
assert_equal(req.to_der, req.dup.to_der)
end

def test_eq
req1 = issue_csr(0, @dn, @rsa1024, "sha1")
req2 = issue_csr(0, @dn, @rsa1024, "sha1")
req3 = issue_csr(0, @dn, @rsa1024, "sha256")

assert_equal false, req1 == 12345
assert_equal true, req1 == req2
assert_equal false, req1 == req3
end

private

def request_error_returns_false
Expand Down