From c6d03c10d7cd9a4d2d56a6acd471ba623b5a73a4 Mon Sep 17 00:00:00 2001 From: Niclas Eklund Date: Fri, 10 Jun 2011 13:35:47 +0200 Subject: ssh: Added User's Guide framework and minor enhancements --- lib/ssh/doc/html/SSH_protocols.png | Bin 0 -> 15381 bytes lib/ssh/doc/src/Makefile | 15 ++++-- lib/ssh/doc/src/SSH_protocols.png | Bin 0 -> 15381 bytes lib/ssh/doc/src/book.xml | 3 ++ lib/ssh/doc/src/make.dep | 19 ++++++++ lib/ssh/doc/src/part.xml | 35 ++++++++++++++ lib/ssh/doc/src/ssh.xml | 2 +- lib/ssh/doc/src/ssh_ug.xml | 95 +++++++++++++++++++++++++++++++++++++ lib/ssh/src/ssh.erl | 2 +- 9 files changed, 165 insertions(+), 6 deletions(-) create mode 100644 lib/ssh/doc/html/SSH_protocols.png create mode 100644 lib/ssh/doc/src/SSH_protocols.png create mode 100644 lib/ssh/doc/src/make.dep create mode 100644 lib/ssh/doc/src/part.xml create mode 100644 lib/ssh/doc/src/ssh_ug.xml diff --git a/lib/ssh/doc/html/SSH_protocols.png b/lib/ssh/doc/html/SSH_protocols.png new file mode 100644 index 0000000000..145c96c4cd Binary files /dev/null and b/lib/ssh/doc/html/SSH_protocols.png differ diff --git a/lib/ssh/doc/src/Makefile b/lib/ssh/doc/src/Makefile index da99c4ea0f..bf65a2a60c 100644 --- a/lib/ssh/doc/src/Makefile +++ b/lib/ssh/doc/src/Makefile @@ -44,14 +44,18 @@ XML_REF3_FILES = \ ssh_sftp.xml \ ssh_sftpd.xml \ -XML_PART_FILES = part_notes.xml -XML_CHAPTER_FILES = notes.xml +XML_PART_FILES = part_notes.xml \ + part.xml +XML_CHAPTER_FILES = notes.xml \ + ssh_ug.xml BOOK_FILES = book.xml XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \ $(XML_PART_FILES) $(XML_CHAPTER_FILES) +IMAGE_FILES = SSH_protocols.png + # ---------------------------------------------------- HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \ @@ -80,16 +84,19 @@ DVIPS_FLAGS += # ---------------------------------------------------- # Targets # ---------------------------------------------------- -$(HTMLDIR)/%.gif: %.gif +$(HTMLDIR)/%.png: %.png $(INSTALL_DATA) $< $@ docs: pdf html man $(TOP_PDF_FILE): $(XML_FILES) +images: $(IMAGE_FILES:%=$(HTMLDIR)/%) + pdf: $(TOP_PDF_FILE) -html: $(HTML_REF_MAN_FILE) +html: images $(HTML_REF_MAN_FILE) + clean clean_docs: rm -rf $(HTMLDIR)/* diff --git a/lib/ssh/doc/src/SSH_protocols.png b/lib/ssh/doc/src/SSH_protocols.png new file mode 100644 index 0000000000..145c96c4cd Binary files /dev/null and b/lib/ssh/doc/src/SSH_protocols.png differ diff --git a/lib/ssh/doc/src/book.xml b/lib/ssh/doc/src/book.xml index fcec1d6f70..d33d9faf15 100644 --- a/lib/ssh/doc/src/book.xml +++ b/lib/ssh/doc/src/book.xml @@ -34,6 +34,9 @@ + + + diff --git a/lib/ssh/doc/src/make.dep b/lib/ssh/doc/src/make.dep new file mode 100644 index 0000000000..9be373481a --- /dev/null +++ b/lib/ssh/doc/src/make.dep @@ -0,0 +1,19 @@ +# ---------------------------------------------------- +# >>>> Do not edit this file <<<< +# This file was automaticly generated by +# /home/otp/bin/docdepend +# ---------------------------------------------------- + + +# ---------------------------------------------------- +# TeX files that the DVI file depend on +# ---------------------------------------------------- + +book.dvi: book.tex ref_man.tex ssh_ug.tex ssh.tex ssh_channel.tex \ + ssh_connection.tex ssh_sftp.tex ssh_sftpd.tex + +# ---------------------------------------------------- +# Source inlined when transforming from source to LaTeX +# ---------------------------------------------------- + +book.tex: ref_man.xml diff --git a/lib/ssh/doc/src/part.xml b/lib/ssh/doc/src/part.xml new file mode 100644 index 0000000000..cca30182a1 --- /dev/null +++ b/lib/ssh/doc/src/part.xml @@ -0,0 +1,35 @@ + + + + +
+ + 2011 + Ericsson AB. 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. + + + + SSH User's Guide + + + + +
+ +

The SSH application is an Erlang implementation of the + SSH protocol.

+
+ +
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 04b7a2ae56..9f8efebbf5 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -217,7 +217,7 @@ daemon(Port) -> daemon(Port, Options) -> - daemon(HostAddress, Port, Options) -> ssh_daemon_ref() + daemon(HostAddress, Port, Options) -> {ok, ssh_daemon_ref()} | {error, atom()} Starts a server listening for SSH connections on the given port. diff --git a/lib/ssh/doc/src/ssh_ug.xml b/lib/ssh/doc/src/ssh_ug.xml new file mode 100644 index 0000000000..0b040a59fd --- /dev/null +++ b/lib/ssh/doc/src/ssh_ug.xml @@ -0,0 +1,95 @@ + + + + +
+ + 2011 + Ericsson AB. All Rights Reserved. + + + The program may be used and/or copied only with the written permission from + Ericsson AB, or in accordance with the terms and conditions stipulated in + the agreement/contract under which the program has been supplied. + + SSH + OTP + + + A + ssh_ug.xml +
+ +
+ Introduction +

The Secure Shell (SSH) is a transport protocol. For more detailed information, + see the following RFCs: +

+ + RFC 4250 - + Protocol Assigned Numbers. + RFC 4251 - + Protocol Architecture. + RFC 4252 - + Authentication Protocol. + RFC 4253 - + Transport Layer Protocol. + RFC 4254 - + Connection Protocol. + RFC 4255 - + Key Fingerprints. + RFC 4344 - + Transport Layer Encryption Modes. + RFC 4716 - + Public Key File Format. + + +

The SSH application is an implementation of the SSH protocol + in Erlang. Conceptually it can be partitioned into four layers:

+ + + SSH Protocol Dependencies + + +
+ +
+ Overview +

The SSH application supports:

+ + + Subsystem - user-named services such as ssh_sftp. + The user can also add other subsystems (e.g. NETCONF). + Shell - interactive shell. + Exec - one-time remote execution (i.e. SCP). See ssh_connection:exec/4 + + + +
+ +
+ Configuration and Start + +

Before the SSH application can be used, there are two things that must be fulfilled:

+ + The Crypto application is started before SSH is. + The Public_key application is loaded when + running an embedded system. + + +
+ Server Side + +

When SSH is supposed to run as server, the function ssh:daemon/[1, 2, 3] needs to + be used to start the daemon.

+ +
+
+ Client Side + +

The client.

+ +
+
+ +
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 719c97e940..9ed6fdbcf8 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -264,7 +264,7 @@ start_daemon(Host, Port, Options, Inet) -> do_start_daemon(Host, Port, Options, SocketOptions) -> case ssh_system_sup:system_supervisor(Host, Port) of undefined -> - %% TODO: It would proably make more sense to call the + %% It would proably make more sense to call the %% address option host but that is a too big change at the %% monent. The name is a legacy name! try sshd_sup:start_child([{address, Host}, -- cgit v1.2.3 From 2084f7e079c951fdadebe23dcff5ec247c6e0158 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 10 Oct 2012 15:27:10 +0200 Subject: ssh: Add Users Guide and enhance man pages --- lib/ssh/doc/man6/.gitignore | 0 lib/ssh/doc/src/Makefile | 17 ++- lib/ssh/doc/src/book.xml | 8 +- lib/ssh/doc/src/fascicules.xml | 5 +- lib/ssh/doc/src/introduction.xml | 54 +++++++ lib/ssh/doc/src/make.dep | 19 --- lib/ssh/doc/src/notes.xml | 8 +- lib/ssh/doc/src/part.xml | 35 ----- lib/ssh/doc/src/ref_man.xml | 25 ++-- lib/ssh/doc/src/ssh.xml | 164 ++++++++++---------- lib/ssh/doc/src/ssh_app.xml | 98 ++++++++++++ lib/ssh/doc/src/ssh_channel.xml | 300 ++++++++++++------------------------- lib/ssh/doc/src/ssh_connection.xml | 254 +++++++++++++++++++++---------- lib/ssh/doc/src/ssh_protocol.xml | 142 ++++++++++++++++++ lib/ssh/doc/src/ssh_sftp.xml | 60 ++++---- lib/ssh/doc/src/ssh_sftpd.xml | 48 +++--- lib/ssh/doc/src/ssh_ug.xml | 95 ------------ lib/ssh/doc/src/user_guide.gif | Bin 1581 -> 0 bytes lib/ssh/doc/src/usersguide.xml | 37 +++++ lib/ssh/doc/src/using_ssh.xml | 288 +++++++++++++++++++++++++++++++++++ lib/ssh/src/ssh.app.src | 2 +- lib/ssh/src/ssh.erl | 12 +- lib/ssh/test/ssh_echo_server.erl | 2 +- 23 files changed, 1066 insertions(+), 607 deletions(-) create mode 100644 lib/ssh/doc/man6/.gitignore create mode 100644 lib/ssh/doc/src/introduction.xml delete mode 100644 lib/ssh/doc/src/make.dep delete mode 100644 lib/ssh/doc/src/part.xml create mode 100644 lib/ssh/doc/src/ssh_app.xml create mode 100644 lib/ssh/doc/src/ssh_protocol.xml delete mode 100644 lib/ssh/doc/src/ssh_ug.xml delete mode 100644 lib/ssh/doc/src/user_guide.gif create mode 100644 lib/ssh/doc/src/usersguide.xml create mode 100644 lib/ssh/doc/src/using_ssh.xml diff --git a/lib/ssh/doc/man6/.gitignore b/lib/ssh/doc/man6/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/ssh/doc/src/Makefile b/lib/ssh/doc/src/Makefile index bf65a2a60c..fc9600f6cd 100644 --- a/lib/ssh/doc/src/Makefile +++ b/lib/ssh/doc/src/Makefile @@ -44,14 +44,18 @@ XML_REF3_FILES = \ ssh_sftp.xml \ ssh_sftpd.xml \ +XML_REF6_FILES = ssh_app.xml + XML_PART_FILES = part_notes.xml \ - part.xml + usersguide.xml XML_CHAPTER_FILES = notes.xml \ - ssh_ug.xml + introduction.xml \ + ssh_protocol.xml \ + using_ssh.xml BOOK_FILES = book.xml -XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \ +XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) $(XML_REF6_FILES)\ $(XML_PART_FILES) $(XML_CHAPTER_FILES) IMAGE_FILES = SSH_protocols.png @@ -66,10 +70,12 @@ EXTRA_FILES = \ $(DEFAULT_GIF_FILES) \ $(DEFAULT_HTML_FILES) \ $(XML_REF3_FILES:%.xml=$(HTMLDIR)/%.html) \ + $(XML_REF6_FILES:%.xml=$(HTMLDIR)/%.html) \ $(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html) MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3) +MAN6_FILES = $(XML_REF6_FILES:%_app.xml=$(MAN6DIR)/%.6) HTML_REF_MAN_FILE = $(HTMLDIR)/index.html @@ -104,7 +110,7 @@ clean clean_docs: rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo) rm -f errs core *~ -man: $(MAN3_FILES) +man: $(MAN3_FILES) $(MAN6_FILES) debug opt: @@ -124,5 +130,8 @@ release_docs_spec: docs $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)" $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3" $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3" + $(INSTALL_DIR) "$(RELEASE_PATH)/man/man6" + $(INSTALL_DATA) $(MAN6_FILES) "$(RELEASE_PATH)/man/man6" + release_spec: diff --git a/lib/ssh/doc/src/book.xml b/lib/ssh/doc/src/book.xml index d33d9faf15..3c2375f96d 100644 --- a/lib/ssh/doc/src/book.xml +++ b/lib/ssh/doc/src/book.xml @@ -1,10 +1,10 @@ - +
- 20052010 + 20052012 Ericsson AB. All Rights Reserved. @@ -34,8 +34,8 @@ - - + + diff --git a/lib/ssh/doc/src/fascicules.xml b/lib/ssh/doc/src/fascicules.xml index 43090b4aed..069d9002e0 100644 --- a/lib/ssh/doc/src/fascicules.xml +++ b/lib/ssh/doc/src/fascicules.xml @@ -1,7 +1,10 @@ - + + + User's Guide + Reference Manual diff --git a/lib/ssh/doc/src/introduction.xml b/lib/ssh/doc/src/introduction.xml new file mode 100644 index 0000000000..837644330f --- /dev/null +++ b/lib/ssh/doc/src/introduction.xml @@ -0,0 +1,54 @@ + + + + +
+ + 2012 + Ericsson AB, 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. + + The Initial Developer of the Original Code is Ericsson AB. + + + Introduction + OTP team + introduction.xml +
+ +
+ Purpose + +

Secure Shell (SSH) is a protocol for secure remote login and + other secure network services over an insecure network. SSH + provides a single, full-duplex, byte-oriented connection between + client and server. The protocol also provides privacy, integrity, + server authentication and man-in-the-middle protection.

+ +

The Erlang SSH application is an implementation of the SSH + protocol in Erlang which offers API functions to write customized + SSH clients and servers as well as making the Erlang shell + available via SSH. Also included in the SSH application are an + SFTP (Secret File Transfer Protocol) client ssh_sftp and server ssh_sftpd.

+
+ +
+ Prerequisites +

It is assumed that the reader is familiar with the concepts of OTP + and has a basic understanding of public keys.

+
+ +
diff --git a/lib/ssh/doc/src/make.dep b/lib/ssh/doc/src/make.dep deleted file mode 100644 index 9be373481a..0000000000 --- a/lib/ssh/doc/src/make.dep +++ /dev/null @@ -1,19 +0,0 @@ -# ---------------------------------------------------- -# >>>> Do not edit this file <<<< -# This file was automaticly generated by -# /home/otp/bin/docdepend -# ---------------------------------------------------- - - -# ---------------------------------------------------- -# TeX files that the DVI file depend on -# ---------------------------------------------------- - -book.dvi: book.tex ref_man.tex ssh_ug.tex ssh.tex ssh_channel.tex \ - ssh_connection.tex ssh_sftp.tex ssh_sftpd.tex - -# ---------------------------------------------------- -# Source inlined when transforming from source to LaTeX -# ---------------------------------------------------- - -book.tex: ref_man.xml diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml index d4acb2ef1a..e58d4e2c36 100644 --- a/lib/ssh/doc/src/notes.xml +++ b/lib/ssh/doc/src/notes.xml @@ -1,4 +1,4 @@ - + @@ -780,7 +780,7 @@

- Ssh timeouts will now behave as expected e.i. defaults to + Ssh timeouts will now behave as expected i.e. defaults to infinity only the user of the ssh application can know of a reasonable timeout value for their application.

