summaryrefslogtreecommitdiff
path: root/shareguard-authnz-external.hs
blob: 56f3dd58ca411a7815ae5bc45fb5c6a8ebf4f8c0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
{-
shareguard-authnz-external: mod_authnz_external-to-ShareGuard interface

  Copyright (C) 2011, 2014  Clint Adams <clint@gnu.org>

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU Affero General Public License as
  published by the Free Software Foundation, either version 3 of the
  License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU Affero General Public License for more details.

  You should have received a copy of the GNU Affero General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.

-}

import Control.Exception.Base (catch)

import System.Exit ( exitWith, ExitCode (..) )
import System.Environment
import System.IO.Error

import Control.Monad.Trans
import Control.Monad.Error

import System.Path.NameManip (normalise_path, guess_dotdot, slice_path)

import Config as C
import DB as D

data AuthQuery = AuthQuery { uname :: String  
			, pass :: String  
			, uri :: String
			}
main = do
	uri <- catch (getEnv "URI") envvarHandler
	cnf <- C.getConfig "/usr/local/etc/shareguard.conf"
	user <- getLine  
	pw <- getLine
	passwords <- D.withDB cnf $ \db -> getUserPw db
	let dbpass = snd $ head $ filter ((==user).fst) passwords
	alldirs <- D.withDB cnf $ \db -> getUserDirs db
	let dirs = map ('/' :) (map snd (filter ((user ==) . fst) alldirs))
	if isValidRequest (AuthQuery user pw uri) dbpass dirs
		then exitWith (ExitSuccess)
		else exitWith (ExitFailure 1)

envvarHandler :: IOError -> IO (String)  
envvarHandler e
    | isDoesNotExistError e = return ""
    | otherwise = ioError e

isValidRequest :: AuthQuery -> String -> [String] -> Bool
isValidRequest (AuthQuery {uname = u, pass = p, uri = req}) dbpass dirs =
	and [isCorrectPassword p dbpass,
		isAuthorizedURI (rootDir $ sanitizeURI req) dirs]

isCorrectPassword :: String -> String -> Bool
isCorrectPassword p1 p2 =
	and [p1 == p2, p2 /= ""]

isAuthorizedURI :: Maybe String -> [String] -> Bool
isAuthorizedURI Nothing _ = False
isAuthorizedURI (Just req) dirs =
	elem req dirs

rootDir :: Maybe String -> Maybe String
rootDir Nothing = Nothing
rootDir (Just x) = Just (head (slice_path x))

sanitizeURI :: String -> Maybe String
sanitizeURI uri =
	guess_dotdot (normalise_path uri)