Skip to content

Commit 7c403e7

Browse files
Davidde94Lukasa
andauthored
Add NIOSSLCertificate debug description for useful debugging (#246)
* Add debug description * Fix test * Linux tests * Update Sources/NIOSSL/SSLCertificate.swift Co-authored-by: Cory Benfield <[email protected]> * Update Sources/NIOSSL/SSLCertificate.swift Co-authored-by: Cory Benfield <[email protected]> * Update Sources/NIOSSL/SSLCertificate.swift Co-authored-by: Cory Benfield <[email protected]> * Address review comments * Move IP address to it's own extension * Add preconditions * PR comments * Fix Swift 5.0 * Pr comments * Update Sources/NIOSSL/SSLCertificate.swift Co-authored-by: Cory Benfield <[email protected]> * Update Sources/NIOSSL/SSLCertificate.swift Co-authored-by: Cory Benfield <[email protected]> * Update Sources/NIOSSL/SSLCertificate.swift Co-authored-by: Cory Benfield <[email protected]> * Update Sources/NIOSSL/SSLCertificate.swift Co-authored-by: Cory Benfield <[email protected]> * Update Sources/NIOSSL/SSLCertificate.swift Co-authored-by: Cory Benfield <[email protected]> * Update Sources/NIOSSL/SSLCertificate.swift Co-authored-by: Cory Benfield <[email protected]> Co-authored-by: Cory Benfield <[email protected]>
1 parent cc0e80d commit 7c403e7

File tree

3 files changed

+81
-0
lines changed

3 files changed

+81
-0
lines changed

Sources/NIOSSL/SSLCertificate.swift

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,3 +434,66 @@ internal class SubjectAltNameSequence: Sequence, IteratorProtocol {
434434
CNIOBoringSSL_GENERAL_NAMES_free(self.nameStack)
435435
}
436436
}
437+
438+
extension NIOSSLCertificate: CustomStringConvertible {
439+
440+
public var description: String {
441+
var desc = "<NIOSSLCertificate"
442+
if let commonNameBytes = self.commonName() {
443+
let commonName = String(decoding: commonNameBytes, as: UTF8.self)
444+
desc += ";common_name=" + commonName
445+
}
446+
if let alternativeName = self.subjectAlternativeNames() {
447+
let altNames = alternativeName.map { name in
448+
switch name {
449+
case .dnsName(let bytes):
450+
return String(decoding: bytes, as: UTF8.self)
451+
case .ipAddress(let address):
452+
return String(describing: address)
453+
}
454+
}.joined(separator: ",")
455+
desc += ";alternative_names=\(altNames)"
456+
}
457+
return desc + ">"
458+
}
459+
460+
}
461+
462+
extension NIOSSLCertificate.IPAddress: CustomStringConvertible {
463+
464+
private static let ipv4AddressLength = 16
465+
private static let ipv6AddressLength = 46
466+
467+
/// A string representation of the IP address.
468+
/// E.g. IPv4: `192.168.0.1`
469+
/// E.g. IPv6: `2001:db8::1`
470+
public var description: String {
471+
switch self {
472+
case .ipv4(let addr):
473+
return self.ipv4ToString(addr)
474+
case .ipv6(let addr):
475+
return self.ipv6ToString(addr)
476+
}
477+
}
478+
479+
private func ipv4ToString(_ address: in_addr) -> String {
480+
var address = address
481+
var dest: [CChar] = Array(repeating: 0, count: NIOSSLCertificate.IPAddress.ipv4AddressLength)
482+
dest.withUnsafeMutableBufferPointer { pointer in
483+
let result = inet_ntop(AF_INET, &address, pointer.baseAddress!, socklen_t(pointer.count))
484+
precondition(result != nil, "The IP address was invalid. This should never happen as we're within the IP address struct.")
485+
}
486+
return String(cString: &dest)
487+
}
488+
489+
private func ipv6ToString(_ address: in6_addr) -> String {
490+
var address = address
491+
var dest: [CChar] = Array(repeating: 0, count: NIOSSLCertificate.IPAddress.ipv6AddressLength)
492+
dest.withUnsafeMutableBufferPointer { pointer in
493+
let result = inet_ntop(AF_INET6, &address, pointer.baseAddress!, socklen_t(pointer.count))
494+
precondition(result != nil, "The IP address was invalid. This should never happen as we're within the IP address struct.")
495+
}
496+
return String(cString: &dest)
497+
}
498+
499+
}

Tests/NIOSSLTests/SSLCertificateTest+XCTest.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ extension SSLCertificateTest {
5454
("testExtractingPublicKey", testExtractingPublicKey),
5555
("testDumpingPEMCert", testDumpingPEMCert),
5656
("testDumpingDERCert", testDumpingDERCert),
57+
("testPrintingDebugDetailsNoAlternativeNames", testPrintingDebugDetailsNoAlternativeNames),
58+
("testPrintingDebugDetailsWithAlternativeNames", testPrintingDebugDetailsWithAlternativeNames),
5759
]
5860
}
5961
}

Tests/NIOSSLTests/SSLCertificateTest.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,4 +380,20 @@ class SSLCertificateTest: XCTestCase {
380380

381381
XCTAssertEqual(certBytes, expectedCertBytes)
382382
}
383+
384+
func testPrintingDebugDetailsNoAlternativeNames() throws {
385+
let expectedDebugDescription = "<NIOSSLCertificate;common_name=robots.sanfransokyo.edu>"
386+
let cert = try assertNoThrowWithValue(NIOSSLCertificate(bytes: .init(samplePemCert.utf8), format: .pem))
387+
let debugString = String(describing: cert)
388+
389+
XCTAssertEqual(debugString, expectedDebugDescription)
390+
}
391+
392+
func testPrintingDebugDetailsWithAlternativeNames() throws {
393+
let expectedDebugDescription = "<NIOSSLCertificate;common_name=localhost;alternative_names=localhost,example.com,192.168.0.1,2001:db8::1>"
394+
let cert = try assertNoThrowWithValue(NIOSSLCertificate(bytes: .init(multiSanCert.utf8), format: .pem))
395+
let debugString = String(describing: cert)
396+
397+
XCTAssertEqual(debugString, expectedDebugDescription)
398+
}
383399
}

0 commit comments

Comments
 (0)