summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2013-07-04 00:51:06 -0400
committerjoe <joe@jerkface.net>2013-07-04 00:51:06 -0400
commit6050a8d12a203f35fea3228e11c5ecce89558935 (patch)
tree1903f06fd5afb8bd234e49ecf02731613206458c
parent5d045775732fdc4af4bf67e441aa904de9632153 (diff)
whosocket.hs demonstrates acquiring uid,pid,tty/display from
a local socket address and port number.
-rw-r--r--Presence/ControlMaybe.hs9
-rw-r--r--Presence/LocalPeerCred.hs6
-rw-r--r--Presence/XMPP.hs42
-rw-r--r--whosocket.hs91
4 files changed, 123 insertions, 25 deletions
diff --git a/Presence/ControlMaybe.hs b/Presence/ControlMaybe.hs
index e277df12..37f6f93c 100644
--- a/Presence/ControlMaybe.hs
+++ b/Presence/ControlMaybe.hs
@@ -1,5 +1,9 @@
1{-# LANGUAGE ScopedTypeVariables #-}
1module ControlMaybe where 2module ControlMaybe where
2 3
4-- import GHC.IO.Exception (IOException(..))
5import Control.Exception as Exception (IOException(..),catch)
6
3withJust (Just x) f = f x 7withJust (Just x) f = f x
4withJust Nothing f = return () 8withJust Nothing f = return ()
5 9
@@ -8,3 +12,8 @@ whenJust acn f = do
8 withJust x f 12 withJust x f
9 13
10 14
15catchIO_ :: IO a -> IO a -> IO a
16catchIO_ a h = Exception.catch a (\(_ :: IOException) -> h)
17
18handleIO_ = flip catchIO_
19
diff --git a/Presence/LocalPeerCred.hs b/Presence/LocalPeerCred.hs
index d3b8d189..b6ec9491 100644
--- a/Presence/LocalPeerCred.hs
+++ b/Presence/LocalPeerCred.hs
@@ -57,7 +57,7 @@ getLocalPeerCred sock = do
57 addr <- getPeerName sock 57 addr <- getPeerName sock
58 muid <- getLocalPeerCred' addr 58 muid <- getLocalPeerCred' addr
59 case muid of 59 case muid of
60 Just uid -> return (Just uid) 60 Just (uid,inode) -> return (Just uid)
61 Nothing -> trace "proc failed." $ fmap (validate . CUid . fromIntegral . sndOf3) (getPeerCred sock) 61 Nothing -> trace "proc failed." $ fmap (validate . CUid . fromIntegral . sndOf3) (getPeerCred sock)
62 where sndOf3 (pid,uid,gid) = uid 62 where sndOf3 (pid,uid,gid) = uid
63 where 63 where
@@ -81,10 +81,12 @@ parseProcNet port host h = do
81 addr <- fmap parseHex $ listToMaybe zs 81 addr <- fmap parseHex $ listToMaybe zs
82 port <- fmap (fromIntegral . as16 . decode . parseHex) $ listToMaybe $ snd (Prelude.splitAt 1 zs) 82 port <- fmap (fromIntegral . as16 . decode . parseHex) $ listToMaybe $ snd (Prelude.splitAt 1 zs)
83 let ys' = snd (Prelude.splitAt 5 (tail ys)) 83 let ys' = snd (Prelude.splitAt 5 (tail ys))
84 ys'' = snd (Prelude.splitAt 2 ys')
84 uid <- listToMaybe ys' 85 uid <- listToMaybe ys'
86 inode <- listToMaybe ys''
85 let peer = (port,decode addr) 87 let peer = (port,decode addr)
86 user = toEnum (read (unpack uid) ::Int) ::UserID -- CUid . fromIntegral $ (read (unpack uid)::Int) 88 user = toEnum (read (unpack uid) ::Int) ::UserID -- CUid . fromIntegral $ (read (unpack uid)::Int)
87 return $ {- trace ("peer:"++show(peer,user)) -} (peer,user) 89 return $ {-trace ("peer:"++show(peer,user,inode))-} (peer,(user,inode))
88 ) 90 )
89 fmap snd . listToMaybe $ filter ((==(port,host)).fst) rs 91 fmap snd . listToMaybe $ filter ((==(port,host)).fst) rs
90 {- trace ("found: "++show u) -} 92 {- trace ("found: "++show u) -}
diff --git a/Presence/XMPP.hs b/Presence/XMPP.hs
index 3f81f000..d35e5617 100644
--- a/Presence/XMPP.hs
+++ b/Presence/XMPP.hs
@@ -241,21 +241,25 @@ tagName (EventBeginElement n _) = n
241tagName _ = "" 241tagName _ = ""
242 242
243handleIQSetBind session cmdChan stanza_id = do 243handleIQSetBind session cmdChan stanza_id = do
244 whenJust nextElement $ \child -> do 244 mchild <- nextElement
245 let unhandledBind = liftIO $ putStrLn $ "unhandled-bind: "++show child 245 case mchild of
246 case tagName child of 246 Just child -> do
247 "{urn:ietf:params:xml:ns:xmpp-bind}resource" 247 let unhandledBind = liftIO $ putStrLn $ "unhandled-bind: "++show child
248 -> do 248 case tagName child of
249 rsc <- lift content 249 "{urn:ietf:params:xml:ns:xmpp-bind}resource"
250 liftIO $ do 250 -> do
251 putStrLn $ "iq-set-bind-resource " ++ show rsc 251 rsc <- lift content
252 setResource session (L.fromChunks [S.encodeUtf8 rsc]) 252 liftIO $ do
253 jid <- getJID session 253 putStrLn $ "iq-set-bind-resource " ++ show rsc
254 atomically $ writeTChan cmdChan (Send $ iq_bind_reply stanza_id (toStrict $ L.decodeUtf8 $ L.show jid) ) 254 setResource session (L.fromChunks [S.encodeUtf8 rsc])
255 forCachedPresence session $ \presence -> do 255 jid <- getJID session
256 xs <- xmlifyPresenceForClient presence 256 atomically $ writeTChan cmdChan (Send $ iq_bind_reply stanza_id (toStrict $ L.decodeUtf8 $ L.show jid) )
257 atomically . writeTChan cmdChan . Send $ xs 257 forCachedPresence session $ \presence -> do
258 _ -> unhandledBind 258 xs <- xmlifyPresenceForClient presence
259 atomically . writeTChan cmdChan . Send $ xs
260 _ -> unhandledBind
261 Nothing -> do
262 liftIO $ putStrLn $ "empty bind request!"
259 263
260 264
261iq_session_reply host stanza_id = 265iq_session_reply host stanza_id =
@@ -598,14 +602,6 @@ fromPeer session = doNestingXML $ do
598 602
599 603
600 604
601{-
602seekRemotePeers :: XMPPConfig config =>
603 config -> TChan Presence -> IO ()
604seekRemotePeers config chan = do
605 putStrLn "unimplemented: seekRemotePeers"
606 -- TODO
607 return ()
608-}
609 605
610data OutBoundMessage = OutBoundPresence Presence | PresenceProbe JID JID 606data OutBoundMessage = OutBoundPresence Presence | PresenceProbe JID JID
611 deriving Prelude.Show 607 deriving Prelude.Show
diff --git a/whosocket.hs b/whosocket.hs
new file mode 100644
index 00000000..5968b152
--- /dev/null
+++ b/whosocket.hs
@@ -0,0 +1,91 @@
1module Main where
2
3import LocalPeerCred
4import ControlMaybe
5
6import System.Directory
7import Data.Char
8import System.Posix.Types
9import System.Posix.Files
10import Data.ByteString.Lazy.Char8 as L (unpack)
11import Data.List (groupBy)
12import Data.Maybe (listToMaybe)
13
14import Network.Socket
15import System.Environment
16import Control.Arrow (first)
17
18usage = do
19 putStrLn $ "whosocket numeric-address port"
20
21main = do
22 args <- getArgs
23 case (args??0,args??1) of
24 (Just addr_str,Just port_str) -> whosocket addr_str port_str
25 _ -> usage
26
27whosocket addr_str port_str = do
28 info <- getAddrInfo (Just $ defaultHints { addrFlags = [ AI_NUMERICHOST ] })
29 (Just addr_str)
30 (Just port_str)
31 let addr = head $ map addrAddress info
32 r <- getLocalPeerCred' addr
33 putStrLn $ "r{"++show addr++"} = " ++ show r
34
35 let Just (uid,inode) = r
36 pid <- scanProc (show uid) (L.unpack inode)
37 putStrLn $ "scanProc --> "++show pid
38 withJust pid $ \(pid,ttydev) -> do
39 tty <- ttyOrDisplay pid ttydev
40 putStrLn $ "pid = " ++ show pid
41 putStrLn $ "tty = " ++ show tty
42
43 return ()
44
45
46makeUidStr "4294967295" = "invalid"
47makeUidStr uid = uid
48
49
50scanProc uid inode = do
51 contents <- getDirectoryContents "/proc" `catchIO_` return []
52 let pids = reverse $ filter (\n -> not (null n) && isDigit (head n)) contents
53 let searchPids [] = return Nothing
54 searchPids (pid:pids) = do
55 loginuid <- fmap makeUidStr $ readFile $ "/proc/"++pid++"/loginuid"
56 if False -- (uid/=loginuid) -- this check proved bad when mcabber ran on tty3
57 then searchPids pids
58 else do
59 -- putStrLn $ "pid "++show pid ++ " --> uid "++show loginuid
60 let loop [] = return Nothing
61 loop ("0":fds) = loop fds
62 loop (fd:fds) = do
63 handleIO_ (loop fds) $ do
64 what <- readSymbolicLink $ "/proc/"++pid++"/fd/"++fd
65 -- putStrLn $ " what= "++show what
66 if (what=="socket:["++inode++"]")
67 then do
68 tty <- readSymbolicLink $ "/proc/"++pid++"/fd/0"
69 return (Just (pid,tty))
70 else loop fds
71 fds <- getDirectoryContents ("/proc/"++pid++"/fd") `catchIO_` return []
72 mb <- loop fds
73 maybe (searchPids pids) (return . Just) mb
74
75 fmap (fmap (first (read :: String -> CPid))) $ searchPids pids
76
77ttyOrDisplay pid ttydev | take 8 ttydev == "/dev/tty" = return (drop 5 ttydev)
78ttyOrDisplay pid ttydev = do
79 env <- handleIO_ (return "") . readFile $ "/proc/"++show pid++"/environ"
80 let vs = unzero $ groupBy (\_ c->c/='\0') env
81 unzero [] = []
82 unzero (v:vs) = v:map tail vs
83 keyvalue xs = (key,value)
84 where
85 (key,ys) = break (=='=') xs
86 value = case ys of { [] -> []; (_:ys') -> ys' }
87 display = listToMaybe . filter ((=="DISPLAY").fst) . map keyvalue $ vs
88 putStrLn $ "display = " ++ show display
89 case display of
90 Just (_,disp) -> return disp
91 _ -> return ttydev