Skip to content

Commit e0311a9

Browse files
authored
Show CRL and OCSP URLs in verify output (#7181)
1 parent 2233ffd commit e0311a9

17 files changed

Lines changed: 364 additions & 0 deletions

File tree

src/NuGet.Core/NuGet.Packaging/Signing/Utility/CertificateUtility.cs

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,16 @@ internal static IReadOnlyList<SignatureLog> X509Certificate2ToLogMessages(X509Ce
5656
issues.Add(SignatureLog.InformationLog($"{indentation}{string.Format(CultureInfo.CurrentCulture, Strings.CertUtilityCertificateIssuer, cert.IssuerName.Name)}"));
5757
issues.Add(SignatureLog.MinimalLog($"{indentation}{string.Format(CultureInfo.CurrentCulture, Strings.CertUtilityCertificateValidity, cert.NotBefore, cert.NotAfter)}"));
5858

59+
foreach (string url in GetCrlDistributionPointUrls(cert))
60+
{
61+
issues.Add(SignatureLog.InformationLog($"{indentation}{string.Format(CultureInfo.CurrentCulture, Strings.CertUtilityCertificateCrlUrl, url)}"));
62+
}
63+
64+
foreach (string url in GetOcspUrls(cert))
65+
{
66+
issues.Add(SignatureLog.InformationLog($"{indentation}{string.Format(CultureInfo.CurrentCulture, Strings.CertUtilityCertificateOcspUrl, url)}"));
67+
}
68+
5969
return issues;
6070
}
6171

@@ -68,6 +78,16 @@ private static void X509Certificate2ToString(X509Certificate2 cert, StringBuilde
6878
certStringBuilder.AppendLine(indentation + string.Format(CultureInfo.CurrentCulture, Strings.CertUtilityCertificateHash, fingerprintAlgorithm.ToString(), certificateFingerprint));
6979
certStringBuilder.AppendLine(indentation + string.Format(CultureInfo.CurrentCulture, Strings.CertUtilityCertificateIssuer, cert.IssuerName.Name));
7080
certStringBuilder.AppendLine(indentation + string.Format(CultureInfo.CurrentCulture, Strings.CertUtilityCertificateValidity, cert.NotBefore, cert.NotAfter));
81+
82+
foreach (string url in GetCrlDistributionPointUrls(cert))
83+
{
84+
certStringBuilder.AppendLine(indentation + string.Format(CultureInfo.CurrentCulture, Strings.CertUtilityCertificateCrlUrl, url));
85+
}
86+
87+
foreach (string url in GetOcspUrls(cert))
88+
{
89+
certStringBuilder.AppendLine(indentation + string.Format(CultureInfo.CurrentCulture, Strings.CertUtilityCertificateOcspUrl, url));
90+
}
7191
}
7292

7393
/// <summary>
@@ -447,5 +467,117 @@ private static bool IsHex(string certificateFingerprint)
447467

448468
return true;
449469
}
470+
471+
/// <summary>
472+
/// Extracts CRL Distribution Point URLs from the certificate's CRL Distribution Points extension (OID 2.5.29.31).
473+
/// </summary>
474+
internal static IReadOnlyList<string> GetCrlDistributionPointUrls(X509Certificate2 cert)
475+
{
476+
const string CrlDistributionPointsOid = "2.5.29.31";
477+
// context-specific primitive tag [6] for uniformResourceIdentifier in GeneralName
478+
const byte GeneralNameUriTag = 0x86;
479+
480+
var urls = new List<string>();
481+
var extension = cert.Extensions[CrlDistributionPointsOid];
482+
483+
if (extension == null)
484+
{
485+
return urls;
486+
}
487+
488+
try
489+
{
490+
// CRLDistributionPoints ::= SEQUENCE OF DistributionPoint
491+
var reader = new DerEncoding.DerSequenceReader(extension.RawData);
492+
493+
while (reader.HasData)
494+
{
495+
// DistributionPoint ::= SEQUENCE { distributionPoint [0] ... }
496+
var dpReader = reader.ReadSequence();
497+
498+
if (dpReader.HasData && dpReader.HasTag(DerEncoding.DerSequenceReader.ContextSpecificConstructedTag0))
499+
{
500+
// distributionPoint [0] CONSTRUCTED
501+
byte[] dpNameData = dpReader.ReadValue((DerEncoding.DerSequenceReader.DerTag)DerEncoding.DerSequenceReader.ContextSpecificConstructedTag0);
502+
var dpNameReader = DerEncoding.DerSequenceReader.CreateForPayload(dpNameData);
503+
504+
if (dpNameReader.HasData && dpNameReader.HasTag(DerEncoding.DerSequenceReader.ContextSpecificConstructedTag0))
505+
{
506+
// fullName [0] CONSTRUCTED = GeneralNames
507+
byte[] fullNameData = dpNameReader.ReadValue((DerEncoding.DerSequenceReader.DerTag)DerEncoding.DerSequenceReader.ContextSpecificConstructedTag0);
508+
var gnReader = DerEncoding.DerSequenceReader.CreateForPayload(fullNameData);
509+
510+
while (gnReader.HasData)
511+
{
512+
byte tag = gnReader.PeekTag();
513+
514+
if (tag == GeneralNameUriTag)
515+
{
516+
byte[] uriBytes = gnReader.ReadValue((DerEncoding.DerSequenceReader.DerTag)GeneralNameUriTag);
517+
urls.Add(Encoding.ASCII.GetString(uriBytes));
518+
}
519+
else
520+
{
521+
gnReader.SkipValue();
522+
}
523+
}
524+
}
525+
}
526+
}
527+
}
528+
catch (System.Security.Cryptography.CryptographicException)
529+
{
530+
}
531+
532+
return urls;
533+
}
534+
535+
/// <summary>
536+
/// Extracts OCSP responder URLs from the certificate's Authority Information Access extension (OID 1.3.6.1.5.5.7.1.1).
537+
/// </summary>
538+
internal static IReadOnlyList<string> GetOcspUrls(X509Certificate2 cert)
539+
{
540+
const string AuthorityInfoAccessOid = "1.3.6.1.5.5.7.1.1";
541+
const string OcspAccessMethodOid = "1.3.6.1.5.5.7.48.1";
542+
// context-specific primitive tag [6] for uniformResourceIdentifier in GeneralName
543+
const byte GeneralNameUriTag = 0x86;
544+
545+
var urls = new List<string>();
546+
var extension = cert.Extensions[AuthorityInfoAccessOid];
547+
548+
if (extension == null)
549+
{
550+
return urls;
551+
}
552+
553+
try
554+
{
555+
// AuthorityInfoAccessSyntax ::= SEQUENCE OF AccessDescription
556+
var reader = new DerEncoding.DerSequenceReader(extension.RawData);
557+
558+
while (reader.HasData)
559+
{
560+
// AccessDescription ::= SEQUENCE { accessMethod OID, accessLocation GeneralName }
561+
var adReader = reader.ReadSequence();
562+
string oid = adReader.ReadOidAsString();
563+
564+
if (string.Equals(oid, OcspAccessMethodOid, StringComparison.Ordinal) && adReader.HasData)
565+
{
566+
byte tag = adReader.PeekTag();
567+
568+
if (tag == GeneralNameUriTag)
569+
{
570+
byte[] uriBytes = adReader.ReadValue((DerEncoding.DerSequenceReader.DerTag)GeneralNameUriTag);
571+
urls.Add(Encoding.ASCII.GetString(uriBytes));
572+
}
573+
}
574+
}
575+
}
576+
catch (System.Security.Cryptography.CryptographicException)
577+
{
578+
}
579+
580+
return urls;
581+
}
450582
}
451583
}

