summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2018-05-19 18:33:40 -0400
committerjoe <joe@jerkface.net>2018-05-19 18:33:40 -0400
commit5fc282406abfe8cfb11ff0ce29562e334fb95755 (patch)
treea05f35bb2865e7b097861d6e564b113d042e90dd
parentea3c97cea6cb2a690afca743fa8fecfbb533d69b (diff)
Activate tox user key from xmpp configuration.
-rw-r--r--Connection.hs1
-rw-r--r--Presence/ConfigFiles.hs2
-rw-r--r--Presence/Presence.hs34
-rw-r--r--Presence/XMPPServer.hs26
-rw-r--r--examples/dhtd.hs19
5 files changed, 61 insertions, 21 deletions
diff --git a/Connection.hs b/Connection.hs
index 3287bc1b..a3004c11 100644
--- a/Connection.hs
+++ b/Connection.hs
@@ -19,6 +19,7 @@ data Policy
19 = RefusingToConnect 19 = RefusingToConnect
20 | OpenToConnect 20 | OpenToConnect
21 | TryingToConnect 21 | TryingToConnect
22 deriving (Eq,Ord,Show)
22 23
23data Connection status = Connection 24data Connection status = Connection
24 { connStatus :: STM (Status status) 25 { connStatus :: STM (Status status)
diff --git a/Presence/ConfigFiles.hs b/Presence/ConfigFiles.hs
index d405bd8f..6354d841 100644
--- a/Presence/ConfigFiles.hs
+++ b/Presence/ConfigFiles.hs
@@ -30,7 +30,7 @@ subscriberFile = "subscribers"
30otherFile = "others" 30otherFile = "others"
31pendingFile = "pending" 31pendingFile = "pending"
32solicitedFile = "solicited" 32solicitedFile = "solicited"
33secretsFile = "secrets" 33secretsFile = "secret"
34 34
35 35
36configPath :: User -> Profile -> String -> IO String 36configPath :: User -> Profile -> String -> IO String
diff --git a/Presence/Presence.hs b/Presence/Presence.hs
index 97b9d5b8..198012de 100644
--- a/Presence/Presence.hs
+++ b/Presence/Presence.hs
@@ -5,7 +5,9 @@
5{-# LANGUAGE TupleSections #-} 5{-# LANGUAGE TupleSections #-}
6module Presence where 6module Presence where
7 7
8import System.Directory
8import System.Environment 9import System.Environment
10import System.IO.Error
9import System.Posix.Signals 11import System.Posix.Signals
10import Control.Concurrent (threadDelay,forkIO,forkOS,killThread,throwTo) 12import Control.Concurrent (threadDelay,forkIO,forkOS,killThread,throwTo)
11import Control.Concurrent.STM 13import Control.Concurrent.STM
@@ -15,6 +17,7 @@ import Control.Monad.Trans
15import Control.Monad.IO.Class (MonadIO, liftIO) 17import Control.Monad.IO.Class (MonadIO, liftIO)
16import Network.Socket ( SockAddr(..), PortNumber ) 18import Network.Socket ( SockAddr(..), PortNumber )
17import System.Endian (fromBE32) 19import System.Endian (fromBE32)
20import Data.Char
18import Data.List (nub, (\\), intersect, groupBy, sort, sortBy ) 21import Data.List (nub, (\\), intersect, groupBy, sort, sortBy )
19import Data.Ord (comparing ) 22import Data.Ord (comparing )
20import Data.Monoid ( (<>), Sum(..), getSum ) 23import Data.Monoid ( (<>), Sum(..), getSum )
@@ -46,6 +49,7 @@ import Crypto.Error
46#endif 49#endif
47import Crypto.PubKey.Curve25519 (SecretKey,toPublic) 50import Crypto.PubKey.Curve25519 (SecretKey,toPublic)
48import Text.Read (readMaybe) 51import Text.Read (readMaybe)
52import System.IO
49 53
50import LockedChan (LockedChan) 54import LockedChan (LockedChan)
51import TraversableT 55import TraversableT
@@ -57,7 +61,7 @@ import ConsoleWriter
57import ClientState 61import ClientState
58import Util 62import Util
59import qualified Connection 63import qualified Connection
60import Network.Tox.NodeId (id2key) 64import Network.Tox.NodeId (id2key,key2id)
61import Crypto.Tox (decodeSecret) 65import Crypto.Tox (decodeSecret)
62 66
63isPeerKey :: ConnectionKey -> Bool 67isPeerKey :: ConnectionKey -> Bool
@@ -124,11 +128,22 @@ newPresenceState cw toxman xmpp = atomically $ do
124 } 128 }
125 129
126 130
131nameForClient :: PresenceState -> ConnectionKey -> IO Text
132nameForClient state k = do
133 mc <- atomically $ do
134 cmap <- readTVar (clients state)
135 return $ Map.lookup k cmap
136 case mc of
137 Nothing -> textHostName
138 Just client -> case clientProfile client of
139 "." -> textHostName
140 profile -> return profile
141
127presenceHooks :: PresenceState -> Int -> Maybe PortNumber -> XMPPServerParameters 142presenceHooks :: PresenceState -> Int -> Maybe PortNumber -> XMPPServerParameters
128presenceHooks state verbosity mport = XMPPServerParameters 143presenceHooks state verbosity mport = XMPPServerParameters
129 { xmppChooseResourceName = chooseResourceName state 144 { xmppChooseResourceName = chooseResourceName state
130 , xmppTellClientHisName = tellClientHisName state 145 , xmppTellClientHisName = tellClientHisName state
131 , xmppTellMyNameToClient = textHostName 146 , xmppTellMyNameToClient = nameForClient state
132 , xmppTellMyNameToPeer = \addr -> return $ addrToText addr 147 , xmppTellMyNameToPeer = \addr -> return $ addrToText addr
133 , xmppTellPeerHisName = return . peerKeyToText 148 , xmppTellPeerHisName = return . peerKeyToText
134 , xmppTellClientNameOfPeer = flip peerKeyToResolvedName 149 , xmppTellClientNameOfPeer = flip peerKeyToResolvedName
@@ -212,22 +227,29 @@ chooseResourceName state k addr clientsNameForMe desired = do
212 status <- atomically $ newTVar Nothing 227 status <- atomically $ newTVar Nothing
213 flgs <- atomically $ newTVar 0 228 flgs <- atomically $ newTVar 0
214 profile <- fmap (fromMaybe ".") 229 profile <- fmap (fromMaybe ".")
215 $ forM ((,) <$> clientsNameForMe <*> toxManager state) $ \(wanted_profile,toxman) -> 230 $ forM ((,) <$> clientsNameForMe <*> toxManager state) $ \(wanted_profile0,toxman) ->
216 case Text.splitAt 43 wanted_profile of 231 case Text.splitAt 43 wanted_profile0 of
217 (pub,".tox") -> do 232 (pub,".tox") -> do
218 -- TODO: Tox key profile. 233 cdir <- ConfigFiles.configPath (L.fromChunks [Text.encodeUtf8 user]) "." ""
234 cfs <- map Text.pack <$> listDirectory cdir `catchIOError` (\e -> return [])
235 let profiles = filter (\f -> Text.toLower f == Text.toLower wanted_profile0) cfs
236 -- hPutStrLn stderr $ "Toxmpp profile " ++ show (user,wanted_profile0,profiles,cfs)
237 let wanted_profile = head $ profiles ++ [wanted_profile0]
219 secs <- configText ConfigFiles.getSecrets user wanted_profile 238 secs <- configText ConfigFiles.getSecrets user wanted_profile
220 case secs of 239 case secs of
221 sec:_ | Just s <- decodeSecret (Text.encodeUtf8 sec) 240 sec:_ | Just s <- decodeSecret (Text.encodeUtf8 sec)
222 , Just (toPublic s) == fmap id2key (readMaybe $ Text.unpack pub) 241 , map toLower (show $ key2id $ toPublic s) == map toLower (Text.unpack pub)
223 -> do activateAccount toxman k wanted_profile s 242 -> do activateAccount toxman k wanted_profile s
243 hPutStrLn stderr $ "loaded tox secret " ++ show sec
224 return wanted_profile 244 return wanted_profile
225 _ -> do 245 _ -> do
226 -- XXX: We should probably fail to connect when an 246 -- XXX: We should probably fail to connect when an
227 -- invalid Tox profile is used. For now, we'll 247 -- invalid Tox profile is used. For now, we'll
228 -- fall back to the Unix account login. 248 -- fall back to the Unix account login.
249 hPutStrLn stderr "failed to find tox secret"
229 return "." 250 return "."
230 ("*.tox","") -> do 251 ("*.tox","") -> do
252 hPutStrLn stderr $ "TODO: Match single tox key profile or generate first."
231 -- TODO: Match single tox key profile or generate first. 253 -- TODO: Match single tox key profile or generate first.
232 _todo 254 _todo
233 _ -> return "." 255 _ -> return "."
diff --git a/Presence/XMPPServer.hs b/Presence/XMPPServer.hs
index c9132d0f..bc5e88da 100644
--- a/Presence/XMPPServer.hs
+++ b/Presence/XMPPServer.hs
@@ -89,6 +89,7 @@ import System.Endian (toBE32)
89import Control.Applicative 89import Control.Applicative
90import System.IO 90import System.IO
91import qualified Connection 91import qualified Connection
92import Util
92 93
93peerport :: PortNumber 94peerport :: PortNumber
94peerport = 5269 95peerport = 5269
@@ -182,9 +183,12 @@ data XMPPServerParameters =
182 { -- | Called when a client requests a resource id. The first Maybe indicates 183 { -- | Called when a client requests a resource id. The first Maybe indicates
183 -- the name the client referred to this server by. The second Maybe is the 184 -- the name the client referred to this server by. The second Maybe is the
184 -- client's preferred resource name. 185 -- client's preferred resource name.
186 --
187 -- Note: The returned domain will be discarded and replaced with the result of
188 -- 'xmppTellMyNameToClient'.
185 xmppChooseResourceName :: ConnectionKey -> SockAddr -> Maybe Text -> Maybe Text -> IO Text 189 xmppChooseResourceName :: ConnectionKey -> SockAddr -> Maybe Text -> Maybe Text -> IO Text
186 , -- | This should indicate the server's hostname that all client's see. 190 , -- | This should indicate the server's hostname that all client's see.
187 xmppTellMyNameToClient :: IO Text 191 xmppTellMyNameToClient :: ConnectionKey -> IO Text
188 , xmppTellMyNameToPeer :: SockAddr -> IO Text 192 , xmppTellMyNameToPeer :: SockAddr -> IO Text
189 , xmppTellClientHisName :: ConnectionKey -> IO Text 193 , xmppTellClientHisName :: ConnectionKey -> IO Text
190 , xmppTellPeerHisName :: ConnectionKey -> IO Text 194 , xmppTellPeerHisName :: ConnectionKey -> IO Text
@@ -896,7 +900,7 @@ xmppInbound :: Server ConnectionKey SockAddr ReleaseKey XML.Event
896xmppInbound sv xmpp k laddr pingflag stanzas output donevar = doNestingXML $ do 900xmppInbound sv xmpp k laddr pingflag stanzas output donevar = doNestingXML $ do
897 let (namespace,tellmyname,tellyourname) = case k of 901 let (namespace,tellmyname,tellyourname) = case k of
898 ClientKey {} -> ( "jabber:client" 902 ClientKey {} -> ( "jabber:client"
899 , xmppTellMyNameToClient xmpp 903 , xmppTellMyNameToClient xmpp k
900 , xmppTellClientHisName xmpp k 904 , xmppTellClientHisName xmpp k
901 ) 905 )
902 PeerKey {} -> ( "jabber:server" 906 PeerKey {} -> ( "jabber:server"
@@ -1240,7 +1244,7 @@ forkConnection :: Server ConnectionKey SockAddr ReleaseKey XML.Event
1240 -> IO (TChan Stanza) 1244 -> IO (TChan Stanza)
1241forkConnection sv xmpp k laddr pingflag src snk stanzas = do 1245forkConnection sv xmpp k laddr pingflag src snk stanzas = do
1242 let (namespace,tellmyname) = case k of 1246 let (namespace,tellmyname) = case k of
1243 ClientKey {} -> ("jabber:client", xmppTellMyNameToClient xmpp) 1247 ClientKey {} -> ("jabber:client", xmppTellMyNameToClient xmpp k)
1244 PeerKey {} -> ("jabber:server",xmppTellMyNameToPeer xmpp laddr) 1248 PeerKey {} -> ("jabber:server",xmppTellMyNameToPeer xmpp laddr)
1245 me <- tellmyname 1249 me <- tellmyname
1246 rdone <- atomically newEmptyTMVar 1250 rdone <- atomically newEmptyTMVar
@@ -1413,14 +1417,15 @@ xmlifyRosterItems solicited stype set = mapM_ item (Set.toList set)
1413sendRoster :: 1417sendRoster ::
1414 StanzaWrap a 1418 StanzaWrap a
1415 -> XMPPServerParameters 1419 -> XMPPServerParameters
1420 -> ConnectionKey
1416 -> TChan Stanza 1421 -> TChan Stanza
1417 -> IO () 1422 -> IO ()
1418sendRoster query xmpp replyto = do 1423sendRoster query xmpp clientKey replyto = do
1419 let k = case stanzaOrigin query of 1424 let k = case stanzaOrigin query of
1420 NetworkOrigin k _ -> Just k 1425 NetworkOrigin k _ -> Just k
1421 LocalPeer -> Nothing -- local peer requested roster? 1426 LocalPeer -> Nothing -- local peer requested roster?
1422 flip (maybe $ return ()) k $ \k -> do 1427 flip (maybe $ return ()) k $ \k -> do
1423 hostname <- xmppTellMyNameToClient xmpp 1428 hostname <- xmppTellMyNameToClient xmpp clientKey
1424 let getlist f = do 1429 let getlist f = do
1425 bs <- f xmpp k 1430 bs <- f xmpp k
1426 return (Set.fromList bs) -- js) 1431 return (Set.fromList bs) -- js)
@@ -1679,10 +1684,11 @@ monitor sv params xmpp = do
1679 case stanzaType stanza of 1684 case stanzaType stanza of
1680 RequestResource clientsNameForMe wanted -> do 1685 RequestResource clientsNameForMe wanted -> do
1681 sockaddr <- socketFromKey sv k 1686 sockaddr <- socketFromKey sv k
1682 rsc <- xmppChooseResourceName xmpp k sockaddr clientsNameForMe wanted 1687 rsc0 <- xmppChooseResourceName xmpp k sockaddr clientsNameForMe wanted
1688 hostname <- xmppTellMyNameToClient xmpp k
1689 let rsc = unsplitJID (n,hostname,r) where (n,_,r) = splitJID rsc0
1683 let reply = iq_bind_reply (stanzaId stanza) rsc 1690 let reply = iq_bind_reply (stanzaId stanza) rsc
1684 -- sendReply quitVar SetResource reply replyto 1691 -- sendReply quitVar SetResource reply replyto
1685 hostname <- xmppTellMyNameToClient xmpp
1686 let requestVersion :: Producer IO XML.Event 1692 let requestVersion :: Producer IO XML.Event
1687 requestVersion = do 1693 requestVersion = do
1688 yield $ EventBeginElement "{jabber:client}iq" 1694 yield $ EventBeginElement "{jabber:client}iq"
@@ -1711,11 +1717,11 @@ monitor sv params xmpp = do
1711 requestVersion 1717 requestVersion
1712 >>= ioWriteChan replyto 1718 >>= ioWriteChan replyto
1713 SessionRequest -> do 1719 SessionRequest -> do
1714 me <- xmppTellMyNameToClient xmpp 1720 me <- xmppTellMyNameToClient xmpp k
1715 let reply = iq_session_reply (stanzaId stanza) me 1721 let reply = iq_session_reply (stanzaId stanza) me
1716 sendReply quitVar Pong reply replyto 1722 sendReply quitVar Pong reply replyto
1717 RequestRoster -> do 1723 RequestRoster -> do
1718 sendRoster stanza xmpp replyto 1724 sendRoster stanza xmpp k replyto
1719 xmppSubscribeToRoster xmpp k 1725 xmppSubscribeToRoster xmpp k
1720 PresenceStatus {} -> do 1726 PresenceStatus {} -> do
1721 xmppInformClientPresence xmpp k stanza 1727 xmppInformClientPresence xmpp k stanza
@@ -1728,7 +1734,7 @@ monitor sv params xmpp = do
1728 NotifyClientVersion name version -> do 1734 NotifyClientVersion name version -> do
1729 enableClientHacks name version replyto 1735 enableClientHacks name version replyto
1730 UnrecognizedQuery query -> do 1736 UnrecognizedQuery query -> do
1731 me <- xmppTellMyNameToClient xmpp 1737 me <- xmppTellMyNameToClient xmpp k
1732 let reply = iq_service_unavailable (stanzaId stanza) me query 1738 let reply = iq_service_unavailable (stanzaId stanza) me query
1733 sendReply quitVar (Error ServiceUnavailable (head reply)) reply replyto 1739 sendReply quitVar (Error ServiceUnavailable (head reply)) reply replyto
1734 Message {} -> do 1740 Message {} -> do
diff --git a/examples/dhtd.hs b/examples/dhtd.hs
index fcb02ace..3e48e4bb 100644
--- a/examples/dhtd.hs
+++ b/examples/dhtd.hs
@@ -38,6 +38,7 @@ import qualified Data.IntMap.Strict as IntMap
38import qualified Data.Map.Strict as Map 38import qualified Data.Map.Strict as Map
39import Data.Maybe 39import Data.Maybe
40import qualified Data.Set as Set 40import qualified Data.Set as Set
41import Data.Tuple
41import Data.Time.Clock 42import Data.Time.Clock
42import qualified Data.XML.Types as XML 43import qualified Data.XML.Types as XML
43import GHC.Conc (threadStatus,ThreadStatus(..)) 44import GHC.Conc (threadStatus,ThreadStatus(..))
@@ -587,7 +588,10 @@ clientSession s@Session{..} sock cnum h = do
587 ++ [mappend " *" . show . Tox.key2id $ pubkey] 588 ++ [mappend " *" . show . Tox.key2id $ pubkey]
588 switchKey $ Just pubkey 589 switchKey $ Just pubkey
589 | "secrets" <- strp s -> cmd0 $ do 590 | "secrets" <- strp s -> cmd0 $ do
590 ks <- atomically $ readTVar userkeys 591 ks <- atomically $ do
592 uks <- readTVar userkeys
593 as <- readTVar (accounts roster)
594 return $ uks ++ map ((userSecret *** Tox.id2key) . swap) (HashMap.toList as)
591 skey <- maybe (return Nothing) (atomically . dhtSecretKey) 595 skey <- maybe (return Nothing) (atomically . dhtSecretKey)
592 $ Map.lookup netname dhts 596 $ Map.lookup netname dhts
593 hPutClient h . showReport $ map mkrow ks ++ case skey >>= encodeSecret of 597 hPutClient h . showReport $ map mkrow ks ++ case skey >>= encodeSecret of
@@ -999,7 +1003,7 @@ sensibleDefaults = Options
999 , ip6bt = True 1003 , ip6bt = True
1000 , ip6tox = True 1004 , ip6tox = True
1001 , dhtkey = Nothing 1005 , dhtkey = Nothing
1002 , verbosity = 1 1006 , verbosity = 2
1003 } 1007 }
1004 1008
1005-- bt=<port>,tox=<port> 1009-- bt=<port>,tox=<port>
@@ -1008,6 +1012,8 @@ parseArgs :: [String] -> Options -> Options
1008parseArgs [] opts = opts 1012parseArgs [] opts = opts
1009parseArgs ("--dhtkey":k:args) opts = parseArgs args opts 1013parseArgs ("--dhtkey":k:args) opts = parseArgs args opts
1010 { dhtkey = decodeSecret $ B.pack k } 1014 { dhtkey = decodeSecret $ B.pack k }
1015parseArgs ("--dht-key":k:args) opts = parseArgs args opts
1016 { dhtkey = decodeSecret $ B.pack k }
1011parseArgs ("-4":args) opts = parseArgs args opts 1017parseArgs ("-4":args) opts = parseArgs args opts
1012 { ip6bt = False 1018 { ip6bt = False
1013 , ip6tox = False } 1019 , ip6tox = False }
@@ -1053,7 +1059,9 @@ newXmmpSink session@(Tox.NCrypto { ncOutgoingQueue, ncPacketQueue }) = C.awaitFo
1053-- XMPP roster. 1059-- XMPP roster.
1054toxman :: Tox.Tox -> ToxManager ConnectionKey 1060toxman :: Tox.Tox -> ToxManager ConnectionKey
1055toxman tox = ToxManager 1061toxman tox = ToxManager
1056 { activateAccount = \k pubname seckey -> atomically $ do 1062 { activateAccount = \k pubname seckey -> do
1063 hPutStrLn stderr $ "toxman ACTIVATE " ++ show (Tox.key2id $ toPublic seckey)
1064 atomically $ do
1057 let ContactInfo{ accounts } = Tox.toxContactInfo tox 1065 let ContactInfo{ accounts } = Tox.toxContactInfo tox
1058 pub = toPublic seckey 1066 pub = toPublic seckey
1059 pubid = Tox.key2id pub 1067 pubid = Tox.key2id pub
@@ -1062,6 +1070,7 @@ toxman tox = ToxManager
1062 acnt <- maybe (newAccount seckey) return macnt 1070 acnt <- maybe (newAccount seckey) return macnt
1063 rs <- readTVar $ clientRefs acnt 1071 rs <- readTVar $ clientRefs acnt
1064 writeTVar (clientRefs acnt) $! Set.insert k rs 1072 writeTVar (clientRefs acnt) $! Set.insert k rs
1073 modifyTVar accounts (HashMap.insert pubid acnt)
1065 return rs 1074 return rs
1066 when (Set.null refs) $ do 1075 when (Set.null refs) $ do
1067 -- Schedule recurring announce. 1076 -- Schedule recurring announce.
@@ -1082,7 +1091,9 @@ toxman tox = ToxManager
1082 -- If this is the last reference to a non-connected contact: 1091 -- If this is the last reference to a non-connected contact:
1083 -- Stop the recurring search for that contact 1092 -- Stop the recurring search for that contact
1084 return () 1093 return ()
1085 , setToxConnectionPolicy = \me them -> \case 1094 , setToxConnectionPolicy = \me them p -> do
1095 hPutStrLn stderr $ "toxman ConnectionPolicy " ++ show (me,them,p)
1096 case p of
1086 TryingToConnect -> do 1097 TryingToConnect -> do
1087 let db@ContactInfo{ accounts } = Tox.toxContactInfo tox 1098 let db@ContactInfo{ accounts } = Tox.toxContactInfo tox
1088 sequence_ $ do 1099 sequence_ $ do