diff --git a/Data/X509/Ext.hs b/Data/X509/Ext.hs
--- a/Data/X509/Ext.hs
+++ b/Data/X509/Ext.hs
@@ -26,6 +26,7 @@
     , ReasonFlag(..)
     -- * Accessor turning extension into a specific one
     , extensionGet
+    , extensionGetE
     , extensionDecode
     , extensionEncode
     ) where
@@ -79,6 +80,15 @@
                             Just (Right e) -> Just e
                             _              -> findExt xs
 
+-- | Get a specific extension from a lists of raw extensions
+extensionGetE :: Extension a => Extensions -> Maybe (Either String a)
+extensionGetE (Extensions Nothing)  = Nothing
+extensionGetE (Extensions (Just l)) = findExt l
+  where findExt []     = Nothing
+        findExt (x:xs) = case extensionDecode x of
+                            Just r         -> Just r
+                            _              -> findExt xs
+
 -- | Try to decode an ExtensionRaw.
 --
 -- If this function return:
@@ -183,6 +193,8 @@
     | AltNameDNS String
     | AltNameURI String
     | AltNameIP  B.ByteString
+    | AltNameXMPP String
+    | AltNameDNSSRV String
     deriving (Show,Eq,Ord)
 
 -- | Provide a way to supply alternate name that can be
@@ -238,26 +250,59 @@
     --extEncode (ExtCrlDistributionPoints )
 
 parseGeneralNames :: ParseASN1 [AltName]
-parseGeneralNames = do
-    c <- getNextContainer Sequence
-    r <- sequence $ map toStringy c
-    return r
+parseGeneralNames = onNextContainer Sequence $ getMany getAddr
   where
-        toStringy (Other Context 1 b) = return $ AltNameRFC822 $ BC.unpack b
-        toStringy (Other Context 2 b) = return $ AltNameDNS $ BC.unpack b
-        toStringy (Other Context 6 b) = return $ AltNameURI $ BC.unpack b
-        toStringy (Other Context 7 b) = return $ AltNameIP  b
-        toStringy b                   = throwError ("GeneralNames: not coping with anything else " ++ show b)
+        getAddr = do
+            m <- onNextContainerMaybe (Container Context 0) getComposedAddr
+            case m of
+                Nothing -> getSimpleAddr
+                Just r  -> return r
+        getComposedAddr = do
+            n <- getNext
+            case n of
+                OID [1,3,6,1,5,5,7,8,5] -> do -- xmpp addr
+                    c <- getNextContainerMaybe (Container Context 0)
+                    case c of
+                        Just [ASN1String cs] ->
+                            case asn1CharacterToString cs of
+                                Nothing -> throwError ("GeneralNames: invalid string for XMPP Addr")
+                                Just s  -> return $ AltNameXMPP s
+                        _ -> throwError ("GeneralNames: expecting string for XMPP Addr got: " ++ show c)
+                OID [1,3,6,1,5,5,7,8,7] -> do -- DNSSRV addr
+                    c <- getNextContainerMaybe (Container Context 0)
+                    case c of
+                        Just [ASN1String cs] ->
+                            case asn1CharacterToString cs of
+                                Nothing -> throwError ("GeneralNames: invalid string for DNSSrv Addr")
+                                Just s  -> return $ AltNameDNSSRV s
+                        _ -> throwError ("GeneralNames: expecting string for DNSSRV Addr got: " ++ show c)
+                OID unknown -> throwError ("GeneralNames: unknown OID " ++ show unknown)
+                _           -> throwError ("GeneralNames: expecting OID but got " ++ show n)
 
+        getSimpleAddr = do
+            n <- getNext
+            case n of
+                (Other Context 1 b) -> return $ AltNameRFC822 $ BC.unpack b
+                (Other Context 2 b) -> return $ AltNameDNS $ BC.unpack b
+                (Other Context 6 b) -> return $ AltNameURI $ BC.unpack b
+                (Other Context 7 b) -> return $ AltNameIP  b
+                _                   -> throwError ("GeneralNames: not coping with unknown stream " ++ show n)
+
 encodeGeneralNames :: [AltName] -> [ASN1]
 encodeGeneralNames names =
     [Start Sequence]
-    ++ map encodeAltName names
+    ++ concatMap encodeAltName names
     ++ [End Sequence]
-  where encodeAltName (AltNameRFC822 n) = Other Context 1 $ BC.pack n
-        encodeAltName (AltNameDNS n)    = Other Context 2 $ BC.pack n
-        encodeAltName (AltNameURI n)    = Other Context 6 $ BC.pack n
-        encodeAltName (AltNameIP n)     = Other Context 7 $ n
+  where encodeAltName (AltNameRFC822 n) = [Other Context 1 $ BC.pack n]
+        encodeAltName (AltNameDNS n)    = [Other Context 2 $ BC.pack n]
+        encodeAltName (AltNameURI n)    = [Other Context 6 $ BC.pack n]
+        encodeAltName (AltNameIP n)     = [Other Context 7 $ n]
+        encodeAltName (AltNameXMPP n)   = [Start (Container Context 0),OID[1,3,6,1,5,5,7,8,5]
+                                          ,Start (Container Context 0), ASN1String $ asn1CharacterString UTF8 n, End (Container Context 0)
+                                          ,End (Container Context 0)]
+        encodeAltName (AltNameDNSSRV n) = [Start (Container Context 0),OID[1,3,6,1,5,5,7,8,5]
+                                          ,Start (Container Context 0), ASN1String $ asn1CharacterString UTF8 n, End (Container Context 0)
+                                          ,End (Container Context 0)]
 
 bitsToFlags :: Enum a => BitArray -> [a]
 bitsToFlags bits = concat $ flip map [0..(bitArrayLength bits-1)] $ \i -> do
diff --git a/x509.cabal b/x509.cabal
--- a/x509.cabal
+++ b/x509.cabal
@@ -1,5 +1,5 @@
 Name:                x509
-Version:             1.4.12
+Version:             1.4.13
 Description:         X509 reader and writer
 License:             BSD3
 License-file:        LICENSE