src/NuGet.Core/NuGet.Packaging/Strings.Designer.cs

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/NuGet.Core/NuGet.Packaging/Strings.resx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,14 @@
271271
<comment>0 - start date
272272
1 - end date</comment>
273273
</data>
274+
<data name="CertUtilityCertificateCrlUrl" xml:space="preserve">
275+
<value>CRL URL: {0}</value>
276+
<comment>0 - CRL distribution point URL</comment>
277+
</data>
278+
<data name="CertUtilityCertificateOcspUrl" xml:space="preserve">
279+
<value>OCSP URL: {0}</value>
280+
<comment>0 - OCSP responder URL</comment>
281+
</data>
274282
<data name="CertUtilityMultipleCertificatesFooter" xml:space="preserve">
275283
<value>... {0} more.</value>
276284
<comment>0 - number of certificates left</comment>

src/NuGet.Core/NuGet.Packaging/xlf/Strings.cs.xlf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@
4444
<note>0 - start date
4545
1 - end date</note>
4646
</trans-unit>
47+
<trans-unit id="CertUtilityCertificateCrlUrl">
48+
<source>CRL URL: {0}</source>
49+
<target state="new">CRL URL: {0}</target>
50+
<note>0 - CRL distribution point URL</note>
51+
</trans-unit>
52+
<trans-unit id="CertUtilityCertificateOcspUrl">
53+
<source>OCSP URL: {0}</source>
54+
<target state="new">OCSP URL: {0}</target>
55+
<note>0 - OCSP responder URL</note>
56+
</trans-unit>
4757
<trans-unit id="CertUtilityMultipleCertificatesFooter">
4858
<source>... {0} more.</source>
4959
<target state="translated">... dalších {0}.</target>

