mirror of
https://github.com/pocoproject/poco.git
synced 2025-04-26 18:11:29 +02:00
add X509 version, serialNumber and signatureAlgorithm
This commit is contained in:
parent
4c4de6b7fb
commit
210bc6d30c
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
include $(POCO_BASE)/build/rules/global
|
include $(POCO_BASE)/build/rules/global
|
||||||
|
|
||||||
|
include $(POCO_BASE)/build/script/openssl_ver
|
||||||
|
|
||||||
SYSLIBS += -lssl -lcrypto
|
SYSLIBS += -lssl -lcrypto
|
||||||
|
|
||||||
objects = Cipher CipherFactory CipherImpl CipherKey CipherKeyImpl \
|
objects = Cipher CipherFactory CipherImpl CipherKey CipherKeyImpl \
|
||||||
|
@ -83,6 +83,13 @@ public:
|
|||||||
~X509Certificate();
|
~X509Certificate();
|
||||||
/// Destroys the X509Certificate.
|
/// Destroys the X509Certificate.
|
||||||
|
|
||||||
|
long version() const;
|
||||||
|
/// Returns the version of the certificate.
|
||||||
|
|
||||||
|
const std::string& serialNumber() const;
|
||||||
|
/// Returns the certificate serial number as a
|
||||||
|
/// string in decimal encoding.
|
||||||
|
|
||||||
const std::string& issuerName() const;
|
const std::string& issuerName() const;
|
||||||
/// Returns the certificate issuer's distinguished name.
|
/// Returns the certificate issuer's distinguished name.
|
||||||
|
|
||||||
@ -144,6 +151,9 @@ public:
|
|||||||
const X509* certificate() const;
|
const X509* certificate() const;
|
||||||
/// Returns the underlying OpenSSL certificate.
|
/// Returns the underlying OpenSSL certificate.
|
||||||
|
|
||||||
|
std::string signatureAlgorithm() const;
|
||||||
|
/// Returns the certificate signature algorithm long name.
|
||||||
|
|
||||||
void print(std::ostream& out) const;
|
void print(std::ostream& out) const;
|
||||||
/// Prints the certificate information to ostream.
|
/// Prints the certificate information to ostream.
|
||||||
|
|
||||||
@ -174,6 +184,7 @@ private:
|
|||||||
|
|
||||||
std::string _issuerName;
|
std::string _issuerName;
|
||||||
std::string _subjectName;
|
std::string _subjectName;
|
||||||
|
std::string _serialNumber;
|
||||||
X509* _pCert;
|
X509* _pCert;
|
||||||
OpenSSLInitializer _openSSLInitializer;
|
OpenSSLInitializer _openSSLInitializer;
|
||||||
};
|
};
|
||||||
@ -182,6 +193,22 @@ private:
|
|||||||
//
|
//
|
||||||
// inlines
|
// inlines
|
||||||
//
|
//
|
||||||
|
|
||||||
|
inline long X509Certificate::version() const
|
||||||
|
{
|
||||||
|
// This is defined by standards (X.509 et al) to be
|
||||||
|
// one less than the certificate version.
|
||||||
|
// So, eg. a version 3 certificate will return 2.
|
||||||
|
return X509_get_version(_pCert) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const std::string& X509Certificate::serialNumber() const
|
||||||
|
{
|
||||||
|
return _serialNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline const std::string& X509Certificate::issuerName() const
|
inline const std::string& X509Certificate::issuerName() const
|
||||||
{
|
{
|
||||||
return _issuerName;
|
return _issuerName;
|
||||||
|
@ -195,7 +195,7 @@ std::string ECKeyImpl::getCurveName(int nid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (-1 == nid) nid = pCurves[0].nid;
|
if (-1 == nid) nid = pCurves[0].nid;
|
||||||
int bufLen = 128;
|
const int bufLen = 128;
|
||||||
char buf[bufLen];
|
char buf[bufLen];
|
||||||
std::memset(buf, 0, bufLen);
|
std::memset(buf, 0, bufLen);
|
||||||
OBJ_obj2txt(buf, bufLen, OBJ_nid2obj(nid), 0);
|
OBJ_obj2txt(buf, bufLen, OBJ_nid2obj(nid), 0);
|
||||||
|
@ -22,7 +22,9 @@
|
|||||||
#if OPENSSL_VERSION_NUMBER >= 0x0907000L
|
#if OPENSSL_VERSION_NUMBER >= 0x0907000L
|
||||||
#include <openssl/conf.h>
|
#include <openssl/conf.h>
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||||
|
#pragma message (OPENSSL_VERSION_TEXT)
|
||||||
|
#endif
|
||||||
|
|
||||||
using Poco::RandomInputStream;
|
using Poco::RandomInputStream;
|
||||||
using Poco::Thread;
|
using Poco::Thread;
|
||||||
|
@ -77,6 +77,7 @@ X509Certificate::X509Certificate(X509* pCert, bool shared):
|
|||||||
X509Certificate::X509Certificate(const X509Certificate& cert):
|
X509Certificate::X509Certificate(const X509Certificate& cert):
|
||||||
_issuerName(cert._issuerName),
|
_issuerName(cert._issuerName),
|
||||||
_subjectName(cert._subjectName),
|
_subjectName(cert._subjectName),
|
||||||
|
_serialNumber(cert._serialNumber),
|
||||||
_pCert(cert._pCert)
|
_pCert(cert._pCert)
|
||||||
{
|
{
|
||||||
_pCert = X509_dup(_pCert);
|
_pCert = X509_dup(_pCert);
|
||||||
@ -96,6 +97,7 @@ void X509Certificate::swap(X509Certificate& cert)
|
|||||||
using std::swap;
|
using std::swap;
|
||||||
swap(cert._issuerName, _issuerName);
|
swap(cert._issuerName, _issuerName);
|
||||||
swap(cert._subjectName, _subjectName);
|
swap(cert._subjectName, _subjectName);
|
||||||
|
swap(cert._serialNumber, _serialNumber);
|
||||||
swap(cert._pCert, _pCert);
|
swap(cert._pCert, _pCert);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,6 +201,17 @@ void X509Certificate::init()
|
|||||||
_issuerName = buffer;
|
_issuerName = buffer;
|
||||||
X509_NAME_oneline(X509_get_subject_name(_pCert), buffer, sizeof(buffer));
|
X509_NAME_oneline(X509_get_subject_name(_pCert), buffer, sizeof(buffer));
|
||||||
_subjectName = buffer;
|
_subjectName = buffer;
|
||||||
|
BIGNUM* pBN = ASN1_INTEGER_to_BN(X509_get_serialNumber(const_cast<X509*>(_pCert)), 0);
|
||||||
|
if (pBN)
|
||||||
|
{
|
||||||
|
char* pSN = BN_bn2hex(pBN);
|
||||||
|
if (pSN)
|
||||||
|
{
|
||||||
|
_serialNumber = pSN;
|
||||||
|
OPENSSL_free(pSN);
|
||||||
|
}
|
||||||
|
BN_free(pBN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -296,6 +309,31 @@ bool X509Certificate::equals(const X509Certificate& otherCertificate) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string X509Certificate::signatureAlgorithm() const
|
||||||
|
{
|
||||||
|
int sigNID = NID_undef;
|
||||||
|
|
||||||
|
#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
|
||||||
|
sigNID = X509_get_signature_nid(_pCert);
|
||||||
|
#else
|
||||||
|
poco_check_ptr(_pCert->sig_alg);
|
||||||
|
sigNID = OBJ_obj2nid(_pCert->sig_alg->algorithm);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (sigNID != NID_undef)
|
||||||
|
{
|
||||||
|
const char* pAlgName = OBJ_nid2ln(sigNID);
|
||||||
|
if (pAlgName) return std::string(pAlgName);
|
||||||
|
else throw OpenSSLException(Poco::format("X509Certificate::"
|
||||||
|
"signatureAlgorithm(): OBJ_nid2ln(%d)", sigNID));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw NotFoundException("X509Certificate::signatureAlgorithm()");
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
X509Certificate::List X509Certificate::readPEM(const std::string& pemFileName)
|
X509Certificate::List X509Certificate::readPEM(const std::string& pemFileName)
|
||||||
{
|
{
|
||||||
List caCertList;
|
List caCertList;
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
include $(POCO_BASE)/build/rules/global
|
include $(POCO_BASE)/build/rules/global
|
||||||
|
|
||||||
|
include $(POCO_BASE)/build/script/openssl_ver
|
||||||
|
|
||||||
# Note: linking order is important, do not change it.
|
# Note: linking order is important, do not change it.
|
||||||
ifeq ($(POCO_CONFIG),FreeBSD)
|
ifeq ($(POCO_CONFIG),FreeBSD)
|
||||||
SYSLIBS += -lssl -lcrypto -lz
|
SYSLIBS += -lssl -lcrypto -lz
|
||||||
|
@ -102,7 +102,7 @@ void PKCS12ContainerTest::fullCert(const X509Certificate& x509)
|
|||||||
std::string organizationName(x509.subjectName(X509Certificate::NID_ORGANIZATION_NAME));
|
std::string organizationName(x509.subjectName(X509Certificate::NID_ORGANIZATION_NAME));
|
||||||
std::string organizationUnitName(x509.subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME));
|
std::string organizationUnitName(x509.subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME));
|
||||||
std::string emailAddress(x509.subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS));
|
std::string emailAddress(x509.subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS));
|
||||||
std::string serialNumber(x509.subjectName(X509Certificate::NID_SERIAL_NUMBER));
|
std::string serialNumber(x509.serialNumber());
|
||||||
|
|
||||||
assert (subjectName == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Server");
|
assert (subjectName == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Server");
|
||||||
assert (issuerName == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Intermediate CA v3");
|
assert (issuerName == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Intermediate CA v3");
|
||||||
@ -113,7 +113,9 @@ void PKCS12ContainerTest::fullCert(const X509Certificate& x509)
|
|||||||
assert (organizationName == "Crypto Vally");
|
assert (organizationName == "Crypto Vally");
|
||||||
assert (organizationUnitName.empty());
|
assert (organizationUnitName.empty());
|
||||||
assert (emailAddress.empty());
|
assert (emailAddress.empty());
|
||||||
assert (serialNumber.empty());
|
assert (serialNumber == "1000");
|
||||||
|
assert (x509.version() == 3);
|
||||||
|
assert (x509.signatureAlgorithm() == "sha256WithRSAEncryption");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -139,7 +141,9 @@ void PKCS12ContainerTest::fullList(const PKCS12Container::CAList& caList,
|
|||||||
assert (caList[certOrder[0]].subjectName(X509Certificate::NID_ORGANIZATION_NAME) == "Crypto Vally");
|
assert (caList[certOrder[0]].subjectName(X509Certificate::NID_ORGANIZATION_NAME) == "Crypto Vally");
|
||||||
assert (caList[certOrder[0]].subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME).empty());
|
assert (caList[certOrder[0]].subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME).empty());
|
||||||
assert (caList[certOrder[0]].subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS).empty());
|
assert (caList[certOrder[0]].subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS).empty());
|
||||||
assert (caList[certOrder[0]].subjectName(X509Certificate::NID_SERIAL_NUMBER).empty());
|
assert (caList[certOrder[0]].serialNumber() == "C3ECA1FCEAA16055");
|
||||||
|
assert (caList[certOrder[0]].version() == 3);
|
||||||
|
assert (caList[certOrder[0]].signatureAlgorithm() == "sha256WithRSAEncryption");
|
||||||
|
|
||||||
assert (caList[certOrder[1]].subjectName() == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Intermediate CA v3");
|
assert (caList[certOrder[1]].subjectName() == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Intermediate CA v3");
|
||||||
assert (caList[certOrder[1]].issuerName() == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Root CA v3");
|
assert (caList[certOrder[1]].issuerName() == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Root CA v3");
|
||||||
@ -150,7 +154,9 @@ void PKCS12ContainerTest::fullList(const PKCS12Container::CAList& caList,
|
|||||||
assert (caList[certOrder[1]].subjectName(X509Certificate::NID_ORGANIZATION_NAME) == "Crypto Vally");
|
assert (caList[certOrder[1]].subjectName(X509Certificate::NID_ORGANIZATION_NAME) == "Crypto Vally");
|
||||||
assert (caList[certOrder[1]].subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME).empty());
|
assert (caList[certOrder[1]].subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME).empty());
|
||||||
assert (caList[certOrder[1]].subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS).empty());
|
assert (caList[certOrder[1]].subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS).empty());
|
||||||
assert (caList[certOrder[1]].subjectName(X509Certificate::NID_SERIAL_NUMBER).empty());
|
assert (caList[certOrder[1]].serialNumber() == "1000");
|
||||||
|
assert (caList[certOrder[1]].version() == 3);
|
||||||
|
assert (caList[certOrder[1]].signatureAlgorithm() == "sha256WithRSAEncryption");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -208,7 +214,9 @@ void PKCS12ContainerTest::certsOnlyList(const PKCS12Container::CAList& caList,
|
|||||||
assert (caList[certOrder[0]].subjectName(X509Certificate::NID_ORGANIZATION_NAME) == "Let's Encrypt");
|
assert (caList[certOrder[0]].subjectName(X509Certificate::NID_ORGANIZATION_NAME) == "Let's Encrypt");
|
||||||
assert (caList[certOrder[0]].subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME).empty());
|
assert (caList[certOrder[0]].subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME).empty());
|
||||||
assert (caList[certOrder[0]].subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS).empty());
|
assert (caList[certOrder[0]].subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS).empty());
|
||||||
assert (caList[certOrder[0]].subjectName(X509Certificate::NID_SERIAL_NUMBER).empty());
|
assert (caList[certOrder[0]].serialNumber() == "D3B17226342332DCF40528512AEC9C6A");
|
||||||
|
assert (caList[certOrder[0]].version() == 3);
|
||||||
|
assert (caList[certOrder[0]].signatureAlgorithm() == "sha256WithRSAEncryption");
|
||||||
|
|
||||||
assert (caList[certOrder[1]].subjectName() == "/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3");
|
assert (caList[certOrder[1]].subjectName() == "/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3");
|
||||||
assert (caList[certOrder[1]].issuerName() == "/O=Digital Signature Trust Co./CN=DST Root CA X3");
|
assert (caList[certOrder[1]].issuerName() == "/O=Digital Signature Trust Co./CN=DST Root CA X3");
|
||||||
@ -219,7 +227,9 @@ void PKCS12ContainerTest::certsOnlyList(const PKCS12Container::CAList& caList,
|
|||||||
assert (caList[certOrder[1]].subjectName(X509Certificate::NID_ORGANIZATION_NAME) == "Let's Encrypt");
|
assert (caList[certOrder[1]].subjectName(X509Certificate::NID_ORGANIZATION_NAME) == "Let's Encrypt");
|
||||||
assert (caList[certOrder[1]].subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME).empty());
|
assert (caList[certOrder[1]].subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME).empty());
|
||||||
assert (caList[certOrder[1]].subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS).empty());
|
assert (caList[certOrder[1]].subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS).empty());
|
||||||
assert (caList[certOrder[1]].subjectName(X509Certificate::NID_SERIAL_NUMBER).empty());
|
assert (caList[certOrder[1]].serialNumber() == "0A0141420000015385736A0B85ECA708");
|
||||||
|
assert (caList[certOrder[1]].version() == 3);
|
||||||
|
assert (caList[certOrder[1]].signatureAlgorithm() == "sha256WithRSAEncryption");
|
||||||
|
|
||||||
assert (caList[certOrder[2]].subjectName() == "/C=US/O=Internet Security Research Group/CN=ISRG Root X1");
|
assert (caList[certOrder[2]].subjectName() == "/C=US/O=Internet Security Research Group/CN=ISRG Root X1");
|
||||||
assert (caList[certOrder[2]].issuerName() == "/C=US/O=Internet Security Research Group/CN=ISRG Root X1");
|
assert (caList[certOrder[2]].issuerName() == "/C=US/O=Internet Security Research Group/CN=ISRG Root X1");
|
||||||
@ -230,7 +240,9 @@ void PKCS12ContainerTest::certsOnlyList(const PKCS12Container::CAList& caList,
|
|||||||
assert (caList[certOrder[2]].subjectName(X509Certificate::NID_ORGANIZATION_NAME) == "Internet Security Research Group");
|
assert (caList[certOrder[2]].subjectName(X509Certificate::NID_ORGANIZATION_NAME) == "Internet Security Research Group");
|
||||||
assert (caList[certOrder[2]].subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME).empty());
|
assert (caList[certOrder[2]].subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME).empty());
|
||||||
assert (caList[certOrder[2]].subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS).empty());
|
assert (caList[certOrder[2]].subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS).empty());
|
||||||
assert (caList[certOrder[2]].subjectName(X509Certificate::NID_SERIAL_NUMBER).empty());
|
assert (caList[certOrder[2]].serialNumber() == "8210CFB0D240E3594463E0BB63828B00");
|
||||||
|
assert (caList[certOrder[2]].version() == 3);
|
||||||
|
assert (caList[certOrder[2]].signatureAlgorithm() == "sha256WithRSAEncryption");
|
||||||
|
|
||||||
assert (caList[certOrder[3]].subjectName() == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Root CA v3");
|
assert (caList[certOrder[3]].subjectName() == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Root CA v3");
|
||||||
assert (caList[certOrder[3]].issuerName() == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Root CA v3");
|
assert (caList[certOrder[3]].issuerName() == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Root CA v3");
|
||||||
@ -241,7 +253,9 @@ void PKCS12ContainerTest::certsOnlyList(const PKCS12Container::CAList& caList,
|
|||||||
assert (caList[certOrder[3]].subjectName(X509Certificate::NID_ORGANIZATION_NAME) == "Crypto Vally");
|
assert (caList[certOrder[3]].subjectName(X509Certificate::NID_ORGANIZATION_NAME) == "Crypto Vally");
|
||||||
assert (caList[certOrder[3]].subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME).empty());
|
assert (caList[certOrder[3]].subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME).empty());
|
||||||
assert (caList[certOrder[3]].subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS).empty());
|
assert (caList[certOrder[3]].subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS).empty());
|
||||||
assert (caList[certOrder[3]].subjectName(X509Certificate::NID_SERIAL_NUMBER).empty());
|
assert (caList[certOrder[3]].serialNumber() == "C3ECA1FCEAA16055");
|
||||||
|
assert (caList[certOrder[3]].version() == 3);
|
||||||
|
assert (caList[certOrder[3]].signatureAlgorithm() == "sha256WithRSAEncryption");
|
||||||
|
|
||||||
assert (caList[certOrder[4]].subjectName() == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Intermediate CA v3");
|
assert (caList[certOrder[4]].subjectName() == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Intermediate CA v3");
|
||||||
assert (caList[certOrder[4]].issuerName() == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Root CA v3");
|
assert (caList[certOrder[4]].issuerName() == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Root CA v3");
|
||||||
@ -252,7 +266,9 @@ void PKCS12ContainerTest::certsOnlyList(const PKCS12Container::CAList& caList,
|
|||||||
assert (caList[certOrder[4]].subjectName(X509Certificate::NID_ORGANIZATION_NAME) == "Crypto Vally");
|
assert (caList[certOrder[4]].subjectName(X509Certificate::NID_ORGANIZATION_NAME) == "Crypto Vally");
|
||||||
assert (caList[certOrder[4]].subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME).empty());
|
assert (caList[certOrder[4]].subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME).empty());
|
||||||
assert (caList[certOrder[4]].subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS).empty());
|
assert (caList[certOrder[4]].subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS).empty());
|
||||||
assert (caList[certOrder[4]].subjectName(X509Certificate::NID_SERIAL_NUMBER).empty());
|
assert (caList[certOrder[4]].serialNumber()== "1000");
|
||||||
|
assert (caList[certOrder[4]].version() == 3);
|
||||||
|
assert (caList[certOrder[4]].signatureAlgorithm() == "sha256WithRSAEncryption");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
2
build/script/openssl_ver
Normal file
2
build/script/openssl_ver
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
which_openssl := $(shell which openssl)
|
||||||
|
$(info $(shell $(which_openssl) version -a))
|
Loading…
x
Reference in New Issue
Block a user