提交 bd789dff 编写于 作者: D Daniel P. Berrange

Add a test case for certificate validation

This test case checks certification validation rules for

 - Basic constraints
 - Key purpose
 - Key usage
 - Start/expiry times

It checks initial context creation sanity checks, and live
session validation
上级 07f9b6f0
......@@ -668,7 +668,7 @@ exclude_file_name_regexp--sc_avoid_strcase = ^tools/virsh\.c$$
_src1=libvirt|fdstream|qemu/qemu_monitor|util/(command|util)|xen/xend_internal|rpc/virnetsocket
exclude_file_name_regexp--sc_avoid_write = \
^(src/($(_src1))|daemon/libvirtd|tools/console)\.c$$
^(src/($(_src1))|daemon/libvirtd|tools/console|tests/virnettlscontexttest)\.c$$
exclude_file_name_regexp--sc_bindtextdomain = ^(tests|examples)/
......
......@@ -34,6 +34,7 @@ utiltest
virbuftest
virnetmessagetest
virnetsockettest
virnettlscontexttest
virshtest
vmx2xmltest
xencapstest
......
......@@ -85,7 +85,7 @@ check_PROGRAMS = virshtest conftest sockettest \
nodeinfotest qparamtest virbuftest \
commandtest commandhelper seclabeltest \
hashtest virnetmessagetest virnetsockettest ssh \
utiltest
utiltest virnettlscontexttest
# This is a fake SSH we use from virnetsockettest
ssh_SOURCES = ssh.c
......@@ -202,6 +202,7 @@ TESTS = virshtest \
hashtest \
virnetmessagetest \
virnetsockettest \
virnettlscontexttest \
utiltest \
$(test_scripts)
......@@ -452,6 +453,11 @@ virnetsockettest_SOURCES = \
virnetsockettest_CFLAGS = -Dabs_builddir="\"$(abs_builddir)\"" $(AM_CFLAGS)
virnetsockettest_LDADD = ../src/libvirt-net-rpc.la $(LDADDS)
virnettlscontexttest_SOURCES = \
virnettlscontexttest.c testutils.h testutils.c pkix_asn1_tab.c
virnettlscontexttest_CFLAGS = -Dabs_builddir="\"$(abs_builddir)\"" $(AM_CFLAGS)
virnettlscontexttest_LDADD = ../src/libvirt-net-rpc.la $(LDADDS) -ltasn1
seclabeltest_SOURCES = \
seclabeltest.c
......
/*
* This file comes from gnutls, licensed under the GPLv3+
*/
#include <config.h>
#include <libtasn1.h>
const ASN1_ARRAY_TYPE pkix_asn1_tab[] = {
{ "PKIX1", 536875024, NULL },
{ NULL, 1073741836, NULL },
{ "id-pkix", 1879048204, NULL },
{ "iso", 1073741825, "1"},
{ "identified-organization", 1073741825, "3"},
{ "dod", 1073741825, "6"},
{ "internet", 1073741825, "1"},
{ "security", 1073741825, "5"},
{ "mechanisms", 1073741825, "5"},
{ "pkix", 1, "7"},
{ "AuthorityKeyIdentifier", 1610612741, NULL },
{ "keyIdentifier", 1610637314, "KeyIdentifier"},
{ NULL, 4104, "0"},
{ "authorityCertIssuer", 1610637314, "GeneralNames"},
{ NULL, 4104, "1"},
{ "authorityCertSerialNumber", 536895490, "CertificateSerialNumber"},
{ NULL, 4104, "2"},
{ "KeyIdentifier", 1073741831, NULL },
{ "SubjectKeyIdentifier", 1073741826, "KeyIdentifier"},
{ "KeyUsage", 1073741830, NULL },
{ "DirectoryString", 1610612754, NULL },
{ "teletexString", 1612709890, "TeletexString"},
{ "MAX", 524298, "1"},
{ "printableString", 1612709890, "PrintableString"},
{ "MAX", 524298, "1"},
{ "universalString", 1612709890, "UniversalString"},
{ "MAX", 524298, "1"},
{ "utf8String", 1612709890, "UTF8String"},
{ "MAX", 524298, "1"},
{ "bmpString", 1612709890, "BMPString"},
{ "MAX", 524298, "1"},
{ "ia5String", 538968066, "IA5String"},
{ "MAX", 524298, "1"},
{ "SubjectAltName", 1073741826, "GeneralNames"},
{ "GeneralNames", 1612709899, NULL },
{ "MAX", 1074266122, "1"},
{ NULL, 2, "GeneralName"},
{ "GeneralName", 1610612754, NULL },
{ "otherName", 1610620930, "AnotherName"},
{ NULL, 4104, "0"},
{ "rfc822Name", 1610620930, "IA5String"},
{ NULL, 4104, "1"},
{ "dNSName", 1610620930, "IA5String"},
{ NULL, 4104, "2"},
{ "x400Address", 1610620941, NULL },
{ NULL, 4104, "3"},
{ "directoryName", 1610620930, "RDNSequence"},
{ NULL, 2056, "4"},
{ "ediPartyName", 1610620941, NULL },
{ NULL, 4104, "5"},
{ "uniformResourceIdentifier", 1610620930, "IA5String"},
{ NULL, 4104, "6"},
{ "iPAddress", 1610620935, NULL },
{ NULL, 4104, "7"},
{ "registeredID", 536879116, NULL },
{ NULL, 4104, "8"},
{ "AnotherName", 1610612741, NULL },
{ "type-id", 1073741836, NULL },
{ "value", 541073421, NULL },
{ NULL, 1073743880, "0"},
{ "type-id", 1, NULL },
{ "IssuerAltName", 1073741826, "GeneralNames"},
{ "BasicConstraints", 1610612741, NULL },
{ "cA", 1610645508, NULL },
{ NULL, 131081, NULL },
{ "pathLenConstraint", 537411587, NULL },
{ "0", 10, "MAX"},
{ "CRLDistributionPoints", 1612709899, NULL },
{ "MAX", 1074266122, "1"},
{ NULL, 2, "DistributionPoint"},
{ "DistributionPoint", 1610612741, NULL },
{ "distributionPoint", 1610637314, "DistributionPointName"},
{ NULL, 2056, "0"},
{ "reasons", 1610637314, "ReasonFlags"},
{ NULL, 4104, "1"},
{ "cRLIssuer", 536895490, "GeneralNames"},
{ NULL, 4104, "2"},
{ "DistributionPointName", 1610612754, NULL },
{ "fullName", 1610620930, "GeneralNames"},
{ NULL, 4104, "0"},
{ "nameRelativeToCRLIssuer", 536879106, "RelativeDistinguishedName"},
{ NULL, 4104, "1"},
{ "ReasonFlags", 1073741830, NULL },
{ "ExtKeyUsageSyntax", 1612709899, NULL },
{ "MAX", 1074266122, "1"},
{ NULL, 2, "KeyPurposeId"},
{ "KeyPurposeId", 1073741836, NULL },
{ "CRLNumber", 1611137027, NULL },
{ "0", 10, "MAX"},
{ "CertificateIssuer", 1073741826, "GeneralNames"},
{ "NumericString", 1610620935, NULL },
{ NULL, 4360, "18"},
{ "IA5String", 1610620935, NULL },
{ NULL, 4360, "22"},
{ "TeletexString", 1610620935, NULL },
{ NULL, 4360, "20"},
{ "PrintableString", 1610620935, NULL },
{ NULL, 4360, "19"},
{ "UniversalString", 1610620935, NULL },
{ NULL, 4360, "28"},
{ "BMPString", 1610620935, NULL },
{ NULL, 4360, "30"},
{ "UTF8String", 1610620935, NULL },
{ NULL, 4360, "12"},
{ "Attribute", 1610612741, NULL },
{ "type", 1073741826, "AttributeType"},
{ "values", 536870927, NULL },
{ NULL, 2, "AttributeValue"},
{ "AttributeType", 1073741836, NULL },
{ "AttributeValue", 1614807053, NULL },
{ "type", 1, NULL },
{ "AttributeTypeAndValue", 1610612741, NULL },
{ "type", 1073741826, "AttributeType"},
{ "value", 2, "AttributeValue"},
{ "id-at", 1879048204, NULL },
{ "joint-iso-ccitt", 1073741825, "2"},
{ "ds", 1073741825, "5"},
{ NULL, 1, "4"},
{ "id-at-initials", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-at"},
{ NULL, 1, "43"},
{ "X520initials", 1073741826, "DirectoryString"},
{ "id-at-generationQualifier", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-at"},
{ NULL, 1, "44"},
{ "X520generationQualifier", 1073741826, "DirectoryString"},
{ "id-at-surname", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-at"},
{ NULL, 1, "4"},
{ "X520surName", 1073741826, "DirectoryString"},
{ "id-at-givenName", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-at"},
{ NULL, 1, "42"},
{ "X520givenName", 1073741826, "DirectoryString"},
{ "id-at-name", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-at"},
{ NULL, 1, "41"},
{ "X520name", 1073741826, "DirectoryString"},
{ "id-at-commonName", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-at"},
{ NULL, 1, "3"},
{ "X520CommonName", 1073741826, "DirectoryString"},
{ "id-at-localityName", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-at"},
{ NULL, 1, "7"},
{ "X520LocalityName", 1073741826, "DirectoryString"},
{ "id-at-stateOrProvinceName", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-at"},
{ NULL, 1, "8"},
{ "X520StateOrProvinceName", 1073741826, "DirectoryString"},
{ "id-at-organizationName", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-at"},
{ NULL, 1, "10"},
{ "X520OrganizationName", 1073741826, "DirectoryString"},
{ "id-at-organizationalUnitName", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-at"},
{ NULL, 1, "11"},
{ "X520OrganizationalUnitName", 1073741826, "DirectoryString"},
{ "id-at-title", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-at"},
{ NULL, 1, "12"},
{ "X520Title", 1073741826, "DirectoryString"},
{ "id-at-description", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-at"},
{ NULL, 1, "13"},
{ "X520Description", 1073741826, "DirectoryString"},
{ "id-at-dnQualifier", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-at"},
{ NULL, 1, "46"},
{ "X520dnQualifier", 1073741826, "PrintableString"},
{ "id-at-countryName", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-at"},
{ NULL, 1, "6"},
{ "X520countryName", 1612709890, "PrintableString"},
{ NULL, 1048586, "2"},
{ "id-at-serialNumber", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-at"},
{ NULL, 1, "5"},
{ "X520serialNumber", 1073741826, "PrintableString"},
{ "id-at-telephoneNumber", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-at"},
{ NULL, 1, "20"},
{ "X520telephoneNumber", 1073741826, "PrintableString"},
{ "id-at-facsimileTelephoneNumber", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-at"},
{ NULL, 1, "23"},
{ "X520facsimileTelephoneNumber", 1073741826, "PrintableString"},
{ "id-at-pseudonym", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-at"},
{ NULL, 1, "65"},
{ "X520pseudonym", 1073741826, "DirectoryString"},
{ "id-at-name", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-at"},
{ NULL, 1, "41"},
{ "X520name", 1073741826, "DirectoryString"},
{ "id-at-streetAddress", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-at"},
{ NULL, 1, "9"},
{ "X520streetAddress", 1073741826, "DirectoryString"},
{ "id-at-postalAddress", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-at"},
{ NULL, 1, "16"},
{ "X520postalAddress", 1073741826, "PostalAddress"},
{ "PostalAddress", 1610612747, NULL },
{ NULL, 2, "DirectoryString"},
{ "id-at-postalCode", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-at"},
{ NULL, 1, "17"},
{ "X520postalCode", 1073741826, "DirectoryString"},
{ "emailAddress", 1880096780, "AttributeType"},
{ "iso", 1073741825, "1"},
{ "member-body", 1073741825, "2"},
{ "us", 1073741825, "840"},
{ "rsadsi", 1073741825, "113549"},
{ "pkcs", 1073741825, "1"},
{ NULL, 1073741825, "9"},
{ NULL, 1, "1"},
{ "Pkcs9email", 1612709890, "IA5String"},
{ "ub-emailaddress-length", 524298, "1"},
{ "Name", 1610612754, NULL },
{ "rdnSequence", 2, "RDNSequence"},
{ "RDNSequence", 1610612747, NULL },
{ NULL, 2, "RelativeDistinguishedName"},
{ "DistinguishedName", 1073741826, "RDNSequence"},
{ "RelativeDistinguishedName", 1612709903, NULL },
{ "MAX", 1074266122, "1"},
{ NULL, 2, "AttributeTypeAndValue"},
{ "Certificate", 1610612741, NULL },
{ "tbsCertificate", 1073741826, "TBSCertificate"},
{ "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"},
{ "signature", 6, NULL },
{ "TBSCertificate", 1610612741, NULL },
{ "version", 1610653698, "Version"},
{ NULL, 1073741833, "v1"},
{ NULL, 2056, "0"},
{ "serialNumber", 1073741826, "CertificateSerialNumber"},
{ "signature", 1073741826, "AlgorithmIdentifier"},
{ "issuer", 1073741826, "Name"},
{ "validity", 1073741826, "Validity"},
{ "subject", 1073741826, "Name"},
{ "subjectPublicKeyInfo", 1073741826, "SubjectPublicKeyInfo"},
{ "issuerUniqueID", 1610637314, "UniqueIdentifier"},
{ NULL, 4104, "1"},
{ "subjectUniqueID", 1610637314, "UniqueIdentifier"},
{ NULL, 4104, "2"},
{ "extensions", 536895490, "Extensions"},
{ NULL, 2056, "3"},
{ "Version", 1610874883, NULL },
{ "v1", 1073741825, "0"},
{ "v2", 1073741825, "1"},
{ "v3", 1, "2"},
{ "CertificateSerialNumber", 1073741827, NULL },
{ "Validity", 1610612741, NULL },
{ "notBefore", 1073741826, "Time"},
{ "notAfter", 2, "Time"},
{ "Time", 1610612754, NULL },
{ "utcTime", 1090519057, NULL },
{ "generalTime", 8388625, NULL },
{ "UniqueIdentifier", 1073741830, NULL },
{ "SubjectPublicKeyInfo", 1610612741, NULL },
{ "algorithm", 1073741826, "AlgorithmIdentifier"},
{ "subjectPublicKey", 6, NULL },
{ "Extensions", 1612709899, NULL },
{ "MAX", 1074266122, "1"},
{ NULL, 2, "Extension"},
{ "Extension", 1610612741, NULL },
{ "extnID", 1073741836, NULL },
{ "critical", 1610645508, NULL },
{ NULL, 131081, NULL },
{ "extnValue", 7, NULL },
{ "CertificateList", 1610612741, NULL },
{ "tbsCertList", 1073741826, "TBSCertList"},
{ "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"},
{ "signature", 6, NULL },
{ "TBSCertList", 1610612741, NULL },
{ "version", 1073758210, "Version"},
{ "signature", 1073741826, "AlgorithmIdentifier"},
{ "issuer", 1073741826, "Name"},
{ "thisUpdate", 1073741826, "Time"},
{ "nextUpdate", 1073758210, "Time"},
{ "revokedCertificates", 1610629131, NULL },
{ NULL, 536870917, NULL },
{ "userCertificate", 1073741826, "CertificateSerialNumber"},
{ "revocationDate", 1073741826, "Time"},
{ "crlEntryExtensions", 16386, "Extensions"},
{ "crlExtensions", 536895490, "Extensions"},
{ NULL, 2056, "0"},
{ "AlgorithmIdentifier", 1610612741, NULL },
{ "algorithm", 1073741836, NULL },
{ "parameters", 541081613, NULL },
{ "algorithm", 1, NULL },
{ "Dss-Sig-Value", 1610612741, NULL },
{ "r", 1073741827, NULL },
{ "s", 3, NULL },
{ "DomainParameters", 1610612741, NULL },
{ "p", 1073741827, NULL },
{ "g", 1073741827, NULL },
{ "q", 1073741827, NULL },
{ "j", 1073758211, NULL },
{ "validationParms", 16386, "ValidationParms"},
{ "ValidationParms", 1610612741, NULL },
{ "seed", 1073741830, NULL },
{ "pgenCounter", 3, NULL },
{ "Dss-Parms", 1610612741, NULL },
{ "p", 1073741827, NULL },
{ "q", 1073741827, NULL },
{ "g", 3, NULL },
{ "CountryName", 1610620946, NULL },
{ NULL, 1073746952, "1"},
{ "x121-dcc-code", 1612709890, "NumericString"},
{ NULL, 1048586, "ub-country-name-numeric-length"},
{ "iso-3166-alpha2-code", 538968066, "PrintableString"},
{ NULL, 1048586, "ub-country-name-alpha-length"},
{ "OrganizationName", 1612709890, "PrintableString"},
{ "ub-organization-name-length", 524298, "1"},
{ "NumericUserIdentifier", 1612709890, "NumericString"},
{ "ub-numeric-user-id-length", 524298, "1"},
{ "OrganizationalUnitNames", 1612709899, NULL },
{ "ub-organizational-units", 1074266122, "1"},
{ NULL, 2, "OrganizationalUnitName"},
{ "OrganizationalUnitName", 1612709890, "PrintableString"},
{ "ub-organizational-unit-name-length", 524298, "1"},
{ "CommonName", 1073741826, "PrintableString"},
{ "pkcs-7-ContentInfo", 1610612741, NULL },
{ "contentType", 1073741826, "pkcs-7-ContentType"},
{ "content", 541073421, NULL },
{ NULL, 1073743880, "0"},
{ "contentType", 1, NULL },
{ "pkcs-7-DigestInfo", 1610612741, NULL },
{ "digestAlgorithm", 1073741826, "pkcs-7-DigestAlgorithmIdentifier"},
{ "digest", 2, "pkcs-7-Digest"},
{ "pkcs-7-Digest", 1073741831, NULL },
{ "pkcs-7-ContentType", 1073741836, NULL },
{ "pkcs-7-SignedData", 1610612741, NULL },
{ "version", 1073741826, "pkcs-7-CMSVersion"},
{ "digestAlgorithms", 1073741826, "pkcs-7-DigestAlgorithmIdentifiers"},
{ "encapContentInfo", 1073741826, "pkcs-7-EncapsulatedContentInfo"},
{ "certificates", 1610637314, "pkcs-7-CertificateSet"},
{ NULL, 4104, "0"},
{ "crls", 1610637314, "pkcs-7-CertificateRevocationLists"},
{ NULL, 4104, "1"},
{ "signerInfos", 2, "pkcs-7-SignerInfos"},
{ "pkcs-7-CMSVersion", 1610874883, NULL },
{ "v0", 1073741825, "0"},
{ "v1", 1073741825, "1"},
{ "v2", 1073741825, "2"},
{ "v3", 1073741825, "3"},
{ "v4", 1, "4"},
{ "pkcs-7-DigestAlgorithmIdentifiers", 1610612751, NULL },
{ NULL, 2, "pkcs-7-DigestAlgorithmIdentifier"},
{ "pkcs-7-DigestAlgorithmIdentifier", 1073741826, "AlgorithmIdentifier"},
{ "pkcs-7-EncapsulatedContentInfo", 1610612741, NULL },
{ "eContentType", 1073741826, "pkcs-7-ContentType"},
{ "eContent", 536895495, NULL },
{ NULL, 2056, "0"},
{ "pkcs-7-CertificateRevocationLists", 1610612751, NULL },
{ NULL, 13, NULL },
{ "pkcs-7-CertificateChoices", 1610612754, NULL },
{ "certificate", 13, NULL },
{ "pkcs-7-CertificateSet", 1610612751, NULL },
{ NULL, 2, "pkcs-7-CertificateChoices"},
{ "pkcs-7-SignerInfos", 1610612751, NULL },
{ NULL, 13, NULL },
{ "pkcs-10-CertificationRequestInfo", 1610612741, NULL },
{ "version", 1610874883, NULL },
{ "v1", 1, "0"},
{ "subject", 1073741826, "Name"},
{ "subjectPKInfo", 1073741826, "SubjectPublicKeyInfo"},
{ "attributes", 536879106, "Attributes"},
{ NULL, 4104, "0"},
{ "Attributes", 1610612751, NULL },
{ NULL, 2, "Attribute"},
{ "pkcs-10-CertificationRequest", 1610612741, NULL },
{ "certificationRequestInfo", 1073741826, "pkcs-10-CertificationRequestInfo"},
{ "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"},
{ "signature", 6, NULL },
{ "pkcs-9-at-challengePassword", 1879048204, NULL },
{ "iso", 1073741825, "1"},
{ "member-body", 1073741825, "2"},
{ "us", 1073741825, "840"},
{ "rsadsi", 1073741825, "113549"},
{ "pkcs", 1073741825, "1"},
{ NULL, 1073741825, "9"},
{ NULL, 1, "7"},
{ "pkcs-9-challengePassword", 1610612754, NULL },
{ "printableString", 1073741826, "PrintableString"},
{ "utf8String", 2, "UTF8String"},
{ "pkcs-9-at-localKeyId", 1879048204, NULL },
{ "iso", 1073741825, "1"},
{ "member-body", 1073741825, "2"},
{ "us", 1073741825, "840"},
{ "rsadsi", 1073741825, "113549"},
{ "pkcs", 1073741825, "1"},
{ NULL, 1073741825, "9"},
{ NULL, 1, "21"},
{ "pkcs-9-localKeyId", 1073741831, NULL },
{ "pkcs-9-at-friendlyName", 1879048204, NULL },
{ "iso", 1073741825, "1"},
{ "member-body", 1073741825, "2"},
{ "us", 1073741825, "840"},
{ "rsadsi", 1073741825, "113549"},
{ "pkcs", 1073741825, "1"},
{ NULL, 1073741825, "9"},
{ NULL, 1, "20"},
{ "pkcs-9-friendlyName", 1612709890, "BMPString"},
{ "255", 524298, "1"},
{ "pkcs-8-PrivateKeyInfo", 1610612741, NULL },
{ "version", 1073741826, "pkcs-8-Version"},
{ "privateKeyAlgorithm", 1073741826, "AlgorithmIdentifier"},
{ "privateKey", 1073741826, "pkcs-8-PrivateKey"},
{ "attributes", 536895490, "Attributes"},
{ NULL, 4104, "0"},
{ "pkcs-8-Version", 1610874883, NULL },
{ "v1", 1, "0"},
{ "pkcs-8-PrivateKey", 1073741831, NULL },
{ "pkcs-8-Attributes", 1610612751, NULL },
{ NULL, 2, "Attribute"},
{ "pkcs-8-EncryptedPrivateKeyInfo", 1610612741, NULL },
{ "encryptionAlgorithm", 1073741826, "AlgorithmIdentifier"},
{ "encryptedData", 2, "pkcs-8-EncryptedData"},
{ "pkcs-8-EncryptedData", 1073741831, NULL },
{ "pkcs-5-des-EDE3-CBC-params", 1612709895, NULL },
{ NULL, 1048586, "8"},
{ "pkcs-5-aes128-CBC-params", 1612709895, NULL },
{ NULL, 1048586, "16"},
{ "pkcs-5-aes192-CBC-params", 1612709895, NULL },
{ NULL, 1048586, "16"},
{ "pkcs-5-aes256-CBC-params", 1612709895, NULL },
{ NULL, 1048586, "16"},
{ "pkcs-5-PBES2-params", 1610612741, NULL },
{ "keyDerivationFunc", 1073741826, "AlgorithmIdentifier"},
{ "encryptionScheme", 2, "AlgorithmIdentifier"},
{ "pkcs-5-PBKDF2-params", 1610612741, NULL },
{ "salt", 1610612754, NULL },
{ "specified", 1073741831, NULL },
{ "otherSource", 2, "AlgorithmIdentifier"},
{ "iterationCount", 1611137027, NULL },
{ "1", 10, "MAX"},
{ "keyLength", 1611153411, NULL },
{ "1", 10, "MAX"},
{ "prf", 16386, "AlgorithmIdentifier"},
{ "pkcs-12-PFX", 1610612741, NULL },
{ "version", 1610874883, NULL },
{ "v3", 1, "3"},
{ "authSafe", 1073741826, "pkcs-7-ContentInfo"},
{ "macData", 16386, "pkcs-12-MacData"},
{ "pkcs-12-PbeParams", 1610612741, NULL },
{ "salt", 1073741831, NULL },
{ "iterations", 3, NULL },
{ "pkcs-12-MacData", 1610612741, NULL },
{ "mac", 1073741826, "pkcs-7-DigestInfo"},
{ "macSalt", 1073741831, NULL },
{ "iterations", 536903683, NULL },
{ NULL, 9, "1"},
{ "pkcs-12-AuthenticatedSafe", 1610612747, NULL },
{ NULL, 2, "pkcs-7-ContentInfo"},
{ "pkcs-12-SafeContents", 1610612747, NULL },
{ NULL, 2, "pkcs-12-SafeBag"},
{ "pkcs-12-SafeBag", 1610612741, NULL },
{ "bagId", 1073741836, NULL },
{ "bagValue", 1614815245, NULL },
{ NULL, 1073743880, "0"},
{ "badId", 1, NULL },
{ "bagAttributes", 536887311, NULL },
{ NULL, 2, "pkcs-12-PKCS12Attribute"},
{ "pkcs-12-KeyBag", 1073741826, "pkcs-8-PrivateKeyInfo"},
{ "pkcs-12-PKCS8ShroudedKeyBag", 1073741826, "pkcs-8-EncryptedPrivateKeyInfo"},
{ "pkcs-12-CertBag", 1610612741, NULL },
{ "certId", 1073741836, NULL },
{ "certValue", 541073421, NULL },
{ NULL, 1073743880, "0"},
{ "certId", 1, NULL },
{ "pkcs-12-CRLBag", 1610612741, NULL },
{ "crlId", 1073741836, NULL },
{ "crlValue", 541073421, NULL },
{ NULL, 1073743880, "0"},
{ "crlId", 1, NULL },
{ "pkcs-12-SecretBag", 1610612741, NULL },
{ "secretTypeId", 1073741836, NULL },
{ "secretValue", 541073421, NULL },
{ NULL, 1073743880, "0"},
{ "secretTypeId", 1, NULL },
{ "pkcs-12-PKCS12Attribute", 1073741826, "Attribute"},
{ "pkcs-7-Data", 1073741831, NULL },
{ "pkcs-7-EncryptedData", 1610612741, NULL },
{ "version", 1073741826, "pkcs-7-CMSVersion"},
{ "encryptedContentInfo", 1073741826, "pkcs-7-EncryptedContentInfo"},
{ "unprotectedAttrs", 536895490, "pkcs-7-UnprotectedAttributes"},
{ NULL, 4104, "1"},
{ "pkcs-7-EncryptedContentInfo", 1610612741, NULL },
{ "contentType", 1073741826, "pkcs-7-ContentType"},
{ "contentEncryptionAlgorithm", 1073741826, "pkcs-7-ContentEncryptionAlgorithmIdentifier"},
{ "encryptedContent", 536895490, "pkcs-7-EncryptedContent"},
{ NULL, 4104, "0"},
{ "pkcs-7-ContentEncryptionAlgorithmIdentifier", 1073741826, "AlgorithmIdentifier"},
{ "pkcs-7-EncryptedContent", 1073741831, NULL },
{ "pkcs-7-UnprotectedAttributes", 1612709903, NULL },
{ "MAX", 1074266122, "1"},
{ NULL, 2, "Attribute"},
{ "id-at-ldap-DC", 1880096780, "AttributeType"},
{ NULL, 1073741825, "0"},
{ NULL, 1073741825, "9"},
{ NULL, 1073741825, "2342"},
{ NULL, 1073741825, "19200300"},
{ NULL, 1073741825, "100"},
{ NULL, 1073741825, "1"},
{ NULL, 1, "25"},
{ "ldap-DC", 1073741826, "IA5String"},
{ "id-at-ldap-UID", 1880096780, "AttributeType"},
{ NULL, 1073741825, "0"},
{ NULL, 1073741825, "9"},
{ NULL, 1073741825, "2342"},
{ NULL, 1073741825, "19200300"},
{ NULL, 1073741825, "100"},
{ NULL, 1073741825, "1"},
{ NULL, 1, "1"},
{ "ldap-UID", 1073741826, "DirectoryString"},
{ "id-pda-dateOfBirth", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-pkix"},
{ NULL, 1073741825, "9"},
{ NULL, 1, "1"},
{ "DateOfBirth", 1082130449, NULL },
{ "id-pda-placeOfBirth", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-pkix"},
{ NULL, 1073741825, "9"},
{ NULL, 1, "2"},
{ "PlaceOfBirth", 1073741826, "DirectoryString"},
{ "id-pda-gender", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-pkix"},
{ NULL, 1073741825, "9"},
{ NULL, 1, "3"},
{ "Gender", 1612709890, "PrintableString"},
{ NULL, 1048586, "1"},
{ "id-pda-countryOfCitizenship", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-pkix"},
{ NULL, 1073741825, "9"},
{ NULL, 1, "4"},
{ "CountryOfCitizenship", 1612709890, "PrintableString"},
{ NULL, 1048586, "2"},
{ "id-pda-countryOfResidence", 1880096780, "AttributeType"},
{ NULL, 1073741825, "id-pkix"},
{ NULL, 1073741825, "9"},
{ NULL, 1, "5"},
{ "CountryOfResidence", 1612709890, "PrintableString"},
{ NULL, 1048586, "2"},
{ "ProxyCertInfo", 1610612741, NULL },
{ "pCPathLenConstraint", 1611153411, NULL },
{ "0", 10, "MAX"},
{ "proxyPolicy", 2, "ProxyPolicy"},
{ "ProxyPolicy", 1610612741, NULL },
{ "policyLanguage", 1073741836, NULL },
{ "policy", 16391, NULL },
{ "id-on-xmppAddr", 1879048204, NULL },
{ NULL, 1073741825, "id-pkix"},
{ NULL, 1073741825, "8"},
{ NULL, 1, "5"},
{ "XmppAddr", 2, "UTF8String"},
{ NULL, 0, NULL }
};
/*
* Copyright (C) 2011 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#include <config.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/socket.h>
#include "testutils.h"
#include "util.h"
#include "virterror_internal.h"
#include "memory.h"
#include "logging.h"
#include "virfile.h"
#include "command.h"
#include "network.h"
#ifndef WIN32
# include <libtasn1.h>
# include <gnutls/gnutls.h>
# include <gnutls/x509.h>
# include "gnutls_1_0_compat.h"
# include "rpc/virnettlscontext.h"
# define VIR_FROM_THIS VIR_FROM_RPC
const char *keyfile = abs_builddir "/virnettlscontexttest-key.pem";
/*
* These store some static data that is needed when
* encoding extensions in the x509 certs
*/
ASN1_TYPE pkix_asn1;
extern const ASN1_ARRAY_TYPE pkix_asn1_tab[];
/*
* To avoid consuming random entropy to generate keys,
* here's one we prepared earlier :-)
*/
gnutls_x509_privkey_t privkey;
# define PRIVATE_KEY \
"-----BEGIN PRIVATE KEY-----\n" \
"MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALVcr" \
"BL40Tm6yq88FBhJNw1aaoCjmtg0l4dWQZ/e9Fimx4ARxFpT+ji4FE" \
"Cgl9s/SGqC+1nvlkm9ViSo0j7MKDbnDB+VRHDvMAzQhA2X7e8M0n9" \
"rPolUY2lIVC83q0BBaOBkCj2RSmT2xTEbbC2xLukSrg2WP/ihVOxc" \
"kXRuyFtzAgMBAAECgYB7slBexDwXrtItAMIH6m/U+LUpNe0Xx48OL" \
"IOn4a4whNgO/o84uIwygUK27ZGFZT0kAGAk8CdF9hA6ArcbQ62s1H" \
"myxrUbF9/mrLsQw1NEqpuUk9Ay2Tx5U/wPx35S3W/X2AvR/ZpTnCn" \
"2q/7ym9fyiSoj86drD7BTvmKXlOnOwQJBAPOFMp4mMa9NGpGuEssO" \
"m3Uwbp6lhcP0cA9MK+iOmeANpoKWfBdk5O34VbmeXnGYWEkrnX+9J" \
"bM4wVhnnBWtgBMCQQC+qAEmvwcfhauERKYznMVUVksyeuhxhCe7EK" \
"mPh+U2+g0WwdKvGDgO0PPt1gq0ILEjspMDeMHVdTwkaVBo/uMhAkA" \
"Z5SsZyCP2aTOPFDypXRdI4eqRcjaEPOUBq27r3uYb/jeboVb2weLa" \
"L1MmVuHiIHoa5clswPdWVI2y0em2IGoDAkBPSp/v9VKJEZabk9Frd" \
"a+7u4fanrM9QrEjY3KhduslSilXZZSxrWjjAJPyPiqFb3M8XXA26W" \
"nz1KYGnqYKhLcBAkB7dt57n9xfrhDpuyVEv+Uv1D3VVAhZlsaZ5Pp" \
"dcrhrkJn2sa/+O8OKvdrPSeeu/N5WwYhJf61+CPoenMp7IFci\n" \
"-----END PRIVATE KEY-----\n"
/*
* This contains parameter about how to generate
* certificates.
*/
struct testTLSCertReq {
gnutls_x509_crt_t crt;
gnutls_x509_crt_t cacrt; /* If not set, then the cert will be self-signed */
const char *filename;
/* Identifying information */
const char *country;
const char *cn;
const char *altname1;
const char *altname2;
const char *ipaddr1;
const char *ipaddr2;
/* Basic constraints */
bool basicConstraintsEnable;
bool basicConstraintsCritical;
bool basicConstraintsIsCA;
/* Key usage */
bool keyUsageEnable;
bool keyUsageCritical;
int keyUsageValue;
/* Key purpose (aka Extended key usage) */
bool keyPurposeEnable;
bool keyPurposeCritical;
const char *keyPurposeOID1;
const char *keyPurposeOID2;
/* if zero, then the current time will be used */
time_t start;
time_t expire;
};
/*
* Turns an ASN1 object into a DER encoded byte array
*/
static void testTLSDerEncode(ASN1_TYPE src,
const char *src_name,
gnutls_datum_t * res)
{
int size;
char *data = NULL;
size = 0;
asn1_der_coding(src, src_name, NULL, &size, NULL);
if (VIR_ALLOC_N(data, size) < 0)
abort();
asn1_der_coding(src, src_name, data, &size, NULL);
res->data = (unsigned char *)data;
res->size = size;
}
/*
* This is a fairly lame x509 certificate generator.
*
* Do not copy/use this code for generating real certificates
* since it leaves out many things that you would want in
* certificates for real world usage.
*
* This is good enough only for doing tests of the libvirt
* TLS certificate code
*/
static void
testTLSGenerateCert(struct testTLSCertReq *req)
{
gnutls_x509_crt_t crt;
int err;
static char buffer[1024*1024];
size_t size = sizeof(buffer);
char serial[5] = { 1, 2, 3, 4, 0 };
gnutls_datum_t der = { (unsigned char *)buffer, size };
time_t start = req->start;
time_t expire = req->expire;
if (!start)
start = time(NULL);
if (!expire)
expire = time(NULL) + (60*60*24);
/*
* Prepare our new certificate object
*/
if ((err = gnutls_x509_crt_init(&crt)) < 0) {
VIR_WARN("Failed to initialize certificate %s", gnutls_strerror(err));
abort();
}
if ((err = gnutls_x509_crt_set_key(crt, privkey)) < 0) {
VIR_WARN("Failed to set certificate key %s", gnutls_strerror(err));
abort();
}
/*
* A v3 certificate is required in order to be able
* set any of the basic constraints, key purpose and
* key usage data
*/
gnutls_x509_crt_set_version(crt, 3);
if (req->country) {
if ((err = gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0,
req->country, strlen(req->country))) < 0) {
VIR_WARN("Failed to set certificate country name %s", gnutls_strerror(err));
abort();
}
}
if (req->cn) {
if ((err = gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COMMON_NAME, 0,
req->cn, strlen(req->cn))) < 0) {
VIR_WARN("Failed to set certificate common name %s", gnutls_strerror(err));
abort();
}
}
/*
* Setup the subject altnames, which are used
* for hostname checks in live sessions
*/
if (req->altname1) {
if ((err = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME,
req->altname1,
strlen(req->altname1),
GNUTLS_FSAN_APPEND))) {
VIR_WARN("Failed to set certificate alt name %s", gnutls_strerror(err));
abort();
}
}
if (req->altname2) {
if ((err = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME,
req->altname2,
strlen(req->altname2),
GNUTLS_FSAN_APPEND))) {
VIR_WARN("Failed to set certificate %s alt name", gnutls_strerror(err));
abort();
}
}
/*
* IP address need to be put into the cert in their
* raw byte form, not strings, hence this is a little
* more complicated
*/
if (req->ipaddr1) {
virSocketAddr addr;
char *data;
int len;
if (virSocketParseAddr(req->ipaddr1, &addr, 0) < 0) {
VIR_WARN("Cannot parse %s", req->ipaddr1);
abort();
}
if (addr.data.sa.sa_family == AF_INET) {
data = (char*)&addr.data.inet4.sin_addr;
len = 4;
} else {
data = (char*)&addr.data.inet6.sin6_addr;
len = 16;
}
if ((err = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_IPADDRESS,
data, len, GNUTLS_FSAN_APPEND))) {
VIR_WARN("Failed to set certificate alt name %s", gnutls_strerror(err));
abort();
}
}
if (req->ipaddr2) {
virSocketAddr addr;
char *data;
int len;
if (virSocketParseAddr(req->ipaddr2, &addr, 0) < 0) {
VIR_WARN("Cannot parse %s", req->ipaddr2);
abort();
}
if (addr.data.sa.sa_family == AF_INET) {
data = (char*)&addr.data.inet4.sin_addr;
len = 4;
} else {
data = (char*)&addr.data.inet6.sin6_addr;
len = 16;
}
if ((err = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_IPADDRESS,
data, len, GNUTLS_FSAN_APPEND))) {
VIR_WARN("Failed to set certificate alt name %s", gnutls_strerror(err));
abort();
}
}
/*
* Basic constraints are used to decide if the cert
* is for a CA or not. We can't use the convenient
* gnutls API for setting this, since it hardcodes
* the 'critical' field which we want control over
*/
if (req->basicConstraintsEnable) {
ASN1_TYPE ext = ASN1_TYPE_EMPTY;
asn1_create_element(pkix_asn1, "PKIX1.BasicConstraints", &ext);
asn1_write_value(ext, "cA", req->basicConstraintsIsCA ? "TRUE" : "FALSE", 1);
asn1_write_value(ext, "pathLenConstraint", NULL, 0);
testTLSDerEncode(ext, "", &der);
if ((err = gnutls_x509_crt_set_extension_by_oid(crt,
"2.5.29.19",
der.data,
der.size,
req->basicConstraintsCritical)) < 0) {
VIR_WARN("Failed to set certificate basic constraints %s", gnutls_strerror(err));
abort();
}
asn1_delete_structure(&ext);
VIR_FREE(der.data);
}
/*
* Next up the key usage extension. Again we can't
* use the gnutls API since it hardcodes the extension
* to be 'critical'
*/
if (req->keyUsageEnable) {
ASN1_TYPE ext = ASN1_TYPE_EMPTY;
char str[2];
str[0] = req->keyUsageValue & 0xff;
str[1] = (req->keyUsageValue >> 8) & 0xff;
asn1_create_element(pkix_asn1, "PKIX1.KeyUsage", &ext);
asn1_write_value(ext, "", str, 9);
testTLSDerEncode(ext, "", &der);
if ((err = gnutls_x509_crt_set_extension_by_oid(crt,
"2.5.29.15",
der.data,
der.size,
req->keyUsageCritical)) < 0) {
VIR_WARN("Failed to set certificate key usage %s", gnutls_strerror(err));
abort();
}
asn1_delete_structure(&ext);
VIR_FREE(der.data);
}
/*
* Finally the key purpose extension. This time
* gnutls has the opposite problem, always hardcoding
* it to be non-critical. So once again we have to
* set this the hard way building up ASN1 data ourselves
*/
if (req->keyPurposeEnable) {
ASN1_TYPE ext = ASN1_TYPE_EMPTY;
asn1_create_element(pkix_asn1, "PKIX1.ExtKeyUsageSyntax", &ext);
if (req->keyPurposeOID1) {
asn1_write_value(ext, "", "NEW", 1);
asn1_write_value(ext, "?LAST", req->keyPurposeOID1, 1);
}
if (req->keyPurposeOID2) {
asn1_write_value(ext, "", "NEW", 1);
asn1_write_value(ext, "?LAST", req->keyPurposeOID2, 1);
}
testTLSDerEncode(ext, "", &der);
if ((err = gnutls_x509_crt_set_extension_by_oid(crt,
"2.5.29.37",
der.data,
der.size,
req->keyPurposeCritical)) < 0) {
VIR_WARN("Failed to set certificate key purpose %s", gnutls_strerror(err));
abort();
}
asn1_delete_structure(&ext);
VIR_FREE(der.data);
}
/*
* Any old serial number will do, so lets pick 5
*/
if ((err = gnutls_x509_crt_set_serial(crt, serial, 5)) < 0) {
VIR_WARN("Failed to set certificate serial %s", gnutls_strerror(err));
abort();
}
if ((err = gnutls_x509_crt_set_activation_time(crt, start)) < 0) {
VIR_WARN("Failed to set certificate activation %s", gnutls_strerror(err));
abort();
}
if ((err = gnutls_x509_crt_set_expiration_time(crt, expire)) < 0) {
VIR_WARN("Failed to set certificate expiration %s", gnutls_strerror(err));
abort();
}
/*
* If no 'cart' is set then we are self signing
* the cert. This is done for CA certs
*/
if ((err = gnutls_x509_crt_sign(crt, req->cacrt ? req->cacrt : crt, privkey) < 0)) {
VIR_WARN("Failed to sign certificate %s", gnutls_strerror(err));
abort();
}
/*
* Finally write the new cert out to disk
*/
if ((err = gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, buffer, &size) < 0)) {
VIR_WARN("Failed to export certificate %s", gnutls_strerror(err));
abort();
}
if (virFileWriteStr(req->filename, buffer, 0600) < 0) {
VIR_WARN("Failed to write certificate %s %s", req->filename, gnutls_strerror(err));
abort();
}
req->crt = crt;
return;
}
/*
* This loads the private key we defined earlier
*/
static gnutls_x509_privkey_t testTLSLoadKey(void)
{
gnutls_x509_privkey_t key;
const gnutls_datum_t data = { (unsigned char *)PRIVATE_KEY, strlen(PRIVATE_KEY) };
gnutls_x509_privkey_init(&key);
gnutls_x509_privkey_import(key, &data, GNUTLS_X509_FMT_PEM);
return key;
}
struct testTLSContextData {
bool isServer;
struct testTLSCertReq careq;
struct testTLSCertReq certreq;
bool expectFail;
};
/*
* This tests sanity checking of our own certificates
*
* This code is done when libvirtd starts up, or before
* a libvirt client connects. The test is ensuring that
* the creation of virNetTLSContextPtr fails if we
* give bogus certs, or suceeds for good certs
*/
static int testTLSContextInit(const void *opaque)
{
struct testTLSContextData *data = (struct testTLSContextData *)opaque;
virNetTLSContextPtr ctxt = NULL;
int ret = -1;
testTLSGenerateCert(&data->careq);
data->certreq.cacrt = data->careq.crt;
testTLSGenerateCert(&data->certreq);
if (data->isServer) {
ctxt = virNetTLSContextNewServer(data->careq.filename,
NULL,
data->certreq.filename,
keyfile,
NULL,
true,
true);
} else {
ctxt = virNetTLSContextNewClient(data->careq.filename,
NULL,
data->certreq.filename,
keyfile,
true,
true);
}
if (ctxt) {
if (data->expectFail) {
VIR_WARN("Expected failure %s against %s",
data->careq.filename, data->certreq.filename);
goto cleanup;
}
} else {
virErrorPtr err = virGetLastError();
if (!data->expectFail) {
VIR_WARN("Unexpected failure %s against %s",
data->careq.filename, data->certreq.filename);
goto cleanup;
}
VIR_DEBUG("Got error %s", err ? err->message : "<unknown>");
}
ret = 0;
cleanup:
virNetTLSContextFree(ctxt);
gnutls_x509_crt_deinit(data->careq.crt);
gnutls_x509_crt_deinit(data->certreq.crt);
data->careq.crt = data->certreq.crt = NULL;
/* When troubleshooting this tests, we often want to leave the certs on disk */
if (getenv("VIRT_TEST_DEBUG_CERTS") == NULL) {
unlink(data->careq.filename);
unlink(data->certreq.filename);
}
return ret;
}
struct testTLSSessionData {
struct testTLSCertReq careq;
struct testTLSCertReq othercareq;
struct testTLSCertReq serverreq;
struct testTLSCertReq clientreq;
bool expectServerFail;
bool expectClientFail;
const char *hostname;
const char *const* wildcards;
};
static ssize_t testWrite(const char *buf, size_t len, void *opaque)
{
int *fd = opaque;
return write(*fd, buf, len);
}
static ssize_t testRead(char *buf, size_t len, void *opaque)
{
int *fd = opaque;
return read(*fd, buf, len);
}
/*
* This tests validation checking of peer certificates
*
* This is replicating the checks that are done for an
* active TLS session after handshake completes. To
* simulate that we create our TLS contexts, skipping
* sanity checks. When then get a socketpair, and
* initiate a TLS session across them. Finally do
* do actual cert validation tests
*/
static int testTLSSessionInit(const void *opaque)
{
struct testTLSSessionData *data = (struct testTLSSessionData *)opaque;
virNetTLSContextPtr clientCtxt = NULL;
virNetTLSContextPtr serverCtxt = NULL;
virNetTLSSessionPtr clientSess = NULL;
virNetTLSSessionPtr serverSess = NULL;
int ret = -1;
int channel[2];
bool clientShake = false;
bool serverShake = false;
/* We'll use this for our fake client-server connection */
if (socketpair(AF_UNIX, SOCK_STREAM, 0, channel) < 0)
abort();
/*
* We have an evil loop to do the handshake in a single
* thread, so we need these non-blocking to avoid deadlock
* of ourselves
*/
ignore_value(virSetNonBlock(channel[0]));
ignore_value(virSetNonBlock(channel[1]));
/* Generate all the certs we need for this test */
testTLSGenerateCert(&data->careq);
data->serverreq.cacrt = data->careq.crt;
testTLSGenerateCert(&data->serverreq);
if (data->othercareq.filename) {
testTLSGenerateCert(&data->othercareq);
data->clientreq.cacrt = data->othercareq.crt;
} else {
data->clientreq.cacrt = data->careq.crt;
}
testTLSGenerateCert(&data->clientreq);
/* We skip initial sanity checks here because we
* want to make sure that problems are being
* detected at the TLS session validation stage
*/
serverCtxt = virNetTLSContextNewServer(data->careq.filename,
NULL,
data->serverreq.filename,
keyfile,
data->wildcards,
false,
true);
clientCtxt = virNetTLSContextNewClient(data->othercareq.filename ?
data->othercareq.filename :
data->careq.filename,
NULL,
data->clientreq.filename,
keyfile,
false,
true);
if (!serverCtxt) {
VIR_WARN("Unexpected failure loading %s against %s",
data->careq.filename, data->serverreq.filename);
goto cleanup;
}
if (!clientCtxt) {
VIR_WARN("Unexpected failure loading %s against %s",
data->othercareq.filename ? data->othercareq.filename :
data->careq.filename, data->clientreq.filename);
goto cleanup;
}
/* Now the real part of the test, setup the sessions */
serverSess = virNetTLSSessionNew(serverCtxt, NULL);
clientSess = virNetTLSSessionNew(clientCtxt, data->hostname);
if (!serverSess) {
VIR_WARN("Unexpected failure using %s against %s",
data->careq.filename, data->serverreq.filename);
goto cleanup;
}
if (!clientSess) {
VIR_WARN("Unexpected failure using %s against %s",
data->othercareq.filename ? data->othercareq.filename :
data->careq.filename, data->clientreq.filename);
goto cleanup;
}
/* For handshake to work, we need to set the I/O callbacks
* to read/write over the socketpair
*/
virNetTLSSessionSetIOCallbacks(serverSess, testWrite, testRead, &channel[0]);
virNetTLSSessionSetIOCallbacks(clientSess, testWrite, testRead, &channel[1]);
/*
* Finally we loop around & around doing handshake on each
* session until we get an error, or the handshake completes.
* This relies on the socketpair being nonblocking to avoid
* deadlocking ourselves upon handshake
*/
do {
int rv;
if (!serverShake) {
rv = virNetTLSSessionHandshake(serverSess);
if (rv < 0)
goto cleanup;
if (rv == VIR_NET_TLS_HANDSHAKE_COMPLETE)
serverShake = true;
}
if (!clientShake) {
rv = virNetTLSSessionHandshake(clientSess);
if (rv < 0)
goto cleanup;
if (rv == VIR_NET_TLS_HANDSHAKE_COMPLETE)
serverShake = true;
}
} while (!clientShake && !serverShake);
/* Finally make sure the server validation does what
* we were expecting
*/
if (virNetTLSContextCheckCertificate(serverCtxt,
serverSess) < 0) {
if (!data->expectServerFail) {
VIR_WARN("Unexpected server cert check fail");
goto cleanup;
} else {
VIR_DEBUG("Got expected server cert fail");
}
} else {
if (data->expectServerFail) {
VIR_WARN("Expected server cert check fail");
goto cleanup;
} else {
VIR_DEBUG("Not unexpected server cert fail");
}
}
/*
* And the same for the client validation check
*/
if (virNetTLSContextCheckCertificate(clientCtxt,
clientSess) < 0) {
if (!data->expectClientFail) {
VIR_WARN("Unexpected client cert check fail");
goto cleanup;
} else {
VIR_DEBUG("Got expected client cert fail");
}
} else {
if (data->expectClientFail) {
VIR_WARN("Expected client cert check fail");
goto cleanup;
} else {
VIR_DEBUG("Not unexpected client cert fail");
}
}
ret = 0;
cleanup:
virNetTLSContextFree(serverCtxt);
virNetTLSContextFree(clientCtxt);
gnutls_x509_crt_deinit(data->careq.crt);
if (data->othercareq.filename)
gnutls_x509_crt_deinit(data->othercareq.crt);
gnutls_x509_crt_deinit(data->clientreq.crt);
gnutls_x509_crt_deinit(data->serverreq.crt);
data->careq.crt = data->othercareq.crt = data->clientreq.crt = data->serverreq.crt = NULL;
/* When troubleshooting this tests, we often want to leave the certs on disk */
if (getenv("VIRT_TEST_DEBUG_CERTS") == NULL) {
unlink(data->careq.filename);
if (data->othercareq.filename)
unlink(data->othercareq.filename);
unlink(data->clientreq.filename);
unlink(data->serverreq.filename);
}
VIR_FORCE_CLOSE(channel[0]);
VIR_FORCE_CLOSE(channel[1]);
return ret;
}
static int
mymain(void)
{
int ret = 0;
if (asn1_array2tree(pkix_asn1_tab, &pkix_asn1, NULL) != ASN1_SUCCESS)
abort();
gnutls_global_init();
privkey = testTLSLoadKey();
if (virFileWriteStr(keyfile, PRIVATE_KEY, 0600) < 0)
return EXIT_FAILURE;
# define DO_CTX_TEST(isServer, caReq, certReq, expectFail) \
do { \
struct testTLSContextData data = { \
isServer, caReq, certReq, expectFail, \
}; \
if (virtTestRun("TLS Context", 1, testTLSContextInit, &data) < 0) \
ret = -1; \
} while (0)
# define DO_SESS_TEST(caReq, serverReq, clientReq, expectServerFail, expectClientFail, hostname, wildcards) \
do { \
struct testTLSSessionData data = { \
caReq, { 0 }, serverReq, clientReq, \
expectServerFail, expectClientFail, hostname, wildcards \
}; \
if (virtTestRun("TLS Session", 1, testTLSSessionInit, &data) < 0) \
ret = -1; \
} while (0)
# define DO_SESS_TEST_EXT(caReq, othercaReq, serverReq, clientReq, expectServerFail, expectClientFail, hostname, wildcards) \
do { \
struct testTLSSessionData data = { \
caReq, othercaReq, serverReq, clientReq, \
expectServerFail, expectClientFail, hostname, wildcards \
}; \
if (virtTestRun("TLS Session", 1, testTLSSessionInit, &data) < 0) \
ret = -1; \
} while (0)
/* A perfect CA, perfect client & perfect server */
/* Basic:CA:critical */
struct testTLSCertReq cacertreq = {
NULL, NULL, "cacert.pem", "UK",
"libvirt CA", NULL, NULL, NULL, NULL,
true, true, true,
true, true, GNUTLS_KEY_KEY_CERT_SIGN,
false, false, NULL, NULL,
0, 0,
};
struct testTLSCertReq servercertreq = {
NULL, NULL, "servercert.pem", "UK",
"libvirt.org", NULL, NULL, NULL, NULL,
true, true, false,
true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
0, 0,
};
struct testTLSCertReq clientcertreq = {
NULL, NULL, "clientcert.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
0, 0,
};
DO_CTX_TEST(true, cacertreq, servercertreq, false);
DO_CTX_TEST(false, cacertreq, clientcertreq, false);
/* Some other CAs which are good */
/* Basic:CA:critical */
struct testTLSCertReq cacert1req = {
NULL, NULL, "cacert1.pem", "UK",
"libvirt CA 1", NULL, NULL, NULL, NULL,
true, true, true,
false, false, 0,
false, false, NULL, NULL,
0, 0,
};
/* Basic:CA:not-critical */
struct testTLSCertReq cacert2req = {
NULL, NULL, "cacert2.pem", "UK",
"libvirt CA 2", NULL, NULL, NULL, NULL,
true, false, true,
false, false, 0,
false, false, NULL, NULL,
0, 0,
};
/* Basic:not-CA:not-critical */
# if 0
/* Default GNUTLS session config forbids use of CAs without
* basic constraints, so skip this otherwise valid test
*/
struct testTLSCertReq cacert3req = {
NULL, NULL, "cacert3.pem", "UK",
"libvirt CA 3", NULL, NULL, NULL, NULL,
true, false, false,
false, false, 0,
false, false, NULL, NULL,
0, 0,
};
# endif
/* Key usage:cert-sign:critical */
struct testTLSCertReq cacert4req = {
NULL, NULL, "cacert4.pem", "UK",
"libvirt CA 4", NULL, NULL, NULL, NULL,
true, true, true,
true, true, GNUTLS_KEY_KEY_CERT_SIGN,
false, false, NULL, NULL,
0, 0,
};
/* Key usage:dig-sig:not-critical */
struct testTLSCertReq cacert5req = {
NULL, NULL, "cacert5.pem", "UK",
"libvirt CA 5", NULL, NULL, NULL, NULL,
true, true, true,
true, false, GNUTLS_KEY_DIGITAL_SIGNATURE,
false, false, NULL, NULL,
0, 0,
};
DO_CTX_TEST(true, cacert1req, servercertreq, false);
DO_CTX_TEST(true, cacert2req, servercertreq, false);
# if 0
DO_CTX_TEST(true, cacert3req, servercertreq, false);
# endif
DO_CTX_TEST(true, cacert4req, servercertreq, false);
DO_CTX_TEST(true, cacert5req, servercertreq, false);
/* Now some bad certs */
/* no-basic */
struct testTLSCertReq cacert6req = {
NULL, NULL, "cacert6.pem", "UK",
"libvirt CA 6", NULL, NULL, NULL, NULL,
false, false, false,
false, false, 0,
false, false, NULL, NULL,
0, 0,
};
/* Key usage:dig-sig:critical */
struct testTLSCertReq cacert7req = {
NULL, NULL, "cacert7.pem", "UK",
"libvirt CA 7", NULL, NULL, NULL, NULL,
true, true, true,
true, true, GNUTLS_KEY_DIGITAL_SIGNATURE,
false, false, NULL, NULL,
0, 0,
};
DO_CTX_TEST(true, cacert6req, servercertreq, true);
DO_CTX_TEST(true, cacert7req, servercertreq, true);
/* Various good servers */
/* no usage or purpose */
struct testTLSCertReq servercert1req = {
NULL, NULL, "servercert1.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
false, false, 0,
false, false, NULL, NULL,
0, 0,
};
/* usage:cert-sign+dig-sig+encipher:critical */
struct testTLSCertReq servercert2req = {
NULL, NULL, "servercert2.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_KEY_CERT_SIGN,
false, false, NULL, NULL,
0, 0,
};
/* usage:cert-sign:not-critical */
struct testTLSCertReq servercert3req = {
NULL, NULL, "servercert3.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
true, false, GNUTLS_KEY_KEY_CERT_SIGN,
false, false, NULL, NULL,
0, 0,
};
/* purpose:server:critical */
struct testTLSCertReq servercert4req = {
NULL, NULL, "servercert4.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
false, false, 0,
true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
0, 0,
};
/* purpose:server:not-critical */
struct testTLSCertReq servercert5req = {
NULL, NULL, "servercert5.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
false, false, 0,
true, false, GNUTLS_KP_TLS_WWW_SERVER, NULL,
0, 0,
};
/* purpose:client+server:critical */
struct testTLSCertReq servercert6req = {
NULL, NULL, "servercert6.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
false, false, 0,
true, true, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER,
0, 0,
};
/* purpose:client+server:not-critical */
struct testTLSCertReq servercert7req = {
NULL, NULL, "servercert7.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
false, false, 0,
true, false, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER,
0, 0,
};
DO_CTX_TEST(true, cacertreq, servercert1req, false);
DO_CTX_TEST(true, cacertreq, servercert2req, false);
DO_CTX_TEST(true, cacertreq, servercert3req, false);
DO_CTX_TEST(true, cacertreq, servercert4req, false);
DO_CTX_TEST(true, cacertreq, servercert5req, false);
DO_CTX_TEST(true, cacertreq, servercert6req, false);
DO_CTX_TEST(true, cacertreq, servercert7req, false);
/* Bad servers */
/* usage:cert-sign:critical */
struct testTLSCertReq servercert8req = {
NULL, NULL, "servercert8.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
true, true, GNUTLS_KEY_KEY_CERT_SIGN,
false, false, NULL, NULL,
0, 0,
};
/* purpose:client:critical */
struct testTLSCertReq servercert9req = {
NULL, NULL, "servercert9.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
false, false, 0,
true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
0, 0,
};
/* usage: none:critical */
struct testTLSCertReq servercert10req = {
NULL, NULL, "servercert10.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
true, true, 0,
false, false, NULL, NULL,
0, 0,
};
DO_CTX_TEST(true, cacertreq, servercert8req, true);
DO_CTX_TEST(true, cacertreq, servercert9req, true);
DO_CTX_TEST(true, cacertreq, servercert10req, true);
/* Various good clients */
/* no usage or purpose */
struct testTLSCertReq clientcert1req = {
NULL, NULL, "clientcert1.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
false, false, 0,
false, false, NULL, NULL,
0, 0,
};
/* usage:cert-sign+dig-sig+encipher:critical */
struct testTLSCertReq clientcert2req = {
NULL, NULL, "clientcert2.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_KEY_CERT_SIGN,
false, false, NULL, NULL,
0, 0,
};
/* usage:cert-sign:not-critical */
struct testTLSCertReq clientcert3req = {
NULL, NULL, "clientcert3.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
true, false, GNUTLS_KEY_KEY_CERT_SIGN,
false, false, NULL, NULL,
0, 0,
};
/* purpose:client:critical */
struct testTLSCertReq clientcert4req = {
NULL, NULL, "clientcert4.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
false, false, 0,
true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
0, 0,
};
/* purpose:client:not-critical */
struct testTLSCertReq clientcert5req = {
NULL, NULL, "clientcert5.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
false, false, 0,
true, false, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
0, 0,
};
/* purpose:client+client:critical */
struct testTLSCertReq clientcert6req = {
NULL, NULL, "clientcert6.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
false, false, 0,
true, true, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER,
0, 0,
};
/* purpose:client+client:not-critical */
struct testTLSCertReq clientcert7req = {
NULL, NULL, "clientcert7.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
false, false, 0,
true, false, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER,
0, 0,
};
DO_CTX_TEST(false, cacertreq, clientcert1req, false);
DO_CTX_TEST(false, cacertreq, clientcert2req, false);
DO_CTX_TEST(false, cacertreq, clientcert3req, false);
DO_CTX_TEST(false, cacertreq, clientcert4req, false);
DO_CTX_TEST(false, cacertreq, clientcert5req, false);
DO_CTX_TEST(false, cacertreq, clientcert6req, false);
DO_CTX_TEST(false, cacertreq, clientcert7req, false);
/* Bad clients */
/* usage:cert-sign:critical */
struct testTLSCertReq clientcert8req = {
NULL, NULL, "clientcert8.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
true, true, GNUTLS_KEY_KEY_CERT_SIGN,
false, false, NULL, NULL,
0, 0,
};
/* purpose:client:critical */
struct testTLSCertReq clientcert9req = {
NULL, NULL, "clientcert9.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
false, false, 0,
true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
0, 0,
};
/* usage: none:critical */
struct testTLSCertReq clientcert10req = {
NULL, NULL, "clientcert10.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
true, true, 0,
false, false, NULL, NULL,
0, 0,
};
DO_CTX_TEST(false, cacertreq, clientcert8req, true);
DO_CTX_TEST(false, cacertreq, clientcert9req, true);
DO_CTX_TEST(false, cacertreq, clientcert10req, true);
/* Expired stuff */
struct testTLSCertReq cacertexpreq = {
NULL, NULL, "cacert.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, true,
true, true, GNUTLS_KEY_KEY_CERT_SIGN,
false, false, NULL, NULL,
0, 1,
};
struct testTLSCertReq servercertexpreq = {
NULL, NULL, "servercert.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
0, 1,
};
struct testTLSCertReq clientcertexpreq = {
NULL, NULL, "clientcert.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
0, 1,
};
DO_CTX_TEST(true, cacertexpreq, servercertreq, true);
DO_CTX_TEST(true, cacertreq, servercertexpreq, true);
DO_CTX_TEST(false, cacertreq, clientcertexpreq, true);
/* Not activated stuff */
struct testTLSCertReq cacertnewreq = {
NULL, NULL, "cacert.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, true,
true, true, GNUTLS_KEY_KEY_CERT_SIGN,
false, false, NULL, NULL,
time(NULL)+(60*60), time(NULL)+(60*60*2),
};
struct testTLSCertReq servercertnewreq = {
NULL, NULL, "servercert.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
time(NULL)+(60*60), time(NULL)+(60*60*2),
};
struct testTLSCertReq clientcertnewreq = {
NULL, NULL, "clientcert.pem", "UK",
"libvirt", NULL, NULL, NULL, NULL,
true, true, false,
true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
time(NULL)+(60*60), time(NULL)+(60*60*2),
};
DO_CTX_TEST(true, cacertnewreq, servercertreq, true);
DO_CTX_TEST(true, cacertreq, servercertnewreq, true);
DO_CTX_TEST(false, cacertreq, clientcertnewreq, true);
DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", NULL);
DO_SESS_TEST_EXT(cacertreq, cacert1req, servercertreq, clientcertreq, true, true, "libvirt.org", NULL);
/* When an altname is set, the CN is ignored, so it must be duplicated
* as an altname for it to match */
struct testTLSCertReq servercertalt1req = {
NULL, NULL, "servercert.pem", "UK",
"libvirt.org", "www.libvirt.org", "libvirt.org", "192.168.122.1", "fec0::dead:beaf",
true, true, false,
true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
0, 0,
};
/* This intentionally doesn't replicate */
struct testTLSCertReq servercertalt2req = {
NULL, NULL, "servercert.pem", "UK",
"libvirt.org", "www.libvirt.org", "wiki.libvirt.org", "192.168.122.1", "fec0::dead:beaf",
true, true, false,
true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
0, 0,
};
DO_SESS_TEST(cacertreq, servercertalt1req, clientcertreq, false, false, "libvirt.org", NULL);
DO_SESS_TEST(cacertreq, servercertalt1req, clientcertreq, false, false, "www.libvirt.org", NULL);
DO_SESS_TEST(cacertreq, servercertalt1req, clientcertreq, false, true, "wiki.libvirt.org", NULL);
DO_SESS_TEST(cacertreq, servercertalt2req, clientcertreq, false, true, "libvirt.org", NULL);
DO_SESS_TEST(cacertreq, servercertalt2req, clientcertreq, false, false, "www.libvirt.org", NULL);
DO_SESS_TEST(cacertreq, servercertalt2req, clientcertreq, false, false, "wiki.libvirt.org", NULL);
const char *const wildcards1[] = {
"C=UK,CN=dogfood",
NULL,
};
const char *const wildcards2[] = {
"C=UK,CN=libvirt",
NULL,
};
const char *const wildcards3[] = {
"C=UK,CN=dogfood",
"C=UK,CN=libvirt",
NULL,
};
const char *const wildcards4[] = {
"C=UK,CN=libvirtstuff",
NULL,
};
const char *const wildcards5[] = {
"C=UK,CN=libvirt*",
NULL,
};
const char *const wildcards6[] = {
"C=UK,CN=*virt*",
NULL,
};
DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, true, false, "libvirt.org", wildcards1);
DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards2);
DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards3);
DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, true, false, "libvirt.org", wildcards4);
DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards5);
DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards6);
unlink(keyfile);
asn1_delete_structure(&pkix_asn1);
return (ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
#else
static int
mymain(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
{
exit (EXIT_AM_SKIP);
}
#endif
VIRT_TEST_MAIN(mymain)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册