Skip to content
This repository has been archived by the owner on Aug 18, 2020. It is now read-only.

Commit

Permalink
[CO-389] Patch x509 parseSAN function to encode IP to valid bytes
Browse files Browse the repository at this point in the history
Turns out that we can't use the 'encode' function from Net.IP as it generates
invalid encoding for x509. I left a NOTE explaining what's going on such that
next readers will know what's going on.
  • Loading branch information
KtorZ committed Sep 24, 2018
1 parent c68ec9c commit d17c915
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 4 deletions.
1 change: 1 addition & 0 deletions x509/cardano-sl-x509.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ library
, filepath
, hourglass
, ip
, network-transport
, optparse-applicative
, text
, universum
Expand Down
34 changes: 30 additions & 4 deletions x509/src/Data/X509/Extra.hs
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,19 @@ import Data.X509.CertificateStore (CertificateStore,
makeCertificateStore)
import Data.X509.Validation
import Net.IP (IP)
import Net.IPv4 (IPv4 (..))
import Net.IPv6 (IPv6 (..))
import Network.Transport.Internal (encodeWord32)

import qualified Crypto.PubKey.RSA.Types as RSA
import qualified Data.ByteString as BS
import qualified Data.ByteString.Base64 as Base64
import qualified Data.ByteString.Builder as BS
import qualified Data.ByteString.Char8 as B8
import qualified Data.ByteString.Lazy as BL
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import qualified Net.IP as IP
import qualified Net.IPv4 as IPv4
import qualified Net.IPv6 as IPv6


--
Expand Down Expand Up @@ -175,10 +177,34 @@ parseSAN :: String -> AltName
parseSAN name =
case IP.decode (toText name) of
Just ip ->
AltNameIP . T.encodeUtf8 $ IP.case_ IPv4.encode IPv6.encode ip
AltNameIP $ IP.case_ ipv4ToBS ipv6ToBS ip

Nothing ->
AltNameDNS name
where
-- NOTE
-- Here, we define custom encoding functions and aren't using the ones
-- defined in `Net.IP`, `Net.IPv4` or `Net.IPv6`.
-- Those methods lead to invalid encodings for the underlying x509 certificates.
--
-- From the RFC 3779 (https://datatracker.ietf.org/doc/rfc3779):
--
-- > IP v4 address - a 32-bit identifier written as four decimal numbers,
-- > each in the range 0 to 255, separated by a ".". 10.5.0.5 is an
-- > example of an IPv4 address.
-- >
-- > IP v6 address - a 128-bit identifier written as eight hexadecimal
-- > quantities, each in the range 0 to ffff, separated by a ":".
-- > 2001:0:200:3:0:0:0:1 is an example of an IPv6 address. One string
-- > of :0: fields may be replaced by "::", thus 2001:0:200:3::1
-- > represents the same address as the immediately preceding example.
ipv4ToBS :: IPv4 -> ByteString
ipv4ToBS (IPv4 bytes) =
encodeWord32 bytes

ipv6ToBS :: IPv6 -> ByteString
ipv6ToBS (IPv6 a b) =
BL.toStrict $ BS.toLazyByteString (BS.word64BE a <> BS.word64BE b)


--
Expand Down Expand Up @@ -282,7 +308,7 @@ validateCertificateIP ip cert =
toCommonName =
asn1CharacterToString >=> (ipFromBytes . B8.pack)
in
if any (== ip) (maybeToList commonName ++ altNames) then
if ip `elem` (maybeToList commonName ++ altNames) then
[]
else
[NameMismatch $ T.unpack $ IP.encode ip]

0 comments on commit d17c915

Please sign in to comment.