From 0a653feba4bea55705114c4285e118e6dc933b3d Mon Sep 17 00:00:00 2001 From: Arash Rouhani Date: Sun, 14 Aug 2011 21:25:27 +0200 Subject: [PATCH] Added Kerberos source file and added to modules --- Web/Authenticate/Kerberos.hs | 72 ++++++++++++++++++++++++++++++++++++ authenticate.cabal | 1 + 2 files changed, 73 insertions(+) create mode 100644 Web/Authenticate/Kerberos.hs diff --git a/Web/Authenticate/Kerberos.hs b/Web/Authenticate/Kerberos.hs new file mode 100644 index 00000000..c2c4aa58 --- /dev/null +++ b/Web/Authenticate/Kerberos.hs @@ -0,0 +1,72 @@ +{-# LANGUAGE OverloadedStrings #-} +-- | Module for using a kerberos authentication service. +-- +-- Please note that all configuration should have been done +-- manually on the machine prior to running the code. +-- +-- On linux machines the configuration might be in /etc/krb5.conf. +-- It's worth checking if the Kerberos service provider (e.g. your university) +-- already provide a complete configuration file. +-- +-- Be certain that you can manually login from a shell by typing +-- +-- > kinit username +-- +-- If you fill in your password and the program returns no error code, +-- then your kerberos configuration is setup properly. +-- Only then can this module be of any use. +module Web.Authenticate.Kerberos + ( loginKerberos + , KerberosAuthResult(..) + ) where + +import Data.Text (Text) +import qualified Data.Text as T +import Data.Maybe (fromJust) +import Control.Monad (msum, guard) +import System.Process (readProcessWithExitCode) +import System.Timeout (timeout) +import System.Exit (ExitCode(..)) + +-- | Occurreable results of a Kerberos login +data KerberosAuthResult = Ok + | NoSuchUser + | WrongPassword + | TimeOut + | UnknownError Text + +instance Show KerberosAuthResult where + show Ok = "Login sucessful" + show NoSuchUser = "Wrong username" + show WrongPassword = "Wrong password" + show TimeOut = "kinit respone timeout" + show (UnknownError msg) = "Unkown error: " ++ T.unpack msg + + +-- Given the errcode and stderr, return error-value +interpretError :: Int -> Text -> KerberosAuthResult +interpretError _ errmsg = fromJust . msum $ + ["Client not found in Kerberos database while getting" --> NoSuchUser, + "Preauthentication failed while getting" --> WrongPassword, + Just $ UnknownError errmsg] + where + substr --> kError = guard (substr `T.isInfixOf` errmsg) >> Just kError + +-- | Given the username and password, try login to Kerberos service +loginKerberos :: Text -- ^ Username + -> Text -- ^ Password + -> IO KerberosAuthResult +loginKerberos username password = do + timedFetch <- timeout (10*1000000) fetch + case timedFetch of + Just res -> return res + Nothing -> return TimeOut + where + fetch :: IO KerberosAuthResult + fetch = do + (exitCode, _out, err) <- readProcessWithExitCode + "kinit" [T.unpack username] (T.unpack password) + case exitCode of + ExitSuccess -> return Ok + ExitFailure x -> return $ interpretError x (T.pack err) + diff --git a/authenticate.cabal b/authenticate.cabal index c4110511..f18323ab 100644 --- a/authenticate.cabal +++ b/authenticate.cabal @@ -43,6 +43,7 @@ library Web.Authenticate.OpenId.Providers, Web.Authenticate.OAuth, Web.Authenticate.Facebook + Web.Authenticate.Kerberos other-modules: Web.Authenticate.Internal, OpenId2.Discovery, OpenId2.Normalization,