{-# LANGUAGE OverloadedStrings #-} module System.Authenticate.SmbClient ( loginSmbClient, SmbClientResult ) where import Control.Applicative import Data.Char import Data.Maybe import Data.Text hiding (head) import Prelude hiding (unlines, null, takeWhile) import System.Exit import System.Process import System.Timeout commandName = "smbclient" -- |The login result type. -- -- If success, return Right with actual username. type SmbClientResult = Either () Text -- |Authenticate with @smbclient@ command. -- -- Return Right if login success, Left otherwise. -- -- This does not accept empty username or password, -- because those has always been success as Guest login. loginSmbClient :: Text -- ^ Server -> Text -- ^ Domain -> Text -- ^ Username -> Text -- ^ Password -> IO SmbClientResult loginSmbClient server domain username password = do timedResult <- timeout (10 * 1000000) process case timedResult of Just result -> return result Nothing -> return $ Left () where domain' = checkedText domain username' = checkedText username password' = checkedText password authInfo dom usr pas = [ "username = " `append` usr, "password = " `append` pas, "domain = " `append` dom] authInfo' = unpack <$> unlines <$> (authInfo <$> domain' <*> username' <*> password') process = case authInfo' of Just a -> validate commandName server a $ Right (fromJust username') _ -> return $ Left () validate command server authInfo successInfo = do (exitCode, _, _) <- readProcessWithExitCode command [ "-L", unpack server, "-A", "/dev/stdin"] authInfo case exitCode of ExitSuccess -> return successInfo _ -> return $ Left () -- |Returns valid words or Nothing. -- -- >>> checkedText $ pack "hello" -- Just "hello" -- >>> checkedText $ pack " hello" -- Just "hello" -- >>> checkedText $ pack "hell o " -- Just "hell o" -- >>> checkedText $ pack "\npassword=" -- Nothing -- >>> checkedText $ pack "hello\npassword=" -- Just "hello" -- >>> checkedText $ pack " " -- Nothing -- >>> checkedText $ pack "\n" -- Nothing -- >>> checkedText $ pack " \n" -- Nothing -- >>> checkedText $ pack "\t" -- Nothing checkedText = noneEmptyText . trimWhite . takeUntilNewline where noneEmptyText text = if null text then Nothing else Just text takeUntilNewline = takeWhile (not . isControl) trimWhite = dropAround isSpace