@@ -833,7 +833,7 @@ caused the ssh daemon to close the connections to all currently logged in users if one user logged out. Another problem related to the supervision tree caused the closing - down of clients to leak processes e.i. all processes was + down of clients to leak processes i.e. all processes was not shutdown correctly.

Own Id: OTP-7676

@@ -925,7 +925,7 @@ slightly changes the options to the API function ssh:daemon/[1,2,3] deprecating all no longer documented options. Note that the new API enforces the "logical way" - of using the old API e.i. making the subsystem process + of using the old API i.e. making the subsystem process part of the ssh applications supervisor tree, so missuses of the old API are not compatible with the new API.

diff --git a/lib/ssh/doc/src/part.xml b/lib/ssh/doc/src/part.xml deleted file mode 100644 index cca30182a1..0000000000 --- a/lib/ssh/doc/src/part.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - -

- - 2011 - Ericsson AB. 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. - - - - SSH User's Guide - - - - -
- -

The SSH application is an Erlang implementation of the - SSH protocol.

-
- - diff --git a/lib/ssh/doc/src/ref_man.xml b/lib/ssh/doc/src/ref_man.xml index 9ab56b28ec..0bd8479343 100644 --- a/lib/ssh/doc/src/ref_man.xml +++ b/lib/ssh/doc/src/ref_man.xml @@ -1,10 +1,10 @@ - +
- 20042010 + 20042012 Ericsson AB. All Rights Reserved. @@ -22,20 +22,21 @@ SSH Reference Manual - Jakob Cederlund - + OTP 2007-10-06 %VSN% - application.sgml + ref_man.xml

The SSH application is an erlang implementation of the - secure shell protocol.

-
- - - - - + secure shell protocol (SSH) as defined by RFC 4250 - 4254

+ + ' + + + + + +
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 9f8efebbf5..907d0efc5c 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -22,13 +22,7 @@
ssh - Ingela Anderton Andin - Håkan Mattsson - - Håkan Mattsson - 2007-10-06 - PA1
ssh Main API of the SSH application @@ -40,18 +34,19 @@ SSH - ssh requires the crypto and public_key applications. - Supported SSH-version is 2.0 - Currently supports only a minimum of mac and encryption algorithms i.e. - hmac-sha1, and aes128-cb and 3des-cbc. + SSH requires the crypto and public_key applications. + Supported SSH version is 2.0 + Supported MAC algorithms: hmac-sha1 + Supported encryption algorithms: aes128-cb and 3des-cbc
- COMMON DATA TYPES + DATA TYPES

Type definitions that are used more than once in - this module:

+ this module and/or abstractions to indicate the intended use of the data + type:

boolean() = true | false

string() = list of ASCII characters

ssh_daemon_ref() - opaque to the user @@ -60,60 +55,64 @@ returned by ssh:connect/3

ip_address() - {N1,N2,N3,N4} % IPv4 | {K1,K2,K3,K4,K5,K6,K7,K8} % IPv6

-

subsystem_spec() = {subsystem_name(), {channel_callback(), channel_init_args()}}

+

subsystem_spec() = {subsystem_name(), + {channel_callback(), channel_init_args()}}

subsystem_name() = string()

channel_callback() = atom() - Name of the erlang module implementing the subsystem using the ssh_channel behavior see ssh_channel(3)

channel_init_args() = list()

- + close(ConnectionRef) -> ok - Closes a ssh connection + Closes an SSH connection ConnectionRef = ssh_connection_ref() -

Closes a ssh connection.

+

Closes an SSH connection.

connect(Host, Port, Options) -> - connect(Host, Port, Options, Timeout) -> {ok, ssh_connection_ref()} - | {error, Reason} + connect(Host, Port, Options, Timeout) -> {ok, + ssh_connection_ref()} | {error, Reason} Connect to an ssh server. Host = string() Port = integer() - The default is , the registered port for SSH. + The default is , the assigned well known port + number for SSH. Options = [{Option, Value}] Timeout = infinity | integer(milliseconds) -

Connects to an SSH server. No channel is started this is done +

Connects to an SSH server. No channel is started. This is done by calling ssh_connect:session_channel/2.

Options are:

-

Sets the user directory e.i. the directory containing +

Sets the user directory i.e. the directory containing ssh configuration files for the user such as - , and - . Defaults to the directory normally - referred to as

+ , and + . Defaults to the + directory normally referred to as +

-

If the user dsa key is protected by a pass phrase it can be +

If the user dsa key is protected by a passphrase it can be supplied with this option.

-

If the user rsa key is protected by a pass phrase it can be +

If the user rsa key is protected by a passphrase it can be supplied with this option.

@@ -138,7 +137,7 @@

Sets the preferred public key algorithm to use for user - authentication. If the the preferred algorithm fails of + authentication. If the the preferred algorithm fails for some reason, the other algorithm is tried. The default is to try first.

@@ -149,11 +148,12 @@ -

Sets a timeout on the transport layer connection. Defaults to infinity.

+

Sets a timeout on the transport layer + connection. Defaults to infinity.

-

Provide a user name. If this option is not given, ssh +

Provides a user name. If this option is not given, ssh reads from the environment ( or on unix, on Windows).

@@ -165,23 +165,9 @@ password if the password authentication method is attempted.

- - -

Provide a fun for password authentication. The fun - will be called as and - should return or .

-
-

Provide a special call-back module for key handling. - The call-back module should be modeled after the - module. The functions that must - be exported are: - , - , - and - . This is considered - somewhat experimental and will be better documented later on.

+

TODO:

@@ -189,7 +175,7 @@ -

Allow an existing file-descriptor to be used +

Allow an existing file descriptor to be used (simply passed on to the transport protocol).

@@ -202,7 +188,8 @@
- connection_info(ConnectionRef, [Option]) ->[{Option, Value}] + connection_info(ConnectionRef, [Option]) ->[{Option, + Value}] Retrieves information about a connection. Option = client_version | server_version | peer @@ -217,7 +204,8 @@ daemon(Port) -> daemon(Port, Options) -> - daemon(HostAddress, Port, Options) -> {ok, ssh_daemon_ref()} | {error, atom()} + daemon(HostAddress, Port, Options) -> {ok, + ssh_daemon_ref()} | {error, atom()} Starts a server listening for SSH connections on the given port. @@ -228,30 +216,32 @@ Value = term() -

Starts a server listening for SSH connections on the given port.

- -

Options are:

+

Starts a server listening for SSH connections on the given + port.

+

Options are:

- Provides specifications for handling of subsystems. The - "sftp" subsystem-spec can be retrieved by calling - ssh_sftpd:subsystem_spec/1. If the subsystems option in not present - the value of [ssh_sftpd:subsystem_spec([])] will be used. - It is of course possible to set the option to the empty list - if you do not want the daemon to run any subsystems at all. + Provides specifications for handling of subsystems. The + "sftp" subsystem spec can be retrieved by calling + ssh_sftpd:subsystem_spec/1. If the subsystems option in + not present the value of + [ssh_sftpd:subsystem_spec([])] will be used. It is + of course possible to set the option to the empty list if + you do not want the daemon to run any subsystems at all. - pid() | - fun(string() = User, ip_address() = PeerAddr) -> pid()}]]> + pid() | fun(string() = User, + ip_address() = PeerAddr) -> pid()}]]> - Defines the read-eval-print loop used when a shell is requested - by the client. Example use the - erlang shell: which is - the default behavior. + Defines the read-eval-print loop used when a shell is + requested by the client. Default is to use the erlang shell: + - + - Provide your own cli implementation, e.i. a channel callback + Provides your own cli implementation, i.e. a channel callback module that implements a shell and command execution. Note that you may customize the shell read-eval-print loop using the option shell which is much less work than implementing @@ -259,27 +249,30 @@ -

Sets the user directory e.i. the directory containing +

Sets the user directory i.e. the directory containing ssh configuration files for the user such as - , and - . Defaults to the directory normally - referred to as

+ , and + . Defaults to the + directory normally referred to as +

-

Sets the system directory, containing the host files - that identifies the host for ssh. The default is - , note that SSH normally - requires the host files there to be readable only by - root.

+

Sets the system directory, containing the host key files + that identifies the host keys for ssh. The default is + , note that for security reasons + this directory is normally only accessible by the root user.

-

Comma separated string that determines which authentication methodes that the server - should support and in what order they will be tried. Defaults to +

Comma separated string that determines which + authentication methodes that the server should support and + in what order they will be tried. Defaults to

- +

Provide passwords for password authentication.They will be used when someone tries to connect to the server and @@ -293,7 +286,7 @@ user. From a security perspective this option makes the server very vulnerable.

- + boolean()}]]>

Provide a function for password validation. This is called with user and password as strings, and should return @@ -335,9 +328,9 @@ Options - see ssh:connect/3 -

Starts an interactive shell to an SSH server on the +

Starts an interactive shell via an SSH server on the given Host. The function waits for user input, - and will not return until the remote shell is ended (e.g. on + and will not return until the remote shell is ended (i.e. exit from the shell).

@@ -346,25 +339,24 @@ start() -> start(Type) -> ok | {error, Reason} - Starts the Ssh application. + Starts the SSH application. Type = permanent | transient | temporary Reason = term() -

Starts the Ssh application. Default type - is temporary. See also - application(3) - Requires that the crypto application has been started. +

Utility function that starts crypto, public_key and the SSH + application. Defult type is temporary. + application(3)

stop() -> ok - Stops the Ssh application. + Stops the SSH application. -

Stops the Ssh application. See also +

Stops the SSH application. See also application(3)

diff --git a/lib/ssh/doc/src/ssh_app.xml b/lib/ssh/doc/src/ssh_app.xml new file mode 100644 index 0000000000..51544d3890 --- /dev/null +++ b/lib/ssh/doc/src/ssh_app.xml @@ -0,0 +1,98 @@ + + + + +
+ + 2012 + Ericsson AB. 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. + + + + SSH + ssh_app.sgml +
+ SSH + The ssh application implements the SSH (Secure Shell) protocol and + provides an SFTP (SSH File Transfer Protocol) client and server. + +
+ DEPENDENCIES +

The ssh application uses the Erlang applications public_key and + crypto to handle public keys and encryption, hence these + applications needs to be loaded for the ssh application to work. In + an embedded environment that means they need to be started with + application:start/[1,2] before the ssh application is started. +

+
+ +
+ CONFIGURATION + +

The ssh application does not currently have an application + specific configuration file as described in application(3), + however it will by default use the following configuration files + from openssh: known_hosts, authorized_keys, authorized_keys2, + id_dsa and id_rsa, ssh_host_dsa_key and ssh_host_rsa_key. By + default Erlang SSH will look for id_dsa, id_rsa, known_hosts + and authorized_keys in ~/.ssh, and the host key files in /etc/ssh + . These locations may be changed by the options user_dir and + system_dir. Public key handling may also be customized by + providing a callback module implementing the behavior ssh_key_api. +

+ +
+ PUBLIC KEYS +

+ id_dsa and id_rsa are the users private key files, note that + the public key is part of the private key so the ssh + application will not use the id_<*>.pub files. These are + for the users convenience when he/she needs to convey their + public key. +

+
+ +
+ KNOW HOSTS +

The known_hosts file contains a list of approved servers and + their public keys. Once a server is listed, it can be verified + without user interaction. +

+
+ +
+ AUTHORIZED KEYS +

The authorized key file keeps track of the user's authorized + public keys. The most common use of this file is to let users + log in without entering their password which is supported by the + Erlang SSH daemon. +

+
+ +
+ HOST KEYS +

Currently rsa and dsa host keys are supported and are + expected to be found in files named ssh_host_rsa_key and + ssh_host_dsa_key. +

+
+
+ +
+ SEE ALSO +

application(3)

+
+ +
diff --git a/lib/ssh/doc/src/ssh_channel.xml b/lib/ssh/doc/src/ssh_channel.xml index c2b7aa94a5..342de97a1b 100644 --- a/lib/ssh/doc/src/ssh_channel.xml +++ b/lib/ssh/doc/src/ssh_channel.xml @@ -1,11 +1,11 @@ - +
2009 - 2009 + 2012 Ericsson AB, All Rights Reserved @@ -22,31 +22,38 @@ The Initial Developer of the Original Code is Ericsson AB. - ssh_channel - Ingela Anderton Andin - - - - - -
ssh_channel Generic Ssh Channel Behavior -

Ssh services are implemented as channels that are multiplexed - over an ssh connection and communicates via the ssh connection - protocol. This module provides a callback API that takes care of - generic channel aspects such as flow control and close messages - and lets the callback functions take care of the service specific - parts. +

SSH services (clients and servers) are implemented as channels + that are multiplexed over an SSH connection and communicates via + the SSH + Connection Protocol . This module provides a callback API + that takes care of generic channel aspects such as flow control + and close messages and lets the callback functions take care of + the service (application) specific parts. This behavior also ensures + that the channel process honors the principal of an OTP-process so + that it can be part of a supervisor tree. This is a requirement of + channel processes implementing a subsystem that will be added to + the SSH applications supervisor tree.

+ +

The functions init/1, terminate/2, handle_ssh_msg/2 and + handle_msg/2 are the functions that are required + to provide the implementation for a server side channel, such as + an SSH subsystem channel that can be plugged into the Erlang ssh + daemon see ssh:daemon/[2, + 3]. + The handle_call/3, handle_cast/2, code_change/3 and enter_loop/1 + functions are only relevant when implementing a client side + channel.

- COMMON DATA TYPES + DATA TYPES

Type definitions that are used more than once in this module and/or abstractions to indicate the intended use of the data @@ -56,31 +63,31 @@

string() = list of ASCII characters

timeout() = infinity | integer() - in milliseconds.

ssh_connection_ref() - opaque to the user returned by - ssh:connect/3 or sent to a ssh channel process

+ ssh:connect/3 or sent to an SSH channel process

ssh_channel_id() = integer()

ssh_data_type_code() = 1 ("stderr") | 0 ("normal") are - currently valid values see RFC 4254 section 5.2.

+ currently valid values see RFC 4254 section 5.2.

call(ChannelRef, Msg) -> - call(ChannelRef, Msg, Timeout) -> Reply | {error, Reason} + call(ChannelRef, Msg, timeout()) -> Reply | {error, Reason} Makes a synchronous call to a channel. ChannelRef = pid() As returned by start_link/4 Msg = term() - Timeout = timeout() Reply = term() Reason = closed | timeout

Makes a synchronous call to the channel process by sending a message and waiting until a reply arrives or a timeout - occurs. The channel will call - CallbackModule:handle_call/3 to handle the message. - If the channel process does not exist {error, closed} is returned. + occurs. The channel will call CallbackModule:handle_call/3 + to handle the message. If the channel process does not exist + {error, closed} is returned.

@@ -98,32 +105,33 @@

Sends an asynchronous message to the channel process and returns ok immediately, ignoring if the destination node or channel process does not exist. The channel will call - CallbackModule:handle_cast/2 to handle the message. + CallbackModule:handle_cast/2 + to handle the message.

enter_loop(State) -> _ - Makes an existing process into a ssh_channel process. + Makes an existing process an ssh_channel process. - State = term() - as returned by ssh_channel:init/1 + State = term() - as returned by ssh_channel:init/1 -

Makes an existing process into a ssh_channel +

Makes an existing process an ssh_channel process. Does not return, instead the calling process will - enter the ssh_channel process receive loop and become a + enter the ssh_channel process receive loop and become an ssh_channel process. The process must have been started using one of the start functions in proc_lib, see proc_lib(3). The user is responsible for any initialization of the process - and needs to call ssh_channel:init/1. + and needs to call ssh_channel:init/1

- init(Options) -> {ok, State} | {ok, State, Timeout} | {stop, Reason} + init(Options) -> {ok, State} | {ok, State, timeout()} | {stop, Reason} Initiates a ssh_channel process. Options = [{Option, Value}] @@ -134,24 +142,27 @@

- The module that implements the channel behavior. + The module that implements the channel behaviour. - The list of arguments to the callback modules + The list of arguments to the callback module's init function. - Reference to the ssh connection. + Reference to the ssh connection as returned by ssh:connect/3 Id of the ssh channel. -

This function is normally not called by the user, it is - only needed if for some reason the channel process needs - to be started with help of proc_lib instead calling - ssh_channel:start/4 or ssh_channel:start_link/4

+

This function is normally not called by the + user. The user only needs to call if for some reason the + channel process needs to be started with help of + proc_lib instead of calling + ssh_channel:start/4 or + ssh_channel:start_link/4

@@ -167,12 +178,12 @@

This function can be used by a channel to explicitly send a reply to a client that called call/[2,3] when the reply cannot be defined in the return value of - CallbackModule:handle_call/3.

+ CallbackModule:handle_call/3.

Client must be the From argument provided to the callback function handle_call/3. Reply is an arbitrary term, - which will be given back to the client as the return value of - ssh_channel:call/[2,3].

+ which will be given back to the client as the return value of + ssh_channel:call/[2,3].>

@@ -180,11 +191,12 @@ start(SshConnection, ChannelId, ChannelCb, CbInitArgs) -> start_link(SshConnection, ChannelId, ChannelCb, CbInitArgs) -> {ok, ChannelRef} | {error, Reason} - Starts a processes that handles a ssh channel. + Starts a processes that handles a SSH channel. SshConnection = ssh_connection_ref() ChannelId = ssh_channel_id() - As returned by ssh_connection:session_channel/[2,4] + As returned by cannot be defined in the return value of + ssh_connection:session_channel/[2,4] ChannelCb = atom() The name of the module implementing the service specific parts of the channel. @@ -193,39 +205,24 @@ ChannelRef = pid() -

Starts a processes that handles a ssh channel. Will be - called internally by the ssh daemon or explicitly by the ssh - client implementations. A channel process traps exit signals - by default. +

Starts a processes that handles an SSH channel. It will be + called internally by the SSH daemon or explicitly by the SSH + client implementations. The behavior will set the + trap_exit flag to true.

-
- CALLBACK FUNCTIONS - -

The functions init/1, terminate/2, handle_ssh_msg/2 and - handle_msg/2 are the functions that are required to provide the - implementation for a server side channel, such as a ssh subsystem - channel that can be plugged into the erlang ssh daemon see - ssh:daemon/[2, 3]. The - handle_call/3, handle_cast/2 code_change/3 and enter_loop/1 - functions are only relevant when implementing a client side - channel.

-
-
CALLBACK TIMEOUTS -

If an integer timeout value is provided in a return value of - one of the callback functions, a timeout will occur unless a - message is received within Timeout milliseconds. A timeout - is represented by the atom timeout which should be handled - by the handle_msg/2 - callback function. The atom infinity can be used to wait - indefinitely, this is the default value.

+ +

The timeout values that may be returned by the callback functions + has the same semantics as in a gen_server + If the timout occurs handle_msg/2 + will be called as handle_msg(timeout, State).

@@ -242,18 +239,19 @@ upgrade/downgrade, i.e. when the instruction {update,Module,Change,...} where Change={advanced,Extra} is given in the appup - file. See OTP - Design Principles for more information. Any new - connection will benefit from a server side upgrade but - already started connections on the server side will not be - affected. + file. See OTP + Design Principles for more information.

-

If there are long lived ssh connections and more - than one upgrade in a short time this may cause the old - connections to fail as only two versions of the code may - be loaded simultaneously.

+

Soft upgrade according to the OTP release concept + is not straight forward for the server side, as subsystem + channel processes are spawned by the SSH application and + hence added to its supervisor tree. It could be possible to + upgrade the subsystem channels, when upgrading the user + application, if the callback functions can handle two + versions of the state, but this function can not be used in + the normal way.

+

In the case of an upgrade, OldVsn is Vsn, and in the case of a downgrade, OldVsn is @@ -269,7 +267,7 @@ - CallbackModule:init(Args) -> {ok, State} | {ok, State, Timeout} | + CallbackModule:init(Args) -> {ok, State} | {ok, State, timeout()} | {stop, Reason} Makes necessary initializations and returns the initial channel state if the initializations succeed. @@ -277,7 +275,6 @@ Args = term() Last argument to ssh_channel:start_link/4. State = term() - Timeout = timeout() Reason = term() @@ -298,17 +295,16 @@ From = opaque to the user should be used as argument to ssh_channel:reply/2 State = term() - Result = {reply, Reply, NewState} | {reply, Reply, NewState, Timeout} - | {noreply, NewState} | {noreply , NewState, Timeout} + Result = {reply, Reply, NewState} | {reply, Reply, NewState, timeout()} + | {noreply, NewState} | {noreply , NewState, timeout()} | {stop, Reason, Reply, NewState} | {stop, Reason, NewState} Reply = term() - will be the return value of ssh_channel:call/[2,3] - Timeout = timeout() - NewState = term() - a possible updated version of State + NewState = term() Reason = term()

Handles messages sent by calling - ssh_channel:call/[2,3] + ssh_channel:call/[2,3]

For more detailed information on timeouts see the section CALLBACK TIMEOUTS.

@@ -322,10 +318,9 @@ Msg = term() State = term() - Result = {noreply, NewState} | {noreply, NewState, Timeout} + Result = {noreply, NewState} | {noreply, NewState, timeout()} | {stop, Reason, NewState} - NewState = term() - a possible updated version of State - Timeout = timeout() + NewState = term() Reason = term() @@ -359,14 +354,14 @@ - This is the first messages that will be received - by the channel, it is sent just before - the ssh_channel:init/1 function returns successfully. - This is especially useful if the server wants - to send a message to the client without first receiving - a message from the client. If the message is not useful - for your particular problem just ignore it by immediately - returning {ok, State}. + This is the first messages that will be received by + the channel, it is sent just before the ssh_channel:init/1 function + returns successfully. This is especially useful if the + server wants to send a message to the client without first + receiving a message from it. If the message is not + useful for your particular scenario just ignore it by + immediately returning {ok, State}. @@ -377,118 +372,19 @@ ssh_channel_id(), State} Handles ssh connection protocol messages. - Msg = {ssh_cm, ssh_connection_ref(), SshMsg} - SshMsg = tuple() - see message list below + Msg = ssh_connection:event() State = term()

