|
|
|
@ -85,11 +85,14 @@ xpFailure = xpWrap |
|
|
|
xpPrim |
|
|
|
xpPrim |
|
|
|
(xpUnit) |
|
|
|
(xpUnit) |
|
|
|
(xpUnit)))) |
|
|
|
(xpUnit)))) |
|
|
|
|
|
|
|
|
|
|
|
-- Challenge element pickler. |
|
|
|
-- Challenge element pickler. |
|
|
|
xpChallenge :: PU [Node] (Maybe Text.Text) |
|
|
|
xpChallenge :: PU [Node] (Maybe Text.Text) |
|
|
|
xpChallenge = xpElemNodes "{urn:ietf:params:xml:ns:xmpp-sasl}challenge" |
|
|
|
xpChallenge = xpElemNodes "{urn:ietf:params:xml:ns:xmpp-sasl}challenge" |
|
|
|
(xpOption $ xpContent xpId) |
|
|
|
(xpOption $ xpContent xpId) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- | pickler for SaslElement |
|
|
|
|
|
|
|
xpSaslElement :: PU [Node] SaslElement |
|
|
|
xpSaslElement = xpAlt saslSel |
|
|
|
xpSaslElement = xpAlt saslSel |
|
|
|
[ xpWrap SaslSuccess (\(SaslSuccess x) -> x) xpSuccess |
|
|
|
[ xpWrap SaslSuccess (\(SaslSuccess x) -> x) xpSuccess |
|
|
|
, xpWrap SaslChallenge (\(SaslChallenge c) -> c) xpChallenge |
|
|
|
, xpWrap SaslChallenge (\(SaslChallenge c) -> c) xpChallenge |
|
|
|
@ -98,6 +101,7 @@ xpSaslElement = xpAlt saslSel |
|
|
|
saslSel (SaslSuccess _) = 0 |
|
|
|
saslSel (SaslSuccess _) = 0 |
|
|
|
saslSel (SaslChallenge _) = 1 |
|
|
|
saslSel (SaslChallenge _) = 1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- | Add quotationmarks around a byte string |
|
|
|
quote :: BS.ByteString -> BS.ByteString |
|
|
|
quote :: BS.ByteString -> BS.ByteString |
|
|
|
quote x = BS.concat ["\"",x,"\""] |
|
|
|
quote x = BS.concat ["\"",x,"\""] |
|
|
|
|
|
|
|
|
|
|
|
@ -105,6 +109,7 @@ saslInit :: Text.Text -> Maybe BS.ByteString -> SaslM Bool |
|
|
|
saslInit mechanism payload = lift . pushElement . saslInitE mechanism $ |
|
|
|
saslInit mechanism payload = lift . pushElement . saslInitE mechanism $ |
|
|
|
Text.decodeUtf8 . B64.encode <$> payload |
|
|
|
Text.decodeUtf8 . B64.encode <$> payload |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- | Pull the next element |
|
|
|
pullSaslElement :: SaslM SaslElement |
|
|
|
pullSaslElement :: SaslM SaslElement |
|
|
|
pullSaslElement = do |
|
|
|
pullSaslElement = do |
|
|
|
el <- lift $ pullPickle (xpEither xpFailure xpSaslElement) |
|
|
|
el <- lift $ pullPickle (xpEither xpFailure xpSaslElement) |
|
|
|
@ -112,6 +117,7 @@ pullSaslElement = do |
|
|
|
Left e ->throwError $ AuthSaslFailure e |
|
|
|
Left e ->throwError $ AuthSaslFailure e |
|
|
|
Right r -> return r |
|
|
|
Right r -> return r |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- | Pull the next element, checking that it is a challenge |
|
|
|
pullChallenge :: SaslM (Maybe BS.ByteString) |
|
|
|
pullChallenge :: SaslM (Maybe BS.ByteString) |
|
|
|
pullChallenge = do |
|
|
|
pullChallenge = do |
|
|
|
e <- pullSaslElement |
|
|
|
e <- pullSaslElement |
|
|
|
@ -122,10 +128,12 @@ pullChallenge = do |
|
|
|
-> return $ Just sc |
|
|
|
-> return $ Just sc |
|
|
|
_ -> throwError AuthChallengeError |
|
|
|
_ -> throwError AuthChallengeError |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- | Extract value from Just, failing with AuthChallengeError on Nothing |
|
|
|
saslFromJust :: Maybe a -> SaslM a |
|
|
|
saslFromJust :: Maybe a -> SaslM a |
|
|
|
saslFromJust Nothing = throwError $ AuthChallengeError |
|
|
|
saslFromJust Nothing = throwError $ AuthChallengeError |
|
|
|
saslFromJust (Just d) = return d |
|
|
|
saslFromJust (Just d) = return d |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- | Pull the next element and check that it is success |
|
|
|
pullSuccess :: SaslM (Maybe Text.Text) |
|
|
|
pullSuccess :: SaslM (Maybe Text.Text) |
|
|
|
pullSuccess = do |
|
|
|
pullSuccess = do |
|
|
|
e <- pullSaslElement |
|
|
|
e <- pullSaslElement |
|
|
|
@ -133,6 +141,8 @@ pullSuccess = do |
|
|
|
SaslSuccess x -> return x |
|
|
|
SaslSuccess x -> return x |
|
|
|
_ -> throwError $ AuthXmlError |
|
|
|
_ -> throwError $ AuthXmlError |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- | Pull the next element. When it's success, return it's payload. |
|
|
|
|
|
|
|
-- If it's a challenge, send an empty response and pull success |
|
|
|
pullFinalMessage :: SaslM (Maybe Text.Text) |
|
|
|
pullFinalMessage :: SaslM (Maybe Text.Text) |
|
|
|
pullFinalMessage = do |
|
|
|
pullFinalMessage = do |
|
|
|
challenge2 <- pullSaslElement |
|
|
|
challenge2 <- pullSaslElement |
|
|
|
@ -143,11 +153,13 @@ pullFinalMessage = do |
|
|
|
pullSuccess |
|
|
|
pullSuccess |
|
|
|
return x |
|
|
|
return x |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- | Extract p=q pairs from a challenge |
|
|
|
toPairs :: BS.ByteString -> SaslM Pairs |
|
|
|
toPairs :: BS.ByteString -> SaslM Pairs |
|
|
|
toPairs ctext = case pairs ctext of |
|
|
|
toPairs ctext = case pairs ctext of |
|
|
|
Left _e -> throwError AuthChallengeError |
|
|
|
Left _e -> throwError AuthChallengeError |
|
|
|
Right r -> return r |
|
|
|
Right r -> return r |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- | Send a SASL response element. The content will be base64-encoded for you |
|
|
|
respond :: Maybe BS.ByteString -> SaslM Bool |
|
|
|
respond :: Maybe BS.ByteString -> SaslM Bool |
|
|
|
respond = lift . pushElement . saslResponseE . |
|
|
|
respond = lift . pushElement . saslResponseE . |
|
|
|
fmap (Text.decodeUtf8 . B64.encode) |
|
|
|
fmap (Text.decodeUtf8 . B64.encode) |
|
|
|
|