Skip to content

Commit 86622cf

Browse files
committed
Fix realpath path existence oracle
1 parent f835a5a commit 86622cf

2 files changed

Lines changed: 243 additions & 89 deletions

File tree

lib/ssh/src/ssh_sftpd.erl

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -328,19 +328,24 @@ handle_op(?SSH_FXP_INIT, Version, B, State) when is_binary(B) ->
328328
ssh_xfer:xf_send_reply(XF1, ?SSH_FXP_VERSION, <<?UINT32(Vsn)>>),
329329
State#state{xf = XF1};
330330
handle_op(?SSH_FXP_REALPATH, ReqId,
331-
<<?UINT32(RLen), RPath:RLen/binary>>,
332-
State0) ->
331+
<<?UINT32(RLen), RPath:RLen/binary>>,
332+
State0) ->
333333
RelPath = relate_file_name(RPath, State0, _Canonicalize=false),
334-
{Res, State} = resolve_symlinks(RelPath, State0),
334+
{Res, #state{root = Root} = State} = resolve_symlinks(RelPath, State0),
335335
case Res of
336-
{ok, AbsPath} ->
337-
NewAbsPath = chroot_filename(AbsPath, State),
338-
XF = State#state.xf,
339-
Attr = #ssh_xfer_attr{type=directory},
340-
ssh_xfer:xf_send_name(XF, ReqId, NewAbsPath, Attr),
341-
State;
342-
{error, _} = Error ->
343-
send_status(Error, ReqId, State)
336+
{ok, AbsPath} ->
337+
case Root =:= "" orelse is_within_root(Root, AbsPath) of
338+
true ->
339+
NewAbsPath = chroot_filename(AbsPath, State),
340+
XF = State#state.xf,
341+
Attr = #ssh_xfer_attr{type=directory},
342+
ssh_xfer:xf_send_name(XF, ReqId, NewAbsPath, Attr),
343+
State;
344+
false ->
345+
send_status({error, enoent}, ReqId, State)
346+
end;
347+
{error, _} = Error ->
348+
send_status(Error, ReqId, State)
344349
end;
345350
handle_op(?SSH_FXP_OPENDIR, ReqId,
346351
<<?UINT32(RLen), RPath:RLen/binary>>,

0 commit comments

Comments
 (0)