2012-09-08 19:21:34 +00:00
|
|
|
{- git-annex assistant repo pairing, core data types
|
2012-09-07 22:04:06 +00:00
|
|
|
-
|
2015-01-21 16:50:09 +00:00
|
|
|
- Copyright 2012 Joey Hess <id@joeyh.name>
|
2012-09-07 22:04:06 +00:00
|
|
|
-
|
|
|
|
- Licensed under the GNU GPL version 3 or higher.
|
|
|
|
-}
|
|
|
|
|
2013-02-10 19:48:38 +00:00
|
|
|
{-# LANGUAGE CPP #-}
|
|
|
|
|
2012-09-07 22:04:06 +00:00
|
|
|
module Assistant.Pairing where
|
|
|
|
|
2012-09-11 07:16:00 +00:00
|
|
|
import Common.Annex
|
2012-09-08 03:23:52 +00:00
|
|
|
import Utility.Verifiable
|
2012-09-10 19:20:18 +00:00
|
|
|
import Assistant.Ssh
|
2012-09-07 22:04:06 +00:00
|
|
|
|
2012-09-08 17:04:19 +00:00
|
|
|
import Control.Concurrent
|
2012-09-08 19:21:34 +00:00
|
|
|
import Network.Socket
|
2012-09-11 16:26:42 +00:00
|
|
|
import Data.Char
|
|
|
|
import qualified Data.Text as T
|
2012-09-07 22:04:06 +00:00
|
|
|
|
2012-09-09 01:06:10 +00:00
|
|
|
data PairStage
|
|
|
|
{- "I'll pair with anybody who shares the secret that can be used
|
|
|
|
- to verify this request." -}
|
|
|
|
= PairReq
|
|
|
|
{- "I've verified your request, and you can verify this to see
|
|
|
|
- that I know the secret. I set up your ssh key already.
|
|
|
|
- Here's mine for you to set up." -}
|
|
|
|
| PairAck
|
|
|
|
{- "I saw your PairAck; you can stop sending them." -}
|
|
|
|
| PairDone
|
2013-11-02 19:10:29 +00:00
|
|
|
deriving (Eq, Read, Show, Ord, Enum)
|
2012-09-07 22:04:06 +00:00
|
|
|
|
2012-09-11 01:55:59 +00:00
|
|
|
newtype PairMsg = PairMsg (Verifiable (PairStage, PairData, SomeAddr))
|
2012-09-08 04:26:47 +00:00
|
|
|
deriving (Eq, Read, Show)
|
|
|
|
|
2012-09-11 05:00:42 +00:00
|
|
|
verifiedPairMsg :: PairMsg -> PairingInProgress -> Bool
|
|
|
|
verifiedPairMsg (PairMsg m) pip = verify m $ inProgressSecret pip
|
|
|
|
|
2012-09-13 04:57:52 +00:00
|
|
|
fromPairMsg :: PairMsg -> Verifiable (PairStage, PairData, SomeAddr)
|
2012-09-09 01:06:10 +00:00
|
|
|
fromPairMsg (PairMsg m) = m
|
2012-09-08 06:02:39 +00:00
|
|
|
|
2012-09-09 01:06:10 +00:00
|
|
|
pairMsgStage :: PairMsg -> PairStage
|
2012-09-11 01:55:59 +00:00
|
|
|
pairMsgStage (PairMsg (Verifiable (s, _, _) _)) = s
|
2012-09-08 04:26:47 +00:00
|
|
|
|
2012-09-10 21:53:51 +00:00
|
|
|
pairMsgData :: PairMsg -> PairData
|
2012-09-11 01:55:59 +00:00
|
|
|
pairMsgData (PairMsg (Verifiable (_, d, _) _)) = d
|
|
|
|
|
|
|
|
pairMsgAddr :: PairMsg -> SomeAddr
|
|
|
|
pairMsgAddr (PairMsg (Verifiable (_, _, a) _)) = a
|
2012-09-10 21:53:51 +00:00
|
|
|
|
2012-09-08 04:26:47 +00:00
|
|
|
data PairData = PairData
|
2012-09-08 18:23:35 +00:00
|
|
|
-- uname -n output, not a full domain name
|
|
|
|
{ remoteHostName :: Maybe HostName
|
2012-09-08 06:02:39 +00:00
|
|
|
, remoteUserName :: UserName
|
2012-09-08 19:40:47 +00:00
|
|
|
, remoteDirectory :: FilePath
|
2012-09-10 19:20:18 +00:00
|
|
|
, remoteSshPubKey :: SshPubKey
|
2012-09-11 07:16:00 +00:00
|
|
|
, pairUUID :: UUID
|
2012-09-07 22:04:06 +00:00
|
|
|
}
|
|
|
|
deriving (Eq, Read, Show)
|
|
|
|
|
2015-02-09 20:34:57 +00:00
|
|
|
checkSane :: PairData -> Bool
|
|
|
|
checkSane p = all (not . any isControl)
|
|
|
|
[ fromMaybe "" (remoteHostName p)
|
|
|
|
, remoteUserName p
|
|
|
|
, remoteDirectory p
|
|
|
|
, remoteSshPubKey p
|
|
|
|
, fromUUID (pairUUID p)
|
|
|
|
]
|
|
|
|
|
2012-09-08 03:23:52 +00:00
|
|
|
type UserName = String
|
2012-09-08 17:04:19 +00:00
|
|
|
|
2012-09-10 21:53:51 +00:00
|
|
|
{- A pairing that is in progress has a secret, a thread that is
|
|
|
|
- broadcasting pairing messages, and a SshKeyPair that has not yet been
|
|
|
|
- set up on disk. -}
|
2012-09-08 19:30:04 +00:00
|
|
|
data PairingInProgress = PairingInProgress
|
|
|
|
{ inProgressSecret :: Secret
|
2012-09-11 01:55:59 +00:00
|
|
|
, inProgressThreadId :: Maybe ThreadId
|
2012-09-10 19:20:18 +00:00
|
|
|
, inProgressSshKeyPair :: SshKeyPair
|
2012-09-11 01:55:59 +00:00
|
|
|
, inProgressPairData :: PairData
|
2012-09-11 16:58:00 +00:00
|
|
|
, inProgressPairStage :: PairStage
|
2012-09-08 19:30:04 +00:00
|
|
|
}
|
2012-09-11 19:06:29 +00:00
|
|
|
deriving (Show)
|
2012-09-08 17:04:19 +00:00
|
|
|
|
2015-04-19 04:38:29 +00:00
|
|
|
data AddrClass = IPv4AddrClass | IPv6AddrClass
|
|
|
|
|
2013-02-10 19:48:38 +00:00
|
|
|
data SomeAddr = IPv4Addr HostAddress
|
|
|
|
{- My Android build of the Network library does not currently have IPV6
|
|
|
|
- support. -}
|
2013-02-27 06:39:22 +00:00
|
|
|
#ifndef __ANDROID__
|
2013-02-10 19:48:38 +00:00
|
|
|
| IPv6Addr HostAddress6
|
|
|
|
#endif
|
2012-09-08 18:23:35 +00:00
|
|
|
deriving (Ord, Eq, Read, Show)
|
2012-09-11 16:26:42 +00:00
|
|
|
|
|
|
|
{- This contains the whole secret, just lightly obfuscated to make it not
|
|
|
|
- too obvious. It's only displayed in the user's web browser. -}
|
2012-09-13 04:29:25 +00:00
|
|
|
newtype SecretReminder = SecretReminder [Int]
|
2012-09-11 16:26:42 +00:00
|
|
|
deriving (Show, Eq, Ord, Read)
|
|
|
|
|
|
|
|
toSecretReminder :: T.Text -> SecretReminder
|
|
|
|
toSecretReminder = SecretReminder . map ord . T.unpack
|
|
|
|
|
|
|
|
fromSecretReminder :: SecretReminder -> T.Text
|
|
|
|
fromSecretReminder (SecretReminder s) = T.pack $ map chr s
|