Handles ssh connection protocol messages that may need service specific attention.

- -

All channels should handle the following messages. For - channels implementing subsystems the handle_ssh_msg-callback - will not be called for any other messages.

- - - - Data has arrived on the channel. When the callback - for this message returns the channel behavior will adjust - the ssh flow control window. - - - Indicteas that the other side will not send any more - data. - - - A signal can be delivered to the remote - process/service using the following message. Some systems - may not implement signals, in which case they should ignore - this message. - - - A remote execution may terminate violently due to a - signal then this message may be received. For details on valid string - values see RFC 4254 section 6.10 - - - When the command running at the other end terminates, - the following message can be sent to return the exit status - of the command. A zero 'exit_status' usually means that the - command terminated successfully. - - -

Channels implementing a shell and command execution on the server side - should also handle the following messages.

- - - - Environment variables may be passed to the - shell/command to be started later. Note that before the - callback returns it should call the function - ssh_connection:reply_request/4 with the boolean value of - WantReply as the second argument. - - - - This message will request that the server start the - execution of the given command. Note that before the - callback returns it should call the function - ssh_connection:reply_request/4 with the boolean value of - WantReply as the second argument. - - - A pseudo-terminal has been requested for the - session. Terminal is the value of the TERM environment - variable value (e.g., vt100). Zero dimension parameters must - be ignored. The character/row dimensions override the pixel - dimensions (when nonzero). Pixel dimensions refer to the - drawable area of the window. The Opcode in the - TerminalModes list is the mnemonic name, represented - as an lowercase erlang atom, defined in RFC 4254 section 8, - or the opcode if the mnemonic name is not listed in the - RFC. Example OP code: 53, mnemonic name ECHO erlang atom: - echo. Note that before the callback returns it should - call the function ssh_connection:reply_request/4 with the - boolean value of WantReply as the second - argument. - - - This message will request that the user's default - shell be started at the other end. Note that before the - callback returns it should call the function - ssh_connection:reply_request/4 with the value of - WantReply as the second argument. - - - - When the window (terminal) size changes on the client - side, it MAY send a message to the other side to inform it - of the new dimensions. -

The following message is completely taken care of by the ssh channel behavior

- + The channel behavior will send a close message to the other side if such a message has not already been sent and then terminate the channel with reason normal. @@ -505,12 +401,12 @@

This function is called by a channel process when it is - about to terminate. Before this function is called ssh_connection:close/2 - will be called if it has not been called earlier. - This function should be the opposite of CallbackModule:init/1 - and do any necessary cleaning up. When it returns, the - channel process terminates with reason Reason. The return value is - ignored. + about to terminate. Before this function is called ssh_connection:close/2 + will be called if it has not been called earlier. + This function should do any necessary cleaning + up. When it returns, the channel process terminates with + reason Reason. The return value is ignored.

diff --git a/lib/ssh/doc/src/ssh_connection.xml b/lib/ssh/doc/src/ssh_connection.xml index a9ae13d556..4480f0a093 100644 --- a/lib/ssh/doc/src/ssh_connection.xml +++ b/lib/ssh/doc/src/ssh_connection.xml @@ -1,11 +1,11 @@ - +
2008 - 2011 + 2012 Ericsson AB, All Rights Reserved @@ -24,69 +24,178 @@ ssh_connection - Ingela Anderton Andin - - - - -
ssh_connection - This module provides an API to the ssh connection protocol. + This module provides API functions to send SSH Connection Protocol + events to the other side of an SSH channel. + -

This module provides an API to the ssh connection protocol. - Not all features of the connection protocol are officially supported yet. - Only the ones supported are documented here.

+

The SSH Connection Protocol is used by clients and servers + (i.e. SSH channels) to communicate over the SSH connection. The + API functions in this module sends SSH Connection Protocol events + that are received as messages by the remote channel. + In the case that the receiving channel is an Erlang process the + message will be on the following format + . If the ssh_channel behavior is used to + implement the channel process these will be handled by + handle_ssh_msg/2 .

-
- COMMON DATA TYPES +
+ DATA TYPES +

Type definitions that are used more than once in this module and/or abstractions to indicate the intended use of the data type:

- +

boolean() = true | false

string() = list of ASCII characters

timeout() = infinity | integer() - in milliseconds.

ssh_connection_ref() - opaque to the user returned by - ssh:connect/3 or sent to a ssh channel processes

+ ssh:connect/3 or sent to an SSH channel processes

ssh_channel_id() = integer()

ssh_data_type_code() = 1 ("stderr") | 0 ("normal") are - currently valid values see RFC 4254 section 5.2.

+ currently valid values see RFC 4254 section 5.2.

ssh_request_status() = success | failure

-
+

event() = {ssh_cm, ssh_connection_ref(), ssh_event_msg()}

+

ssh_event_msg() = data_events() | status_events() | terminal_events()

+ + + data_events() + + + + Data has arrived on the channel. This event is sent as + result of calling ssh_connection:send/[3,4,5] + + + Indicates that the other side will not send any more + data. This event is sent as result of calling ssh_connection:send_eof/2 + + + + + status_events() + + + + + A signal can be delivered to the remote process/service + using the following message. Some systems will not support + signals, in which case they should ignore this message. There is + currently no funtion to generate this event as the signals + refered to are on OS-level and not something generated by an + Erlang program. + + + + A remote execution may terminate violently due to a signal + then this message may be received. For details on valid string + values see RFC 4254 section 6.10. Special case of the signals + mentioned above. + + + When the command running at the other end terminates, the + following message can be sent to return the exit status of the + command. A zero 'exit_status' usually means that the command + terminated successfully. This event is sent as result of calling + + ssh_connection:exit_status/3 + + + This event is sent as result of calling + ssh_connection:close/2 Both the handling of this + event and sending of it will be taken care of by the + ssh_channel behavior. + + + -
- MESSAGES SENT TO CHANNEL PROCESSES + terminal_events() + + +

Channels implementing a shell and command execution on the + server side should handle the following messages that may be sent by client channel processes.

+ +

Events that includes a WantReply expects the event handling + process to call ssh_connection:reply_request/4 + with the boolean value of WantReply as the second + argument.

+ + + + Environment variables may be passed to the shell/command + to be started later. This event is sent as result of calling ssh_connection:setenv/5 + + + + A pseudo-terminal has been requested for the + session. Terminal is the value of the TERM environment + variable value (e.g., vt100). Zero dimension parameters must + be ignored. The character/row dimensions override the pixel + dimensions (when nonzero). Pixel dimensions refer to the + drawable area of the window. The Opcode in the + TerminalModes list is the mnemonic name, represented + as an lowercase erlang atom, defined in + RFC 4254 section 8, + or the opcode if the mnemonic name is not listed in the + RFC. Example OP code: 53, mnemonic name ECHO erlang atom: + echo. There is currently no API function to generate this + event. + + + This message will request that the user's default shell + be started at the other end. This event is sent as result of calling ssh_connection:shell/2 + + + + When the window (terminal) size changes on the client + side, it MAY send a message to the server side to inform it of + the new dimensions. There is currently no API function to generate this + event. -

As a result of the ssh connection protocol messages on the form - - will be sent to a channel process. The term will contain - information regarding the ssh connection protocol event, - for details see the ssh channel behavior callback handle_ssh_msg/2

-
- - + + This message will request that the server starts + execution of the given command. This event is sent as result of calling ssh_connection:exec/4 + +
+ + +
+ + adjust_window(ConnectionRef, ChannelId, NumOfBytes) -> ok - Adjusts the ssh flowcontrol window. + Adjusts the SSH flowcontrol window. ConnectionRef = ssh_connection_ref() ChannelId = ssh_channel_id() NumOfBytes = integer() -

Adjusts the ssh flowcontrol window.

+

Adjusts the SSH flowcontrol window. This shall be done by both client and server side channel processes.

-

This will be taken care of by the ssh_channel - behavior when the callback - handle_ssh_msg/2 has returned after processing a - {ssh_cm, ssh_connection_ref(), {data, ssh_channel_id(), - ssh_data_type_code(), binary()}} - message, and should normally not be called explicitly.

+

Channels implemented with the ssh_channel + behavior will normaly not need to call this function as flow control + will be handled by the behavior. The behavior will adjust the window every time + the callback + handle_ssh_msg/2 has returned after processing channel data

@@ -98,20 +207,19 @@ ChannelId = ssh_channel_id() -

Sends a close message on the channel ChannelId +

A server or client channel process can choose to close their session by sending a close event.

-

This function will be called by the ssh channel +

This function will be called by the ssh_channel behavior when the channel is terminated see ssh_channel(3) and should - normally not be called explicitly.

+ marker="ssh_channel"> ssh_channel(3) so channels implemented with the + behavior should not call this function explicitly.

exec(ConnectionRef, ChannelId, Command, TimeOut) -> ssh_request_status() - Will request that the server start the - execution of the given command. + Request that the server start the execution of the given command. ConnectionRef = ssh_connection_ref() ChannelId = ssh_channel_id() @@ -119,44 +227,39 @@ Timeout = timeout() -

Will request that the server start the execution of the - given command, the result will be received as:

