aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssh/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssh/src')
-rw-r--r--lib/ssh/src/ssh_bits.erl46
-rw-r--r--lib/ssh/src/ssh_connection_handler.erl33
-rw-r--r--lib/ssh/src/ssh_sftp.erl165
-rw-r--r--lib/ssh/src/ssh_transport.erl155
-rw-r--r--lib/ssh/src/ssh_transport.hrl13
5 files changed, 214 insertions, 198 deletions
diff --git a/lib/ssh/src/ssh_bits.erl b/lib/ssh/src/ssh_bits.erl
index 8bedaaf0c5..3ce7758447 100644
--- a/lib/ssh/src/ssh_bits.erl
+++ b/lib/ssh/src/ssh_bits.erl
@@ -30,39 +30,31 @@
-export([random/1]).
%%%----------------------------------------------------------------
-name_list([Name]) -> to_bin(Name);
-name_list([Name|Ns]) -> <<(to_bin(Name))/binary, ",", (name_list(Ns))/binary>>;
-name_list([]) -> <<>>.
-
-to_bin(A) when is_atom(A) -> list_to_binary(atom_to_list(A));
-to_bin(S) when is_list(S) -> list_to_binary(S);
-to_bin(B) when is_binary(B) -> B.
+name_list(NamesList) -> list_to_binary(lists:join($,, NamesList)).
%%%----------------------------------------------------------------
%%% Multi Precision Integer encoding
mpint(-1) -> <<0,0,0,1,16#ff>>;
mpint(0) -> <<0,0,0,0>>;
-mpint(X) when X < 0 -> mpint_neg(X,0,[]);
-mpint(X) -> mpint_pos(X,0,[]).
-
-mpint_neg(-1,I,Ds=[MSB|_]) ->
- if MSB band 16#80 =/= 16#80 ->
- <<?UINT32((I+1)), (list_to_binary([255|Ds]))/binary>>;
- true ->
- <<?UINT32(I), (list_to_binary(Ds))/binary>>
- end;
-mpint_neg(X,I,Ds) ->
- mpint_neg(X bsr 8,I+1,[(X band 255)|Ds]).
-
-mpint_pos(0,I,Ds=[MSB|_]) ->
- if MSB band 16#80 == 16#80 ->
- <<?UINT32((I+1)), (list_to_binary([0|Ds]))/binary>>;
- true ->
- <<?UINT32(I), (list_to_binary(Ds))/binary>>
+mpint(I) when I>0 ->
+ <<B1,V/binary>> = binary:encode_unsigned(I),
+ case B1 band 16#80 of
+ 16#80 ->
+ <<(size(V)+2):32/unsigned-big-integer, 0,B1,V/binary >>;
+ _ ->
+ <<(size(V)+1):32/unsigned-big-integer, B1,V/binary >>
end;
-mpint_pos(X,I,Ds) ->
- mpint_pos(X bsr 8,I+1,[(X band 255)|Ds]).
-
+mpint(N) when N<0 ->
+ Sxn = 8*size(binary:encode_unsigned(-N)),
+ Sxn1 = Sxn+8,
+ <<W:Sxn1>> = <<1, 0:Sxn>>,
+ <<B1,V/binary>> = binary:encode_unsigned(W+N),
+ case B1 band 16#80 of
+ 16#80 ->
+ <<(size(V)+1):32/unsigned-big-integer, B1,V/binary >>;
+ _ ->
+ <<(size(V)+2):32/unsigned-big-integer, 255,B1,V/binary >>
+ end.
%%%----------------------------------------------------------------
%% random/1
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index 4496c657c3..dcf509ca09 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -1481,31 +1481,36 @@ renegotiation(_) -> false.
%%--------------------------------------------------------------------
supported_host_keys(client, _, Options) ->
try
- case proplists:get_value(public_key,
- proplists:get_value(preferred_algorithms,Options,[])
- ) of
- undefined ->
- ssh_transport:default_algorithms(public_key);
- L ->
- L -- (L--ssh_transport:default_algorithms(public_key))
- end
+ find_sup_hkeys(Options)
of
[] ->
- {stop, {shutdown, "No public key algs"}};
+ error({shutdown, "No public key algs"});
Algs ->
[atom_to_list(A) || A<-Algs]
catch
exit:Reason ->
- {stop, {shutdown, Reason}}
+ error({shutdown, Reason})
end;
supported_host_keys(server, KeyCb, Options) ->
- [atom_to_list(A) || A <- proplists:get_value(public_key,
- proplists:get_value(preferred_algorithms,Options,[]),
- ssh_transport:default_algorithms(public_key)
- ),
+ [atom_to_list(A) || A <- find_sup_hkeys(Options),
available_host_key(KeyCb, A, Options)
].
+
+find_sup_hkeys(Options) ->
+ case proplists:get_value(public_key,
+ proplists:get_value(preferred_algorithms,Options,[])
+ )
+ of
+ undefined ->
+ ssh_transport:default_algorithms(public_key);
+ L ->
+ NonSupported = L--ssh_transport:supported_algorithms(public_key),
+ L -- NonSupported
+ end.
+
+
+
%% Alg :: atom()
available_host_key(KeyCb, Alg, Opts) ->
element(1, catch KeyCb:host_key(Alg, Opts)) == ok.
diff --git a/lib/ssh/src/ssh_sftp.erl b/lib/ssh/src/ssh_sftp.erl
index afc2fb88ff..b937f0412d 100644
--- a/lib/ssh/src/ssh_sftp.erl
+++ b/lib/ssh/src/ssh_sftp.erl
@@ -37,7 +37,7 @@
-export([open/3, open_tar/3, opendir/2, close/2, readdir/2, pread/4, read/3,
open/4, open_tar/4, opendir/3, close/3, readdir/3, pread/5, read/4,
apread/4, aread/3, pwrite/4, write/3, apwrite/4, awrite/3,
- pwrite/5, write/4,
+ pwrite/5, write/4,
position/3, real_path/2, read_file_info/2, get_file_info/2,
position/4, real_path/3, read_file_info/3, get_file_info/3,
write_file_info/3, read_link_info/2, read_link/2, make_symlink/3,
@@ -52,7 +52,7 @@
%% TODO: Should be placed elsewhere ssh_sftpd should not call functions in ssh_sftp!
-export([info_to_attr/1, attr_to_info/1]).
--record(state,
+-record(state,
{
xf,
rep_buf = <<>>,
@@ -64,7 +64,7 @@
-record(fileinf,
{
- handle,
+ handle,
offset,
size,
mode
@@ -81,7 +81,7 @@
enc_text_buf = <<>>, % Encrypted text
plain_text_buf = <<>> % Decrypted text
}).
-
+
-define(FILEOP_TIMEOUT, infinity).
-define(NEXT_REQID(S),
@@ -98,7 +98,7 @@ start_channel(Cm) when is_pid(Cm) ->
start_channel(Socket) when is_port(Socket) ->
start_channel(Socket, []);
start_channel(Host) when is_list(Host) ->
- start_channel(Host, []).
+ start_channel(Host, []).
start_channel(Socket, Options) when is_port(Socket) ->
Timeout =
@@ -110,7 +110,7 @@ start_channel(Socket, Options) when is_port(Socket) ->
TO
end,
case ssh:connect(Socket, Options, Timeout) of
- {ok,Cm} ->
+ {ok,Cm} ->
case start_channel(Cm, Options) of
{ok, Pid} ->
{ok, Pid, Cm};
@@ -124,13 +124,13 @@ start_channel(Cm, Opts) when is_pid(Cm) ->
Timeout = proplists:get_value(timeout, Opts, infinity),
{_, ChanOpts, SftpOpts} = handle_options(Opts, [], [], []),
case ssh_xfer:attach(Cm, [], ChanOpts) of
- {ok, ChannelId, Cm} ->
- case ssh_channel:start(Cm, ChannelId,
+ {ok, ChannelId, Cm} ->
+ case ssh_channel:start(Cm, ChannelId,
?MODULE, [Cm, ChannelId, SftpOpts]) of
{ok, Pid} ->
case wait_for_version_negotiation(Pid, Timeout) of
ok ->
- {ok, Pid};
+ {ok, Pid};
TimeOut ->
TimeOut
end;
@@ -150,7 +150,7 @@ start_channel(Host, Port, Opts) ->
Timeout = proplists:get_value(timeout, SftpOpts, infinity),
case ssh_xfer:connect(Host, Port, SshOpts, ChanOpts, Timeout) of
{ok, ChannelId, Cm} ->
- case ssh_channel:start(Cm, ChannelId, ?MODULE, [Cm,
+ case ssh_channel:start(Cm, ChannelId, ?MODULE, [Cm,
ChannelId, SftpOpts]) of
{ok, Pid} ->
case wait_for_version_negotiation(Pid, Timeout) of
@@ -165,7 +165,7 @@ start_channel(Host, Port, Opts) ->
{error, ignore}
end;
Error ->
- Error
+ Error
end.
stop_channel(Pid) ->
@@ -174,12 +174,12 @@ stop_channel(Pid) ->
OldValue = process_flag(trap_exit, true),
link(Pid),
exit(Pid, ssh_sftp_stop_channel),
- receive
+ receive
{'EXIT', Pid, normal} ->
ok
after 5000 ->
exit(Pid, kill),
- receive
+ receive
{'EXIT', Pid, killed} ->
ok
end
@@ -209,9 +209,9 @@ open_tar(Pid, File, Mode, FileOpTimeout) ->
erl_tar:init(Pid, write,
fun(write, {_,Data}) ->
write_to_remote_tar(Pid, Handle, to_bin(Data), FileOpTimeout);
- (position, {_,Pos}) ->
+ (position, {_,Pos}) ->
position(Pid, Handle, Pos, FileOpTimeout);
- (close, _) ->
+ (close, _) ->
close(Pid, Handle, FileOpTimeout)
end);
{true,false,[{crypto,{CryptoInitFun,CryptoEncryptFun,CryptoEndFun}}]} ->
@@ -245,9 +245,9 @@ open_tar(Pid, File, Mode, FileOpTimeout) ->
erl_tar:init(Pid, read,
fun(read2, {_,Len}) ->
read_repeat(Pid, Handle, Len, FileOpTimeout);
- (position, {_,Pos}) ->
+ (position, {_,Pos}) ->
position(Pid, Handle, Pos, FileOpTimeout);
- (close, _) ->
+ (close, _) ->
close(Pid, Handle, FileOpTimeout)
end);
{false,true,[{crypto,{CryptoInitFun,CryptoDecryptFun}}]} ->
@@ -258,9 +258,9 @@ open_tar(Pid, File, Mode, FileOpTimeout) ->
erl_tar:init(Pid, read,
fun(read2, {_,Len}) ->
read_buf(Pid, SftpHandle, BufHandle, Len, FileOpTimeout);
- (position, {_,Pos}) ->
+ (position, {_,Pos}) ->
position_buf(Pid, SftpHandle, BufHandle, Pos, FileOpTimeout);
- (close, _) ->
+ (close, _) ->
call(Pid, {erase_bufinf,BufHandle}, FileOpTimeout),
close(Pid, SftpHandle, FileOpTimeout)
end);
@@ -292,7 +292,7 @@ pread(Pid, Handle, Offset, Len, FileOpTimeout) ->
read(Pid, Handle, Len) ->
read(Pid, Handle, Len, ?FILEOP_TIMEOUT).
read(Pid, Handle, Len, FileOpTimeout) ->
- call(Pid, {read,false,Handle, Len}, FileOpTimeout).
+ call(Pid, {read,false,Handle, Len}, FileOpTimeout).
%% TODO this ought to be a cast! Is so in all practial meaning
%% even if it is obscure!
@@ -301,7 +301,7 @@ apread(Pid, Handle, Offset, Len) ->
%% TODO this ought to be a cast!
aread(Pid, Handle, Len) ->
- call(Pid, {read,true,Handle, Len}, infinity).
+ call(Pid, {read,true,Handle, Len}, infinity).
pwrite(Pid, Handle, Offset, Data) ->
pwrite(Pid, Handle, Offset, Data, ?FILEOP_TIMEOUT).
@@ -367,7 +367,7 @@ make_symlink(Pid, Name, Target) ->
make_symlink(Pid, Name, Target, ?FILEOP_TIMEOUT).
make_symlink(Pid, Name, Target, FileOpTimeout) ->
call(Pid, {make_symlink,false, Name, Target}, FileOpTimeout).
-
+
rename(Pid, FromFile, ToFile) ->
rename(Pid, FromFile, ToFile, ?FILEOP_TIMEOUT).
rename(Pid, FromFile, ToFile, FileOpTimeout) ->
@@ -411,8 +411,8 @@ list_dir(Pid, Name, FileOpTimeout) ->
close(Pid, Handle, FileOpTimeout),
case Res of
{ok, List} ->
- NList = lists:foldl(fun({Nm, _Info},Acc) ->
- [Nm|Acc] end,
+ NList = lists:foldl(fun({Nm, _Info},Acc) ->
+ [Nm|Acc] end,
[], List),
{ok,NList};
Error -> Error
@@ -482,7 +482,7 @@ write_file_loop(Pid, Handle, Pos, Bin, Remain, PacketSz, FileOpTimeout) ->
<<_:Pos/binary, Data:PacketSz/binary, _/binary>> = Bin,
case write(Pid, Handle, Data, FileOpTimeout) of
ok ->
- write_file_loop(Pid, Handle,
+ write_file_loop(Pid, Handle,
Pos+PacketSz, Bin, Remain-PacketSz,
PacketSz, FileOpTimeout);
Error ->
@@ -510,7 +510,7 @@ init([Cm, ChannelId, Options]) ->
Xf = #ssh_xfer{cm = Cm,
channel = ChannelId},
{ok, #state{xf = Xf,
- req_id = 0,
+ req_id = 0,
rep_buf = <<>>,
inf = new_inf(),
opts = Options}};
@@ -519,7 +519,7 @@ init([Cm, ChannelId, Options]) ->
Error ->
{stop, {shutdown, Error}}
end.
-
+
%%--------------------------------------------------------------------
%% Function: handle_call/3
%% Description: Handling call messages
@@ -541,7 +541,7 @@ handle_call({{timeout, Timeout}, wait_for_version_negotiation}, From,
handle_call({_, wait_for_version_negotiation}, _, State) ->
{reply, ok, State};
-
+
handle_call({{timeout, infinity}, Msg}, From, State) ->
do_handle_call(Msg, From, State);
handle_call({{timeout, Timeout}, Msg}, From, #state{req_id = Id} = State) ->
@@ -555,13 +555,13 @@ code_change(_OldVsn, State, _Extra) ->
{ok, State}.
do_handle_call({get_bufinf,BufHandle}, _From, S=#state{inf=I0}) ->
- {reply, dict:find(BufHandle,I0), S};
+ {reply, maps:find(BufHandle,I0), S};
do_handle_call({put_bufinf,BufHandle,B}, _From, S=#state{inf=I0}) ->
- {reply, ok, S#state{inf=dict:store(BufHandle,B,I0)}};
+ {reply, ok, S#state{inf=maps:put(BufHandle,B,I0)}};
do_handle_call({erase_bufinf,BufHandle}, _From, S=#state{inf=I0}) ->
- {reply, ok, S#state{inf=dict:erase(BufHandle,I0)}};
+ {reply, ok, S#state{inf=maps:remove(BufHandle,I0)}};
do_handle_call({open, Async,FileName,Mode}, From, #state{xf = XF} = State) ->
{Access,Flags,Attrs} = open_mode(XF#ssh_xfer.vsn, Mode),
@@ -636,7 +636,7 @@ do_handle_call({pread,Async,Handle,At,Length}, From, State) ->
binary -> {{ok,Data}, State2};
text -> {{ok,binary_to_list(Data)}, State2}
end;
- (Rep, State2) ->
+ (Rep, State2) ->
{Rep, State2}
end);
Error ->
@@ -777,7 +777,7 @@ do_handle_call(recv_window, _From, State) ->
do_handle_call(stop, _From, State) ->
{stop, shutdown, ok, State};
-do_handle_call(Call, _From, State) ->
+do_handle_call(Call, _From, State) ->
{reply, {error, bad_call, Call, State}, State}.
%%--------------------------------------------------------------------
@@ -785,13 +785,13 @@ do_handle_call(Call, _From, State) ->
%%
%% Description: Handles channel messages
%%--------------------------------------------------------------------
-handle_ssh_msg({ssh_cm, _ConnectionManager,
- {data, _ChannelId, 0, Data}}, #state{rep_buf = Data0} =
+handle_ssh_msg({ssh_cm, _ConnectionManager,
+ {data, _ChannelId, 0, Data}}, #state{rep_buf = Data0} =
State0) ->
State = handle_reply(State0, <<Data0/binary,Data/binary>>),
{ok, State};
-handle_ssh_msg({ssh_cm, _ConnectionManager,
+handle_ssh_msg({ssh_cm, _ConnectionManager,
{data, _ChannelId, 1, Data}}, State) ->
error_logger:format("ssh: STDERR: ~s\n", [binary_to_list(Data)]),
{ok, State};
@@ -803,7 +803,7 @@ handle_ssh_msg({ssh_cm, _, {signal, _, _}}, State) ->
%% Ignore signals according to RFC 4254 section 6.9.
{ok, State};
-handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, _, Error, _}},
+handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, _, Error, _}},
State0) ->
State = reply_all(State0, {error, Error}),
{stop, ChannelId, State};
@@ -823,7 +823,7 @@ handle_msg({ssh_channel_up, _, _}, #state{opts = Options, xf = Xf} = State) ->
{ok, State};
%% Version negotiation timed out
-handle_msg({timeout, undefined, From},
+handle_msg({timeout, undefined, From},
#state{xf = #ssh_xfer{channel = ChannelId}} = State) ->
ssh_channel:reply(From, {error, timeout}),
{stop, ChannelId, State};
@@ -839,12 +839,12 @@ handle_msg({timeout, Id, From}, #state{req_list = ReqList0} = State) ->
end;
%% Connection manager goes down
-handle_msg({'DOWN', _Ref, _Type, _Process, _},
+handle_msg({'DOWN', _Ref, _Type, _Process, _},
#state{xf = #ssh_xfer{channel = ChannelId}} = State) ->
{stop, ChannelId, State};
-
+
%% Stopped by user
-handle_msg({'EXIT', _, ssh_sftp_stop_channel},
+handle_msg({'EXIT', _, ssh_sftp_stop_channel},
#state{xf = #ssh_xfer{channel = ChannelId}} = State) ->
{stop, ChannelId, State};
@@ -883,10 +883,10 @@ call(Pid, Msg, TimeOut) ->
handle_reply(State, <<?UINT32(Len),Reply:Len/binary,Rest/binary>>) ->
do_handle_reply(State, Reply, Rest);
-handle_reply(State, Data) ->
+handle_reply(State, Data) ->
State#state{rep_buf = Data}.
-do_handle_reply(#state{xf = Xf} = State,
+do_handle_reply(#state{xf = Xf} = State,
<<?SSH_FXP_VERSION, ?UINT32(Version), BinExt/binary>>, Rest) ->
Ext = ssh_xfer:decode_ext(BinExt),
case Xf#ssh_xfer.vsn of
@@ -899,7 +899,7 @@ do_handle_reply(#state{xf = Xf} = State,
ok
end,
ssh_channel:reply(From, ok)
- end,
+ end,
State#state{xf = Xf#ssh_xfer{vsn = Version, ext = Ext}, rep_buf = Rest};
do_handle_reply(State0, Data, Rest) ->
@@ -919,9 +919,9 @@ handle_req_reply(State0, {_, ReqID, _} = XfReply) ->
List = lists:keydelete(ReqID, 1, State0#state.req_list),
State1 = State0#state { req_list = List },
case catch Fun(xreply(XfReply),State1) of
- {'EXIT', _} ->
+ {'EXIT', _} ->
State1;
- State ->
+ State ->
State
end
end.
@@ -998,15 +998,15 @@ reply_all(State, Reply) ->
make_reply(ReqID, true, From, State) ->
{reply, {async, ReqID},
update_request_info(ReqID, State,
- fun(Reply,State1) ->
+ fun(Reply,State1) ->
async_reply(ReqID,Reply,From,State1)
end)};
make_reply(ReqID, false, From, State) ->
{noreply,
update_request_info(ReqID, State,
- fun(Reply,State1) ->
- sync_reply(Reply, From, State1)
+ fun(Reply,State1) ->
+ sync_reply(Reply, From, State1)
end)}.
make_reply_post(ReqID, true, From, State, PostFun) ->
@@ -1074,13 +1074,13 @@ attr_to_info(A) when is_record(A, ssh_xfer_attr) ->
unix_to_datetime(undefined) ->
undefined;
unix_to_datetime(UTCSecs) ->
- UTCDateTime =
+ UTCDateTime =
calendar:gregorian_seconds_to_datetime(UTCSecs + 62167219200),
erlang:universaltime_to_localtime(UTCDateTime).
datetime_to_unix(undefined) ->
undefined;
-datetime_to_unix(LocalDateTime) ->
+datetime_to_unix(LocalDateTime) ->
UTCDateTime = erlang:localtime_to_universaltime(LocalDateTime),
calendar:datetime_to_gregorian_seconds(UTCDateTime) - 62167219200.
@@ -1128,11 +1128,11 @@ open_mode3(Modes) ->
end,
{[], Fl, A}.
-%% accessors for inf dict
-new_inf() -> dict:new().
+%% accessors for inf map
+new_inf() -> #{}.
add_new_handle(Handle, FileMode, Inf) ->
- dict:store(Handle, #fileinf{offset=0, size=0, mode=FileMode}, Inf).
+ maps:put(Handle, #fileinf{offset=0, size=0, mode=FileMode}, Inf).
update_size(Handle, NewSize, State) ->
OldSize = get_size(Handle, State),
@@ -1152,27 +1152,24 @@ update_offset(Handle, NewOffset, State0) ->
%% access size and offset for handle
put_size(Handle, Size, State) ->
Inf0 = State#state.inf,
- case dict:find(Handle, Inf0) of
+ case maps:find(Handle, Inf0) of
{ok, FI} ->
- State#state{inf=dict:store(Handle, FI#fileinf{size=Size}, Inf0)};
+ State#state{inf=maps:put(Handle, FI#fileinf{size=Size}, Inf0)};
_ ->
- State#state{inf=dict:store(Handle, #fileinf{size=Size,offset=0},
- Inf0)}
+ State#state{inf=maps:put(Handle, #fileinf{size=Size,offset=0}, Inf0)}
end.
put_offset(Handle, Offset, State) ->
Inf0 = State#state.inf,
- case dict:find(Handle, Inf0) of
+ case maps:find(Handle, Inf0) of
{ok, FI} ->
- State#state{inf=dict:store(Handle, FI#fileinf{offset=Offset},
- Inf0)};
+ State#state{inf=maps:put(Handle, FI#fileinf{offset=Offset}, Inf0)};
_ ->
- State#state{inf=dict:store(Handle, #fileinf{size=Offset,
- offset=Offset}, Inf0)}
+ State#state{inf=maps:put(Handle, #fileinf{size=Offset, offset=Offset}, Inf0)}
end.
get_size(Handle, State) ->
- case dict:find(Handle, State#state.inf) of
+ case maps:find(Handle, State#state.inf) of
{ok, FI} ->
FI#fileinf.size;
_ ->
@@ -1180,11 +1177,11 @@ get_size(Handle, State) ->
end.
%% get_offset(Handle, State) ->
-%% {ok, FI} = dict:find(Handle, State#state.inf),
+%% {ok, FI} = maps:find(Handle, State#state.inf),
%% FI#fileinf.offset.
get_mode(Handle, State) ->
- case dict:find(Handle, State#state.inf) of
+ case maps:find(Handle, State#state.inf) of
{ok, FI} ->
FI#fileinf.mode;
_ ->
@@ -1192,14 +1189,14 @@ get_mode(Handle, State) ->
end.
erase_handle(Handle, State) ->
- FI = dict:erase(Handle, State#state.inf),
+ FI = maps:remove(Handle, State#state.inf),
State#state{inf = FI}.
%%
%% Caluclate a integer offset
%%
lseek_position(Handle, Pos, State) ->
- case dict:find(Handle, State#state.inf) of
+ case maps:find(Handle, State#state.inf) of
{ok, #fileinf{offset=O, size=S}} ->
lseek_pos(Pos, O, S);
_ ->
@@ -1229,7 +1226,7 @@ lseek_pos({cur, Offset}, CurOffset, _CurSize)
true ->
{ok, NewOffset}
end;
-lseek_pos({eof, Offset}, _CurOffset, CurSize)
+lseek_pos({eof, Offset}, _CurOffset, CurSize)
when is_integer(Offset) andalso -(?SSH_FILEXFER_LARGEFILESIZE) =< Offset andalso
Offset < ?SSH_FILEXFER_LARGEFILESIZE ->
NewOffset = CurSize + Offset,
@@ -1239,7 +1236,7 @@ lseek_pos({eof, Offset}, _CurOffset, CurSize)
{ok, NewOffset}
end;
lseek_pos(_, _, _) ->
- {error, einval}.
+ {error, einval}.
%%%================================================================
%%%
@@ -1277,13 +1274,13 @@ position_buf(Pid, SftpHandle, BufHandle, Pos, FileOpTimeout) ->
case Pos of
{cur,0} when Mode==write ->
{ok,Size+size(Buf0)};
-
+
{cur,0} when Mode==read ->
{ok,Size};
-
+
_ when Mode==read, is_integer(Pos) ->
Skip = Pos-Size,
- if
+ if
Skip < 0 ->
{error, cannot_rewind};
Skip == 0 ->
@@ -1318,7 +1315,7 @@ read_buf(Pid, SftpHandle, BufHandle, WantedLen, FileOpTimeout) ->
eof
end.
-do_the_read_buf(_Pid, _SftpHandle, WantedLen, _Packet, _FileOpTimeout,
+do_the_read_buf(_Pid, _SftpHandle, WantedLen, _Packet, _FileOpTimeout,
B=#bufinf{plain_text_buf=PlainBuf0,
size = Size})
when size(PlainBuf0) >= WantedLen ->
@@ -1327,7 +1324,7 @@ do_the_read_buf(_Pid, _SftpHandle, WantedLen, _Packet, _FileOpTimeout,
{ok,ResultBin,B#bufinf{plain_text_buf=PlainBuf,
size = Size + WantedLen}};
-do_the_read_buf(Pid, SftpHandle, WantedLen, Packet, FileOpTimeout,
+do_the_read_buf(Pid, SftpHandle, WantedLen, Packet, FileOpTimeout,
B0=#bufinf{plain_text_buf = PlainBuf0,
enc_text_buf = EncBuf0,
chunksize = undefined
@@ -1335,12 +1332,12 @@ do_the_read_buf(Pid, SftpHandle, WantedLen, Packet, FileOpTimeout,
when size(EncBuf0) > 0 ->
%% We have (at least) one decodable byte waiting for decodeing.
{ok,DecodedBin,B} = apply_crypto(EncBuf0, B0),
- do_the_read_buf(Pid, SftpHandle, WantedLen, Packet, FileOpTimeout,
+ do_the_read_buf(Pid, SftpHandle, WantedLen, Packet, FileOpTimeout,
B#bufinf{plain_text_buf = <<PlainBuf0/binary, DecodedBin/binary>>,
enc_text_buf = <<>>
});
-
-do_the_read_buf(Pid, SftpHandle, WantedLen, Packet, FileOpTimeout,
+
+do_the_read_buf(Pid, SftpHandle, WantedLen, Packet, FileOpTimeout,
B0=#bufinf{plain_text_buf = PlainBuf0,
enc_text_buf = EncBuf0,
chunksize = ChunkSize0
@@ -1349,11 +1346,11 @@ do_the_read_buf(Pid, SftpHandle, WantedLen, Packet, FileOpTimeout,
%% We have (at least) one chunk of decodable bytes waiting for decodeing.
<<ToDecode:ChunkSize0/binary, EncBuf/binary>> = EncBuf0,
{ok,DecodedBin,B} = apply_crypto(ToDecode, B0),
- do_the_read_buf(Pid, SftpHandle, WantedLen, Packet, FileOpTimeout,
+ do_the_read_buf(Pid, SftpHandle, WantedLen, Packet, FileOpTimeout,
B#bufinf{plain_text_buf = <<PlainBuf0/binary, DecodedBin/binary>>,
enc_text_buf = EncBuf
});
-
+
do_the_read_buf(Pid, SftpHandle, WantedLen, Packet, FileOpTimeout, B=#bufinf{enc_text_buf = EncBuf0}) ->
%% We must read more bytes and append to the buffer of encoded bytes.
case read(Pid, SftpHandle, Packet, FileOpTimeout) of
@@ -1370,7 +1367,7 @@ do_the_read_buf(Pid, SftpHandle, WantedLen, Packet, FileOpTimeout, B=#bufinf{enc
write_buf(Pid, SftpHandle, BufHandle, PlainBin, FileOpTimeout) ->
{ok,{_Window,Packet}} = send_window(Pid, FileOpTimeout),
{ok,B0=#bufinf{plain_text_buf=PTB}} = call(Pid, {get_bufinf,BufHandle}, FileOpTimeout),
- case do_the_write_buf(Pid, SftpHandle, Packet, FileOpTimeout,
+ case do_the_write_buf(Pid, SftpHandle, Packet, FileOpTimeout,
B0#bufinf{plain_text_buf = <<PTB/binary,PlainBin/binary>>}) of
{ok, B} ->
call(Pid, {put_bufinf,BufHandle,B}, FileOpTimeout),
@@ -1379,7 +1376,7 @@ write_buf(Pid, SftpHandle, BufHandle, PlainBin, FileOpTimeout) ->
{error,Error}
end.
-do_the_write_buf(Pid, SftpHandle, Packet, FileOpTimeout,
+do_the_write_buf(Pid, SftpHandle, Packet, FileOpTimeout,
B=#bufinf{enc_text_buf = EncBuf0,
size = Size})
when size(EncBuf0) >= Packet ->
@@ -1421,9 +1418,9 @@ do_the_write_buf(_Pid, _SftpHandle, _Packet, _FileOpTimeout, B) ->
apply_crypto(In, B=#bufinf{crypto_state = CState0,
crypto_fun = F}) ->
case F(In,CState0) of
- {ok,EncodedBin,CState} ->
+ {ok,EncodedBin,CState} ->
{ok, EncodedBin, B#bufinf{crypto_state=CState}};
- {ok,EncodedBin,CState,ChunkSize} ->
+ {ok,EncodedBin,CState,ChunkSize} ->
{ok, EncodedBin, B#bufinf{crypto_state=CState,
chunksize=ChunkSize}}
end.
diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl
index a7cc4cd52c..02209d5dfd 100644
--- a/lib/ssh/src/ssh_transport.erl
+++ b/lib/ssh/src/ssh_transport.erl
@@ -79,6 +79,15 @@ default_algorithms() -> [{K,default_algorithms(K)} || K <- algo_classes()].
algo_classes() -> [kex, public_key, cipher, mac, compression].
+default_algorithms(kex) ->
+ supported_algorithms(kex, [
+ 'diffie-hellman-group1-sha1' % Gone in OpenSSH 7.3.p1
+ ]);
+
+default_algorithms(public_key) ->
+ supported_algorithms(public_key, [
+ 'ssh-dss' % Gone in OpenSSH 7.3.p1
+ ]);
default_algorithms(cipher) ->
supported_algorithms(cipher, same(['AEAD_AES_128_GCM',
@@ -95,34 +104,39 @@ supported_algorithms() -> [{K,supported_algorithms(K)} || K <- algo_classes()].
supported_algorithms(kex) ->
select_crypto_supported(
[
- {'ecdh-sha2-nistp256', [{public_keys,ecdh}, {ec_curve,secp256r1}, {hashs,sha256}]},
{'ecdh-sha2-nistp384', [{public_keys,ecdh}, {ec_curve,secp384r1}, {hashs,sha384}]},
- {'diffie-hellman-group14-sha1', [{public_keys,dh}, {hashs,sha}]},
+ {'ecdh-sha2-nistp521', [{public_keys,ecdh}, {ec_curve,secp521r1}, {hashs,sha512}]},
+ {'ecdh-sha2-nistp256', [{public_keys,ecdh}, {ec_curve,secp256r1}, {hashs,sha256}]},
{'diffie-hellman-group-exchange-sha256', [{public_keys,dh}, {hashs,sha256}]},
+ {'diffie-hellman-group16-sha512', [{public_keys,dh}, {hashs,sha512}]}, % In OpenSSH 7.3.p1
+ {'diffie-hellman-group18-sha512', [{public_keys,dh}, {hashs,sha512}]}, % In OpenSSH 7.3.p1
+ {'diffie-hellman-group14-sha256', [{public_keys,dh}, {hashs,sha256}]}, % In OpenSSH 7.3.p1
+ {'diffie-hellman-group14-sha1', [{public_keys,dh}, {hashs,sha}]},
{'diffie-hellman-group-exchange-sha1', [{public_keys,dh}, {hashs,sha}]},
- {'ecdh-sha2-nistp521', [{public_keys,ecdh}, {ec_curve,secp521r1}, {hashs,sha512}]},
{'diffie-hellman-group1-sha1', [{public_keys,dh}, {hashs,sha}]}
]);
supported_algorithms(public_key) ->
select_crypto_supported(
- [{'ecdsa-sha2-nistp256', [{public_keys,ecdsa}, {hashs,sha256}, {ec_curve,secp256r1}]},
+ [
{'ecdsa-sha2-nistp384', [{public_keys,ecdsa}, {hashs,sha384}, {ec_curve,secp384r1}]},
{'ecdsa-sha2-nistp521', [{public_keys,ecdsa}, {hashs,sha512}, {ec_curve,secp521r1}]},
+ {'ecdsa-sha2-nistp256', [{public_keys,ecdsa}, {hashs,sha256}, {ec_curve,secp256r1}]},
{'ssh-rsa', [{public_keys,rsa}, {hashs,sha} ]},
- {'ssh-dss', [{public_keys,dss}, {hashs,sha} ]}
+ {'ssh-dss', [{public_keys,dss}, {hashs,sha} ]} % Gone in OpenSSH 7.3.p1
]);
supported_algorithms(cipher) ->
same(
select_crypto_supported(
- [{'aes256-ctr', [{ciphers,{aes_ctr,256}}]},
- {'aes192-ctr', [{ciphers,{aes_ctr,192}}]},
- {'aes128-ctr', [{ciphers,{aes_ctr,128}}]},
- {'aes128-cbc', [{ciphers,aes_cbc128}]},
+ [
+ {'[email protected]', [{ciphers,{aes_gcm,256}}]},
+ {'aes256-ctr', [{ciphers,{aes_ctr,256}}]},
+ {'aes192-ctr', [{ciphers,{aes_ctr,192}}]},
{'[email protected]', [{ciphers,{aes_gcm,128}}]},
- {'[email protected]', [{ciphers,{aes_gcm,256}}]},
- {'AEAD_AES_128_GCM', [{ciphers,{aes_gcm,128}}]},
+ {'aes128-ctr', [{ciphers,{aes_ctr,128}}]},
{'AEAD_AES_256_GCM', [{ciphers,{aes_gcm,256}}]},
+ {'AEAD_AES_128_GCM', [{ciphers,{aes_gcm,128}}]},
+ {'aes128-cbc', [{ciphers,aes_cbc128}]},
{'3des-cbc', [{ciphers,des3_cbc}]}
]
));
@@ -275,11 +289,12 @@ handle_kexinit_msg(#ssh_msg_kexinit{} = CounterPart, #ssh_msg_kexinit{} = Own,
true ->
key_exchange_first_msg(Algoritms#alg.kex,
Ssh0#ssh{algorithms = Algoritms});
- _ ->
+ {false,Alg} ->
%% TODO: Correct code?
ssh_connection_handler:disconnect(
#ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
- description = "Selection of key exchange algorithm failed"
+ description = "Selection of key exchange algorithm failed: "
+ ++ Alg
})
end;
@@ -289,30 +304,39 @@ handle_kexinit_msg(#ssh_msg_kexinit{} = CounterPart, #ssh_msg_kexinit{} = Own,
case verify_algorithm(Algoritms) of
true ->
{ok, Ssh#ssh{algorithms = Algoritms}};
- _ ->
+ {false,Alg} ->
ssh_connection_handler:disconnect(
#ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
- description = "Selection of key exchange algorithm failed"
+ description = "Selection of key exchange algorithm failed: "
+ ++ Alg
})
end.
-verify_algorithm(#alg{kex = undefined}) -> false;
-verify_algorithm(#alg{hkey = undefined}) -> false;
-verify_algorithm(#alg{send_mac = undefined}) -> false;
-verify_algorithm(#alg{recv_mac = undefined}) -> false;
-verify_algorithm(#alg{encrypt = undefined}) -> false;
-verify_algorithm(#alg{decrypt = undefined}) -> false;
-verify_algorithm(#alg{compress = undefined}) -> false;
-verify_algorithm(#alg{decompress = undefined}) -> false;
-verify_algorithm(#alg{kex = Kex}) -> lists:member(Kex, supported_algorithms(kex)).
+verify_algorithm(#alg{kex = undefined}) -> {false, "kex"};
+verify_algorithm(#alg{hkey = undefined}) -> {false, "hkey"};
+verify_algorithm(#alg{send_mac = undefined}) -> {false, "send_mac"};
+verify_algorithm(#alg{recv_mac = undefined}) -> {false, "recv_mac"};
+verify_algorithm(#alg{encrypt = undefined}) -> {false, "encrypt"};
+verify_algorithm(#alg{decrypt = undefined}) -> {false, "decrypt"};
+verify_algorithm(#alg{compress = undefined}) -> {false, "compress"};
+verify_algorithm(#alg{decompress = undefined}) -> {false, "decompress"};
+verify_algorithm(#alg{kex = Kex}) ->
+ case lists:member(Kex, supported_algorithms(kex)) of
+ true -> true;
+ false -> {false, "kex"}
+ end.
%%%----------------------------------------------------------------
%%%
%%% Key exchange initialization
%%%
key_exchange_first_msg(Kex, Ssh0) when Kex == 'diffie-hellman-group1-sha1' ;
- Kex == 'diffie-hellman-group14-sha1' ->
+ Kex == 'diffie-hellman-group14-sha1' ;
+ Kex == 'diffie-hellman-group14-sha256' ;
+ Kex == 'diffie-hellman-group16-sha512' ;
+ Kex == 'diffie-hellman-group18-sha512'
+ ->
{G, P} = dh_group(Kex),
Sz = dh_bits(Ssh0#ssh.algorithms),
{Public, Private} = generate_key(dh, [P,G,2*Sz]),
@@ -358,6 +382,9 @@ key_exchange_first_msg(Kex, Ssh0) when Kex == 'ecdh-sha2-nistp256' ;
%%%
%%% diffie-hellman-group1-sha1
%%% diffie-hellman-group14-sha1
+%%% diffie-hellman-group14-sha256
+%%% diffie-hellman-group16-sha512
+%%% diffie-hellman-group18-sha512
%%%
handle_kexdh_init(#ssh_msg_kexdh_init{e = E},
Ssh0 = #ssh{algorithms = #alg{kex=Kex} = Algs}) ->
@@ -378,7 +405,7 @@ handle_kexdh_init(#ssh_msg_kexdh_init{e = E},
h_sig = H_SIG
}, Ssh0),
{ok, SshPacket, Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}},
- shared_secret = K,
+ shared_secret = ssh_bits:mpint(K),
exchanged_hash = H,
session_id = sid(Ssh1, H)}};
@@ -404,7 +431,7 @@ handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = PeerPubHostKey,
case verify_host_key(Ssh0, PeerPubHostKey, H, H_SIG) of
ok ->
{SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0),
- {ok, SshPacket, Ssh#ssh{shared_secret = K,
+ {ok, SshPacket, Ssh#ssh{shared_secret = ssh_bits:mpint(K),
exchanged_hash = H,
session_id = sid(Ssh, H)}};
Error ->
@@ -542,7 +569,7 @@ handle_kex_dh_gex_init(#ssh_msg_kex_dh_gex_init{e = E},
ssh_packet(#ssh_msg_kex_dh_gex_reply{public_host_key = MyPubHostKey,
f = Public,
h_sig = H_SIG}, Ssh0),
- {ok, SshPacket, Ssh#ssh{shared_secret = K,
+ {ok, SshPacket, Ssh#ssh{shared_secret = ssh_bits:mpint(K),
exchanged_hash = H,
session_id = sid(Ssh, H)
}};
@@ -578,7 +605,7 @@ handle_kex_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{public_host_key = PeerPubHostK
case verify_host_key(Ssh0, PeerPubHostKey, H, H_SIG) of
ok ->
{SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0),
- {ok, SshPacket, Ssh#ssh{shared_secret = K,
+ {ok, SshPacket, Ssh#ssh{shared_secret = ssh_bits:mpint(K),
exchanged_hash = H,
session_id = sid(Ssh, H)}};
_Error ->
@@ -628,7 +655,7 @@ handle_kex_ecdh_init(#ssh_msg_kex_ecdh_init{q_c = PeerPublic},
h_sig = H_SIG},
Ssh0),
{ok, SshPacket, Ssh1#ssh{keyex_key = {{MyPublic,MyPrivate},Curve},
- shared_secret = K,
+ shared_secret = ssh_bits:mpint(K),
exchanged_hash = H,
session_id = sid(Ssh1, H)}}
catch
@@ -654,7 +681,7 @@ handle_kex_ecdh_reply(#ssh_msg_kex_ecdh_reply{public_host_key = PeerPubHostKey,
case verify_host_key(Ssh0, PeerPubHostKey, H, H_SIG) of
ok ->
{SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0),
- {ok, SshPacket, Ssh#ssh{shared_secret = K,
+ {ok, SshPacket, Ssh#ssh{shared_secret = ssh_bits:mpint(K),
exchanged_hash = H,
session_id = sid(Ssh, H)}};
Error ->
@@ -756,9 +783,8 @@ accepted_host(Ssh, PeerName, Public, Opts) ->
yes == yes_no(Ssh, "New host " ++ PeerName ++ " accept")
end.
-known_host_key(#ssh{opts = Opts, key_cb = Mod, peer = Peer} = Ssh,
+known_host_key(#ssh{opts = Opts, key_cb = Mod, peer = {PeerName,_}} = Ssh,
Public, Alg) ->
- PeerName = peer_name(Peer),
case Mod:is_host_key(Public, PeerName, Alg, Opts) of
true ->
ok;
@@ -1604,48 +1630,27 @@ mac('hmac-sha2-256', Key, SeqNum, Data) ->
mac('hmac-sha2-512', Key, SeqNum, Data) ->
crypto:hmac(sha512, Key, [<<?UINT32(SeqNum)>>, Data]).
-%% return N hash bytes (HASH)
-hash(SSH, Char, Bits) ->
- HASH =
- case SSH#ssh.kex of
- 'diffie-hellman-group1-sha1' ->
- fun(Data) -> crypto:hash(sha, Data) end;
- 'diffie-hellman-group14-sha1' ->
- fun(Data) -> crypto:hash(sha, Data) end;
-
- 'diffie-hellman-group-exchange-sha1' ->
- fun(Data) -> crypto:hash(sha, Data) end;
- 'diffie-hellman-group-exchange-sha256' ->
- fun(Data) -> crypto:hash(sha256, Data) end;
-
- 'ecdh-sha2-nistp256' ->
- fun(Data) -> crypto:hash(sha256,Data) end;
- 'ecdh-sha2-nistp384' ->
- fun(Data) -> crypto:hash(sha384,Data) end;
- 'ecdh-sha2-nistp521' ->
- fun(Data) -> crypto:hash(sha512,Data) end;
- _ ->
- exit({bad_algorithm,SSH#ssh.kex})
- end,
- hash(SSH, Char, Bits, HASH).
-hash(_SSH, _Char, 0, _HASH) ->
+%%%----------------------------------------------------------------
+%% return N hash bytes (HASH)
+hash(_SSH, _Char, 0) ->
<<>>;
-hash(SSH, Char, N, HASH) ->
- K = ssh_bits:mpint(SSH#ssh.shared_secret),
+hash(SSH, Char, N) ->
+ HashAlg = sha(SSH#ssh.kex),
+ K = SSH#ssh.shared_secret,
H = SSH#ssh.exchanged_hash,
- SessionID = SSH#ssh.session_id,
- K1 = HASH([K, H, Char, SessionID]),
+ K1 = crypto:hash(HashAlg, [K, H, Char, SSH#ssh.session_id]),
Sz = N div 8,
- <<Key:Sz/binary, _/binary>> = hash(K, H, K1, N-128, HASH),
+ <<Key:Sz/binary, _/binary>> = hash(K, H, K1, N-128, HashAlg),
Key.
-hash(_K, _H, Ki, N, _HASH) when N =< 0 ->
+hash(_K, _H, Ki, N, _HashAlg) when N =< 0 ->
Ki;
-hash(K, H, Ki, N, HASH) ->
- Kj = HASH([K, H, Ki]),
- hash(K, H, <<Ki/binary, Kj/binary>>, N-128, HASH).
+hash(K, H, Ki, N, HashAlg) ->
+ Kj = crypto:hash(HashAlg, [K, H, Ki]),
+ hash(K, H, <<Ki/binary, Kj/binary>>, N-128, HashAlg).
+%%%----------------------------------------------------------------
kex_h(SSH, Key, E, F, K) ->
KeyBin = public_key:ssh_encode(Key, ssh2_pubkey),
L = <<?Estring(SSH#ssh.c_version), ?Estring(SSH#ssh.s_version),
@@ -1688,11 +1693,17 @@ sha(secp384r1) -> sha384;
sha(secp521r1) -> sha512;
sha('diffie-hellman-group1-sha1') -> sha;
sha('diffie-hellman-group14-sha1') -> sha;
+sha('diffie-hellman-group14-sha256') -> sha256;
+sha('diffie-hellman-group16-sha512') -> sha512;
+sha('diffie-hellman-group18-sha512') -> sha512;
sha('diffie-hellman-group-exchange-sha1') -> sha;
sha('diffie-hellman-group-exchange-sha256') -> sha256;
sha(?'secp256r1') -> sha(secp256r1);
sha(?'secp384r1') -> sha(secp384r1);
-sha(?'secp521r1') -> sha(secp521r1).
+sha(?'secp521r1') -> sha(secp521r1);
+sha('ecdh-sha2-nistp256') -> sha(secp256r1);
+sha('ecdh-sha2-nistp384') -> sha(secp384r1);
+sha('ecdh-sha2-nistp521') -> sha(secp521r1).
mac_key_bytes('hmac-sha1') -> 20;
@@ -1715,9 +1726,6 @@ mac_digest_size('AEAD_AES_128_GCM') -> 16;
mac_digest_size('AEAD_AES_256_GCM') -> 16;
mac_digest_size(none) -> 0.
-peer_name({Host, _}) ->
- Host.
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Diffie-Hellman utils
@@ -1725,7 +1733,10 @@ peer_name({Host, _}) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
dh_group('diffie-hellman-group1-sha1') -> ?dh_group1;
-dh_group('diffie-hellman-group14-sha1') -> ?dh_group14.
+dh_group('diffie-hellman-group14-sha1') -> ?dh_group14;
+dh_group('diffie-hellman-group14-sha256') -> ?dh_group14;
+dh_group('diffie-hellman-group16-sha512') -> ?dh_group16;
+dh_group('diffie-hellman-group18-sha512') -> ?dh_group18.
%%%----------------------------------------------------------------
parallell_gen_key(Ssh = #ssh{keyex_key = {x, {G, P}},
diff --git a/lib/ssh/src/ssh_transport.hrl b/lib/ssh/src/ssh_transport.hrl
index f91cb1dd63..19b3f5c437 100644
--- a/lib/ssh/src/ssh_transport.hrl
+++ b/lib/ssh/src/ssh_transport.hrl
@@ -112,7 +112,7 @@
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% diffie-hellman-group1-sha1 | diffie-hellman-group14-sha1
+%% diffie-hellman-group*-sha*
-define(SSH_MSG_KEXDH_INIT, 30).
-define(SSH_MSG_KEXDH_REPLY, 31).
@@ -238,4 +238,15 @@
-define(dh_group14,
{2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF}).
+%%% rfc 3526, ch5
+%%% Size 4096-bit
+-define(dh_group16,
+ {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF}).
+
+%%% rfc 3526, ch7
+%%% Size 8192-bit
+-define(dh_group18,
+ {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF}).
+
+
-endif. % -ifdef(ssh_transport).