Skip to content

Instantly share code, notes, and snippets.

@ng-pe
Last active July 17, 2023 09:12
Show Gist options
  • Save ng-pe/a88da92b7061bbaceff441ac8dca62e2 to your computer and use it in GitHub Desktop.
Save ng-pe/a88da92b7061bbaceff441ac8dca62e2 to your computer and use it in GitHub Desktop.
#!/usr/bin/perl
use strict;
use warnings;
use 5.008;
use IO::Socket::INET;
use Net::SSLeay qw/XN_FLAG_RFC2253 ASN1_STRFLGS_ESC_MSB/;
use Time::Piece;
use Data::Dumper;
print "PostgreSQL Certificate";
# get_cert_details() based on https://github.com/rurban/Net-SSLeay/blob/master/examples/x509_cert_details.pl Sample
sub get_cert_details {
my $x509 = shift;
my $rv = {};
my $flag_rfc22536_utf8 = (XN_FLAG_RFC2253) & (~ ASN1_STRFLGS_ESC_MSB);
die 'ERROR: $x509 is NULL, gonna quit' unless $x509;
warn "Info: dumping subject\n";
my $subj_name = Net::SSLeay::X509_get_subject_name($x509);
my $subj_count = Net::SSLeay::X509_NAME_entry_count($subj_name);
$rv->{subject}->{count} = $subj_count;
$rv->{subject}->{oneline} = Net::SSLeay::X509_NAME_oneline($subj_name);
$rv->{subject}->{print_rfc2253} = Net::SSLeay::X509_NAME_print_ex($subj_name);
$rv->{subject}->{print_rfc2253_utf8} = Net::SSLeay::X509_NAME_print_ex($subj_name, $flag_rfc22536_utf8);
$rv->{subject}->{print_rfc2253_utf8_decoded} = Net::SSLeay::X509_NAME_print_ex($subj_name, $flag_rfc22536_utf8, 1);
for my $i (0..$subj_count-1) {
my $entry = Net::SSLeay::X509_NAME_get_entry($subj_name, $i);
my $asn1_string = Net::SSLeay::X509_NAME_ENTRY_get_data($entry);
my $asn1_object = Net::SSLeay::X509_NAME_ENTRY_get_object($entry);
my $nid = Net::SSLeay::OBJ_obj2nid($asn1_object);
$rv->{subject}->{entries}->[$i] = {
oid => Net::SSLeay::OBJ_obj2txt($asn1_object,1),
data => Net::SSLeay::P_ASN1_STRING_get($asn1_string),
data_utf8_decoded => Net::SSLeay::P_ASN1_STRING_get($asn1_string, 1),
nid => ($nid>0) ? $nid : undef,
ln => ($nid>0) ? Net::SSLeay::OBJ_nid2ln($nid) : undef,
sn => ($nid>0) ? Net::SSLeay::OBJ_nid2sn($nid) : undef,
};
}
warn "Info: dumping issuer\n";
my $issuer_name = Net::SSLeay::X509_get_issuer_name($x509);
my $issuer_count = Net::SSLeay::X509_NAME_entry_count($issuer_name);
$rv->{issuer}->{count} = $issuer_count;
$rv->{issuer}->{oneline} = Net::SSLeay::X509_NAME_oneline($issuer_name);
$rv->{issuer}->{print_rfc2253} = Net::SSLeay::X509_NAME_print_ex($issuer_name);
$rv->{issuer}->{print_rfc2253_utf8} = Net::SSLeay::X509_NAME_print_ex($issuer_name, $flag_rfc22536_utf8);
$rv->{issuer}->{print_rfc2253_utf8_decoded} = Net::SSLeay::X509_NAME_print_ex($issuer_name, $flag_rfc22536_utf8, 1);
for my $i (0..$issuer_count-1) {
my $entry = Net::SSLeay::X509_NAME_get_entry($issuer_name, $i);
my $asn1_string = Net::SSLeay::X509_NAME_ENTRY_get_data($entry);
my $asn1_object = Net::SSLeay::X509_NAME_ENTRY_get_object($entry);
my $nid = Net::SSLeay::OBJ_obj2nid($asn1_object);
$rv->{issuer}->{entries}->[$i] = {
oid => Net::SSLeay::OBJ_obj2txt($asn1_object,1),
data => Net::SSLeay::P_ASN1_STRING_get($asn1_string),
data_utf8_decoded => Net::SSLeay::P_ASN1_STRING_get($asn1_string, 1),
nid => ($nid>0) ? $nid : undef,
ln => ($nid>0) ? Net::SSLeay::OBJ_nid2ln($nid) : undef,
sn => ($nid>0) ? Net::SSLeay::OBJ_nid2sn($nid) : undef,
};
}
warn "Info: dumping alternative names\n";
$rv->{subject}->{altnames} = [ Net::SSLeay::X509_get_subjectAltNames($x509) ];
#XXX-TODO maybe add a function for dumping issuerAltNames
#$rv->{issuer}->{altnames} = [ Net::SSLeay::X509_get_issuerAltNames($x509) ];
warn "Info: dumping hashes/fingerprints\n";
$rv->{hash}->{subject} = { dec=>Net::SSLeay::X509_subject_name_hash($x509), hex=>sprintf("%X",Net::SSLeay::X509_subject_name_hash($x509)) };
$rv->{hash}->{issuer} = { dec=>Net::SSLeay::X509_issuer_name_hash($x509), hex=>sprintf("%X",Net::SSLeay::X509_issuer_name_hash($x509)) };
$rv->{hash}->{issuer_and_serial} = { dec=>Net::SSLeay::X509_issuer_and_serial_hash($x509), hex=>sprintf("%X",Net::SSLeay::X509_issuer_and_serial_hash($x509)) };
$rv->{fingerprint}->{md5} = Net::SSLeay::X509_get_fingerprint($x509, "md5");
$rv->{fingerprint}->{sha1} = Net::SSLeay::X509_get_fingerprint($x509, "sha1");
my $sha1_digest = Net::SSLeay::EVP_get_digestbyname("sha1");
$rv->{digest_sha1}->{pubkey} = Net::SSLeay::X509_pubkey_digest($x509, $sha1_digest);
$rv->{digest_sha1}->{x509} = Net::SSLeay::X509_digest($x509, $sha1_digest);
warn "Info: dumping expiration\n";
$rv->{not_before} = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notBefore($x509));
$rv->{not_after} = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notAfter($x509));
warn "Info: dumping serial number\n";
my $ai = Net::SSLeay::X509_get_serialNumber($x509);
$rv->{serial} = {
hex => Net::SSLeay::P_ASN1_INTEGER_get_hex($ai),
dec => Net::SSLeay::P_ASN1_INTEGER_get_dec($ai),
long => Net::SSLeay::ASN1_INTEGER_get($ai),
};
$rv->{version} = Net::SSLeay::X509_get_version($x509);
warn "Info: dumping extensions\n";
my $ext_count = Net::SSLeay::X509_get_ext_count($x509);
$rv->{extensions}->{count} = $ext_count;
for my $i (0..$ext_count-1) {
my $ext = Net::SSLeay::X509_get_ext($x509,$i);
my $asn1_string = Net::SSLeay::X509_EXTENSION_get_data($ext);
my $asn1_object = Net::SSLeay::X509_EXTENSION_get_object($ext);
my $nid = Net::SSLeay::OBJ_obj2nid($asn1_object);
$rv->{extensions}->{entries}->[$i] = {
critical => Net::SSLeay::X509_EXTENSION_get_critical($ext),
oid => Net::SSLeay::OBJ_obj2txt($asn1_object,1),
nid => ($nid>0) ? $nid : undef,
ln => ($nid>0) ? Net::SSLeay::OBJ_nid2ln($nid) : undef,
sn => ($nid>0) ? Net::SSLeay::OBJ_nid2sn($nid) : undef,
data => Net::SSLeay::X509V3_EXT_print($ext),
};
}
warn "Info: dumping CDP\n";
$rv->{cdp} = [ Net::SSLeay::P_X509_get_crl_distribution_points($x509) ];
warn "Info: dumping extended key usage\n";
$rv->{extkeyusage} = {
oid => [ Net::SSLeay::P_X509_get_ext_key_usage($x509,0) ],
nid => [ Net::SSLeay::P_X509_get_ext_key_usage($x509,1) ],
sn => [ Net::SSLeay::P_X509_get_ext_key_usage($x509,2) ],
ln => [ Net::SSLeay::P_X509_get_ext_key_usage($x509,3) ],
};
warn "Info: dumping key usage\n";
$rv->{keyusage} = [ Net::SSLeay::P_X509_get_key_usage($x509) ];
warn "Info: dumping netscape cert type\n";
$rv->{ns_cert_type} = [ Net::SSLeay::P_X509_get_netscape_cert_type($x509) ];
warn "Info: dumping other info\n";
$rv->{certificate_type} = Net::SSLeay::X509_certificate_type($x509);
$rv->{signature_alg} = Net::SSLeay::OBJ_obj2txt(Net::SSLeay::P_X509_get_signature_alg($x509));
$rv->{pubkey_alg} = Net::SSLeay::OBJ_obj2txt(Net::SSLeay::P_X509_get_pubkey_alg($x509));
$rv->{pubkey_size} = Net::SSLeay::EVP_PKEY_size(Net::SSLeay::X509_get_pubkey($x509));
$rv->{pubkey_bits} = Net::SSLeay::EVP_PKEY_bits(Net::SSLeay::X509_get_pubkey($x509));
$rv->{pubkey_id} = Net::SSLeay::EVP_PKEY_id(Net::SSLeay::X509_get_pubkey($x509));
return $rv;
}
sub dump_details {
my ($data, $comment) = @_;
print "\n";
eval { require Data::Dump };
if (!$@) {
# Data::Dump creates nicer output
print "# $comment\n";
print "# hashref dumped via Data::Dump\n";
$Data::Dump::TRY_BASE64 = 0 if $Data::Dump::TRY_BASE64;
print Data::Dump::pp($data);
}
else {
print "# $comment\n";
print "# hashref dumped via Data::Dumper\n";
print Dumper($data);
}
print "\n";
}
sub check_tlscert {
# Create socket
my $cc = IO::Socket::INET->new(
PeerAddr => "127.0.0.1",
PeerPort => 5432,
Proto => 'tcp'
) or die "Failed to create socket: $!\n";
my $payload = pack('C*', 0, 0, 0, 8, 4, 210, 22, 47);
$cc->send($payload);
my $resp = '';
$cc->recv($resp, 1);
if ($resp eq 'S') {
print "Resquest StartTLS : OK\n";
} else {
print "Resquest StartTLS : PostgreSQL refuse start SSL! (not available or activate feature)\n";
}
# Create SSL Wrap on Socket
my $ctx = Net::SSLeay::CTX_new() or die "Failed to create SSL context: $!\n";
my $ssl = Net::SSLeay::new($ctx);
Net::SSLeay::set_fd($ssl, fileno($cc));
Net::SSLeay::connect($ssl);
print "Info -> Actual Cipher is :`" . Net::SSLeay::get_cipher($ssl) . "'\n";
my $x509 = Net::SSLeay::get_peer_certificate($ssl);
my $cert_details = get_cert_details($x509);
dump_details($cert_details, "");
# Close SSL and socket properly :
my $sslshutdown = Net::SSLeay::shutdown($ssl);
Net::SSLeay::free($ssl);
Net::SSLeay::CTX_free ($ctx);
close $cc;
}
check_tlscert();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment