Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for validating server hostnames and IP addresses #171

Merged
merged 1 commit into from
Apr 22, 2024

Conversation

Lukasa
Copy link
Collaborator

@Lukasa Lukasa commented Apr 22, 2024

Motivation

To make Swift Certificates useful for the Web PKI it's vital that we can validate that a particular certificate is authoritative for a specific domain. This requires a new verifier policy.

Modifications

Added ServerIdentityPolicy
Added tests

Result

We can validate the identity of remote servers.

@Lukasa Lukasa added the 🔼 needs-minor-version-bump For PRs that when merged cause a bump of the minor version, ie. 1.x.0 -> 1.(x+1).0 label Apr 22, 2024
/// This policy implements the logic for service validation as specified by
/// RFC 6125 (https://tools.ietf.org/search/rfc6125), which loosely speaking
/// defines the common algorithm used for validating that an X.509 certificate
/// is valid for a given service
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT

Suggested change
/// is valid for a given service
/// is valid for a given service.

Comment on lines +42 to +40
/// - serverHostname: The hostname used to connect to the server.
/// - serverIP: The IP address of the server, if known.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Presumably you have to pass one or the other or both right? Can we enforce this in the type contract somehow?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't, but I don't think it's necessary. If you pass neither, we'll fail to validate any cert.

///
/// Does nothing if the value is nil.
@inlinable
mutating func convert() -> ServerIdentityPolicy.IPAddress? {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: Shouldn't this rather be an init on ServerIdentityPolicy.IPAdress that takes a ServerIdentityPolicy.LazyIPAddress and on the optional we can just call flatMap?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, because we modify this value as well.

@Lukasa Lukasa force-pushed the cb-add-identity-policy branch 12 times, most recently from b9dc9d0 to bdc4aa0 Compare April 22, 2024 12:27

@inlinable
public mutating func chainMeetsPolicyRequirements(chain: UnverifiedCertificateChain) -> PolicyEvaluationResult {
let targetIP = self.serverIP.convert()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is caching the result. Why don't we do this just in the init? Is this laziness actually useful?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The advantage of the laziness here is that if we never have to analyse a cert, we never do the construction.

Comment on lines 64 to 66
if let serverHostname = self.serverHostname, self.convertedServerHostname == nil {
self.convertedServerHostname = PreparedServerHostname(lowercaseASCIIBytes: serverHostname)
}
Copy link
Member

@dnadoba dnadoba Apr 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are doing another way of caching here as well but forgot to set serverHostname to nil if the failable PreparedServerHostname.init returns nil. This means we are repeatedly trying to prepare the server hostname if it isn't a valid hostname. I suggest we move this to an init or model the internal state as an enum so we are sure we only do the initial conversion once.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can do the enum state, that works for me.

@Lukasa Lukasa force-pushed the cb-add-identity-policy branch 3 times, most recently from a668913 to 4a2fa6c Compare April 22, 2024 12:57
Motivation

To make Swift Certificates useful for the Web PKI it's vital
that we can validate that a particular certificate is authoritative
for a specific domain. This requires a new verifier policy.

Modifications

Added ServerIdentityPolicy
Added tests

Result

We can validate the identity of remote servers.
@Lukasa Lukasa merged commit 4975de4 into apple:main Apr 22, 2024
5 of 6 checks passed
@Lukasa Lukasa deleted the cb-add-identity-policy branch April 22, 2024 15:24
@Lukasa
Copy link
Collaborator Author

Lukasa commented Apr 22, 2024

Ah dang, merged too early.

}

let subsequentIndex = self.index(after: index)
return (self[..<index], self[subsequentIndex...])
Copy link
Member

@dnadoba dnadoba Apr 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will crash if index is self.endIndex

let array = [Int]()
_ = array.splitAroundIndex(array.endIndex) // Fatal error: Range requires lowerBound <= upperBound

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🔼 needs-minor-version-bump For PRs that when merged cause a bump of the minor version, ie. 1.x.0 -> 1.(x+1).0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants