aboutsummaryrefslogtreecommitdiff
path: root/src/mod_http_fileserver.erl
diff options
context:
space:
mode:
authorPaweł Chmielowski <pchmielowski@process-one.net>2016-11-17 12:59:27 +0100
committerPaweł Chmielowski <pchmielowski@process-one.net>2016-11-17 12:59:46 +0100
commit995c97671d418264d35aa2308f642bf382832638 (patch)
tree2717ad7b21ec2a2aeaec28c7a1f99b11e71f375d /src/mod_http_fileserver.erl
parentFix typo (diff)
Add auth to mod_http_fileserver
Diffstat (limited to 'src/mod_http_fileserver.erl')
-rw-r--r--src/mod_http_fileserver.erl88
1 files changed, 62 insertions, 26 deletions
diff --git a/src/mod_http_fileserver.erl b/src/mod_http_fileserver.erl
index 728a2d137..a896cb8b4 100644
--- a/src/mod_http_fileserver.erl
+++ b/src/mod_http_fileserver.erl
@@ -56,7 +56,7 @@
-record(state,
{host, docroot, accesslog, accesslogfd,
directory_indices, custom_headers, default_content_type,
- content_types = []}).
+ content_types = [], user_access = none}).
-define(PROCNAME, ejabberd_mod_http_fileserver).
@@ -133,7 +133,8 @@ start_link(Host, Opts) ->
init([Host, Opts]) ->
try initialize(Host, Opts) of
{DocRoot, AccessLog, AccessLogFD, DirectoryIndices,
- CustomHeaders, DefaultContentType, ContentTypes} ->
+ CustomHeaders, DefaultContentType, ContentTypes,
+ UserAccess} ->
{ok, #state{host = Host,
accesslog = AccessLog,
accesslogfd = AccessLogFD,
@@ -141,7 +142,8 @@ init([Host, Opts]) ->
directory_indices = DirectoryIndices,
custom_headers = CustomHeaders,
default_content_type = DefaultContentType,
- content_types = ContentTypes}}
+ content_types = ContentTypes,
+ user_access = UserAccess}}
catch
throw:Reason ->
{stop, Reason}
@@ -165,7 +167,15 @@ initialize(Host, Opts) ->
[]),
DefaultContentType = gen_mod:get_opt(default_content_type, Opts,
fun iolist_to_binary/1,
- ?DEFAULT_CONTENT_TYPE),
+ ?DEFAULT_CONTENT_TYPE),
+ UserAccess0 = gen_mod:get_opt(must_authenticate_with, Opts,
+ mod_opt_type(must_authenticate_with),
+ []),
+ UserAccess = case UserAccess0 of
+ [] -> none;
+ _ ->
+ dict:from_list(UserAccess0)
+ end,
ContentTypes = build_list_content_types(
gen_mod:get_opt(content_types, Opts,
fun(L) when is_list(L) ->
@@ -180,7 +190,7 @@ initialize(Host, Opts) ->
[str:join([[$*, K, " -> ", V] || {K, V} <- ContentTypes],
<<", ">>)]),
{DocRoot, AccessLog, AccessLogFD, DirectoryIndices,
- CustomHeaders, DefaultContentType, ContentTypes}.
+ CustomHeaders, DefaultContentType, ContentTypes, UserAccess}.
%% @spec (AdminCTs::[CT], Default::[CT]) -> [CT]
@@ -246,10 +256,11 @@ try_open_log(FN, Host) ->
%% {stop, Reason, State}
%% Description: Handling call messages
%%--------------------------------------------------------------------
-handle_call({serve, LocalPath}, _From, State) ->
- Reply = serve(LocalPath, State#state.docroot, State#state.directory_indices,
+handle_call({serve, LocalPath, Auth}, _From, State) ->
+ Reply = serve(LocalPath, Auth, State#state.docroot, State#state.directory_indices,
State#state.custom_headers,
- State#state.default_content_type, State#state.content_types),
+ State#state.default_content_type, State#state.content_types,
+ State#state.user_access),
{reply, Reply, State};
handle_call(_Request, _From, State) ->
{reply, ok, State}.
@@ -305,9 +316,9 @@ code_change(_OldVsn, State, _Extra) ->
%% @doc Handle an HTTP request.
%% LocalPath is the part of the requested URL path that is "local to the module".
%% Returns the page to be sent back to the client and/or HTTP status code.
-process(LocalPath, Request) ->
+process(LocalPath, #request{host = Host, auth = Auth} = Request) ->
?DEBUG("Requested ~p", [LocalPath]),
- try gen_server:call(get_proc_name(Request#request.host), {serve, LocalPath}) of
+ try gen_server:call(get_proc_name(Host), {serve, LocalPath, Auth}) of
{FileSize, Code, Headers, Contents} ->
add_to_log(FileSize, Code, Request),
{Code, Headers, Contents}
@@ -318,21 +329,38 @@ process(LocalPath, Request) ->
ejabberd_web:error(not_found)
end.
-serve(LocalPath, DocRoot, DirectoryIndices, CustomHeaders, DefaultContentType, ContentTypes) ->
- FileName = filename:join(filename:split(DocRoot) ++ LocalPath),
- case file:read_file_info(FileName) of
- {error, enoent} -> ?HTTP_ERR_FILE_NOT_FOUND;
- {error, enotdir} -> ?HTTP_ERR_FILE_NOT_FOUND;
- {error, eacces} -> ?HTTP_ERR_FORBIDDEN;
- {ok, #file_info{type = directory}} -> serve_index(FileName,
- DirectoryIndices,
- CustomHeaders,
- DefaultContentType,
- ContentTypes);
- {ok, FileInfo} -> serve_file(FileInfo, FileName,
- CustomHeaders,
- DefaultContentType,
- ContentTypes)
+
+serve(LocalPath, Auth, DocRoot, DirectoryIndices, CustomHeaders, DefaultContentType,
+ ContentTypes, UserAccess) ->
+ CanProceed = case {UserAccess, Auth} of
+ {none, _} -> true;
+ {_, {User, Pass}} ->
+ case dict:find(User, UserAccess) of
+ {ok, Pass} -> true;
+ _ -> false
+ end;
+ _ ->
+ false
+ end,
+ case CanProceed of
+ true ->
+ FileName = filename:join(filename:split(DocRoot) ++ LocalPath),
+ case file:read_file_info(FileName) of
+ {error, enoent} -> ?HTTP_ERR_FILE_NOT_FOUND;
+ {error, enotdir} -> ?HTTP_ERR_FILE_NOT_FOUND;
+ {error, eacces} -> ?HTTP_ERR_FORBIDDEN;
+ {ok, #file_info{type = directory}} -> serve_index(FileName,
+ DirectoryIndices,
+ CustomHeaders,
+ DefaultContentType,
+ ContentTypes);
+ {ok, FileInfo} -> serve_file(FileInfo, FileName,
+ CustomHeaders,
+ DefaultContentType,
+ ContentTypes)
+ end;
+ _ ->
+ ?HTTP_ERR_FORBIDDEN
end.
%% Troll through the directory indices attempting to find one which
@@ -466,6 +494,14 @@ mod_opt_type(default_content_type) ->
mod_opt_type(directory_indices) ->
fun (L) when is_list(L) -> L end;
mod_opt_type(docroot) -> fun (A) -> A end;
+mod_opt_type(must_authenticate_with) ->
+ fun (L) when is_list(L) ->
+ lists:map(fun(UP) when is_binary(UP) ->
+ [K, V] = binary:split(UP, <<":">>),
+ {K, V}
+ end, L)
+ end;
mod_opt_type(_) ->
[accesslog, content_types, custom_headers,
- default_content_type, directory_indices, docroot].
+ default_content_type, directory_indices, docroot,
+ must_authenticate_with].