src/NuGet.Core/NuGet.Packaging/xlf/Strings.de.xlf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@
4444
<note>0 - start date
4545
1 - end date</note>
4646
</trans-unit>
47+
<trans-unit id="CertUtilityCertificateCrlUrl">
48+
<source>CRL URL: {0}</source>
49+
<target state="new">CRL URL: {0}</target>
50+
<note>0 - CRL distribution point URL</note>
51+
</trans-unit>
52+
<trans-unit id="CertUtilityCertificateOcspUrl">
53+
<source>OCSP URL: {0}</source>
54+
<target state="new">OCSP URL: {0}</target>
55+
<note>0 - OCSP responder URL</note>
56+
</trans-unit>
4757
<trans-unit id="CertUtilityMultipleCertificatesFooter">
4858
<source>... {0} more.</source>
4959
<target state="translated">... {0} weitere.</target>

src/NuGet.Core/NuGet.Packaging/xlf/Strings.es.xlf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@
4444
<note>0 - start date
4545
1 - end date</note>
4646
</trans-unit>
47+
<trans-unit id="CertUtilityCertificateCrlUrl">
48+
<source>CRL URL: {0}</source>
49+
<target state="new">CRL URL: {0}</target>
50+
<note>0 - CRL distribution point URL</note>
51+
</trans-unit>
52+
<trans-unit id="CertUtilityCertificateOcspUrl">
53+
<source>OCSP URL: {0}</source>
54+
<target state="new">OCSP URL: {0}</target>
55+
<note>0 - OCSP responder URL</note>
56+
</trans-unit>
4757
<trans-unit id="CertUtilityMultipleCertificatesFooter">
4858
<source>... {0} more.</source>
4959
<target state="translated">... {0} más.</target>

src/NuGet.Core/NuGet.Packaging/xlf/Strings.fr.xlf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@
4444
<note>0 - start date
4545
1 - end date</note>
4646
</trans-unit>
47+
<trans-unit id="CertUtilityCertificateCrlUrl">
48+
<source>CRL URL: {0}</source>
49+
<target state="new">CRL URL: {0}</target>
50+
<note>0 - CRL distribution point URL</note>
51+
</trans-unit>
52+
<trans-unit id="CertUtilityCertificateOcspUrl">
53+
<source>OCSP URL: {0}</source>
54+
<target state="new">OCSP URL: {0}</target>
55+
<note>0 - OCSP responder URL</note>
56+
</trans-unit>
4757
<trans-unit id="CertUtilityMultipleCertificatesFooter">
4858
<source>... {0} more.</source>
4959
<target state="translated">... {0} de plus.</target>

src/NuGet.Core/NuGet.Packaging/xlf/Strings.it.xlf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@
4444
<note>0 - start date
4545
1 - end date</note>
4646
</trans-unit>
47+
<trans-unit id="CertUtilityCertificateCrlUrl">
48+
<source>CRL URL: {0}</source>
49+
<target state="new">CRL URL: {0}</target>
50+
<note>0 - CRL distribution point URL</note>
51+
</trans-unit>
52+
<trans-unit id="CertUtilityCertificateOcspUrl">
53+
<source>OCSP URL: {0}</source>
54+
<target state="new">OCSP URL: {0}</target>
55+
<note>0 - OCSP responder URL</note>
56+
</trans-unit>
4757
<trans-unit id="CertUtilityMultipleCertificatesFooter">
4858
<source>... {0} more.</source>
4959
<target state="translated">... altri {0}.</target>

src/NuGet.Core/NuGet.Packaging/xlf/Strings.ja.xlf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@
4444
<note>0 - start date
4545
1 - end date</note>
4646
</trans-unit>
47+
<trans-unit id="CertUtilityCertificateCrlUrl">
48+
<source>CRL URL: {0}</source>
49+
<target state="new">CRL URL: {0}</target>
50+
<note>0 - CRL distribution point URL</note>
51+
</trans-unit>
52+
<trans-unit id="CertUtilityCertificateOcspUrl">
53+
<source>OCSP URL: {0}</source>
54+
<target state="new">OCSP URL: {0}</target>
55+
<note>0 - OCSP responder URL</note>
56+
</trans-unit>
4757
<trans-unit id="CertUtilityMultipleCertificatesFooter">
4858
<source>... {0} more.</source>
4959
<target state="translated">... さらに {0}。</target>

src/NuGet.Core/NuGet.Packaging/xlf/Strings.ko.xlf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@
4444
<note>0 - start date
4545
1 - end date</note>
4646
</trans-unit>
47+
<trans-unit id="CertUtilityCertificateCrlUrl">
48+
<source>CRL URL: {0}</source>
49+
<target state="new">CRL URL: {0}</target>
50+
<note>0 - CRL distribution point URL</note>
51+
</trans-unit>
52+
<trans-unit id="CertUtilityCertificateOcspUrl">
53+
<source>OCSP URL: {0}</source>
54+
<target state="new">OCSP URL: {0}</target>
55+
<note>0 - OCSP responder URL</note>
56+
</trans-unit>
4757
<trans-unit id="CertUtilityMultipleCertificatesFooter">
4858
<source>... {0} more.</source>
4959
<target state="translated">...기타 {0}개.</target>

0 commit comments

Comments
 (0)