module Data.X509.DistinguishedName
( DistinguishedName(..)
, DistinguishedNameInner(..)
, ASN1CharacterString(..)
, DnElement(..)
, getDnElement
) where
import Control.Applicative
import Data.Monoid
import Data.ASN1.Types
import Data.X509.Internal
newtype DistinguishedName = DistinguishedName { getDistinguishedElements :: [(OID, ASN1CharacterString)] }
deriving (Show,Eq,Ord)
data DnElement =
DnCommonName
| DnCountry
| DnOrganization
| DnOrganizationUnit
| DnEmailAddress
deriving (Show,Eq)
instance OIDable DnElement where
getObjectID DnCommonName = [2,5,4,3]
getObjectID DnCountry = [2,5,4,6]
getObjectID DnOrganization = [2,5,4,10]
getObjectID DnOrganizationUnit = [2,5,4,11]
getObjectID DnEmailAddress = [1,2,840,113549,1,9,1]
getDnElement :: DnElement -> DistinguishedName -> Maybe ASN1CharacterString
getDnElement element (DistinguishedName els) = lookup (getObjectID element) els
newtype DistinguishedNameInner = DistinguishedNameInner DistinguishedName
deriving (Show,Eq)
instance Monoid DistinguishedName where
mempty = DistinguishedName []
mappend (DistinguishedName l1) (DistinguishedName l2) = DistinguishedName (l1++l2)
instance ASN1Object DistinguishedName where
toASN1 dn = \xs -> encodeDN dn ++ xs
fromASN1 = runParseASN1State parseDN
instance ASN1Object DistinguishedNameInner where
toASN1 (DistinguishedNameInner dn) = \xs -> encodeDNinner dn ++ xs
fromASN1 = runParseASN1State (DistinguishedNameInner . DistinguishedName <$> parseDNInner)
parseDN :: ParseASN1 DistinguishedName
parseDN = DistinguishedName <$> onNextContainer Sequence parseDNInner
parseDNInner :: ParseASN1 [(OID, ASN1CharacterString)]
parseDNInner = concat `fmap` getMany parseOneDN
parseOneDN :: ParseASN1 [(OID, ASN1CharacterString)]
parseOneDN = onNextContainer Set $ getMany $ do
s <- getNextContainer Sequence
case s of
[OID oid, ASN1String cs] -> return (oid, cs)
_ -> throwError ("expecting [OID,String] got " ++ show s)
encodeDNinner :: DistinguishedName -> [ASN1]
encodeDNinner (DistinguishedName dn) = concatMap dnSet dn
where dnSet (oid, cs) = asn1Container Set $ asn1Container Sequence [OID oid, ASN1String cs]
encodeDN :: DistinguishedName -> [ASN1]
encodeDN dn = asn1Container Sequence $ encodeDNinner dn