+

Should be called by a client channel process to request that the server starts execution of the + given command, the result will be several messages according to the following pattern. Note + that the last message will be a channel close message, as the exec request is a one time + execution that closes the channel when it is done.

- N X {ssh_cm, - ssh_connection_ref(), {data, ssh_channel_id(), ssh_data_type_code(), - binary() = Data}} + N x {ssh_cm, ssh_connection_ref(), + {data, ssh_channel_id(), ssh_data_type_code(), binary() = Data}} The result of executing the command may be only one line or thousands of lines depending on the command. - 1 X {ssh_cm, ssh_connection_ref(), {eof, ssh_channel_id()}} + 0 or 1 x {ssh_cm, ssh_connection_ref(), {eof, ssh_channel_id()}} Indicates that no more data will be sent. - 0 or 1 X {ssh_cm, + 0 or 1 x {ssh_cm, ssh_connection_ref(), {exit_signal, ssh_channel_id(), string() = ExitSignal, string() = ErrorMsg, string() = LanguageString}} Not all systems send signals. For details on valid string values see RFC 4254 section 6.10 - 0 or 1 X {ssh_cm, ssh_connection_ref(), {exit_status, + 0 or 1 x {ssh_cm, ssh_connection_ref(), {exit_status, ssh_channel_id(), integer() = ExitStatus}} It is recommended by the ssh connection protocol that this message shall be sent, but that may not always be the case. - 1 X {ssh_cm, ssh_connection_ref(), + 1 x {ssh_cm, ssh_connection_ref(), {closed, ssh_channel_id()}} Indicates that the ssh channel started for the execution of the command has now been shutdown. - -

These message should be handled by the - client. The ssh channel - behavior can be used when writing a client. -

- exit_status(ConnectionRef, ChannelId, Status) -> ok Sends the exit status of a command to the client. @@ -166,9 +269,9 @@ Status = integer() -

Sends the exit status of a command to the client.

+

Should be called by a server channel process to sends the exit status of a command to the client.

-
+ reply_request(ConnectionRef, WantReply, Status, CannelId) -> ok @@ -183,10 +286,9 @@

Sends status replies to requests where the requester has stated that they want a status report e.i . WantReply = true, if WantReply is false calling this function will be a - "noop". Should be called after handling an ssh connection + "noop". Should be called while handling an ssh connection protocol message containing a WantReply boolean - value. See the ssh_channel behavior callback handle_ssh_msg/2 + value.

@@ -206,7 +308,7 @@ Timeout = timeout() -

Sends channel data. +

Should be called by client- and server channel processes to send data to each other.

@@ -228,9 +330,7 @@ session_channel(ConnectionRef, Timeout) -> session_channel(ConnectionRef, InitialWindowSize, MaxPacketSize, Timeout) -> {ok, ssh_channel_id()} | {error, Reason} - Opens a channel for a ssh session. A session is a - remote execution of a program. The program may be a shell, an - application, a system command, or some built-in subsystem. + Opens a channel for a ssh session. ConnectionRef = ssh_connection_ref() InitialWindowSize = integer() @@ -239,9 +339,8 @@ Reason = term() -

Opens a channel for a ssh session. A session is a - remote execution of a program. The program may be a shell, an - application, a system command, or some built-in subsystem. +

Opens a channel for an SSH session. The channel id returned from this function + is the id used as input to the other funtions in this module.

@@ -258,8 +357,8 @@ Timeout = timeout() -

Environment variables may be passed to the shell/command to be - started later. +

Environment variables may be passed before starting the + shell/command. Should be called by a client channel processes.

@@ -267,17 +366,16 @@ shell(ConnectionRef, ChannelId) -> ssh_request_status() - Will request that the user's default shell (typically - defined in /etc/passwd in UNIX systems) be started at the other + Requests that the user's default shell (typically + defined in /etc/passwd in UNIX systems) shall be executed at the server end. ConnectionRef = ssh_connection_ref() ChannelId = ssh_channel_id() -

Will request that the user's default shell (typically - defined in /etc/passwd in UNIX systems) be started at the - other end. +

Should be called by a client channel process to request that the user's default shell (typically + defined in /etc/passwd in UNIX systems) shall be executed at the server end.

@@ -292,7 +390,7 @@ Timeout = timeout() -

Sends a request to execute a predefined subsystem. +

Should be called by a client channel process for requesting to execute a predefined subsystem on the server.

diff --git a/lib/ssh/doc/src/ssh_protocol.xml b/lib/ssh/doc/src/ssh_protocol.xml new file mode 100644 index 0000000000..529558759e --- /dev/null +++ b/lib/ssh/doc/src/ssh_protocol.xml @@ -0,0 +1,142 @@ + + + + +
+ + 2012 + Ericsson AB. All Rights Reserved. + + + The program may be used and/or copied only with the written permission from + Ericsson AB, or in accordance with the terms and conditions stipulated in + the agreement/contract under which the program has been supplied. + + Secure Shell (SSH) + OTP + + %VSN% + ssh_protocol.xml +
+ +
+ SSH Protocol Overview + +

Conceptually the SSH protocol can be partitioned into four + layers:

+ + + SSH Protocol Architecture + + +
+ Transport Protocol + +

The SSH Transport Protocol is a secure, low level transport. + It provides strong encryption, cryptographic host + authentication and integrity protection. Currently, only a + minimum of MAC- (message authentication code, a short piece of + information used to authenticate a message) and encryption + algorithms see ssh(3) +

+
+ +
+ Authentication Protocol + +

The SSH authentication protocol is a general-purpose user + authentication protocol run over the SSH transport + protocol. Erlang SSH supports user authentication using public + key technology (RSA and DSA, X509-certificates are currently not + supported). It is also possible to use a so called keyboard + interactive authentication. This method is suitable for + interactive authentication methods that do not need any special + software support on the client side. Instead, all authentication + data should be entered via the keyboad. It is also possible + to use a pure password based authentication scheme, note that in + this case the the plain text password will be encrypted befor sent + over the network. +

+
+ +
+ Connection Protocol + +

The SSH Connection Protocol provides application-support + services over the transport pipe, such as channel multiplexing, + flow control, remote program execution, signal propagation, + connection forwarding, etc. Functions for handling the SSH + Connection Protocol can be found in the module ssh_connection. +

+
+ +
+ Channels + +

All terminal sessions, forwarded connections etc., are + channels. Multiple channels are multiplexed into a single + connection, and all channels are flow-controlled. Typically an + SSH client will open a channel, send data/commands, receive + data/"control information" and when it is done close the + channel. The ssh_channel behaviour makes it easy to + write your own SSH client/server processes that use flow + control. It handles generic parts of SSH channel managment and + lets you focus on the application logic. +

+ +

Channels comes in three flavors

+ + + Subsystem - named services that can be run as + part of an SSH server such as SFTP ssh_sftp, that is built in to the + SSH daemon (server) by default but may be disabled. The Erlang SSH + daemon may be configured to run any Erlang + implemented SSH subsystem. + + Shell - interactive shell. By default the + Erlang daemon will run the Erlang shell. It is + possible to customize the shell by providing your own + read-eval-print loop. It is also possible, but much more work, + to provide your own CLI (Command Line Interface) implementation. + + Exec - one-time remote execution (like + SCP). See ssh_connection:exec/4 + +
+ +

Channels are flow controlled. No data may be sent to a channel + peer until a message is received to indicate that window space is + available. The 'initial window size' specifies how many bytes of + channel data that can be sent to the channel peer without adjusting the + window. +

+ +

+ For more detailed information about the SSH protocol, see the + following RFCs: +

+ + + RFC 4250 - + Protocol Assigned Numbers. + RFC 4251 - + Protocol Architecture. + RFC 4252 - + Authentication Protocol. + RFC 4253 - + Transport Layer Protocol. + RFC 4254 - + Connection Protocol. + RFC 4255 - + Key Fingerprints. + RFC 4344 - + Transport Layer Encryption Modes. + RFC 4716 - + Public Key File Format. + +
+
diff --git a/lib/ssh/doc/src/ssh_sftp.xml b/lib/ssh/doc/src/ssh_sftp.xml index c1f75461b1..28576c9ef0 100644 --- a/lib/ssh/doc/src/ssh_sftp.xml +++ b/lib/ssh/doc/src/ssh_sftp.xml @@ -1,10 +1,10 @@ - +
- 20052010 + 20052012 Ericsson AB. All Rights Reserved. @@ -22,25 +22,20 @@ ssh_sftp - Jakob Cederlund - - 1 - - + OTP 2005-09-22 - PA1 ssh_sftp.sgml
ssh_sftp SFTP client.

This module implements an SFTP (SSH FTP) client. SFTP is a - secure, encrypted file transfer service available for - SSH.

+ secure, encrypted file transfer service available for + SSH.

- COMMON DATA TYPES + DATA TYPES

Type definitions that are used more than once in this module and/or abstractions to indicate the intended use of the data type:

@@ -51,8 +46,8 @@
TIMEOUTS -

If the request functions for the sftp channel return {error, timeout} - it does not mean that the request did not reach the server and was +

If the request functions for the SFTP channel return {error, timeout} + it does not guarantee that the request did not reach the server and was not performed, it only means that we did not receive an answer from the server within the time that was expected.

@@ -64,7 +59,7 @@ start_channel(Host, Options) -> start_channel(Host, Port, Options) -> {ok, Pid} | {ok, Pid, ConnectionRef} | {error, Reason} - Starts a sftp client + Starts a SFTP client Host = string() ConnectionRef = ssh_connection_ref() @@ -73,11 +68,11 @@ Reason = term() -

If not provided, setups a ssh connection in this case a - connection reference will be returned too. A ssh channel - process is started to handle the communication with the SFTP - server, the returned pid for this process should be used as - input to all other API functions in this module.

+

If no connection reference is provided, a connection is set + up and the new connection is returned. An SSH channel process + is started to handle the communication with the SFTP server. + The returned pid for this process should be used as input to + all other API functions in this module.

Options are:

@@ -95,13 +90,13 @@ stop_channel(ChannelPid) -> ok - Stops the sftp client channel. + Stops the SFTP client channel. ChannelPid = pid() -

Stops a sftp channel. If the ssh connection should be closed - call ssh:close/1.

+

Stops an SFTP channel. Does not close the SSH connetion. + Use ssh:close/1 to close it.

@@ -133,8 +128,9 @@ Reason = term() -

Writes a file to the server, like . - The file is created if it's not there.

+

Writes a file to the server, like + . The file is created if + it does not exist or is owerwritten if it does.

@@ -169,7 +165,7 @@

Opens a file on the server, and returns a handle that - is used for reading or writing.

+ can be used for reading or writing.

@@ -184,7 +180,7 @@

Opens a handle to a directory on the server, the handle - is used for reading directory contents.

+ can be used for reading directory contents.

@@ -218,7 +214,7 @@

Reads bytes from the file referenced by - . Returns , or , or + . Returns , , or . If the file is opened with , is a binary, otherwise it is a string.

If the file is read past eof, only the remaining bytes @@ -267,9 +263,9 @@ Reason = term() -

Write to the file referenced by . +

Writes to the file referenced by . The file should be opened with or - flag. Returns if successful and + flag. Returns if successful or S otherwise.

Typical error reasons are:

@@ -317,14 +313,14 @@ ChannelPid = pid() Handle = term() Location = Offset | {bof, Offset} | {cur, Offset} | {eof, Offset} | bof | cur | eof - Offset = int() + Offset = integer() Timeout = timeout() NewPosition = integer() Reason = term()

Sets the file position of the file referenced by . - Returns (as an absolute offset) if + Returns (as an absolute offset) if successful, otherwise . is one of the following:

@@ -413,7 +409,7 @@ Reason = term() -

Read the link target from the symbolic link specified +

Reads the link target from the symbolic link specified by , like .

diff --git a/lib/ssh/doc/src/ssh_sftpd.xml b/lib/ssh/doc/src/ssh_sftpd.xml index b3d64e72b4..a4273195b5 100644 --- a/lib/ssh/doc/src/ssh_sftpd.xml +++ b/lib/ssh/doc/src/ssh_sftpd.xml @@ -1,10 +1,10 @@ - +
- 20052010 + 20052012 Ericsson AB. All Rights Reserved. @@ -22,23 +22,17 @@ ssh_sftpd - Ingela Anderton Andin - - 1 - - 2005-09-22 - PA1 ssh_sftpd.sgml
ssh_sftpd - Specifies a channel process to handle a sftp subsystem. + Specifies the channel process to handle an sftp subsystem.

Specifies a channel process to handle a sftp subsystem.

- COMMON DATA TYPES + DATA TYPES

subsystem_spec() = {subsystem_name(), {channel_callback(), channel_init_args()}}

subsystem_name() = "sftp"

channel_callback() = atom() - Name of the erlang module implementing the @@ -65,28 +59,28 @@ -

Determines which module to call for communicating with - the file server. Default value is ssh_sftpd_file that uses the - file and filelib API:s to access the standard OTP file - server. This option may be used to plug in the use of - other file servers.

- - - -

The default value is 0, which means that there is no upper limit. - If supplied, the number of filenames returned to the sftp client per READDIR - request, is limited to at most the given value.

-
+

Determines which module to call for accessing + the file server. The default value is ssh_sftpd_file that uses the + file and filelib API:s to access the standard OTP file + server. This option may be used to plug in + other file servers.

+ + + +

The default value is 0, which means that there is no upper limit. + If supplied, the number of filenames returned to the sftp client per READDIR + request is limited to at most the given value.

+

Sets the sftp root directory. The user will then not be - able to see any files above this root. If for instance - the root is set to /tmp the user will see this - directory as / and if the user does cd /etc - the user will end up in /tmp/etc. + able to see any files above this root. If for instance + the root is set to /tmp the user will see this + directory as / and if the user does cd /etc + the user will end up in /tmp/etc.

- + diff --git a/lib/ssh/doc/src/ssh_ug.xml b/lib/ssh/doc/src/ssh_ug.xml deleted file mode 100644 index 0b040a59fd..0000000000 --- a/lib/ssh/doc/src/ssh_ug.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - - -
- - 2011 - Ericsson AB. All Rights Reserved. - - - The program may be used and/or copied only with the written permission from - Ericsson AB, or in accordance with the terms and conditions stipulated in - the agreement/contract under which the program has been supplied. - - SSH - OTP - - - A - ssh_ug.xml -
- -
- Introduction -

The Secure Shell (SSH) is a transport protocol. For more detailed information, - see the following RFCs: -

- - RFC 4250 - - Protocol Assigned Numbers. - RFC 4251 - - Protocol Architecture. - RFC 4252 - - Authentication Protocol. - RFC 4253 - - Transport Layer Protocol. - RFC 4254 - - Connection Protocol. - RFC 4255 - - Key Fingerprints. - RFC 4344 - - Transport Layer Encryption Modes. - RFC 4716 - - Public Key File Format. - - -

The SSH application is an implementation of the SSH protocol - in Erlang. Conceptually it can be partitioned into four layers:

- - - SSH Protocol Dependencies - - -
- -
- Overview -

The SSH application supports:

- - - Subsystem - user-named services such as ssh_sftp. - The user can also add other subsystems (e.g. NETCONF). - Shell - interactive shell. - Exec - one-time remote execution (i.e. SCP). See ssh_connection:exec/4 - - - -
- -
- Configuration and Start - -

Before the SSH application can be used, there are two things that must be fulfilled:

- - The Crypto application is started before SSH is. - The Public_key application is loaded when - running an embedded system. - - -
- Server Side - -

When SSH is supposed to run as server, the function ssh:daemon/[1, 2, 3] needs to - be used to start the daemon.

- -
-
- Client Side - -

The client.

- -
-
- -
diff --git a/lib/ssh/doc/src/user_guide.gif b/lib/ssh/doc/src/user_guide.gif deleted file mode 100644 index e6275a803d..0000000000 Binary files a/lib/ssh/doc/src/user_guide.gif and /dev/null differ diff --git a/lib/ssh/doc/src/usersguide.xml b/lib/ssh/doc/src/usersguide.xml new file mode 100644 index 0000000000..c818003090 --- /dev/null +++ b/lib/ssh/doc/src/usersguide.xml @@ -0,0 +1,37 @@ + + + + +
+ + 2012 + Ericsson AB. 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. + + + + SSH User's Guide + OTP Team + 2012-10-11 + usersguide.xml +
+ +

The SSH application implements the SSH (Secure Shell) protocol and + provides an SFTP (Secret File Transfer Protocol) client and server. +

+
+ + + +
diff --git a/lib/ssh/doc/src/using_ssh.xml b/lib/ssh/doc/src/using_ssh.xml new file mode 100644 index 0000000000..db17c6fd1c --- /dev/null +++ b/lib/ssh/doc/src/using_ssh.xml @@ -0,0 +1,288 @@ + + + + +
+ + 2012 + Ericsson AB. 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. + + + + Getting started + using_ssh.xml +
+ +
+ General information +

The examples in the following sections use the utility function + ssh:start/0 that starts + all needed applications (crypto, public_key and ssh). All examples + are run in an Erlang shell, or in a bash shell using openssh to + illustrate how the erlang ssh application can be used. The + exampels are run as the user otptest on a local network where the + user is authorized to login in over ssh to the host "tarlop". If + nothing else is stated it is persumed that the otptest user has an + entry in tarlop's authorized_keys file (may log in via ssh without + entering a password). Also tarlop is a known host in the user + otptests known_hosts file so that host verification can be done + without user interaction. +

+
+ +
+ Using the Erlang SSH Terminal Client + +

The user otptest, that has bash as default shell, uses the + ssh:shell/1 client to connect to the openssh daemon running on a + host called tarlop. Note that currently this client is very simple + and you should not be expected to be as fancy as the openssh + client.

+ + + 1> ssh:start(). + ok + 2> {ok, S} = ssh:shell("tarlop"). + >pwd + /home/otptest + >exit + logout + 3> + +
+ +
+ Running an Erlang SSH Daemon + +

The option system_dir must be a directory containing a host + key file and it defaults to /etc/ssh. For details see section + Configuration Files in ssh(6). +

+ +

Normaly the /etc/ssh directory is only readable by root.

+
+ +

The option user_dir defaults to the users ~/.ssh directory

+ +

In the following exampel we have generate new keys and host keys as + to be able to run the example without having root privilages

+ + + $bash> ssh-keygen -t rsa -f /tmp/ssh_daemon/ssh_host_rsa_key + [...] + $bash> ssh-keygen -t rsa -f /tmp/otptest_user/.ssh/id_rsa + [...] + + +

And add the public hostkey to the known_hosts file of the user otptest. Then we can do

+ + + 1> ssh:start(). + ok + 2> {ok, Sshd} = ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon/ssh_host_rsa_key"}, + {user_dir, "/tmp/otptest_user/.ssh"}]). + {ok,<0.54.0>} + 3> + + +

Use the openssh client from a shell to connect to the Erlang ssh daemon.

+ + + $bash> ssh tarlop -p 8989 -i /tmp/otptest_user/.ssh/id_rsa + Eshell V5.10 (abort with ^G) + 1> + + +

There is two ways of shuting down an SSH daemon

+ +

1: Stops the listener, but leaves existing connections started by the listener up and running.

+ + + 3> ssh:stop_listener(Sshd). + ok + 4> + + +

2: Stops the listener and all connections started by the listener.

+ + + 3> ssh:stop_daemon(Sshd) + ok + 4> + + +
+ +
+ One Time Execution + +

In the following example the Erlang shell is the client process + that receives the channel replies. If you run this example + in your environment you may get fewer or more messages back as + this depends on the OS and shell on the machine running the ssh + daemon. See also ssh_connection:exec/4 + +

+ + + 1> ssh:start(). + ok + 2> {ok, ConnectionRef} = ssh:connect("tarlop", 22, []). + {ok,<0.57.0>} + 3>{ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity). + {ok,0} + 4> success = ssh_connection:exec(ConnectionRef, ChannelId, "pwd", infinity). + 5> flush(). + Shell got {ssh_cm,<0.57.0>,{data,0,0,<<"/home/otptest\n">>}} + Shell got {ssh_cm,<0.57.0>,{eof,0}} + Shell got {ssh_cm,<0.57.0>,{exit_status,0,0}} + Shell got {ssh_cm,<0.57.0>,{closed,0}} + ok + 6> + + +

Note only the channel is closed the connection is still up and can handle other channels

+ + + 6> {ok, NewChannelId} = ssh_connection:session_channel(ConnectionRef, infinity). + {ok,1} + ... + +
+ +
+ SFTP (SSH File Transport Protocol) server + + + 1> ssh:start(). + ok + 2> ssh:daemon(8989, [{system_dir, "."}, + {subsystems, [ssh_sftpd:subsystem_spec([{cwd, "/tmp/sftp/example"}])]}]). + {ok,<0.54.0>} + 3> + + +

Run the openssh sftp client

+ + + $bash> sftp -oPort=8989 tarlop + Connecting to tarlop... + sftp> pwd + Remote working directory: /tmp/sftp/example + sftp> + +
+ +
+ SFTP (SSH File Transport Protocol) client + + + 1> ssh:start(). + ok + 2> {ok, ChannelPid, Connection} = ssh_sftp:start_channel("tarlop", []). + {ok,<0.57.0>,<0.51.0>} + 3> ssh_sftp:read_file(ChannelPid, "/home/otptest/test.txt"). + {ok,<<"This is a test file\n">>} + +
+ +
+ Creating a subsystem + +

A very small SSH subsystem that echos N bytes could be implemented like this.

+ + +-module(ssh_echo_server). +-behaviour(ssh_channel). +-record(state, { + n, + id, + cm + }). +-export([init/1, handle_msg/2, handle_ssh_msg/2, terminate/2]). + +init([N]) -> + {ok, #state{n = N}}. + +handle_msg({ssh_channel_up, ChannelId, ConnectionManager}, State) -> + {ok, State#state{id = ChannelId, + cm = ConnectionManager}}. + +handle_ssh_msg({ssh_cm, CM, {data, ChannelId, 0, Data}}, #state{n = N} = State) -> + M = N - size(Data), + case M > 0 of + true -> + ssh_connection:send(CM, ChannelId, Data), + {ok, State#state{n = M}}; + false -> + <<SendData:N/binary, _/binary>> = Data, + ssh_connection:send(CM, ChannelId, SendData), + ssh_connection:send_eof(CM, ChannelId), + {stop, ChannelId, State} + end; +handle_ssh_msg({ssh_cm, _ConnectionManager, + {data, _ChannelId, 1, Data}}, State) -> + error_logger:format(standard_error, " ~p~n", [binary_to_list(Data)]), + {ok, State}; + +handle_ssh_msg({ssh_cm, _ConnectionManager, {eof, _ChannelId}}, State) -> + {ok, State}; + +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, _}}, + State) -> + {stop, ChannelId, State}; + +handle_ssh_msg({ssh_cm, _, {exit_status, ChannelId, _Status}}, State) -> + {stop, ChannelId, State}. + +terminate(_Reason, _State) -> + ok. + + +

And run like this on the host tarlop with the keys generated in section 3.3

+ + + 1> ssh:start(). + ok + 2> ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon/ssh_host_rsa_key"}, + {user_dir, "/tmp/otptest_user/.ssh"} + {subsystems, [{"echo_n", {ssh_echo_server, [10]}}]}]). + {ok,<0.54.0>} + 3> + + + + 1> ssh:start(). + ok + 2>{ok, ConnectionRef} = ssh:connect("tarlop", 8989, [{user_dir, "/tmp/otptest_user/.ssh"}]). + {ok,<0.57.0>} + 3>{ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity). + 4> success = ssh_connection:subsystem(ConnectionRef, ChannelId, "echo_n", infinity). + 5> ok = ssh_connection:send(ConnectionRef, ChannelId, "0123456789", infinity), + 6> flush(). + {ssh_msg, <0.57.0>, {data, 0, 1, "0123456789"}} + {ssh_msg, <0.57.0>, {eof, 0}} + {ssh_msg, <0.57.0>, {closed, 0}} + 7> {error, closed} = ssh_connection:send(ConnectionRef, ChannelId, "10", infinity), + + +
+ +
diff --git a/lib/ssh/src/ssh.app.src b/lib/ssh/src/ssh.app.src index 316c09eb06..a96c1a510c 100644 --- a/lib/ssh/src/ssh.app.src +++ b/lib/ssh/src/ssh.app.src @@ -35,7 +35,7 @@ ssh_userreg, ssh_xfer]}, {registered, []}, - {applications, [kernel, stdlib, crypto]}, + {applications, [kernel, stdlib, crypto, public_key]}, {env, []}, {mod, {ssh_app, []}}]}. diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 9ed6fdbcf8..f163539e75 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -41,19 +41,23 @@ %% %% Type = permanent | transient | temporary %% -%% Description: Starts the inets application. Default type +%% Description: Starts the ssh application. Default type %% is temporary. see application(3) %%-------------------------------------------------------------------- start() -> + application:start(crypto), + application:start(public_key), application:start(ssh). start(Type) -> + application:start(crypto, Type), + application:start(public_key, Type), application:start(ssh, Type). %%-------------------------------------------------------------------- %% Function: stop() -> ok %% -%% Description: Stops the inets application. +%% Description: Stops the ssh application. %%-------------------------------------------------------------------- stop() -> application:stop(ssh). @@ -325,8 +329,6 @@ handle_option([{user_passwords, _} = Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{pwdfun, _} = Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); -handle_option([{user_auth, _} = Opt | Rest],SocketOptions, SshOptions ) -> - handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{key_cb, _} = Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{role, _} = Opt | Rest], SocketOptions, SshOptions) -> @@ -400,8 +402,6 @@ handle_ssh_option({user_passwords, Value} = Opt) when is_list(Value)-> Opt; handle_ssh_option({pwdfun, Value} = Opt) when is_function(Value) -> Opt; -handle_ssh_option({user_auth, Value} = Opt) when is_function(Value) -> - Opt; handle_ssh_option({key_cb, Value} = Opt) when is_atom(Value) -> Opt; handle_ssh_option({compression, Value} = Opt) when is_atom(Value) -> diff --git a/lib/ssh/test/ssh_echo_server.erl b/lib/ssh/test/ssh_echo_server.erl index 739aabe6fb..64686231e2 100644 --- a/lib/ssh/test/ssh_echo_server.erl +++ b/lib/ssh/test/ssh_echo_server.erl @@ -50,7 +50,7 @@ handle_ssh_msg({ssh_cm, CM, {data, ChannelId, 0, Data}}, #state{n = N} = State) end; handle_ssh_msg({ssh_cm, _ConnectionManager, {data, _ChannelId, 1, Data}}, State) -> - error_logger:format("ssh: STDERR: ~s\n", [binary_to_list(Data)]), + error_logger:format(standard_error, " ~p~n", [binary_to_list(Data)]), {ok, State}; handle_ssh_msg({ssh_cm, _ConnectionManager, {eof, _ChannelId}}, State) -> -- cgit v1.2.3 From 671cf55d2388ef3c30f8e0e6b3e5ec824b02da09 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Tue, 6 Nov 2012 10:55:39 +0100 Subject: ssh: Document and clean up SSH behaviours --- lib/ssh/doc/src/Makefile | 7 +- lib/ssh/doc/src/introduction.xml | 2 +- lib/ssh/doc/src/ref_man.xml | 16 +++-- lib/ssh/doc/src/ssh.xml | 28 +++++--- lib/ssh/doc/src/ssh_app.xml | 6 +- lib/ssh/doc/src/ssh_channel.xml | 109 +++++++++++++++-------------- lib/ssh/doc/src/ssh_client_key_api.xml | 124 +++++++++++++++++++++++++++++++++ lib/ssh/doc/src/ssh_connection.xml | 4 +- lib/ssh/doc/src/ssh_protocol.xml | 20 ++++-- lib/ssh/doc/src/ssh_server_key_api.xml | 90 ++++++++++++++++++++++++ lib/ssh/doc/src/ssh_sftp.xml | 5 +- lib/ssh/doc/src/using_ssh.xml | 34 +++++---- lib/ssh/src/Makefile | 4 +- lib/ssh/src/ssh.app.src | 4 +- lib/ssh/src/ssh.erl | 37 ++++++---- lib/ssh/src/ssh_auth.erl | 26 +++---- lib/ssh/src/ssh_auth.hrl | 4 +- lib/ssh/src/ssh_channel.erl | 37 +++++++--- lib/ssh/src/ssh_client_key.erl | 34 +++++++++ lib/ssh/src/ssh_client_key_api.erl | 35 ++++++++++ lib/ssh/src/ssh_connection_handler.erl | 4 +- lib/ssh/src/ssh_file.erl | 29 ++++---- lib/ssh/src/ssh_key_api.erl | 45 ------------ lib/ssh/src/ssh_server_key.erl | 33 +++++++++ lib/ssh/src/ssh_server_key_api.erl | 30 ++++++++ lib/ssh/src/ssh_sftpd.erl | 12 +--- lib/ssh/src/ssh_subsystem.erl | 47 +++++++++++++ lib/ssh/src/ssh_transport.erl | 4 +- lib/ssh/test/ssh_echo_server.erl | 2 +- 29 files changed, 622 insertions(+), 210 deletions(-) create mode 100644 lib/ssh/doc/src/ssh_client_key_api.xml create mode 100644 lib/ssh/doc/src/ssh_server_key_api.xml create mode 100644 lib/ssh/src/ssh_client_key.erl create mode 100644 lib/ssh/src/ssh_client_key_api.erl delete mode 100644 lib/ssh/src/ssh_key_api.erl create mode 100644 lib/ssh/src/ssh_server_key.erl create mode 100644 lib/ssh/src/ssh_server_key_api.erl create mode 100644 lib/ssh/src/ssh_subsystem.erl diff --git a/lib/ssh/doc/src/Makefile b/lib/ssh/doc/src/Makefile index fc9600f6cd..0e79d9979f 100644 --- a/lib/ssh/doc/src/Makefile +++ b/lib/ssh/doc/src/Makefile @@ -37,10 +37,11 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN) # Target Specs # ---------------------------------------------------- XML_APPLICATION_FILES = ref_man.xml -XML_REF3_FILES = \ - ssh.xml \ +XML_REF3_FILES = ssh.xml \ ssh_channel.xml \ - ssh_connection.xml\ + ssh_connection.xml \ + ssh_client_key_api.xml \ + ssh_server_key_api.xml \ ssh_sftp.xml \ ssh_sftpd.xml \ diff --git a/lib/ssh/doc/src/introduction.xml b/lib/ssh/doc/src/introduction.xml index 837644330f..aac8de0f76 100644 --- a/lib/ssh/doc/src/introduction.xml +++ b/lib/ssh/doc/src/introduction.xml @@ -40,7 +40,7 @@ protocol in Erlang which offers API functions to write customized SSH clients and servers as well as making the Erlang shell available via SSH. Also included in the SSH application are an - SFTP (Secret File Transfer Protocol) client ssh_sftp and server ssh_sftpd.

diff --git a/lib/ssh/doc/src/ref_man.xml b/lib/ssh/doc/src/ref_man.xml index 0bd8479343..88203b5034 100644 --- a/lib/ssh/doc/src/ref_man.xml +++ b/lib/ssh/doc/src/ref_man.xml @@ -31,12 +31,14 @@

The SSH application is an erlang implementation of the secure shell protocol (SSH) as defined by RFC 4250 - 4254

- ' - - - - - - + + + + + + + + + diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 907d0efc5c..517cbf1ef9 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -48,7 +48,7 @@ this module and/or abstractions to indicate the intended use of the data type:

boolean() = true | false

-

string() = list of ASCII characters

+

string() = [byte()]

ssh_daemon_ref() - opaque to the user returned by ssh:daemon/[1,2,3]

ssh_connection_ref() - opaque to the user @@ -134,7 +134,7 @@ password. Do note that it may not always be desirable to use those options from a security point of view.

- +

Sets the preferred public key algorithm to use for user authentication. If the the preferred algorithm fails for @@ -143,15 +143,15 @@ -

List of public key algorithms to try to use, ssh_rsa and ssh_dsa available. - Will override

+

List of public key algorithms to try to use, 'ssh-rsa' and 'ssh-dss' available. + Will override

Sets a timeout on the transport layer - connection. Defaults to infinity.

+ connection. Defaults to infinity.

- +

Provides a user name. If this option is not given, ssh reads from the environment ( or @@ -165,9 +165,11 @@ password if the password authentication method is attempted.

- + -

TODO:

+

Module implementing the behaviour ssh_client_key_api. + Can be used to customize the handling of public keys. +

@@ -177,7 +179,7 @@

Allow an existing file descriptor to be used (simply passed on to the transport protocol).

- +

Determines if SSH shall use IPv6 or not.

@@ -293,6 +295,12 @@ if the password is valid and otherwise.

+ + +

Module implementing the behaviour ssh_server_key_api. + Can be used to customize the handling of public keys. +

+

Allow an existing file-descriptor to be used @@ -347,7 +355,7 @@

Utility function that starts crypto, public_key and the SSH application. Defult type is temporary. - application(3) + See also application(3)

diff --git a/lib/ssh/doc/src/ssh_app.xml b/lib/ssh/doc/src/ssh_app.xml index 51544d3890..c01f44936a 100644 --- a/lib/ssh/doc/src/ssh_app.xml +++ b/lib/ssh/doc/src/ssh_app.xml @@ -22,7 +22,7 @@ SSH - ssh_app.sgml + ssh_app.xml SSH The ssh application implements the SSH (Secure Shell) protocol and @@ -50,7 +50,9 @@ and authorized_keys in ~/.ssh, and the host key files in /etc/ssh . These locations may be changed by the options user_dir and system_dir. Public key handling may also be customized by - providing a callback module implementing the behavior ssh_key_api. + providing a callback module implementing the behaviors + ssh_client_key_api and + ssh_server_key_api.

diff --git a/lib/ssh/doc/src/ssh_channel.xml b/lib/ssh/doc/src/ssh_channel.xml index 342de97a1b..f0083ae8d1 100644 --- a/lib/ssh/doc/src/ssh_channel.xml +++ b/lib/ssh/doc/src/ssh_channel.xml @@ -25,7 +25,7 @@ ssh_channel ssh_channel - Generic Ssh Channel Behavior + -behaviour(ssh_channel).

SSH services (clients and servers) are implemented as channels @@ -41,15 +41,12 @@ the SSH applications supervisor tree.

-

The functions init/1, terminate/2, handle_ssh_msg/2 and - handle_msg/2 are the functions that are required - to provide the implementation for a server side channel, such as - an SSH subsystem channel that can be plugged into the Erlang ssh - daemon see ssh:daemon/[2, - 3]. - The handle_call/3, handle_cast/2, code_change/3 and enter_loop/1 - functions are only relevant when implementing a client side - channel.

+ When implementing a SSH subsystem use the + -behaviour(ssh_subsystem). instead of -behaviour(ssh_channel). + as the only relevant callback functions for subsystems are + init/1, handle_ssh_msg/2, handle_msg/2 and terminate/2, so the ssh_subsystem + behaviour is limited version of the ssh_channel behaviour. +
@@ -72,20 +69,22 @@ call(ChannelRef, Msg) -> - call(ChannelRef, Msg, timeout()) -> Reply | {error, Reason} + call(ChannelRef, Msg, Timeout) -> Reply | {error, Reason} Makes a synchronous call to a channel. ChannelRef = pid() As returned by start_link/4 Msg = term() + Timeout = timeout() Reply = term() Reason = closed | timeout +

Makes a synchronous call to the channel process by sending a message and waiting until a reply arrives or a timeout occurs. The channel will call CallbackModule:handle_call/3 + "#Module:handle_call-3">Module:handle_call/3 to handle the message. If the channel process does not exist {error, closed} is returned.

@@ -105,7 +104,7 @@

Sends an asynchronous message to the channel process and returns ok immediately, ignoring if the destination node or channel process does not exist. The channel will call - CallbackModule:handle_cast/2 + Module:handle_cast/2 to handle the message.

@@ -131,10 +130,13 @@
- init(Options) -> {ok, State} | {ok, State, timeout()} | {stop, Reason} + init(Options) -> {ok, State} | {ok, State, Timeout} | {stop, Reason} Initiates a ssh_channel process. - Options = [{Option, Value}] + Options = [{Option, Value}] + State = term() + Timeout = timeout() + Reason = term()

@@ -178,7 +180,7 @@

This function can be used by a channel to explicitly send a reply to a client that called call/[2,3] when the reply cannot be defined in the return value of - CallbackModule:handle_call/3.

+ Module:handle_call/3.

Client must be the From argument provided to the callback function handle_call/3. Reply is an arbitrary term, @@ -221,53 +223,56 @@

The timeout values that may be returned by the callback functions has the same semantics as in a gen_server - If the timout occurs handle_msg/2 + If the timeout occurs handle_msg/2 will be called as handle_msg(timeout, State).

- CallbackModule:code_change(OldVsn, State, Extra) -> {ok, + Module:code_change(OldVsn, State, Extra) -> {ok, NewState} Converts process state when code is changed. - Converts process state when code is changed. + OldVsn = term() + In the case of an upgrade, OldVsn is Vsn, and + in the case of a downgrade, OldVsn is + {down,Vsn}. Vsn is defined by the vsn + attribute(s) of the old version of the callback module + Module. If no such attribute is defined, the version is + the checksum of the BEAM file. + State = term() + The internal state of the channel. + Extra = term() + Passed as-is from the {advanced,Extra} + part of the update instruction. -

This function is called by a client side channel when it - should update its internal state during a release - upgrade/downgrade, i.e. when the instruction - {update,Module,Change,...} where - Change={advanced,Extra} is given in the appup - file. See OTP - Design Principles for more information. -

+

Converts process state when code is changed.

-

Soft upgrade according to the OTP release concept - is not straight forward for the server side, as subsystem - channel processes are spawned by the SSH application and - hence added to its supervisor tree. It could be possible to - upgrade the subsystem channels, when upgrading the user - application, if the callback functions can handle two - versions of the state, but this function can not be used in - the normal way.

-
+

This function is called by a client side channel when it + should update its internal state during a release + upgrade/downgrade, i.e. when the instruction + {update,Module,Change,...} where + Change={advanced,Extra} is given in the appup + file. See OTP + Design Principles for more information. +

+ +

Soft upgrade according to the OTP release concept + is not straight forward for the server side, as subsystem + channel processes are spawned by the SSH application and + hence added to its supervisor tree. It could be possible to + upgrade the subsystem channels, when upgrading the user + application, if the callback functions can handle two + versions of the state, but this function can not be used in + the normal way.

+
-

In the case of an upgrade, OldVsn is Vsn, and - in the case of a downgrade, OldVsn is - {down,Vsn}. Vsn is defined by the vsn - attribute(s) of the old version of the callback module - Module. If no such attribute is defined, the version - is the checksum of the BEAM file.

-

State is the internal state of the channel.

-

Extra is passed as-is from the {advanced,Extra} - part of the update instruction.

-

The function should return the updated internal state.

- CallbackModule:init(Args) -> {ok, State} | {ok, State, timeout()} | + Module:init(Args) -> {ok, State} | {ok, State, timeout()} | {stop, Reason} Makes necessary initializations and returns the initial channel state if the initializations succeed. @@ -287,7 +292,7 @@ - CallbackModule:handle_call(Msg, From, State) -> Result + Module:handle_call(Msg, From, State) -> Result Handles messages sent by calling ssh_channel:call/[2,3] @@ -312,7 +317,7 @@ - CallbackModule:handle_cast(Msg, State) -> Result + Module:handle_cast(Msg, State) -> Result Handles messages sent by calling ssh_channel:cact/2 @@ -334,7 +339,7 @@ - CallbackModule:handle_msg(Msg, State) -> {ok, State} | + Module:handle_msg(Msg, State) -> {ok, State} | {stop, ChannelId, State} Handle other messages than ssh connection protocol, @@ -368,7 +373,7 @@ - CallbackModule:handle_ssh_msg(Msg, State) -> {ok, State} | {stop, + Module:handle_ssh_msg(Msg, State) -> {ok, State} | {stop, ssh_channel_id(), State} Handles ssh connection protocol messages. @@ -393,7 +398,7 @@ - CallbackModule:terminate(Reason, State) -> _ + Module:terminate(Reason, State) -> _ Reason = term() diff --git a/lib/ssh/doc/src/ssh_client_key_api.xml b/lib/ssh/doc/src/ssh_client_key_api.xml new file mode 100644 index 0000000000..abc1070e78 --- /dev/null +++ b/lib/ssh/doc/src/ssh_client_key_api.xml @@ -0,0 +1,124 @@ + + + + +
+ + 2012 + Ericsson AB, 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. + + The Initial Developer of the Original Code is Ericsson AB. + + ssh_client_key_api +
+ ssh_client_key_api + + -behaviour(ssh_client_key_api). + + +

Behavior describing the API for an SSH client's public key handling. + By implementing the callbacks defined. + in this behavior it is possible to customize the SSH client's public key + handling. By default the SSH application implements this behavior + with help of the standard openssh files, see ssh(6).

+
+ +
+ DATA TYPES + +

Type definitions that are used more than once in this module + and/or abstractions to indicate the intended use of the data + type:

+ +

boolean() = true | false

+

string() = [byte()]

+

public_key() = #'RSAPublicKey'{}| {integer(), #'Dss-Parms'{}}| term()

+

private_key() = #'RSAPublicKey'{}| {integer(), #'Dss-Parms'{}}| term()

+

public_key_algorithm() = 'ssh-rsa'| 'ssh-dss' | atom()

+ +
+ + + + Module:add_host_key(HostNames, Key, ConnectOptions) -> ok | {error, Reason} + Adds a host key to the set of trusted host keys + + HostNames = string() + Description of the host that owns the PublicKey + + Key = public_key() + Normally an RSA or DSA public key but handling of other public keys can be added + + ConnectOptions = proplists:proplist() + Options provided to ssh:connect/[3,4] + Reason = term() + + +

Adds a host key to the set of trusted host keys

+
+
+ + + Module:is_host_key(Key, Host, Algorithm, ConnectOptions) -> Result + Checks if a host key is trusted + + Key = public_key() + Normally an RSA or DSA public key but handling of other public keys can be added + + Host = string() + Description of the host + + Algorithm = public_key_algorithm() + Host key algorithm. Should support 'ssh-rsa'| 'ssh-dss' but additional algorithms + can be handled. + + ConnectOptions = proplists:proplist() + Options provided to ssh:connect/[3,4] + + Result = boolean() + + +

Checks if a host key is trusted

+
+
+ + + Module:user_key(Algorithm, ConnectOptions) -> + {ok, PrivateKey} | {error, Reason} + Fetches the users "public key" matching the Algorithm. + + Algorithm = public_key_algorithm() + Host key algorithm. Should support 'ssh-rsa'| 'ssh-dss' but additional algorithms + can be handled. + + ConnectOptions = proplists:proplist() + Options provided to ssh:connect/[3,4] + + PrivateKey = private_key() + The private key of the user matching the Algorithm + + Reason = term() + + + +

Fetches the users "public key" matching the Algorithm. + The private key contains the public key +

+
+
+ +
+ +
diff --git a/lib/ssh/doc/src/ssh_connection.xml b/lib/ssh/doc/src/ssh_connection.xml index 4480f0a093..c66622307f 100644 --- a/lib/ssh/doc/src/ssh_connection.xml +++ b/lib/ssh/doc/src/ssh_connection.xml @@ -91,7 +91,7 @@ refered to are on OS-level and not something generated by an Erlang program. - A remote execution may terminate violently due to a signal @@ -274,7 +274,7 @@
- reply_request(ConnectionRef, WantReply, Status, CannelId) -> ok + reply_request(ConnectionRef, WantReply, Status, ChannelId) -> ok Send status replies to requests that want such replies. ConnectionRef = ssh_connection_ref() diff --git a/lib/ssh/doc/src/ssh_protocol.xml b/lib/ssh/doc/src/ssh_protocol.xml index 529558759e..6a253c43eb 100644 --- a/lib/ssh/doc/src/ssh_protocol.xml +++ b/lib/ssh/doc/src/ssh_protocol.xml @@ -37,7 +37,7 @@ authentication and integrity protection. Currently, only a minimum of MAC- (message authentication code, a short piece of information used to authenticate a message) and encryption - algorithms see ssh(3) + algorithms are supported see ssh(3)

@@ -52,10 +52,18 @@ interactive authentication. This method is suitable for interactive authentication methods that do not need any special software support on the client side. Instead, all authentication - data should be entered via the keyboad. It is also possible + data should be entered via the keyboard. It is also possible to use a pure password based authentication scheme, note that in - this case the the plain text password will be encrypted befor sent - over the network. + this case the the plain text password will be encrypted before sent + over the network. There are several configuration options for + authentication handling available in + ssh:connect/[3,4] + and ssh:daemon/[2,3] + It is also possible to customize the public key handling + by implementing the behaviours ssh_client_key_api and + ssh_server_key_api

@@ -82,7 +90,7 @@ channel. The ssh_channel behaviour makes it easy to write your own SSH client/server processes that use flow - control. It handles generic parts of SSH channel managment and + control. It handles generic parts of SSH channel management and lets you focus on the application logic.

@@ -91,7 +99,7 @@ Subsystem - named services that can be run as part of an SSH server such as SFTP ssh_sftp, that is built in to the + marker="ssh_sftpd">ssh_sftpd, that is built in to the SSH daemon (server) by default but may be disabled. The Erlang SSH daemon may be configured to run any Erlang implemented SSH subsystem. diff --git a/lib/ssh/doc/src/ssh_server_key_api.xml b/lib/ssh/doc/src/ssh_server_key_api.xml new file mode 100644 index 0000000000..78ff105387 --- /dev/null +++ b/lib/ssh/doc/src/ssh_server_key_api.xml @@ -0,0 +1,90 @@ + + + + +
+ + 2012 + Ericsson AB, 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. + + The Initial Developer of the Original Code is Ericsson AB. + + ssh_server_key_api +
+ ssh_server_key_api + + -behaviour(ssh_server_key_api). + + +

Behaviour describing the API for an SSH server's public key handling.By implementing the callbacks defined + in this behavior it is possible to customize the SSH server's public key + handling. By default the SSH application implements this behavior + with help of the standard openssh files, see ssh(6).

+
+ +
+ DATA TYPES + +

Type definitions that are used more than once in this module + and/or abstractions to indicate the intended use of the data + type:

+ +

boolean() = true | false

+

string() = [byte()]

+

public_key() = #'RSAPublicKey'{}| {integer(), #'Dss-Parms'{}}| term()

+

private_key() = #'RSAPublicKey'{}| {integer(), #'Dss-Parms'{}}| term()

+

public_key_algorithm() = 'ssh-rsa'| 'ssh-dss' | atom()

+
+ + + + Module:host_key(Algorithm, DaemonOptions) -> + {ok, Key} | {error, Reason} + Fetches the hosts private key + + Algorithm = public_key_algorithm() + Host key algorithm. Should support 'ssh-rsa'| 'ssh-dss' but additional algorithms + can be handled. + DaemonOptions = proplists:proplist() + Options provided to ssh:daemon/[2,3] + Key = private_key() + The private key of the host matching the Algorithm + Reason = term() + + +

Fetches the hosts private key

+
+
+ + + Module:is_auth_key(Key, User, DaemonOptions) -> Result + Checks if the user key is authorized + + Key = public_key() + Normally an RSA or DSA public key but handling of other public keys can be added + User = string() + The user owning the public key + DaemonOptions = proplists:proplist() + Options provided to ssh:daemon/[2,3] + Result = boolean() + + +

Checks if the user key is authorized

+
+
+ +
+ +
diff --git a/lib/ssh/doc/src/ssh_sftp.xml b/lib/ssh/doc/src/ssh_sftp.xml index 28576c9ef0..0d61e57edb 100644 --- a/lib/ssh/doc/src/ssh_sftp.xml +++ b/lib/ssh/doc/src/ssh_sftp.xml @@ -486,8 +486,9 @@ Reason = term() -

Deletes a directory specified by . The directory - should be empty.

+

Deletes a directory specified by . + Note that the directory must be empty before it can be successfully deleted +

diff --git a/lib/ssh/doc/src/using_ssh.xml b/lib/ssh/doc/src/using_ssh.xml index db17c6fd1c..1a54f3f964 100644 --- a/lib/ssh/doc/src/using_ssh.xml +++ b/lib/ssh/doc/src/using_ssh.xml @@ -37,7 +37,7 @@ nothing else is stated it is persumed that the otptest user has an entry in tarlop's authorized_keys file (may log in via ssh without entering a password). Also tarlop is a known host in the user - otptests known_hosts file so that host verification can be done + otptest's known_hosts file so that host verification can be done without user interaction.

@@ -72,12 +72,12 @@ marker="ssh_app">ssh(6).

-

Normaly the /etc/ssh directory is only readable by root.

+

Normally the /etc/ssh directory is only readable by root.

The option user_dir defaults to the users ~/.ssh directory

-

In the following exampel we have generate new keys and host keys as +

In the following example we generate new keys and host keys as to be able to run the example without having root privilages

@@ -87,12 +87,13 @@ [...] -

And add the public hostkey to the known_hosts file of the user otptest. Then we can do

+

Create the file /tmp/otptest_user/.ssh/authrized_keys and add the content + of /tmp/otptest_user/.ssh/id_rsa.pub Now we can do

1> ssh:start(). ok - 2> {ok, Sshd} = ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon/ssh_host_rsa_key"}, + 2> {ok, Sshd} = ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"}, {user_dir, "/tmp/otptest_user/.ssh"}]). {ok,<0.54.0>} 3> @@ -101,12 +102,16 @@

Use the openssh client from a shell to connect to the Erlang ssh daemon.

- $bash> ssh tarlop -p 8989 -i /tmp/otptest_user/.ssh/id_rsa + $bash> ssh tarlop -p 8989 -i /tmp/otptest_user/.ssh/id_rsa -o UserKnownHostsFile=/tmp/otptest_user/.ssh/known_hosts + The authenticity of host 'tarlop' can't be established. + RSA key fingerprint is 14:81:80:50:b1:1f:57:dd:93:a8:2d:2f:dd:90:ae:a8. + Are you sure you want to continue connecting (yes/no)? yes + Warning: Permanently added 'tarlop' (RSA) to the list of known hosts. Eshell V5.10 (abort with ^G) 1> -

There is two ways of shuting down an SSH daemon

+

There are two ways of shutting down an SSH daemon

1: Stops the listener, but leaves existing connections started by the listener up and running.

@@ -169,7 +174,7 @@ 1> ssh:start(). ok - 2> ssh:daemon(8989, [{system_dir, "."}, + 2> ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"}, {user_dir, "/tmp/otptest_user/.ssh"}, {subsystems, [ssh_sftpd:subsystem_spec([{cwd, "/tmp/sftp/example"}])]}]). {ok,<0.54.0>} 3> @@ -178,7 +183,7 @@

Run the openssh sftp client

- $bash> sftp -oPort=8989 tarlop + $bash> sftp -oPort=8989 -o IdentityFile=/tmp/otptest_user/.ssh/id_rsa -o UserKnownHostsFile=/tmp/otptest_user/.ssh/known_hosts tarlop Connecting to tarlop... sftp> pwd Remote working directory: /tmp/sftp/example @@ -202,11 +207,12 @@
Creating a subsystem -

A very small SSH subsystem that echos N bytes could be implemented like this.

+

A very small SSH subsystem that echos N bytes could be implemented like this. + See also ssh_channel(3)

-module(ssh_echo_server). --behaviour(ssh_channel). +-behaviour(ssh_subsystem). -record(state, { n, id, @@ -261,7 +267,7 @@ terminate(_Reason, _State) -> 1> ssh:start(). ok - 2> ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon/ssh_host_rsa_key"}, + 2> ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"}, {user_dir, "/tmp/otptest_user/.ssh"} {subsystems, [{"echo_n", {ssh_echo_server, [10]}}]}]). {ok,<0.54.0>} @@ -275,12 +281,12 @@ terminate(_Reason, _State) -> {ok,<0.57.0>} 3>{ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity). 4> success = ssh_connection:subsystem(ConnectionRef, ChannelId, "echo_n", infinity). - 5> ok = ssh_connection:send(ConnectionRef, ChannelId, "0123456789", infinity), + 5> ok = ssh_connection:send(ConnectionRef, ChannelId, "0123456789", infinity). 6> flush(). {ssh_msg, <0.57.0>, {data, 0, 1, "0123456789"}} {ssh_msg, <0.57.0>, {eof, 0}} {ssh_msg, <0.57.0>, {closed, 0}} - 7> {error, closed} = ssh_connection:send(ConnectionRef, ChannelId, "10", infinity), + 7> {error, closed} = ssh_connection:send(ConnectionRef, ChannelId, "10", infinity).
diff --git a/lib/ssh/src/Makefile b/lib/ssh/src/Makefile index b8eecd3fa2..323f0af191 100644 --- a/lib/ssh/src/Makefile +++ b/lib/ssh/src/Makefile @@ -41,7 +41,9 @@ RELSYSDIR = $(RELEASE_PATH)/lib/ssh-$(VSN) BEHAVIOUR_MODULES= \ ssh_sftpd_file_api \ ssh_channel \ - ssh_key_api + ssh_subsystem \ + ssh_client_key_api \ + ssh_server_key_api MODULES= \ ssh \ diff --git a/lib/ssh/src/ssh.app.src b/lib/ssh/src/ssh.app.src index a96c1a510c..a0ba7cf7d9 100644 --- a/lib/ssh/src/ssh.app.src +++ b/lib/ssh/src/ssh.app.src @@ -10,6 +10,7 @@ ssh_auth, ssh_bits, ssh_cli, + ssh_client_key_api, ssh_channel, ssh_channel_sup, ssh_connection, @@ -21,13 +22,14 @@ sshd_sup, ssh_file, ssh_io, - ssh_key_api, ssh_math, ssh_no_io, + ssh_server_key_api, ssh_sftp, ssh_sftpd, ssh_sftpd_file, ssh_sftpd_file_api, + ssh_subsystem, ssh_subsystem_sup, ssh_sup, ssh_system_sup, diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index f163539e75..a3ba8148eb 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -80,7 +80,7 @@ connect(Host, Port, Options, Timeout) -> {error, _Reason} = Error -> Error; {SocketOptions, SshOptions} -> - DisableIpv6 = proplists:get_value(ip_v6_disabled, SshOptions, false), + DisableIpv6 = proplists:get_value(ipv6_disabled, SshOptions, false), Inet = inetopt(DisableIpv6), do_connect(Host, Port, [Inet | SocketOptions], [{user_pid, self()}, {host, Host} | fix_idle_time(SshOptions)], Timeout, DisableIpv6) @@ -173,7 +173,7 @@ daemon(HostAddr, Port, Options0) -> _ -> Options0 end, - DisableIpv6 = proplists:get_value(ip_v6_disabled, Options0, false), + DisableIpv6 = proplists:get_value(ipv6_disabled, Options0, false), {Host, Inet, Options} = case HostAddr of any -> {ok, Host0} = inet:gethostname(), @@ -346,7 +346,10 @@ handle_option([{disconnectfun, _} = Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{failfun, _} = Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); -handle_option([{ip_v6_disabled, _} = Opt | Rest], SocketOptions, SshOptions) -> +%%Backwards compatibility should not be underscore between ip and v6 in API +handle_option([{ip_v6_disabled, Value} | Rest], SocketOptions, SshOptions) -> + handle_option(Rest, SocketOptions, [handle_ssh_option({ipv6_disabled, Value}) | SshOptions]); +handle_option([{ipv6_disabled, _} = Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{transport, _} = Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); @@ -379,10 +382,14 @@ handle_ssh_option({silently_accept_hosts, Value} = Opt) when Value == true; Valu Opt; handle_ssh_option({user_interaction, Value} = Opt) when Value == true; Value == false -> Opt; -handle_ssh_option({public_key_alg, Value} = Opt) when Value == ssh_rsa; Value == ssh_dsa -> +handle_ssh_option({public_key_alg, ssh_dsa}) -> + {public_key_alg, 'ssh-dss'}; +handle_ssh_option({public_key_alg, ssh_rsa}) -> + {public_key_alg, 'ssh-rsa'}; +handle_ssh_option({public_key_alg, Value} = Opt) when Value == 'ssh-rsa'; Value == 'ssh-dss' -> Opt; handle_ssh_option({pref_public_key_algs, Value} = Opt) when is_list(Value), length(Value) >= 1 -> - case check_pref_algs(Value) of + case handle_pref_algs(Value, []) of true -> Opt; _ -> @@ -420,7 +427,9 @@ handle_ssh_option({disconnectfun , Value} = Opt) when is_function(Value) -> Opt; handle_ssh_option({failfun, Value} = Opt) when is_function(Value) -> Opt; -handle_ssh_option({ip_v6_disabled, Value} = Opt) when is_boolean(Value) -> + +handle_ssh_option({ipv6_disabled, Value} = Opt) when Value == true; + Value == false -> Opt; handle_ssh_option({transport, {Protocol, Cb, ClosTag}} = Opt) when is_atom(Protocol), is_atom(Cb), @@ -448,7 +457,7 @@ handle_inet_option({active, _} = Opt) -> "and activ is handled internaly user is not allowd" "to specify this option"}}); handle_inet_option({inet, _} = Opt) -> - throw({error, {{eoptions, Opt},"Is set internaly use ip_v6_disabled to" + throw({error, {{eoptions, Opt},"Is set internaly use ipv6_disabled to" " enforce iv4 in the server, client will fallback to ipv4 if" " it can not use ipv6"}}); handle_inet_option({reuseaddr, _} = Opt) -> @@ -458,14 +467,18 @@ handle_inet_option({reuseaddr, _} = Opt) -> handle_inet_option(Opt) -> Opt. %% Check preferred algs -check_pref_algs([]) -> - true; -check_pref_algs([H|T]) -> +handle_pref_algs([], Acc) -> + {true, lists:reverse(Acc)}; +handle_pref_algs([H|T], Acc) -> case H of ssh_dsa -> - check_pref_algs(T); + handle_pref_algs(T, ['ssh-dss'| Acc]); ssh_rsa -> - check_pref_algs(T); + handle_pref_algs(T, ['ssh-rsa'| Acc]); + 'ssh-dss' -> + handle_pref_algs(T, ['ssh-dss'| Acc]); + 'ssh-rsa' -> + handle_pref_algs(T, ['ssh-rsa'| Acc]); _ -> false end. diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl index c436793dc4..cb0c7751f0 100644 --- a/lib/ssh/src/ssh_auth.erl +++ b/lib/ssh/src/ssh_auth.erl @@ -48,17 +48,18 @@ publickey_msg([Alg, #ssh{user = User, case KeyCb:user_key(Alg, Opts) of {ok, Key} -> + StrAlgo = algorithm_string(Alg), PubKeyBlob = encode_public_key(Key), SigData = build_sig_data(SessionId, - User, Service, PubKeyBlob, Alg), + User, Service, PubKeyBlob, StrAlgo), Sig = ssh_transport:sign(SigData, Hash, Key), - SigBlob = list_to_binary([?string(Alg), ?binary(Sig)]), + SigBlob = list_to_binary([?string(StrAlgo), ?binary(Sig)]), ssh_transport:ssh_packet( #ssh_msg_userauth_request{user = User, service = Service, method = "publickey", data = [?TRUE, - ?string(Alg), + ?string(StrAlgo), ?binary(PubKeyBlob), ?binary(SigBlob)]}, Ssh); @@ -120,8 +121,7 @@ init_userauth_request_msg(#ssh{opts = Opts} = Ssh) -> data = <<>>}, case proplists:get_value(pref_public_key_algs, Opts, false) of false -> - FirstAlg = algorithm(proplists:get_value(public_key_alg, Opts, - ?PREFERRED_PK_ALG)), + FirstAlg = proplists:get_value(public_key_alg, Opts, ?PREFERRED_PK_ALG), SecondAlg = other_alg(FirstAlg), AllowUserInt = proplists:get_value(user_interaction, Opts, true), Prefs = method_preference(FirstAlg, SecondAlg, AllowUserInt), @@ -130,7 +130,7 @@ init_userauth_request_msg(#ssh{opts = Opts} = Ssh) -> userauth_methods = none, service = "ssh-connection"}); Algs -> - FirstAlg = algorithm(lists:nth(1, Algs)), + FirstAlg = lists:nth(1, Algs), case length(Algs) =:= 2 of true -> SecondAlg = other_alg(FirstAlg), @@ -358,7 +358,7 @@ verify_sig(SessionId, User, Service, Alg, KeyBlob, SigWLen, Opts) -> {ok, Key} = decode_public_key_v2(KeyBlob, Alg), KeyCb = proplists:get_value(key_cb, Opts, ssh_file), - case KeyCb:is_auth_key(Key, User, Alg, Opts) of + case KeyCb:is_auth_key(Key, User, Opts) of true -> PlainText = build_sig_data(SessionId, User, Service, KeyBlob, Alg), @@ -381,9 +381,9 @@ build_sig_data(SessionId, User, Service, KeyBlob, Alg) -> ?binary(KeyBlob)], list_to_binary(Sig). -algorithm(ssh_rsa) -> +algorithm_string('ssh-rsa') -> "ssh-rsa"; -algorithm(ssh_dsa) -> +algorithm_string('ssh-dss') -> "ssh-dss". decode_keyboard_interactive_prompts(NumPrompts, Data) -> @@ -457,10 +457,10 @@ userauth_pk_messages() -> binary]} % key blob ]. -other_alg("ssh-rsa") -> - "ssh-dss"; -other_alg("ssh-dss") -> - "ssh-rsa". +other_alg('ssh-rsa') -> + 'ssh-dss'; +other_alg('ssh-dss') -> + 'ssh-rsa'. decode_public_key_v2(K_S, "ssh-rsa") -> case ssh_bits:decode(K_S,[string,mpint,mpint]) of ["ssh-rsa", E, N] -> diff --git a/lib/ssh/src/ssh_auth.hrl b/lib/ssh/src/ssh_auth.hrl index e74ee10041..6cd8e6bf14 100644 --- a/lib/ssh/src/ssh_auth.hrl +++ b/lib/ssh/src/ssh_auth.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2010. All Rights Reserved. +%% Copyright Ericsson AB 2008-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 @@ -23,7 +23,7 @@ -define(SUPPORTED_AUTH_METHODS, "publickey,keyboard-interactive,password"). --define(PREFERRED_PK_ALG, ssh_rsa). +-define(PREFERRED_PK_ALG, 'ssh-rsa'). -define(SSH_MSG_USERAUTH_REQUEST, 50). -define(SSH_MSG_USERAUTH_FAILURE, 51). diff --git a/lib/ssh/src/ssh_channel.erl b/lib/ssh/src/ssh_channel.erl index 1938858420..4e8f8538c2 100644 --- a/lib/ssh/src/ssh_channel.erl +++ b/lib/ssh/src/ssh_channel.erl @@ -23,14 +23,35 @@ -include("ssh_connect.hrl"). -%%% Optional callbacks handle_call/3, handle_cast/2, handle_msg/2, -%%% code_change/3 -%% Should be further specified later --callback init(Options::list()) -> - {ok, State::term()} | {ok, State::term(), Timeout::timeout()} | - {stop, Reason ::term()}. - --callback terminate(term(), term()) -> term(). +-callback init(Args :: term()) -> + {ok, State :: term()} | {ok, State :: term(), timeout() | hibernate} | + {stop, Reason :: term()} | ignore. +-callback handle_call(Request :: term(), From :: {pid(), Tag :: term()}, + State :: term()) -> + {reply, Reply :: term(), NewState :: term()} | + {reply, Reply :: term(), NewState :: term(), timeout() | hibernate} | + {noreply, NewState :: term()} | + {noreply, NewState :: term(), timeout() | hibernate} | + {stop, Reason :: term(), Reply :: term(), NewState :: term()} | + {stop, Reason :: term(), NewState :: term()}. +-callback handle_cast(Request :: term(), State :: term()) -> + {noreply, NewState :: term()} | + {noreply, NewState :: term(), timeout() | hibernate} | + {stop, Reason :: term(), NewState :: term()}. + +-callback terminate(Reason :: (normal | shutdown | {shutdown, term()} | + term()), + State :: term()) -> + term(). +-callback code_change(OldVsn :: (term() | {down, term()}), State :: term(), + Extra :: term()) -> + {ok, NewState :: term()} | {error, Reason :: term()}. + +-callback handle_msg(Msg ::term(), State :: term()) -> + {noreply, NewState :: term()} | + {noreply, NewState :: term(), timeout() | hibernate} | + {stop, Reason :: term(), NewState :: term()}. + -callback handle_ssh_msg({ssh_cm, ConnectionRef::term(), SshMsg::term()}, State::term()) -> {ok, State::term()} | diff --git a/lib/ssh/src/ssh_client_key.erl b/lib/ssh/src/ssh_client_key.erl new file mode 100644 index 0000000000..2c48884dc2 --- /dev/null +++ b/lib/ssh/src/ssh_client_key.erl @@ -0,0 +1,34 @@ +%% +%% %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_client_key). + +-include_lib("public_key/include/public_key.hrl"). +-include("ssh.hrl"). + +-callback is_host_key(Key :: public_key(), Host :: string(), + Algorithm :: 'ssh-rsa'| 'ssh-dsa'| atom(), Options :: proplists:proplist()) -> + boolean(). + +-callback user_key(Algorithm :: 'ssh-rsa'| 'ssh-dsa'| atom(), Options :: list()) -> + {ok, PrivateKey :: term()} | {error, string()}. + + +-callback add_host_key(Host :: string(), PublicKey :: term(), Options :: list()) -> + ok | {error, Error::term()}. diff --git a/lib/ssh/src/ssh_client_key_api.erl b/lib/ssh/src/ssh_client_key_api.erl new file mode 100644 index 0000000000..eed0b85f47 --- /dev/null +++ b/lib/ssh/src/ssh_client_key_api.erl @@ -0,0 +1,35 @@ +%% +%% %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_client_key_api). + +-include_lib("public_key/include/public_key.hrl"). +-include("ssh.hrl"). + +-callback is_host_key(PublicKey :: #'RSAPublicKey'{}| {integer(), #'Dss-Parms'{}}| term() , Host :: string(), + Algorithm :: 'ssh-rsa'| 'ssh-dss'| atom(), ConnectOptions :: proplists:proplist()) -> + boolean(). + +-callback user_key(Algorithm :: 'ssh-rsa'| 'ssh-dss'| atom(), ConnectOptions :: proplists:proplists()) -> + {ok, PrivateKey :: #'RSAPrivateKey'{}| #'DSAPrivateKey'{} | term()} | {error, string()}. + + +-callback add_host_key(Host :: string(), PublicKey :: #'RSAPublicKey'{}| {integer(), #'Dss-Parms'{}}| term(), + Options :: list()) -> + ok | {error, Error::term()}. diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index d8950a7b67..b79e8530b7 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -749,9 +749,9 @@ extract_algs([], NewList) -> lists:reverse(NewList); extract_algs([H|T], NewList) -> case H of - ssh_dsa -> + 'ssh-dss' -> extract_algs(T, ["ssh-dss"|NewList]); - ssh_rsa -> + 'ssh-rsa' -> extract_algs(T, ["ssh-rsa"|NewList]) end. available_host_key(KeyCb, "ssh-dss"= Alg, Opts) -> diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl index a6b82a7a13..f115a32710 100644 --- a/lib/ssh/src/ssh_file.erl +++ b/lib/ssh/src/ssh_file.erl @@ -23,7 +23,8 @@ -module(ssh_file). --behaviour(ssh_key_api). +-behaviour(ssh_server_key_api). +-behaviour(ssh_client_key_api). -include_lib("public_key/include/public_key.hrl"). -include_lib("kernel/include/file.hrl"). @@ -34,7 +35,7 @@ user_key/2, is_host_key/4, add_host_key/3, - is_auth_key/4]). + is_auth_key/3]). -define(PERM_700, 8#700). @@ -53,8 +54,8 @@ host_key(Algorithm, Opts) -> decode(File, Password). -is_auth_key(Key, User, Alg, Opts) -> - case lookup_user_key(Key, User, Alg, Opts) of +is_auth_key(Key, User,Opts) -> + case lookup_user_key(Key, User, Opts) of {ok, Key} -> true; _ -> @@ -138,13 +139,13 @@ add_host_key(Host, Key, Opts) -> Error end. -lookup_user_key(Key, User, Alg, Opts) -> +lookup_user_key(Key, User, Opts) -> SshDir = ssh_dir({remoteuser,User}, Opts), - case lookup_user_key_f(Key, User, SshDir, Alg, "authorized_keys", Opts) of + case lookup_user_key_f(Key, User, SshDir, "authorized_keys", Opts) of {ok, Key} -> {ok, Key}; _ -> - lookup_user_key_f(Key, User, SshDir, Alg, "authorized_keys2", Opts) + lookup_user_key_f(Key, User, SshDir, "authorized_keys2", Opts) end. @@ -213,9 +214,9 @@ do_lookup_host_key(Host, Alg, Opts) -> Error -> Error end. -identity_key_filename("ssh-dss") -> +identity_key_filename('ssh-dss') -> "id_dsa"; -identity_key_filename("ssh-rsa") -> +identity_key_filename('ssh-rsa') -> "id_rsa". identity_pass_phrase("ssh-dss") -> @@ -261,9 +262,9 @@ host_name(Atom) when is_atom(Atom) -> host_name(List) -> List. -key_match(#'RSAPublicKey'{}, "ssh-rsa") -> +key_match(#'RSAPublicKey'{}, 'ssh-rsa') -> true; -key_match({_, #'Dss-Parms'{}}, "ssh-dss") -> +key_match({_, #'Dss-Parms'{}}, 'ssh-dss') -> true; key_match(_, _) -> false. @@ -272,11 +273,11 @@ add_key_fd(Fd, Host,Key) -> SshBin = public_key:ssh_encode([{Key, [{hostnames, [Host]}]}], known_hosts), file:write(Fd, SshBin). -lookup_user_key_f(_, _User, [], _Alg, _F, _Opts) -> +lookup_user_key_f(_, _User, [], _F, _Opts) -> {error, nouserdir}; -lookup_user_key_f(_, _User, nouserdir, _Alg, _F, _Opts) -> +lookup_user_key_f(_, _User, nouserdir, _F, _Opts) -> {error, nouserdir}; -lookup_user_key_f(Key, _User, Dir, _Alg, F, _Opts) -> +lookup_user_key_f(Key, _User, Dir, F, _Opts) -> FileName = filename:join(Dir, F), case file:open(FileName, [read, binary]) of {ok, Fd} -> diff --git a/lib/ssh/src/ssh_key_api.erl b/lib/ssh/src/ssh_key_api.erl deleted file mode 100644 index 8085c12e21..0000000000 --- a/lib/ssh/src/ssh_key_api.erl +++ /dev/null @@ -1,45 +0,0 @@ -%% -%% %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(). diff --git a/lib/ssh/src/ssh_server_key.erl b/lib/ssh/src/ssh_server_key.erl new file mode 100644 index 0000000000..8140114990 --- /dev/null +++ b/lib/ssh/src/ssh_server_key.erl @@ -0,0 +1,33 @@ +%% +%% %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_server_key). + +-include_lib("public_key/include/public_key.hrl"). +-include("ssh.hrl"). + +-type ssh_algorithm() :: string(). + +-callback host_key(Algorithm :: ssh_algorithm(), Options :: list()) -> + {ok, [{public_key(), Attributes::list()}]} | public_key() + | {error, string()}. + +-callback is_auth_key(Key :: public_key(), User :: string(), + Algorithm :: ssh_algorithm(), Options :: list()) -> + boolean(). diff --git a/lib/ssh/src/ssh_server_key_api.erl b/lib/ssh/src/ssh_server_key_api.erl new file mode 100644 index 0000000000..4fd660ecb5 --- /dev/null +++ b/lib/ssh/src/ssh_server_key_api.erl @@ -0,0 +1,30 @@ +%% +%% %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_server_key_api). + +-include_lib("public_key/include/public_key.hrl"). +-include("ssh.hrl"). + +-callback host_key(Algorithm :: 'ssh-rsa'| 'ssh-dss'| atom(), DaemonOptions :: proplists:proplist()) -> + {ok, PrivateKey :: #'RSAPrivateKey'{}| #'DSAPrivateKey'{} | term()} | {error, string()}. + +-callback is_auth_key(PublicKey :: #'RSAPublicKey'{}| {integer(), #'Dss-Parms'{}}| term(), + User :: string(), DaemonOptions :: proplists:proplist()) -> + boolean(). diff --git a/lib/ssh/src/ssh_sftpd.erl b/lib/ssh/src/ssh_sftpd.erl index ec7b76b0b3..6d6f4a0121 100644 --- a/lib/ssh/src/ssh_sftpd.erl +++ b/lib/ssh/src/ssh_sftpd.erl @@ -24,7 +24,7 @@ -module(ssh_sftpd). %%-behaviour(gen_server). --behaviour(ssh_channel). +-behaviour(ssh_subsystem). -include_lib("kernel/include/file.hrl"). @@ -36,7 +36,7 @@ -export([subsystem_spec/1, listen/1, listen/2, listen/3, stop/1]). --export([init/1, handle_ssh_msg/2, handle_msg/2, terminate/2, code_change/3]). +-export([init/1, handle_ssh_msg/2, handle_msg/2, terminate/2]). -record(state, { xf, % [{channel,ssh_xfer states}...] @@ -127,14 +127,6 @@ init(Options) -> xf = #ssh_xfer{vsn = Vsn, ext = []}}}. -%%-------------------------------------------------------------------- -%% Function: code_change(OldVsn, State, Extra) -> {ok, NewState} -%% Description: -%%-------------------------------------------------------------------- -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - - %%-------------------------------------------------------------------- %% Function: handle_ssh_msg(Args) -> {ok, State} | {stop, ChannelId, State} %% diff --git a/lib/ssh/src/ssh_subsystem.erl b/lib/ssh/src/ssh_subsystem.erl new file mode 100644 index 0000000000..5a9fa32668 --- /dev/null +++ b/lib/ssh/src/ssh_subsystem.erl @@ -0,0 +1,47 @@ +-module(ssh_subsystem). + +%% API to special server side channel that can be pluged into the erlang ssh daemeon +-callback init(Args :: term()) -> + {ok, State :: term()} | {ok, State :: term(), timeout() | hibernate} | + {stop, Reason :: term()} | ignore. + +-callback terminate(Reason :: (normal | shutdown | {shutdown, term()} | + term()), + State :: term()) -> + term(). + +-callback handle_msg(Msg ::term(), State :: term()) -> + {noreply, NewState :: term()} | + {noreply, NewState :: term(), timeout() | hibernate} | + {stop, Reason :: term(), NewState :: term()}. + +-callback handle_ssh_msg({ssh_cm, ConnectionRef::term(), SshMsg::term()}, + State::term()) -> {ok, State::term()} | + {stop, ChannelId::integer(), + State::term()}. + +%%% API +-export([start/4, start/5, start_link/4, start_link/5, enter_loop/1]). + +%% gen_server callbacks +-export([init/1, terminate/2]). + +start(ConnectionManager, ChannelId, CallBack, CbInitArgs) -> + ssh_channel:start(ConnectionManager, ChannelId, CallBack, CbInitArgs, undefined). + +start(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec) -> + ssh_channel:start(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec). + +start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs) -> + ssh_channel:start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, undefined). + +start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec) -> + ssh_channel:start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec). + +enter_loop(State) -> + ssh_channel:enter_loop(State). + +init(Args) -> + ssh_channel:init(Args). +terminate(Reason, State) -> + ssh_channel:terminate(Reason, State). diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 7f6e7d9946..1abb69921d 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -449,7 +449,7 @@ verify_host_key_rsa(SSH, K_S, H, H_SIG) -> false -> {error, bad_signature}; true -> - known_host_key(SSH, Public, "ssh-rsa") + known_host_key(SSH, Public, 'ssh-rsa') end; _ -> {error, bad_format} @@ -464,7 +464,7 @@ verify_host_key_dss(SSH, K_S, H, H_SIG) -> false -> {error, bad_signature}; true -> - known_host_key(SSH, Public, "ssh-dss") + known_host_key(SSH, Public, 'ssh-dss') end; _ -> {error, bad_host_key_format} diff --git a/lib/ssh/test/ssh_echo_server.erl b/lib/ssh/test/ssh_echo_server.erl index 64686231e2..007b00c373 100644 --- a/lib/ssh/test/ssh_echo_server.erl +++ b/lib/ssh/test/ssh_echo_server.erl @@ -21,7 +21,7 @@ %%% Description: Example ssh server -module(ssh_echo_server). --behaviour(ssh_channel). +-behaviour(ssh_subsytem). -record(state, { n, id, -- cgit v1.2.3