Skip to content

Commit

Permalink
Check certificate SAN IP address when appropriate (#96)
Browse files Browse the repository at this point in the history
* Check ip address instead of hostname
when appropiate


Co-authored-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
  • Loading branch information
Firgeis and anmonteiro authored May 28, 2021
1 parent 9828c6b commit abab9cb
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 9 deletions.
23 changes: 20 additions & 3 deletions HACKING.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#### Configuration (ca.conf)

```
[ req ]
encrypt_key = no
default_md = sha256
Expand All @@ -25,16 +26,21 @@ keyUsage=critical, digitalSignature, keyEncipherment
basicConstraints=critical,CA:TRUE
extendedKeyUsage=critical,serverAuth
subjectKeyIdentifier = hash
```

#### Create the CA certificate

openssl genpkey -algorithm EC -out ca.key -pkeyopt ec_paramgen_curve:secp384r1 -pkeyopt ec_param_enc:named_curve
openssl req -new -x509 -days 3650 -config ca.conf -out ca.pem -key ca.key
```shell
$ openssl genpkey -algorithm EC -out ca.key -pkeyopt ec_paramgen_curve:secp384r1 -pkeyopt ec_param_enc:named_curve

$ openssl req -new -x509 -days 3650 -config ca.conf -out ca.pem -key ca.key
```

### Server cert

#### Configuration (server.conf)

```
[ req ]
encrypt_key = no
default_md = sha256
Expand All @@ -48,25 +54,32 @@ ST = California
L = San Francisco
O = Piaf
CN = localhost
```

#### Extensions (ssl-extensions-x509.conf)

```
[v3_ca]
keyUsage=critical, digitalSignature, keyEncipherment
basicConstraints=critical,CA:FALSE
extendedKeyUsage=critical,serverAuth
subjectKeyIdentifier = hash
# subjectAltName = IP:127.0.0.1
```

#### Create the server certificate

```shell
openssl genpkey -algorithm EC -out server.key -pkeyopt ec_paramgen_curve:secp384r1 -pkeyopt ec_param_enc:named_curve
openssl req -new -config server.conf -out server.csr -key server.key
openssl x509 -req -in server.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out server.pem -days 3650 -extensions v3_ca -extfile ./ssl-extensions-x509.conf
```

### Client cert

#### Configuration (client.conf)

```
[ req ]
encrypt_key = no
default_md = sha256
Expand All @@ -80,11 +93,15 @@ ST = California
L = San Francisco
O = Piaf
CN = localhost
```

#### Extensions (ssl-extensions-x509.conf)

```
[v3_ca]
keyUsage=critical, digitalSignature, keyEncipherment
basicConstraints=critical,CA:FALSE
extendedKeyUsage=critical,clientAuth
subjectKeyIdentifier = hash
subjectKeyIdentifier = hash
```

3 changes: 2 additions & 1 deletion lib/dune
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@
lwt_ssl
magic-mime
ssl
uri))
uri
ipaddr))
14 changes: 10 additions & 4 deletions lib/openssl.ml
Original file line number Diff line number Diff line change
Expand Up @@ -344,10 +344,16 @@ let connect ~hostname ~config ~alpn_protocols fd =
in
let s = Lwt_ssl.embed_uninitialized_socket fd ctx in
let ssl_sock = Lwt_ssl.ssl_socket_of_uninitialized_socket s in
Ssl.set_client_SNI_hostname ssl_sock hostname;
(* https://wiki.openssl.org/index.php/Hostname_validation *)
Ssl.set_hostflags ssl_sock [ No_partial_wildcards ];
Ssl.set_host ssl_sock hostname;
(* If hostname is an IP address, check that instead of the hostname *)
let ipaddr = Ipaddr.of_string hostname in
(match ipaddr with
| Ok ipadr ->
Ssl.set_ip ssl_sock (Ipaddr.to_string ipadr)
| _ ->
Ssl.set_client_SNI_hostname ssl_sock hostname;
(* https://wiki.openssl.org/index.php/Hostname_validation *)
Ssl.set_hostflags ssl_sock [ No_partial_wildcards ];
Ssl.set_host ssl_sock hostname);
let open Lwt.Syntax in
let+ socket_or_error =
Lwt.catch
Expand Down
6 changes: 6 additions & 0 deletions lib_test/certificates/server_san_ip.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-----BEGIN PRIVATE KEY-----
MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDBT2b/o8tXcxUd8pQJA
xx/2DQgfkfPjpAj6m1bIPARwhW6h+2Q8mT77gzvL5EgAy1yhZANiAARPhTFHdVnv
dw81b76o/4YsxA/bAA5QRfU/jpa1P1I/ItBy1gRtzfi8N9xrXu6CSr2KWTe5y7g9
rYpK+4VHe8b6WhuvsT8rKzQTqwmpL7frERo2nUKUZ7+FOFfPtck+zpg=
-----END PRIVATE KEY-----
15 changes: 15 additions & 0 deletions lib_test/certificates/server_san_ip.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE-----
MIICWjCCAeCgAwIBAgIUHlXS/Hpb4q7oAKsgrLDUY8bdN9MwCgYIKoZIzj0EAwIw
VjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNh
biBGcmFuY2lzY28xDTALBgNVBAoMBFBpYWYxCzAJBgNVBAMMAkNBMB4XDTIxMDUy
NzAxMzY0NVoXDTMxMDUyNTAxMzY0NVowXTELMAkGA1UEBhMCVVMxEzARBgNVBAgM
CkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBFBp
YWYxEjAQBgNVBAMMCWxvY2FsaG9zdDB2MBAGByqGSM49AgEGBSuBBAAiA2IABE+F
MUd1We93DzVvvqj/hizED9sADlBF9T+OlrU/Uj8i0HLWBG3N+Lw33Gte7oJKvYpZ
N7nLuD2tikr7hUd7xvpaG6+xPysrNBOrCakvt+sRGjadQpRnv4U4V8+1yT7OmKNo
MGYwDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYI
KwYBBQUHAwEwHQYDVR0OBBYEFNsBtKnjTyAjHvCO8F+TSF+oN+nkMA8GA1UdEQQI
MAaHBH8AAAEwCgYIKoZIzj0EAwIDaAAwZQIxAOYNtdwidJVyYL8IB6p167crCGw/
3NH8UXuA1pYusStTBNeP0ZqBBQIGc026YH7y3gIwNytgMIJHr/ejQiT5r1CGyBOV
oBmQs2wFRJpXBEjXO40URl3dWykux4ruOQ4ryKVJ
-----END CERTIFICATE-----
30 changes: 30 additions & 0 deletions lib_test/test_client.ml
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,36 @@ let test_https_server_certs _ () =
(Uri.of_string "https://localhost:9443")
in
let response = Result.get_ok response in
Alcotest.check
response_testable
"expected response"
(Response.create
~version:Versions.HTTP.v1_1
~headers:Headers.(of_list [ Well_known.content_length, "1" ])
`OK)
response;
let* () = Helper_server.teardown server in
(* Verify server SAN IP address *)
let* server, _ =
Helper_server.listen
~http_port:8080
~certfile:"server_san_ip.pem"
~certkey:"server_san_ip.key"
()
in
let* response =
Client.Oneshot.get
~config:
{ Config.default with
follow_redirects = true
; max_redirects = 1
; allow_insecure = false
; max_http_version = Versions.HTTP.v1_1
; cacert = Some (Cert.Filepath (Helper_server.cert_path // "ca.pem"))
}
(Uri.of_string "https://127.0.0.1:9443")
in
let response = Result.get_ok response in
Alcotest.check
response_testable
"expected response"
Expand Down
2 changes: 1 addition & 1 deletion nix/sources.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
let
overlays =
builtins.fetchTarball
https://github.com/anmonteiro/nix-overlays/archive/58960d0.tar.gz;
https://github.com/anmonteiro/nix-overlays/archive/becef04.tar.gz;

in
import "${overlays}/sources.nix" {
Expand Down

0 comments on commit abab9cb

Please # to comment.