diff --git a/cfg.mk b/cfg.mk index f2a951d5de..977ea87a0b 100644 --- a/cfg.mk +++ b/cfg.mk @@ -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)/ diff --git a/tests/.gitignore b/tests/.gitignore index 32457abc7b..7159c3737b 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -34,6 +34,7 @@ utiltest virbuftest virnetmessagetest virnetsockettest +virnettlscontexttest virshtest vmx2xmltest xencapstest diff --git a/tests/Makefile.am b/tests/Makefile.am index 971ab706e1..1c91a1e590 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -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 diff --git a/tests/pkix_asn1_tab.c b/tests/pkix_asn1_tab.c new file mode 100644 index 0000000000..5d5ca3db5d --- /dev/null +++ b/tests/pkix_asn1_tab.c @@ -0,0 +1,567 @@ +/* + * This file comes from gnutls, licensed under the GPLv3+ + */ + +#include +#include + +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 } +}; diff --git a/tests/virnettlscontexttest.c b/tests/virnettlscontexttest.c new file mode 100644 index 0000000000..c8775ebbff --- /dev/null +++ b/tests/virnettlscontexttest.c @@ -0,0 +1,1245 @@ +/* + * 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 + */ + +#include + +#include +#include +#include + +#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 +# include +# include +# 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 : ""); + } + + 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)