diff options
Diffstat (limited to 'lib/ssh/src')
-rw-r--r-- | lib/ssh/src/Makefile | 5 | ||||
-rw-r--r-- | lib/ssh/src/ssh.app.src | 1 | ||||
-rw-r--r-- | lib/ssh/src/ssh.erl | 4 | ||||
-rw-r--r-- | lib/ssh/src/ssh_auth.erl | 36 | ||||
-rw-r--r-- | lib/ssh/src/ssh_connection_manager.erl | 6 | ||||
-rw-r--r-- | lib/ssh/src/ssh_file.erl | 30 | ||||
-rw-r--r-- | lib/ssh/src/ssh_key_api.erl | 45 |
7 files changed, 105 insertions, 22 deletions
diff --git a/lib/ssh/src/Makefile b/lib/ssh/src/Makefile index cd9618c139..7be97abf66 100644 --- a/lib/ssh/src/Makefile +++ b/lib/ssh/src/Makefile @@ -36,7 +36,11 @@ RELSYSDIR = $(RELEASE_PATH)/lib/ssh-$(VSN) # Common Macros # ---------------------------------------------------- +# Behaviour (api) modules are first so they are compiled when +# the compiler reaches a callback module using them. MODULES= \ + ssh_sftpd_file_api \ + ssh_key_api \ ssh \ ssh_sup \ sshc_sup \ @@ -63,7 +67,6 @@ MODULES= \ ssh_sftp \ ssh_sftpd \ ssh_sftpd_file\ - ssh_sftpd_file_api \ ssh_transport \ ssh_userreg \ ssh_xfer diff --git a/lib/ssh/src/ssh.app.src b/lib/ssh/src/ssh.app.src index 154c72485e..7a58dbe54f 100644 --- a/lib/ssh/src/ssh.app.src +++ b/lib/ssh/src/ssh.app.src @@ -21,6 +21,7 @@ sshd_sup, ssh_file, ssh_io, + ssh_key_api, ssh_math, ssh_no_io, ssh_sftp, diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index c47db64497..5751f2eaa0 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -306,6 +306,10 @@ handle_options([{connect_timeout, _} = Opt | Rest], SockOpts, Opts) -> handle_options(Rest, SockOpts, [Opt | Opts]); handle_options([{user, _} = Opt | Rest], SockOpts, Opts) -> handle_options(Rest, SockOpts, [Opt | Opts]); +handle_options([{dsa_pass_phrase, _} = Opt | Rest], SockOpts, Opts) -> + handle_options(Rest, SockOpts, [Opt | Opts]); +handle_options([{rsa_pass_phrase, _} = Opt | Rest], SockOpts, Opts) -> + handle_options(Rest, SockOpts, [Opt | Opts]); handle_options([{password, _} = Opt | Rest], SockOpts, Opts) -> handle_options(Rest, SockOpts, [Opt | Opts]); handle_options([{user_passwords, _} = Opt | Rest], SockOpts, Opts) -> diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl index a2e74a12bb..62d684f4dc 100644 --- a/lib/ssh/src/ssh_auth.erl +++ b/lib/ssh/src/ssh_auth.erl @@ -71,29 +71,43 @@ password_msg([#ssh{opts = Opts, io_cb = IoCb, ssh_bits:install_messages(userauth_passwd_messages()), Password = case proplists:get_value(password, Opts) of undefined -> - IoCb:read_password("ssh password: "); + user_interaction(Opts, IoCb); PW -> PW end, - ssh_transport:ssh_packet( - #ssh_msg_userauth_request{user = User, - service = Service, - method = "password", - data = - <<?BOOLEAN(?FALSE), - ?STRING(list_to_binary(Password))>>}, - Ssh). + case Password of + not_ok -> + not_ok; + _ -> + ssh_transport:ssh_packet( + #ssh_msg_userauth_request{user = User, + service = Service, + method = "password", + data = + <<?BOOLEAN(?FALSE), + ?STRING(list_to_binary(Password))>>}, + Ssh) + end. + +user_interaction(Opts, IoCb) -> + case proplists:get_value(allow_user_interaction, Opts, true) of + true -> + IoCb:read_password("ssh password: "); + false -> + not_ok + end. + %% See RFC 4256 for info on keyboard-interactive keyboard_interactive_msg([#ssh{user = User, - service = Service} = Ssh]) -> + service = Service} = Ssh]) -> ssh_bits:install_messages(userauth_keyboard_interactive_messages()), ssh_transport:ssh_packet( #ssh_msg_userauth_request{user = User, service = Service, method = "keyboard-interactive", data = << ?STRING(<<"">>), - ?STRING(<<>>) >> }, + ?STRING(<<>>) >> }, Ssh). service_request_msg(Ssh) -> diff --git a/lib/ssh/src/ssh_connection_manager.erl b/lib/ssh/src/ssh_connection_manager.erl index 9bfd5270da..f729276e65 100644 --- a/lib/ssh/src/ssh_connection_manager.erl +++ b/lib/ssh/src/ssh_connection_manager.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2010. All Rights Reserved. +%% Copyright Ericsson AB 2008-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -144,7 +144,7 @@ adjust_window(ConnectionManager, Channel, Bytes) -> cast(ConnectionManager, {adjust_window, Channel, Bytes}). close(ConnectionManager, ChannelId) -> - try call(ConnectionManager, {close, ChannelId}) of + try call(ConnectionManager, {close, ChannelId}) of ok -> ok; {error, channel_closed} -> @@ -604,6 +604,8 @@ call(Pid, Msg, Timeout) -> exit:{timeout, _} -> {error, timeout}; exit:{normal, _} -> + {error, channel_closed}; + exit:{noproc,_} -> {error, channel_closed} end. diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl index 97ebf77e82..d05fa8e09a 100644 --- a/lib/ssh/src/ssh_file.erl +++ b/lib/ssh/src/ssh_file.erl @@ -23,6 +23,8 @@ -module(ssh_file). +-behaviour(ssh_key_api). + -include_lib("public_key/include/public_key.hrl"). -include_lib("kernel/include/file.hrl"). @@ -44,7 +46,10 @@ %% Used by server host_key(Algorithm, Opts) -> File = file_name(system, file_base_name(Algorithm), Opts), - Password = proplists:get_value(password, Opts, ignore), + %% We do not expect host keys to have pass phrases + %% so probably we could hardcod Password = ignore, but + %% we keep it as an undocumented option for now. + Password = proplists:get_value(identity_pass_phrase(Algorithm), Opts, ignore), decode(File, Password). @@ -66,9 +71,9 @@ is_host_key(Key, PeerName, Algorithm, Opts) -> false end. -user_key(Alg, Opts) -> - File = file_name(user, identity_key_filename(Alg), Opts), - Password = proplists:get_value(password, Opts, ignore), +user_key(Algorithm, Opts) -> + File = file_name(user, identity_key_filename(Algorithm), Opts), + Password = proplists:get_value(identity_pass_phrase(Algorithm), Opts, ignore), decode(File, Password). @@ -208,10 +213,20 @@ do_lookup_host_key(Host, Alg, Opts) -> Error -> Error end. -identity_key_filename("ssh-dss") -> "id_dsa"; -identity_key_filename("ssh-rsa") -> "id_rsa". +identity_key_filename("ssh-dss") -> + "id_dsa"; +identity_key_filename("ssh-rsa") -> + "id_rsa". + +identity_pass_phrase("ssh-dss") -> + dsa_pass_phrase; +identity_pass_phrase('ssh-dss') -> + dsa_pass_phrase; +identity_pass_phrase('ssh-rsa') -> + rsa_pass_phrase; +identity_pass_phrase("ssh-rsa") -> + rsa_pass_phrase. - lookup_host_key_fd(Fd, Host, KeyType) -> case io:get_line(Fd, '') of eof -> @@ -288,7 +303,6 @@ is_auth_key(Key, Key) -> is_auth_key(_,_) -> false. - default_user_dir()-> {ok,[[Home|_]]} = init:get_argument(home), UserDir = filename:join(Home, ".ssh"), diff --git a/lib/ssh/src/ssh_key_api.erl b/lib/ssh/src/ssh_key_api.erl new file mode 100644 index 0000000000..8085c12e21 --- /dev/null +++ b/lib/ssh/src/ssh_key_api.erl @@ -0,0 +1,45 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2011-2012. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(ssh_key_api). + +-include_lib("public_key/include/public_key.hrl"). +-include("ssh.hrl"). + +-type ssh_algorithm() :: string(). +-type file_error() :: file:posix() | badarg | system_limit | terminated. + +-callback host_key(Algorithm :: ssh_algorithm(), Options :: list()) -> + {ok, [{public_key(), Attributes::list()}]} | public_key() + | {error, string()}. + +-callback user_key(Algorithm :: ssh_algorithm(), Options :: list()) -> + {ok, [{public_key(), Attributes::list()}]} | public_key() + | {error, string()}. + +-callback is_host_key(Key :: public_key(), PeerName :: string(), + Algorithm :: ssh_algorithm(), Options :: list()) -> + boolean(). + +-callback add_host_key(Host :: string(), Key :: public_key(), Options :: list()) -> + ok | {error, file_error()}. + +-callback is_auth_key(Key :: public_key(), User :: string(), + Algorithm :: ssh_algorithm(), Options :: list()) -> + boolean(). |