summaryrefslogtreecommitdiff
path: root/lib/ssh/doc/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssh/doc/src')
-rw-r--r--lib/ssh/doc/src/Makefile29
-rw-r--r--lib/ssh/doc/src/configure_algos.xml7
-rw-r--r--lib/ssh/doc/src/introduction.xml4
-rw-r--r--lib/ssh/doc/src/notes.xml704
-rw-r--r--lib/ssh/doc/src/ref_man.xml6
-rw-r--r--lib/ssh/doc/src/specs.xml14
-rw-r--r--lib/ssh/doc/src/ssh.xml1851
-rw-r--r--lib/ssh/doc/src/ssh_app.xml92
-rw-r--r--lib/ssh/doc/src/ssh_client_channel.xml (renamed from lib/ssh/doc/src/ssh_channel.xml)199
-rw-r--r--lib/ssh/doc/src/ssh_client_key_api.xml57
-rw-r--r--lib/ssh/doc/src/ssh_connection.xml466
-rw-r--r--lib/ssh/doc/src/ssh_file.xml285
-rw-r--r--lib/ssh/doc/src/ssh_protocol.xml8
-rw-r--r--lib/ssh/doc/src/ssh_server_channel.xml176
-rw-r--r--lib/ssh/doc/src/ssh_server_key_api.xml49
-rw-r--r--lib/ssh/doc/src/ssh_sftp.xml481
-rw-r--r--lib/ssh/doc/src/ssh_sftpd.xml38
-rw-r--r--lib/ssh/doc/src/terminology.xml185
-rw-r--r--lib/ssh/doc/src/usersguide.xml3
-rw-r--r--lib/ssh/doc/src/using_ssh.xml543
20 files changed, 3538 insertions, 1659 deletions
diff --git a/lib/ssh/doc/src/Makefile b/lib/ssh/doc/src/Makefile
index f54f5e0708..4e32dd9976 100644
--- a/lib/ssh/doc/src/Makefile
+++ b/lib/ssh/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2017. All Rights Reserved.
+# Copyright Ericsson AB 2004-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -38,23 +38,27 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
# Target Specs
# ----------------------------------------------------
XML_APPLICATION_FILES = ref_man.xml
-XML_REF3_FILES = ssh.xml \
- ssh_channel.xml \
- ssh_connection.xml \
+XML_REF3_FILES = \
+ ssh.xml \
+ ssh_client_channel.xml \
ssh_client_key_api.xml \
+ ssh_connection.xml \
+ ssh_server_channel.xml \
ssh_server_key_api.xml \
+ ssh_file.xml \
ssh_sftp.xml \
ssh_sftpd.xml \
XML_REF6_FILES = ssh_app.xml
-XML_PART_FILES = \
- usersguide.xml
-XML_CHAPTER_FILES = notes.xml \
+XML_PART_FILES = usersguide.xml
+
+XML_CHAPTER_FILES = \
+ notes.xml \
introduction.xml \
using_ssh.xml \
+ terminology.xml \
configure_algos.xml
-# ssh_protocol.xml \
BOOK_FILES = book.xml
@@ -84,12 +88,19 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
+SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml)
+
+TOP_SPECS_FILE = specs.xml
+
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
XML_FLAGS +=
DVIPS_FLAGS +=
+#SPECS_FLAGS = -I../../include -I../../../kernel/include
+SPECS_FLAGS = -I../../../public_key/include -I../../../public_key/src -I../../..
+
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
@@ -109,8 +120,10 @@ html: images $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
+ rm -f $(SPECS_FILES)
rm -f errs core *~
man: $(MAN3_FILES) $(MAN6_FILES)
diff --git a/lib/ssh/doc/src/configure_algos.xml b/lib/ssh/doc/src/configure_algos.xml
index dd60324851..fa45b1cb4c 100644
--- a/lib/ssh/doc/src/configure_algos.xml
+++ b/lib/ssh/doc/src/configure_algos.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2017</year>
- <year>2017</year>
+ <year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -117,6 +117,7 @@
<p>Due to this, it impossible to list in documentation what algorithms that are available in a certain installation.</p>
<p>There is an important command to list the actual algorithms and their ordering:
<seealso marker="ssh#default_algorithms-0">ssh:default_algorithms/0</seealso>.</p>
+ <marker id="example_default_algorithms"/>
<code type="erl">
0> ssh:default_algorithms().
[{kex,['ecdh-sha2-nistp384','ecdh-sha2-nistp521',
@@ -156,7 +157,7 @@
<section>
<title>Replacing the default set: preferred_algorithms</title>
- <p>See the <seealso marker="ssh#option_preferred_algorithms">Reference Manual</seealso> for details</p>
+ <p>See the <seealso marker="ssh#type-preferred_algorithms_common_option">Reference Manual</seealso> for details</p>
<p>Here follows a series of examples ranging from simple to more complex.</p>
@@ -301,7 +302,7 @@
First one has to list them with <c>ssh:default_algorithms()</c> and then do changes in the lists.</p>
<p>To facilitate addition or removal of algorithms the option <c>modify_algorithms</c> is available.
- See the <seealso marker="ssh#option_modify_algorithms">Reference Manual</seealso> for details.</p>
+ See the <seealso marker="ssh#type-modify_algorithms_common_option">Reference Manual</seealso> for details.</p>
<p>The option takes a list with instructions to append, prepend or remove algorithms:</p>
<code type="erl">
diff --git a/lib/ssh/doc/src/introduction.xml b/lib/ssh/doc/src/introduction.xml
index b7a73e2597..8444daf0cc 100644
--- a/lib/ssh/doc/src/introduction.xml
+++ b/lib/ssh/doc/src/introduction.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2012</year>
- <year>2016</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -145,7 +145,7 @@
data that can be sent to the channel peer without adjusting the
window. Typically, an SSH client opens a channel, sends data (commands),
receives data (control information), and then closes the channel.
- The <seealso marker="ssh_channel">ssh_channel</seealso> behaviour
+ The <seealso marker="ssh_client_channel">ssh_client_channel</seealso> behaviour
handles generic parts of SSH channel management. This makes it easy
to write your own SSH client/server processes that use flow-control
and thus opens for more focus on the application logic.
diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml
index 353d0cddb4..e79cbaa336 100644
--- a/lib/ssh/doc/src/notes.xml
+++ b/lib/ssh/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2017</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -30,6 +30,644 @@
<file>notes.xml</file>
</header>
+<section><title>Ssh 4.8.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed that <c>ssh_connection:send</c> could allocate a
+ large amount of memory if given an iolist() as input
+ data.</p>
+ <p>
+ Own Id: OTP-16373</p>
+ </item>
+ <item>
+ <p>
+ Safe atom conversions.</p>
+ <p>
+ Own Id: OTP-16375</p>
+ </item>
+ <item>
+ <p>
+ Constant time comparisons added.</p>
+ <p>
+ Own Id: OTP-16376</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.8.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The ssh cli (e.g shell) server behaved strangely when
+ characters were inserted in a string such that the last
+ characters tried to wrap the line.</p>
+ <p>
+ Own Id: OTP-14849 Aux Id: ERL-545 </p>
+ </item>
+ <item>
+ <p>
+ If an OTP SSH server was serving an "exec" request and
+ the executed code used Erlang <c>standard_io</c> for
+ input/output, the I/O was erroneously handled by the
+ *server's* group leader, so the I/O turned up in the the
+ server's Erlang shell (if any). The user at the client
+ side did therefor not see that I/O.</p>
+ <p>
+ This is corrected now, so the client - for example the
+ ssh OS shell command - handles the I/O. The user could
+ send input to the server side exec handling code by
+ writing on the terminal, and server side output from for
+ example io:format is presented on the terminal - not only
+ the functional result.</p>
+ <p>
+ NOTE 1: Servers executing exec requests with the old,
+ undocumented ways of specifying the custom exec handler
+ is not changed. Changed are only the two cases where the
+ server's 'exec' option either:<br/> 1) is not specified
+ (i.e. using the default shell) or, <br/> 2) it has the
+ <c>{direct, fun(...) -&gt; ... end}</c> value format.</p>
+ <p>
+ NOTE 2: Previously an end-of-line marker was appended on
+ the result and error reports at the client side. They are
+ removed now and the error reports are slightly enhanced.</p>
+ <p>
+ TECHNICAL DETAILS: The server's device
+ <c>standard_input</c> receives data events from the exec
+ request's channel, and the device <c>standard_output</c>
+ is sending its data by data events to the client on that
+ channel. The result is that <c>standard_io</c> is now
+ performed by the client's group leader.</p>
+ <p>
+ Own Id: OTP-15417 Aux Id: OTP-16108 </p>
+ </item>
+ <item>
+ <p>
+ The functions ssh:shell/1,2,3 left the connection open
+ when they returned. That leakage is fixed now.</p>
+ <p>
+ Own Id: OTP-16047</p>
+ </item>
+ <item>
+ <p>
+ Corrected that an Erlang SSH server could return the
+ status code 4294967295 instead of 255 on some errors of
+ an exec request.</p>
+ <p>
+ Own Id: OTP-16123</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Internal simplification of ssh_sftp/ssh_xfer</p>
+ <p>
+ Own Id: OTP-15972</p>
+ </item>
+ <item>
+ <p>
+ The documentation of <seealso
+ marker="ssh:using_ssh#one-time-execution">One-Time
+ Execution</seealso> in the User's Guide is updated with
+ more examples.</p>
+ <p>
+ Own Id: OTP-16108 Aux Id: OTP-15417 </p>
+ </item>
+ <item>
+ <p>
+ The new value <c>'disabled'</c> is introduced in the SSH
+ daemon options 'exec' and 'shell'. Previously they lacked
+ a clear way of disabling them.</p>
+ <p>
+ Own Id: OTP-16113</p>
+ </item>
+ <item>
+ <p>
+ The old algorithms 'aes192_cbc', 'aes256_cbc' and
+ 'hmac-sha1-96' are added for compatibility with older
+ peers.</p>
+ <p>
+ The mac 'hmac-sha1-96' is nowadays not recommended and
+ must therefore be explicitly enabled. Use for example the
+ Option value <c>{modify_algorithms, [{append,
+ [{mac,['hmac-sha1-96']}]}]}</c></p>
+ <p>
+ Own Id: OTP-16170</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.8</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed wrong type definition for the daemon option
+ <c>subsystems</c>.</p>
+ <p>
+ Own Id: OTP-15820</p>
+ </item>
+ <item>
+ <p>
+ Fixed a possible SSH logging crash if there was a problem
+ in an early stage of session setup.</p>
+ <p>
+ Own Id: OTP-15962 Aux Id: ERL-990 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The documentation for the modules ssh_connection,
+ ssh_sftp and ssh_sftpd are now generated from the
+ -spec:s.</p>
+ <p>
+ Own Id: OTP-15395</p>
+ </item>
+ <item>
+ <p>
+ Internal cleanup including removal of the internal file
+ <c>ssh_userauth.hrl</c>.</p>
+ <p>
+ Own Id: OTP-15876 Aux Id: PR-2255, PR-2256 </p>
+ </item>
+ <item>
+ <p>
+ Removed unused definitions in <c>ssh.hrl</c>.</p>
+ <p>
+ Own Id: OTP-15929 Aux Id: PR-2297 </p>
+ </item>
+ <item>
+ <p>
+ Removed unused fields in the internal
+ <c>#connection{}</c> record.</p>
+ <p>
+ Own Id: OTP-15984</p>
+ </item>
+ <item>
+ <p>
+ To get information of a <c>connection_ref()</c> from for
+ example <c>ssh:connect/3</c>, there was previously one
+ function available namely <c>ssh:connection_info/2</c>.
+ This ticket adds <c>ssh:connection_info/1</c> which
+ returns all information.</p>
+ <p>
+ For daemons (servers) started with for example
+ <c>ssh:daemon/2</c> the function <c>ssh:daemon_info/1</c>
+ returning all information was available. This ticket adds
+ <c>ssh:daemon_info/2</c> which returns only the
+ information specified in the second argument.</p>
+ <p>
+ The info of connections and of daemons now also includes
+ the item '<c>options</c>'. Only those options that does
+ not have their default values are returned.</p>
+ <p>
+ For a connection also the items '<c>algorithms</c>' and
+ '<c>channels</c>' are added.</p>
+ <p>
+ Own Id: OTP-16040</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.7.7</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ SSH uses the new crypto API.</p>
+ <p>
+ Own Id: OTP-15673</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.7.6.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed that <c>ssh_connection:send</c> could allocate a
+ large amount of memory if given an iolist() as input
+ data.</p>
+ <p>
+ Own Id: OTP-16373</p>
+ </item>
+ <item>
+ <p>
+ Safe atom conversions.</p>
+ <p>
+ Own Id: OTP-16375</p>
+ </item>
+ <item>
+ <p>
+ Constant time comparisons added.</p>
+ <p>
+ Own Id: OTP-16376</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.7.6.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The ssh cli (e.g shell) server behaved strangely when
+ characters were inserted in a string so that the last
+ characters tried to wrap the line.</p>
+ <p>
+ Own Id: OTP-14849 Aux Id: ERL-545 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.7.6.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed a possible SSH logging crash if there was a problem
+ in an early stage of session setup.</p>
+ <p>
+ Own Id: OTP-15962 Aux Id: ERL-990 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.7.6</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ When an SSH server receives the very first message on a
+ new TCP connection, and that message is not the expected
+ one, the 64 first bytes of the received message are now
+ dumped in the INFO REPORT that reports the Protocol
+ Error.</p>
+ <p>
+ This facilitates the debugging of who sends the bad
+ message or of detecting a possible port scanning.</p>
+ <p>
+ Own Id: OTP-15772</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.7.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The callback <c>ssh_channel:init/1</c> was missing in
+ OTP-21</p>
+ <p>
+ Own Id: OTP-15762</p>
+ </item>
+ <item>
+ <p>
+ If a client was connected to an server on an already open
+ socket, the callback <c>fun(PeerName,FingerPrint)</c> in
+ the <c>accept_callback</c> option passed the local name
+ in the argument PeerName instead of the remote name.</p>
+ <p>
+ Own Id: OTP-15763</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.7.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ SSH sftp daemon now accepts an SSH_FXP_STAT message
+ encoded according to the wrong sftp version. Some clients
+ sends such messages.</p>
+ <p>
+ Own Id: OTP-15498 Aux Id: ERL-822, PR-2077 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.7.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed port leakage if a ssh:daemon call failed.</p>
+ <p>
+ Own Id: OTP-15397 Aux Id: ERL-801 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.7.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Incompatibility with newer OpenSSH fixed. Previously
+ versions 7.8 and later could cause Erlang SSH to exit.</p>
+ <p>
+ Own Id: OTP-15413</p>
+ </item>
+ <item>
+ <p>
+ The '<c>exec</c>' option for ssh daemons had wrong format
+ in the documentation.</p>
+ <p>
+ Own Id: OTP-15416</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Added public key methods ssh-ed25519 and ssh-ed448.</p>
+ <p>
+ Requires OpenSSL 1.1.1 or higher as cryptolib under the
+ OTP application <c>crypto</c>.</p>
+ <p>
+ Own Id: OTP-15094 Aux Id: OTP-15419 </p>
+ </item>
+ <item>
+ <p>
+ The SSH property tests are now adapted to the PropEr
+ testing tool.</p>
+ <p>
+ Own Id: OTP-15312</p>
+ </item>
+ <item>
+ <p>
+ The term "user" was not documented in the SSH app. A new
+ chapter with terminology is added to the User's Manual
+ where the term "user" is defined.</p>
+ <p>
+ A reference manual page about the module <c>ssh_file</c>
+ is also added. This is the default callback module for
+ user's keys, host keys etc.</p>
+ <p>
+ Own Id: OTP-15314</p>
+ </item>
+ <item>
+ <p>
+ Host and user key checking is made more robust.</p>
+ <p>
+ Own Id: OTP-15424</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.7.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Extended the undocumented <c>ssh_dbg</c> debug module
+ with an api for a circular trace buffer. This makes it
+ easy to record the last low-level events before an error
+ is detected. It is intended for solving difficult errors.</p>
+ <p>
+ Own Id: OTP-15020</p>
+ </item>
+ <item>
+ <p>
+ The key exchange methods
+ <c>'curve25519-sha256@libssh.org'</c>,
+ <c>'curve25519-sha256'</c> and <c>'curve448-sha512'</c>
+ are implemented. The last two are defined in
+ https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves</p>
+ <p>
+ They all depends on that OpenSSL 1.1.1 or higher is used
+ as cryptolib.</p>
+ <p>
+ Own Id: OTP-15133 Aux Id: OTP-15240 </p>
+ </item>
+ <item>
+ <p>
+ The cipher '<c>chacha20-poly1305@openssh.com</c>' is now
+ supported if OpenSSL 1.1.1 or higher is used as
+ cryptolib.</p>
+ <p>
+ Own Id: OTP-15209 Aux Id: OTP-15164 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.7</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ If the daemon port listener is restarted, it could
+ potentially fail with <c>eaddrinuse</c> if the timing is
+ unlucky. It will now retry and exponentially back off the
+ listener restart a few times before failing.</p>
+ <p>
+ Own Id: OTP-14955</p>
+ </item>
+ <item>
+ <p>
+ A channel callback module always got the module name as
+ reason in a call to terminate. Now it will get the proper
+ Reason, usually 'normal'.</p>
+ <p>
+ Own Id: OTP-15084</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The option <c>exec</c> has new option values defined to
+ make it much more easy to implement an own <c>exec</c>
+ server.</p>
+ <p>
+ An option called <c>exec</c> for daemons implementing the
+ handling of 'exec' requests has existed a long time but
+ has been undocumented. The old undocumented value - as
+ well as its behavior - is kept for compatibility EXCEPT
+ that error messages are changed and are sent as
+ "stderror" text.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-14851</p>
+ </item>
+ <item>
+ <p>
+ Updated ssh_connection:shell/2 documentation.</p>
+ <p>
+ Own Id: OTP-14880</p>
+ </item>
+ <item>
+ <p>
+ The experimental <c>ssh_dbg</c> module is completely
+ re-written. Its purpose is to make tracing and debugging
+ easier on deployed systems.</p>
+ <p>
+ Own Id: OTP-14896</p>
+ </item>
+ <item>
+ <p>
+ The SSH supervisor structure has been slightly changed.
+ This makes stopping the ssh application considerably
+ faster if there are open connections. This is important
+ in for example restarts.</p>
+ <p>
+ Own Id: OTP-14988</p>
+ </item>
+ <item>
+ <p>
+ The type specifications in SSH are completly reworked and
+ the following types are renamed:</p>
+ <p>
+ <c>ssh:ssh_connection_ref()</c> is changed to
+ <c>ssh:connection_ref()</c>, </p>
+ <p>
+ <c>ssh:ssh_daemon_ref()</c> is changed to
+ <c>ssh:daemon_ref()</c>,</p>
+ <p>
+ <c>ssh:ssh_channel_id()</c> is changed to
+ <c>ssh:channel_id()</c>.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-15002 Aux Id: OTP-15030 </p>
+ </item>
+ <item>
+ <p>
+ The internal timer handling in SSH is now based on the
+ gen_statem timers.</p>
+ <p>
+ Own Id: OTP-15019</p>
+ </item>
+ <item>
+ <p>
+ Removed the undocumented and unused modules
+ <c>ssh_client_key.erl</c> and <c>ssh_server_key.erl</c>.</p>
+ <p>
+ Own Id: OTP-15028</p>
+ </item>
+ <item>
+ <p>
+ The Reference Manual pages are partly updated.</p>
+ <p>
+ The ssh page is now generated from specs and types, is
+ restructured and is partly rephrased.</p>
+ <p>
+ The ssh_channel, ssh_connection, ssh_client_key_api,
+ ssh_server_key_api and ssh_sftp pages are updated with
+ links, correct type names and some minor changes.</p>
+ <p>
+ Own Id: OTP-15030 Aux Id: OTP-15002 </p>
+ </item>
+ <item>
+ <p>
+ The behaviors <c>ssh_channel</c> and
+ <c>ssh_daemon_channel</c> are renamed to
+ <c>ssh_client_channel</c> and <c>ssh_server_channel</c>
+ respectively.</p>
+ <p>
+ The old modules are kept for compatibility but should
+ preferably be replaced when updating callback modules
+ referring them.</p>
+ <p>
+ Own Id: OTP-15041</p>
+ </item>
+ <item>
+ <p>
+ New test suite for channels.</p>
+ <p>
+ Own Id: OTP-15051</p>
+ </item>
+ <item>
+ <p>
+ The <c>rekey_limit</c> option could now set the max time
+ as well as the previously max data amount.</p>
+ <p>
+ Own Id: OTP-15069 Aux Id: ERL-617 </p>
+ </item>
+ <item>
+ <p>
+ Changed process exit supervision from links to monitors.</p>
+ <p>
+ Own Id: OTP-15082</p>
+ </item>
+ <item>
+ <p>
+ Better handling of misbehaving channel callback modules.</p>
+ <p>
+ Own Id: OTP-15083</p>
+ </item>
+ <item>
+ <p>
+ A new moduli file is generated. This file is used for the
+ recommended <c>diffie-hellman-group-exchange-sha256</c>
+ key exchange algorithm in SSH.</p>
+ <p>
+ Own Id: OTP-15113</p>
+ </item>
+ </list>
+ </section>
+</section>
+
<section><title>Ssh 4.6.9.7</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -141,7 +779,6 @@
</section>
<section><title>Ssh 4.6.9.1</title>
-
<section><title>Fixed Bugs and Malfunctions</title>
<list>
<item>
@@ -192,7 +829,6 @@
</section>
<section><title>Ssh 4.6.8</title>
-
<section><title>Fixed Bugs and Malfunctions</title>
<list>
<item>
@@ -243,8 +879,6 @@
</item>
</list>
</section>
-
-
<section><title>Improvements and New Features</title>
<list>
<item>
@@ -651,6 +1285,48 @@
</section>
+<section><title>Ssh 4.4.2.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix rare spurios shutdowns of ssh servers when receiveing
+ <c>{'EXIT',_,normal}</c> messages.</p>
+ <p>
+ Own Id: OTP-15018</p>
+ </item>
+ <item>
+ <p>
+ Host key hash erroneously calculated for clients
+ following draft-00 of RFC 4419, for example PuTTY</p>
+ <p>
+ Own Id: OTP-15064</p>
+ </item>
+ <item>
+ <p>
+ Renegotiation could fail in some states</p>
+ <p>
+ Own Id: OTP-15066</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.4.2.3</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ An ssh_sftp server (running version 6) could fail if it
+ is told to remove a file which in fact is a directory.</p>
+ <p>
+ Own Id: OTP-15004</p>
+ </item>
+ </list>
+ </section>
+</section>
<section><title>Ssh 4.4.2.2</title>
<section><title>Improvements and New Features</title>
@@ -1055,6 +1731,21 @@
</section>
+<section><title>Ssh 4.2.2.6</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix rare spurios shutdowns of ssh servers when receiveing
+ <c>{'EXIT',_,normal}</c> messages.</p>
+ <p>
+ Own Id: OTP-15018</p>
+ </item>
+ </list>
+ </section>
+</section>
+
+
<section><title>Ssh 4.2.2.5</title>
<section><title>Improvements and New Features</title>
<list>
@@ -2661,7 +3352,7 @@
</item>
<item>
<p>
- Fixed internal error on when client and server can not
+ Fixed internal error on when client and server cannot
agree o which authmethod to use.</p>
<p>
Own Id: OTP-10731 Aux Id: seq12237 </p>
@@ -3726,4 +4417,3 @@
</section>
</chapter>
-
diff --git a/lib/ssh/doc/src/ref_man.xml b/lib/ssh/doc/src/ref_man.xml
index 140ebd8c76..60572b985b 100644
--- a/lib/ssh/doc/src/ref_man.xml
+++ b/lib/ssh/doc/src/ref_man.xml
@@ -4,7 +4,7 @@
<application xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>2004</year><year>2016</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -35,10 +35,12 @@
</description>
<xi:include href="ssh_app.xml"/>
<xi:include href="ssh.xml"/>
- <xi:include href="ssh_channel.xml"/>
+ <xi:include href="ssh_client_channel.xml"/>
+ <xi:include href="ssh_server_channel.xml"/>
<xi:include href="ssh_connection.xml"/>
<xi:include href="ssh_client_key_api.xml"/>
<xi:include href="ssh_server_key_api.xml"/>
+ <xi:include href="ssh_file.xml"/>
<xi:include href="ssh_sftp.xml"/>
<xi:include href="ssh_sftpd.xml"/>
</application>
diff --git a/lib/ssh/doc/src/specs.xml b/lib/ssh/doc/src/specs.xml
new file mode 100644
index 0000000000..a6517f3660
--- /dev/null
+++ b/lib/ssh/doc/src/specs.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<specs xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="../specs/specs_ssh.xml"/>
+ <xi:include href="../specs/specs_ssh_client_channel.xml"/>
+ <xi:include href="../specs/specs_ssh_client_key_api.xml"/>
+ <xi:include href="../specs/specs_ssh_connection.xml"/>
+ <xi:include href="../specs/specs_ssh_server_channel.xml"/>
+ <xi:include href="../specs/specs_ssh_server_key_api.xml"/>
+ <xi:include href="../specs/specs_ssh_file.xml"/>
+ <xi:include href="../specs/specs_ssh_sftp.xml"/>
+ <xi:include href="../specs/specs_ssh_sftpd.xml"/>
+</specs>
+
+
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
index acf94ff6af..862f79ac56 100644
--- a/lib/ssh/doc/src/ssh.xml
+++ b/lib/ssh/doc/src/ssh.xml
@@ -4,15 +4,15 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2017</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
+
+ http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
@@ -28,188 +28,189 @@
<date>2007-10-06</date>
<rev></rev>
</header>
- <module>ssh</module>
+ <module since="">ssh</module>
<modulesummary>Main API of the ssh application</modulesummary>
<description>
- <p>Interface module for the <c>ssh</c> application.</p>
- <p>See <seealso marker="ssh:SSH_app#supported">ssh(6)</seealso> for details of supported version,
- algorithms and unicode support.</p>
+ <p>This is the interface module for the <c>SSH</c> application.
+ The Secure Shell (SSH) Protocol is a protocol for secure remote login
+ and other secure network services over an insecure network.
+ See <seealso marker="ssh:SSH_app#supported">ssh(6)</seealso> for details of supported RFCs, versions,
+ algorithms and unicode handling.
+ </p>
+ <p>With the SSH application it is possible to start <i>clients</i> and to start <i>daemons</i> (servers).
+ </p>
+ <p>Clients are started with
+ <seealso marker="#connect/2">connect/2</seealso>,
+ <seealso marker="#connect/3">connect/3</seealso> or
+ <seealso marker="#connect/4">connect/4</seealso>. They open an encrypted connection on top of TCP/IP.
+ In that encrypted connection one or more channels could be opened with
+ <seealso marker="ssh_connection#session_channel/2">ssh_connection:session_channel/2,4</seealso>.
+ </p>
+ <p>Each channel is an isolated "pipe" between a client-side process and a server-side process. Those process
+ pairs could handle for example file transfers (sftp) or remote command execution (shell, exec and/or cli).
+ If a custom shell is implemented, the user of the client could execute the special commands remotely. Note that
+ the user is not necessarily a human but probably a system interfacing the SSH app.
+ </p>
+ <p>A server-side subssystem (channel) server is requested by the client with
+ <seealso marker="ssh_connection#subsystem/4">ssh_connection:subsystem/4</seealso>.
+ </p>
+ <p>A server (daemon) is started with
+ <seealso marker="#daemon/2">daemon/1</seealso>,
+ <seealso marker="#daemon/2">daemon/2</seealso> or
+ <seealso marker="#daemon/2">daemon/3</seealso>.
+ Possible channel handlers (subsystems) are declared with the
+ <seealso marker="#type-subsystem_daemon_option">subsystem</seealso> option when the daemon is started.
+ </p>
+ <p>To just run a shell on a remote machine, there are functions that bundles the needed
+ three steps needed into one:
+ <seealso marker="#shell/1">shell/1,2,3</seealso>.
+ Similarily, to just open an sftp (file transfer) connection to a remote machine, the simplest way is to use
+ <seealso marker="ssh_sftp#start_channel/1">ssh_sftp:start_channel/1,2,3</seealso>.
+ </p>
+ <p>To write your own client channel handler, use the behaviour
+ <seealso marker="ssh_client_channel">ssh_client_channel</seealso>. For server channel handlers use
+ <seealso marker="ssh_server_channel">ssh_server_channel</seealso> behaviour (replaces ssh_daemon_channel).
+ </p>
+ <p>Both clients and daemons accepts options that controls the exact behaviour. Some options are common to both.
+ The three sets are called
+ <seealso marker="#type-client_options">Client Options</seealso>,
+ <seealso marker="#type-daemon_options">Daemon Options</seealso> and
+ <seealso marker="#type-common_options">Common Options</seealso>.
+ </p>
+ <p>The descriptions of the options uses the
+ <seealso marker="doc/reference_manual:typespec">Erlang Type Language</seealso> with explaining text.
+ </p>
+ <note>
+ <p>The <seealso marker="users_guide">User's Guide</seealso> has examples and a
+ <seealso marker="using_ssh">Getting Started</seealso>
+ section.
+ </p>
+ </note>
</description>
<section>
- <title>OPTIONS</title>
- <p>The exact behaviour of some functions can be adjusted with the use of options which are documented together
- with the functions. Generally could each option be used at most one time in each function call. If given two or more
- times, the effect is not predictable unless explicitly documented.</p>
- <p>The options are of different kinds:</p>
- <taglist>
- <tag>Limits</tag>
- <item><p>which alters limits in the system, for example number of simultaneous login attempts.</p></item>
-
- <tag>Timeouts</tag>
- <item><p>which give some defined behaviour if too long time elapses before a given event or action,
- for example time to wait for an answer.</p></item>
-
- <tag>Callbacks</tag>
- <item><p>which gives the caller of the function the possibility to execute own code on some events,
- for example calling an own logging function or to perform an own login function</p></item>
-
- <tag>Behaviour</tag>
- <item><p>which changes the systems behaviour.</p></item>
- </taglist>
+ <title>Keys and files</title>
+ <p>A number of objects must be present for the SSH application to work.
+ Thoose objects are per default stored in files.
+ The default names, paths and file formats are the same as for
+ <url href="http://www.openssh.com">OpenSSH</url>. Keys could be generated with the <c>ssh-keygen</c>
+ program from OpenSSH. See the
+ <seealso marker="using_ssh#running-an-erlang-ssh-daemon">User's Guide</seealso>.
+ </p>
+
+ <p>The paths could easily be changed by options:
+ <seealso marker="ssh_file#type-user_dir_common_option"><c>user_dir</c></seealso> and
+ <seealso marker="ssh_file#type-system_dir_daemon_option"><c>system_dir</c></seealso>.
+ </p>
+ <p>A completly different storage could be interfaced by writing call-back modules
+ using the behaviours
+ <seealso marker="ssh_client_key_api">ssh_client_key_api</seealso> and/or
+ <seealso marker="ssh_server_key_api">ssh_server_key_api</seealso>.
+ A callback module is installed with the option
+ <seealso marker="#type-key_cb_common_option"><c>key_cb</c></seealso>
+ to the client and/or the daemon.
+ </p>
+
+ <section>
+ <title>Daemons</title>
+ <p>The keys are by default stored in files:</p>
+ <list>
+ <item>Mandatory: one or more <i>Host key(s)</i>, both private and public. Default is to
+ store them in the directory <c>/etc/ssh</c> in the files
+ <list>
+ <item><c>ssh_host_dsa_key</c> and <c>ssh_host_dsa_key.pub</c></item>
+ <item><c>ssh_host_rsa_key</c> and <c>ssh_host_rsa_key.pub</c></item>
+ <item><c>ssh_host_ecdsa_key</c> and <c>ssh_host_ecdsa_key.pub</c></item>
+ </list>
+ <p>The host keys directory could be changed with the option
+ <seealso marker="ssh_file#type-system_dir_daemon_option"><c>system_dir</c></seealso>.</p>
+ </item>
+ <item>Optional: one or more <i>User's public key</i> in case of <c>publickey</c> authorization.
+ Default is to store them concatenated in the file <c>.ssh/authorized_keys</c> in the user's home directory.
+ <p>The user keys directory could be changed with the option
+ <seealso marker="ssh_file#type-user_dir_common_option"><c>user_dir</c></seealso>.</p>
+ </item>
+ </list>
+ </section>
+
+ <section>
+ <title>Clients</title>
+ <p>The keys and some other data are by default stored in files in the directory <c>.ssh</c>
+ in the user's home directory.</p>
+ <p>The directory could be changed with the option
+ <seealso marker="ssh_file#type-user_dir_common_option"><c>user_dir</c></seealso>.
+ </p>
+ <list>
+ <item>Optional: a list of <i>Host public key(s)</i> for previously connected hosts. This list
+ is handled by the SSH application without any need of user assistance. The default
+ is to store them in the file <c>known_hosts</c>.
+ <p>The
+ <seealso marker="#type-host_accepting_client_options">host_accepting_client_options()</seealso>
+ are associated with this list of keys.
+ </p>
+ </item>
+ <item>Optional: one or more <i>User's private key(s)</i> in case of <c>publickey</c> authorization.
+ The default files are
+ <list>
+ <item><c>id_dsa</c> and <c>id_dsa.pub</c></item>
+ <item><c>id_rsa</c> and <c>id_rsa.pub</c></item>
+ <item><c>id_ecdsa</c> and <c>id_ecdsa.pub</c></item>
+ </list>
+ </item>
+ </list>
+ </section>
+
</section>
- <section>
- <title>DATA TYPES</title>
- <p>Type definitions that are used more than once in
- this module, or abstractions to indicate the intended use of the data
- type, or both:</p>
- <taglist>
- <tag><c>boolean() =</c></tag>
- <item><p><c>true | false</c></p></item>
- <tag><c>string() =</c></tag>
- <item><p><c>[byte()]</c></p></item>
- <tag><c>ssh_daemon_ref() =</c></tag>
- <item><p>opaque() -
- as returned by <c>ssh:daemon/[1,2,3]</c></p></item>
- <tag><c>ssh_connection_ref() =</c></tag>
- <item><p>opaque() - as returned by <c>ssh:connect/3</c></p></item>
- <tag><c>ip_address() =</c></tag>
- <item><p><c>inet::ip_address</c></p></item>
- <tag><c>subsystem_spec() =</c></tag>
- <item><p><c>{subsystem_name(),
- {channel_callback(), channel_init_args()}}</c></p></item>
- <tag><c>subsystem_name() =</c></tag>
- <item><p><c>string()</c></p></item>
- <tag><c>channel_callback() =</c></tag>
- <item><p><c>atom()</c> - Name of the Erlang module
- implementing the subsystem using the <c>ssh_channel</c> behavior, see
- <seealso marker="ssh_channel">ssh_channel(3)</seealso></p></item>
- <tag><c>key_cb() =</c></tag>
- <item>
- <p><c>atom() | {atom(), list()}</c></p>
- <p><c>atom()</c> - Name of the erlang module implementing the behaviours
- <seealso marker="ssh_client_key_api">ssh_client_key_api</seealso> or
- <seealso marker="ssh_client_key_api">ssh_client_key_api</seealso> as the
- case maybe.</p>
- <p><c>list()</c> - List of options that can be passed to the callback module.</p>
- </item>
- <tag><c>channel_init_args() =</c></tag>
- <item><p><c>list()</c></p></item>
-
- <tag><c>algs_list() =</c></tag>
- <item><p><c>list( alg_entry() )</c></p></item>
-
- <tag><c>alg_entry() =</c></tag>
- <item><p><c>{kex, simple_algs()} | {public_key, simple_algs()} | {cipher, double_algs()} | {mac, double_algs()} | {compression, double_algs()}</c></p></item>
-
- <tag><c>simple_algs() =</c></tag>
- <item><p><c>list( atom() )</c></p></item>
-
- <tag><c>double_algs() =</c></tag>
- <item><p><c>[{client2serverlist,simple_algs()},{server2client,simple_algs()}] | simple_algs()</c></p></item>
+ <!--
+ ================================================================
+ = Data types =
+ ================================================================
+ -->
- <tag><c>modify_algs_list() =</c></tag>
- <item><p><c>list( {append,algs_list()} | {prepend,algs_list()} | {rm,algs_list()} )</c></p></item>
- </taglist>
-</section>
+ <datatypes>
- <funcs>
-
- <func>
- <name>close(ConnectionRef) -> ok </name>
- <fsummary>Closes an SSH connection.</fsummary>
- <type>
- <v>ConnectionRef = ssh_connection_ref()</v>
- </type>
- <desc><p>Closes an SSH connection.</p>
+ <datatype_title>Client Options</datatype_title>
+
+ <datatype>
+ <name name="client_options"/>
+ <name name="client_option"/>
+ <desc>
+ <p>Options for <seealso marker="#connect/3">clients</seealso>.
+ The individual options are further explained below or by following the hyperlinks.
+ </p>
</desc>
- </func>
-
- <func>
- <name>connect(Host, Port, Options) -> </name>
- <name>connect(Host, Port, Options, Timeout) -> </name>
- <name>connect(TcpSocket, Options) -> </name>
- <name>connect(TcpSocket, Options, Timeout) ->
- {ok, ssh_connection_ref()} | {error, Reason}</name>
- <fsummary>Connects to an SSH server.</fsummary>
- <type>
- <v>Host = string()</v>
- <v>Port = integer()</v>
- <d><c><![CDATA[22]]></c> is default, the assigned well-known port
- number for SSH.</d>
- <v>Options = [{Option, Value}]</v>
- <v>Timeout = infinity | integer()</v>
- <d>Negotiation time-out in milli-seconds. The default value is <c>infinity</c>.
- For connection time-out, use option <c>{connect_timeout, timeout()}</c>.</d>
- <v>TcpSocket = port()</v>
- <d>The socket is supposed to be from <seealso marker="kernel:gen_tcp#connect-3">gen_tcp:connect</seealso> or <seealso marker="kernel:gen_tcp#accept-1">gen_tcp:accept</seealso> with option <c>{active,false}</c></d>
- </type>
+ </datatype>
+
+ <datatype>
+ <name name="host_accepting_client_options"/>
+ <name name="accept_hosts"/>
+ <name name="fp_digest_alg"/>
+ <name name="accept_callback"/>
+ <name name="fingerprint"/>
<desc>
- <p>Connects to an SSH server. No channel is started. This is done
- by calling
- <seealso marker="ssh_connection#session_channel/2">
- ssh_connection:session_channel/[2, 4]</seealso>.</p>
- <p>Options:</p>
<taglist>
- <tag><c><![CDATA[{inet, inet | inet6}]]></c></tag>
+ <tag><c>silently_accept_hosts</c></tag>
<item>
- <p>IP version to use.</p>
- </item>
- <tag><marker id="opt_user_dir"></marker><c><![CDATA[{user_dir, string()}]]></c></tag>
- <item>
- <p>Sets the user directory, that is, the directory containing
- <c>ssh</c> configuration files for the user, such as
- <c><![CDATA[known_hosts]]></c>, <c><![CDATA[id_rsa,
- id_dsa]]></c>, and
- <c><![CDATA[authorized_key]]></c>. Defaults to the
- directory normally referred to as
- <c><![CDATA[~/.ssh]]></c>.</p>
- </item>
- <tag><c><![CDATA[{dsa_pass_phrase, string()}]]></c></tag>
- <item>
- <p>If the user DSA key is protected by a passphrase, it can be
- supplied with this option.
- </p>
- </item>
- <tag><c><![CDATA[{rsa_pass_phrase, string()}]]></c></tag>
- <item>
- <p>If the user RSA key is protected by a passphrase, it can be
- supplied with this option.
- </p>
- </item>
- <tag><c><![CDATA[{ecdsa_pass_phrase, string()}]]></c></tag>
- <item>
- <p>If the user ECDSA key is protected by a passphrase, it can be
- supplied with this option.
- </p>
- </item>
- <tag>
- <c><![CDATA[{silently_accept_hosts, boolean()}]]></c> <br/>
- <c><![CDATA[{silently_accept_hosts, CallbackFun}]]></c> <br/>
- <c><![CDATA[{silently_accept_hosts, {HashAlgoSpec, CallbackFun} }]]></c> <br/>
- <br/>
- <c><![CDATA[HashAlgoSpec = crypto:digest_type() | [ crypto:digest_type() ] ]]></c><br/>
- <c><![CDATA[CallbackFun = fun(PeerName, FingerPrint) -> boolean()]]></c><br/>
- <c><![CDATA[PeerName = string()]]></c><br/>
- <c><![CDATA[FingerPrint = string() | [ string() ] ]]></c>
- </tag>
- <item>
- <p>This option guides the <c>connect</c> function how to act when the connected server presents a Host
+ <p>This option guides the <c>connect</c> function on how to act when the connected server presents a Host
Key that the client has not seen before. The default is to ask the user with a question on stdio of whether to
accept or reject the new Host Key.
- See also the option <seealso marker="#opt_user_dir"><c>user_dir</c></seealso>
- for the path to the file <c>known_hosts</c> where previously accepted Host Keys are recorded.
- </p>
+ See the option <seealso marker="ssh_file#type-user_dir_common_option"><c>user_dir</c></seealso>
+ for specifying the path to the file <c>known_hosts</c> where previously accepted Host Keys are recorded.
+ See also the option
+ <seealso marker="#type-key_cb_common_option">key_cb</seealso>
+ for the general way to handle keys.
+ </p>
<p>The option can be given in three different forms as seen above:</p>
<list>
- <item>The value is a <c>boolean()</c>. The value <c>true</c> will make the client accept any unknown
- Host Key without any user interaction. The value <c>false</c> keeps the default behaviour of asking the
- the user on stdio.
+ <item>The value is a <c>boolean()</c>.
+ The value <c>true</c> will make the client accept any unknown Host Key without any user interaction.
+ The value <c>false</c> preserves the default behaviour of asking the user on stdio.
</item>
- <item>A <c>CallbackFun</c> will be called and the boolean return value <c>true</c> will make the client
- accept the Host Key. A return value of <c>false</c> will make the client to reject the Host Key and therefore
- also the connection will be closed. The arguments to the fun are:
+ <item>An <c>accept_callback()</c> will be called and the boolean return value <c>true</c>
+ will make the client
+ accept the Host Key. A return value of <c>false</c> will make the client to reject the Host Key and as a
+ result the connection will be closed. The arguments to the fun are:
<list type="bulleted">
<item><c>PeerName</c> - a string with the name or address of the remote host.</item>
<item><c>FingerPrint</c> - the fingerprint of the Host Key as
@@ -218,471 +219,392 @@
</item>
</list>
</item>
- <item>A tuple <c>{HashAlgoSpec, CallbackFun}</c>. The <c>HashAlgoSpec</c> specifies which hash algorithm
- shall be used to calculate the fingerprint used in the call of the <c>CallbackFun</c>. The <c>HashALgoSpec</c>
- is either an atom or a list of atoms as the first argument in
- <seealso marker="public_key:public_key#ssh_hostkey_fingerprint-2">public_key:ssh_hostkey_fingerprint/2</seealso>.
- If it is a list of hash algorithm names, the <c>FingerPrint</c> argument in the <c>CallbackFun</c> will be
- a list of fingerprints in the same order as the corresponding name in the <c>HashAlgoSpec</c> list.
+ <item>A tuple <c>{HashAlgoSpec, accept_callback}</c>. The <c>HashAlgoSpec</c>
+ specifies which hash algorithm
+ shall be used to calculate the fingerprint used in the call of the <c>accept_callback()</c>.
+ The <c>HashALgoSpec</c>
+ is either an atom or a list of atoms as the first argument in
+ <seealso marker="public_key:public_key#ssh_hostkey_fingerprint-2">public_key:ssh_hostkey_fingerprint/2</seealso>.
+ If it is a list of hash algorithm names, the <c>FingerPrint</c> argument in the
+ <c>accept_callback()</c> will be
+ a list of fingerprints in the same order as the corresponding name in the <c>HashAlgoSpec</c> list.
</item>
</list>
</item>
-
- <tag><c><![CDATA[{save_accepted_host, boolean()}]]></c></tag>
- <item>
- <p>If <c>true</c>, the client saves an accepted host key to avoid the
- accept question the next time the same host is connected. If the option
- <c>key_cb</c> is not present, the key is saved in the file "known_hosts".
- </p>
- <p>If <c>false</c>, the key is not saved and the key will still be unknown
- at the next access of the same host.
- </p>
- </item>
-
- <tag><c><![CDATA[{user_interaction, boolean()}]]></c></tag>
+
+ <tag><c>user_interaction</c></tag>
<item>
<p>If <c>false</c>, disables the client to connect to the server
if any user interaction is needed, such as accepting
the server to be added to the <c>known_hosts</c> file, or
- supplying a password. Defaults to <c>true</c>.
- Even if user interaction is allowed it can be
+ supplying a password.</p>
+ <p>Even if user interaction is allowed it can be
suppressed by other options, such as <c>silently_accept_hosts</c>
and <c>password</c>. However, those options are not always desirable
to use from a security point of view.</p>
+ <p>Defaults to <c>true</c>.</p>
</item>
- <tag><c><![CDATA[{disconnectfun, fun(Reason:term()) -> _}]]></c></tag>
- <item>
- <p>Provides a fun to implement your own logging when a server disconnects the client.</p>
- </item>
-
- <tag><c><![CDATA[{unexpectedfun, fun(Message:term(), Peer) -> report | skip }]]></c></tag>
- <item>
- <p>Provides a fun to implement your own logging or other action when an unexpected message arrives.
- If the fun returns <c>report</c> the usual info report is issued but if <c>skip</c> is returned no
- report is generated.</p>
- <p><c>Peer</c> is in the format of <c>{Host,Port}</c>.</p>
- </item>
-
- <tag><c><![CDATA[{pref_public_key_algs, list()}]]></c></tag>
- <item>
- <p>List of user (client) public key algorithms to try to use.</p>
- <p>The default value is the <c>public_key</c> entry in
- <seealso marker="#default_algorithms/0">ssh:default_algorithms/0</seealso>.
- </p>
- <p>If there is no public key of a specified type available, the corresponding entry is ignored.
- Note that the available set is dependent on the underlying cryptolib and current user's public keys.
- </p>
- </item>
-
- <tag><marker id="option_preferred_algorithms"></marker>
- <c><![CDATA[{preferred_algorithms, algs_list()}]]></c></tag>
+ <tag><c>save_accepted_host</c></tag>
<item>
- <p>List of algorithms to use in the algorithm negotiation. The default <c>algs_list()</c> can
- be obtained from <seealso marker="#default_algorithms/0">default_algorithms/0</seealso>.
+ <p>If <c>true</c>, the client saves an accepted host key to avoid the
+ accept question the next time the same host is connected. If the option
+ <seealso marker="#type-key_cb_common_option"><c>key_cb</c></seealso>
+ is not present, the key is saved in the file "known_hosts". See option
+ <seealso marker="ssh_file#type-user_dir_common_option"><c>user_dir</c></seealso> for
+ the location of that file.
</p>
- <p>If an alg_entry() is missing in the algs_list(), the default value is used for that entry.</p>
- <p>Here is an example of this option:</p>
- <code>
-{preferred_algorithms,
- [{public_key,['ssh-rsa','ssh-dss']},
- {cipher,[{client2server,['aes128-ctr']},
- {server2client,['aes128-cbc','3des-cbc']}]},
- {mac,['hmac-sha2-256','hmac-sha1']},
- {compression,[none,zlib]}
- ]
-}
-</code>
- <p>The example specifies different algorithms in the two directions (client2server and server2client),
- for cipher but specifies the same algorithms for mac and compression in both directions.
- The kex (key exchange) is implicit but public_key is set explicitly.</p>
-
- <p>For background and more examples see the <seealso marker="configure_algos#introduction">User's Guide</seealso>.</p>
-
- <warning>
- <p>Changing the values can make a connection less secure. Do not change unless you
- know exactly what you are doing. If you do not understand the values then you
- are not supposed to change them.</p>
- </warning>
- </item>
-
- <tag><marker id="option_modify_algorithms"></marker>
- <c><![CDATA[{modify_algorithms, modify_algs_list()}]]></c></tag>
- <item>
- <p>Modifies the list of algorithms to use in the algorithm negotiation. The modifications are
- applied after the option <c>preferred_algorithms</c> (if existing) is applied.</p>
- <p>The algoritm for modifications works like this:</p>
- <list>
- <item>
- <p>Input is the <c>modify_algs_list()</c> and a set of algorithms <c>A</c>
- obtained from the <c>preferred_algorithms</c> option if existing, or else from the
- <seealso marker="ssh#default_algorithms-0">ssh:default_algorithms/0</seealso>.
- </p>
- </item>
- <item>
- <p>The head of the <c>modify_algs_list()</c> modifies <c>A</c> giving the result <c>A'</c>.</p>
- <p>The possible modifications are:</p>
- <list>
- <item>
- <p>Append or prepend supported but not enabled algorithm(s) to the list of
- algorithms. If the wanted algorithms already are in <c>A</c> they will first
- be removed and then appended or prepended,
- </p>
- </item>
- <item>
- <p>Remove (rm) one or more algorithms from <c>A</c>.
- </p>
- </item>
- </list>
- </item>
- <item>
- <p>Repeat the modification step with the tail of <c>modify_algs_list()</c> and the resulting
- <c>A'</c>.
- </p>
- </item>
- </list>
- <p>If an unsupported algorithm is in the <c>modify_algs_list()</c>, it will be silently ignored</p>
- <p>If there are more than one modify_algorithms options, the result is undefined.</p>
- <p>Here is an example of this option:</p>
- <code>
-{modify_algorithms,
- [{prepend, [{kex, ['diffie-hellman-group1-sha1']}],
- {rm, [{compression, [none]}]}
- ]
-}
-</code>
- <p>The example specifies that:</p>
- <list>
- <item><p>the old key exchange algorithm 'diffie-hellman-group1-sha1' should be
- the main alternative. It will be the main alternative since it is prepened to the list</p>
- </item>
- <item><p>The compression algorithm none (= no compression) is removed so compression is enforced</p>
- </item>
- </list>
- <p>For background and more examples see the <seealso marker="configure_algos#introduction">User's Guide</seealso>.</p>
- </item>
-
- <tag><c><![CDATA[{dh_gex_limits,{Min=integer(),I=integer(),Max=integer()}}]]></c></tag>
- <item>
- <p>Sets the three diffie-hellman-group-exchange parameters that guides the connected server in choosing a group.
- See RFC 4419 for the function of thoose. The default value is <c>{1024, 6144, 8192}</c>.
+ <p>If <c>false</c>, the key is not saved and the key will still be unknown
+ at the next access of the same host.
</p>
+ <p>Defaults to <c>true</c></p>
</item>
- <tag><c><![CDATA[{connect_timeout, timeout()}]]></c></tag>
+ <tag><c>quiet_mode</c></tag>
<item>
- <p>Sets a time-out on the transport layer
- connection. For <c>gen_tcp</c> the time is in milli-seconds and the default value is
- <c>infinity</c>.</p>
+ <p>If <c>true</c>, the client does not print anything on authorization.</p>
+ <p>Defaults to <c>false</c></p>
</item>
+ </taglist>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{auth_methods, string()}]]></c></tag>
- <item>
- <p>Comma-separated string that determines which
- authentication methods that the client shall support and
- in which order they are tried. Defaults to
- <c><![CDATA["publickey,keyboard-interactive,password"]]></c></p>
- </item>
-
- <tag><c><![CDATA[{user, string()}]]></c></tag>
+ <datatype>
+ <name name="authentication_client_options"/>
+ <desc>
+ <taglist>
+ <tag><c>user</c></tag>
<item>
- <p>Provides a username. If this option is not given, <c>ssh</c>
+ <p>Provides the username. If this option is not given, <c>ssh</c>
reads from the environment (<c><![CDATA[LOGNAME]]></c> or
<c><![CDATA[USER]]></c> on UNIX,
<c><![CDATA[USERNAME]]></c> on Windows).</p>
</item>
- <tag><c><![CDATA[{password, string()}]]></c></tag>
+ <tag><c>password</c></tag>
<item>
<p>Provides a password for password authentication.
If this option is not given, the user is asked for a
password, if the password authentication method is
attempted.</p>
</item>
+ </taglist>
+ </desc>
+ </datatype>
- <!--tag><c><![CDATA[{send_ext_info, boolean()}]]></c></tag>
- <item>
- <p>Send a list of extensions to the server if the server has asked for it. See
- <url href="https://tools.ietf.org/html/draft-ietf-curdle-ssh-ext-info">Draft-ietf-curdle-ssh-ext-info (work in progress)</url> for details.
- </p>
- <p>Currently the client do not react on any extensions.
- </p>
- <p>Default value is <c>true</c>.
- </p>
- </item-->
+ <datatype>
+ <name name="diffie_hellman_group_exchange_client_option"/>
+ <desc>
+ <p>Sets the three diffie-hellman-group-exchange parameters that guides the connected server in choosing a group.
+ See
+ <url href="https://tools.ietf.org/html/rfc4419">RFC 4419</url>
+ for the details. The default value is <c>{1024, 6144, 8192}</c>.
+ </p>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{recv_ext_info, boolean()}]]></c></tag>
- <item>
- <p>Tell the server that the client accepts extension negotiation. See
- <url href="https://tools.ietf.org/html/draft-ietf-curdle-ssh-ext-info">Draft-ietf-curdle-ssh-ext-info (work in progress)</url> for details.
- </p>
- <p>Currently implemented extension is <c>server-sig-algs</c> which is the list of the server's preferred
- user's public key algorithms.
- </p>
- <p>Default value is <c>true</c>.
- </p>
- </item>
+ <datatype>
+ <name name="connect_timeout_client_option"/>
+ <desc>
+ <p>Sets a timeout on the transport layer connect time.
+ For <seealso marker="kernel:gen_tcp"><c>gen_tcp</c></seealso> the time is in milli-seconds and the default
+ value is <c>infinity</c>.
+ </p>
+ <p>See the parameter <c>Timeout</c> in <seealso marker="#connect/4">connect/4</seealso> for
+ a timeout of the negotiation phase.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="recv_ext_info_client_option"/>
+ <desc>
+ <p>Make the client tell the server that the client accepts extension negotiation, that is,
+ include <c>ext-info-c</c> in the kexinit message sent. See
+ <url href="https://tools.ietf.org/html/rfc8308">RFC 8308</url>
+ for details and <seealso marker="SSH_app#supported-ext-info">ssh(6)</seealso>
+ for a list of currently implemented extensions.
+ </p>
+ <p>
+ Default value is <c>true</c> which is compatible with other implementations not supporting ext-info.
+ </p>
+ </desc>
+ </datatype>
+
+ <!--................................................................-->
+ <datatype_title>Daemon Options (Server Options)</datatype_title>
+
+ <datatype>
+ <name name="daemon_options"/>
+ <name name="daemon_option"/>
+ <desc>
+ <p>Options for <seealso marker="#daemon/1">daemons</seealso>.
+ The individual options are further explained below or by following the hyperlinks.
+ </p>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{key_cb, key_cb()}]]></c></tag>
+
+ <datatype>
+ <name name="subsystem_daemon_option"/>
+ <name name="subsystem_specs"/>
+ <name name="subsystem_spec"/>
+ <desc>
+ <p>Defines a subsystem in the daemon.</p>
+ <p>The <c>subsystem_name</c> is the name that a client requests to start with for example
+ <seealso marker="ssh_connection#subsystem/4">ssh_connection:subsystem/4</seealso>.
+ </p>
+ <p>The <c>channel_callback</c> is the module that implements the
+ <seealso marker="ssh_server_channel">ssh_server_channel</seealso> (replaces ssh_daemon_channel)
+ behaviour in the daemon. See the section
+ <seealso marker="using_ssh#usersguide_creating_a_subsystem">Creating a Subsystem</seealso>
+ in the User's Guide for more information and an example.
+ </p>
+ <p>If the subsystems option is not present, the value of <c>ssh_sftpd:subsystem_spec([])</c> is used.
+ This enables the sftp subsystem by default.
+ The option can be set to the empty list if you do not want the daemon to run any subsystems.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="shell_daemon_option"/>
+ <name name="shell_spec"/>
+ <name name="shell_fun"/>
+ <name name="'shell_fun/1'"/>
+ <name name="'shell_fun/2'"/>
+ <desc>
+ <p>Defines the read-eval-print loop used in a daemon when a shell is requested by the client.
+ The default is to use the Erlang shell: <c><![CDATA[{shell, start, []}]]></c>
+ </p>
+ <p>See the option <seealso marker="#type-exec_daemon_option"><c>exec-option</c></seealso>
+ for a description of how the daemon executes shell-requests and exec-requests depending on
+ the shell- and exec-options.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="exec_daemon_option"/>
+ <name name="exec_spec"/>
+ <desc/>
+ </datatype>
+ <datatype>
+ <name name="exec_fun"/>
+ <desc/>
+ </datatype>
+ <datatype>
+ <name name="'exec_fun/1'"/>
+ <name name="'exec_fun/2'"/>
+ <name name="'exec_fun/3'"/>
+ <desc/>
+ </datatype>
+ <datatype>
+ <name name="exec_result"/>
+ <desc>
+ <p>This option changes how the daemon executes exec-requests from clients. The term in the return value
+ is formatted to a string if it is a non-string type. No trailing newline is added in the ok-case.
+ </p>
+ <p>See the User's Guide section on
+ <seealso marker="using_ssh#one-time-execution">One-Time Execution</seealso> for examples.
+ </p>
+ <p>Error texts are returned on channel-type 1 which usually is piped to <c>stderr</c> on e.g Linux systems.
+ Texts from a successful execution are returned on channel-type 0 and
+ will in similar manner be piped to <c>stdout</c>. The exit-status code
+ is set to 0 for success and 255 for errors. The exact results presented on the client side depends on the
+ client and the client's operating system.
+ </p>
+ <p>In case of the <c>{direct, exec_fun()}</c> variant or no exec-option at all,
+ all reads from <c>standard_input</c> will be from the received data-events of type 0.
+ Those are sent by the client. Similarily all writes to <c>standard_output</c>
+ will be sent as data-events to the client. An OS shell client like the command 'ssh' will usally use
+ stdin and stdout for the user interface.
+ </p>
+ <p>The option cooperates with the daemon-option <seealso marker="#type-shell_daemon_option"><c>shell</c></seealso>
+ in the following way:</p>
+
+ <taglist>
+ <tag>1. If neither the <seealso marker="#type-exec_daemon_option"><c>exec-option</c></seealso> nor the
+ <seealso marker="#type-shell_daemon_option"><c>shell-option</c></seealso> is present:</tag>
<item>
- <p>Module implementing the behaviour <seealso
- marker="ssh_client_key_api">ssh_client_key_api</seealso>. Can be used to
- customize the handling of public keys. If callback options are provided
- along with the module name, they are made available to the callback
- module via the options passed to it under the key 'key_cb_private'.
- </p>
+ <p>The default Erlang evaluator is used both for exec and shell requests.
+ The result is returned to the client.</p>
</item>
- <tag><c><![CDATA[{quiet_mode, atom() = boolean()}]]></c></tag>
+ <tag>2. If the <seealso marker="#type-exec_daemon_option"><c>exec_spec</c></seealso>'s value is <c>disabled</c>
+ (the <seealso marker="#type-shell_daemon_option"><c>shell-option</c></seealso> may or may not be present):</tag>
<item>
- <p>If <c>true</c>, the client does not print anything on authorization.</p>
+ <p>No exec-requests are executed but shell-requests are not affected, they follow the
+ <seealso marker="#type-shell_daemon_option"><c>shell_spec</c></seealso>'s value.</p>
</item>
- <tag><c><![CDATA[{id_string, random | string()}]]></c></tag>
+ <tag>3. If the <seealso marker="#type-exec_daemon_option"><c>exec-option</c></seealso>
+ is present and the <seealso marker="#type-exec_daemon_option"><c>exec_spec</c></seealso> value =/= <c>disabled</c>
+ (the <seealso marker="#type-shell_daemon_option"><c>shell-option</c></seealso> may or may not be present):</tag>
<item>
- <p>The string that the client presents to a connected server initially. The default value is "Erlang/VSN" where VSN is the ssh application version number.
- </p>
- <p>The value <c>random</c> will cause a random string to be created at each connection attempt. This is to make it a bit more difficult for a malicious peer to find the ssh software brand and version.
+ <p>The <seealso marker="#type-exec_daemon_option"><c>exec_spec</c></seealso>
+ <c>fun()</c> is called with the same number of parameters as the arity of the fun,
+ and the result is returned to the client.
+ Shell-requests are not affected, they follow the
+ <seealso marker="#type-shell_daemon_option"><c>shell_spec</c></seealso>'s value.
</p>
</item>
-
- <tag><c><![CDATA[{fd, file_descriptor()}]]></c></tag>
- <item>
- <p>Allows an existing file descriptor to be used
- (by passing it on to the transport protocol).</p></item>
- <tag><c><![CDATA[{rekey_limit, integer()}]]></c></tag>
+
+ <tag>4. If the <seealso marker="#type-exec_daemon_option"><c>exec-option</c></seealso> is absent, and the
+ <seealso marker="#type-shell_daemon_option"><c>shell-option</c></seealso>
+ is present with the default Erlang shell as the
+ <seealso marker="#type-shell_daemon_option"><c>shell_spec</c></seealso>'s
+ value:</tag>
<item>
- <p>Provides, in bytes, when rekeying is to be initiated.
- Defaults to once per each GB and once per hour.</p>
+ <p>The default Erlang evaluator is used both for exec and shell requests.
+ The result is returned to the client.</p>
</item>
- <tag><c><![CDATA[{idle_time, integer()}]]></c></tag>
+
+ <tag>5. If the <seealso marker="#type-exec_daemon_option"><c>exec-option</c></seealso> is absent, and the
+ <seealso marker="#type-shell_daemon_option"><c>shell-option</c></seealso>
+ is present with a value that is neither the default Erlang shell nor the value <c>disabled</c>:</tag>
<item>
- <p>Sets a time-out on a connection when no channels are active.
- Defaults to <c>infinity</c>.</p></item>
- <tag><c><![CDATA[{ssh_msg_debug_fun, fun(ConnectionRef::ssh_connection_ref(), AlwaysDisplay::boolean(), Msg::binary(), LanguageTag::binary()) -> _}]]></c></tag>
+ <p>The exec-request is not evaluated and an error message is returned to the client. Shell-requests
+ are executed according to the value of the
+ <seealso marker="#type-shell_daemon_option"><c>shell_spec</c></seealso>.</p>
+ </item>
+
+ <tag>6. If the <seealso marker="#type-exec_daemon_option"><c>exec-option</c></seealso> is absent, and the
+ <seealso marker="#type-shell_daemon_option"><c>shell_spec</c></seealso>'s value is <c>disabled</c>:</tag>
<item>
- <p>Provide a fun to implement your own logging of the SSH message SSH_MSG_DEBUG. The last three parameters are from the message, see RFC4253, section 11.3. The <c>ConnectionRef</c> is the reference to the connection on which the message arrived. The return value from the fun is not checked.</p>
- <p>The default behaviour is ignore the message.
- To get a printout for each message with <c>AlwaysDisplay = true</c>, use for example <c>{ssh_msg_debug_fun, fun(_,true,M,_)-> io:format("DEBUG: ~p~n", [M]) end}</c></p>
+ <p>Exec requests are executed by the default shell, but shell-requests are not executed.</p>
</item>
</taglist>
- </desc>
- </func>
+ <p>If a custom CLI is installed (see the option
+ <seealso marker="#type-ssh_cli_daemon_option"><c>ssh_cli</c></seealso>)
+ the rules above are replaced by thoose implied by the custom CLI.
+ </p>
+ <note>
+ <p>The <seealso marker="#type-exec_daemon_option"><c>exec-option</c></seealso>
+ has existed for a long time but has not previously been documented. The old
+ definition and behaviour are retained but obey the rules 1-6 above if conflicting.
+ The old and undocumented style should not be used in new programs.</p>
+ </note>
+ </desc>
+ </datatype>
- <func>
- <name>connection_info(ConnectionRef, [Option]) ->[{Option,
- Value}]</name>
- <fsummary>Retrieves information about a connection.</fsummary>
- <type>
- <v>Option = client_version | server_version | user | peer | sockname </v>
- <v>Value = [option_value()] </v>
- <v>option_value() = {{Major::integer(), Minor::integer()}, VersionString::string()} |
- User::string() | Peer::{inet:hostname(), {inet::ip_adress(), inet::port_number()}} |
- Sockname::{inet::ip_adress(), inet::port_number()}</v>
- </type>
+ <datatype>
+ <name name="deprecated_exec_opt"/>
<desc>
- <p>Retrieves information about a connection.</p>
+ <p>Old-style exec specification that are kept for compatibility, but should not be used in
+ new programs</p>
</desc>
- </func>
-
- <func>
- <name>daemon(Port) -> </name>
- <name>daemon(Port, Options) -> </name>
- <name>daemon(HostAddress, Port, Options) -> </name>
- <name>daemon(TcpSocket) -> </name>
- <name>daemon(TcpSocket, Options) -> {ok, ssh_daemon_ref()} | {error, atom()}</name>
- <fsummary>Starts a server listening for SSH connections
- on the given port.</fsummary>
- <type>
- <v>Port = integer()</v>
- <v>HostAddress = ip_address() | any | loopback</v>
- <v>Options = [{Option, Value}]</v>
- <v>Option = atom()</v>
- <v>Value = term()</v>
- <v>TcpSocket = port()</v>
- <d>The socket is supposed to be from <seealso marker="kernel:gen_tcp#connect-3">gen_tcp:connect</seealso> or <seealso marker="kernel:gen_tcp#accept-1">gen_tcp:accept</seealso> with option <c>{active,false}</c></d>
- </type>
- <desc>
- <p>Starts a server listening for SSH connections on the given
- port. If the <c>Port</c> is 0, a random free port is selected. See
- <seealso marker="#daemon_info/1">daemon_info/1</seealso> about how to find the selected port number.</p>
-
- <p>Please note that by historical reasons both the <c>HostAddress</c> argument and the inet socket option
- <c>ip</c> set the listening address. This is a source of possible inconsistent settings.</p>
+ </datatype>
- <p>The rules for handling the two address passing options are:</p>
- <list>
- <item>if <c>HostAddress</c> is an IP-address, that IP-address is the listening address.
- An 'ip'-option will be discarded if present.</item>
-
- <item>if <c>HostAddress</c> is <c>loopback</c>, the listening address
- is <c>loopback</c> and an loopback address will be choosen by the underlying layers.
- An 'ip'-option will be discarded if present.</item>
-
- <item>if <c>HostAddress</c> is <c>any</c> and no 'ip'-option is present, the listening address is
- <c>any</c> and the socket will listen to all addresses</item>
-
- <item>if <c>HostAddress</c> is <c>any</c> and an 'ip'-option is present, the listening address is
- set to the value of the 'ip'-option</item>
- </list>
-
- <p>Options:</p>
- <taglist>
- <tag><c><![CDATA[{inet, inet | inet6}]]></c></tag>
- <item><p>IP version to use when the host address is specified as <c>any</c>.</p></item>
- <tag><c><![CDATA[{subsystems, [subsystem_spec()]}]]></c></tag>
- <item>
- <p>Provides specifications for handling of subsystems. The
- "sftp" subsystem specification is retrieved by calling
- <c>ssh_sftpd:subsystem_spec/1</c>. If the subsystems option is
- not present, the value of
- <c>[ssh_sftpd:subsystem_spec([])]</c> is used.
- The option can be set to the empty list if
- you do not want the daemon to run any subsystems.</p>
- </item>
- <tag><c><![CDATA[{shell, {Module, Function, Args} |
- fun(string() = User) - > pid() | fun(string() = User,
- ip_address() = PeerAddr) -> pid()}]]></c></tag>
- <item>
- <p>Defines the read-eval-print loop used when a shell is
- requested by the client. The default is to use the Erlang shell:
- <c><![CDATA[{shell, start, []}]]></c></p>
- </item>
- <tag><c><![CDATA[{ssh_cli, {channel_callback(),
- channel_init_args()} | no_cli}]]></c></tag>
- <item>
- <p>Provides your own CLI implementation, that is, a channel callback
- module that implements a shell and command execution. The shell
- read-eval-print loop can be customized, using the
- option <c>shell</c>. This means less work than implementing
- an own CLI channel. If set to <c>no_cli</c>, the CLI channels
- are disabled and only subsystem channels are allowed.</p>
- </item>
- <tag><c><![CDATA[{user_dir, string()}]]></c></tag>
- <item>
- <p>Sets the user directory. That is, the directory containing
- <c>ssh</c> configuration files for the user, such as
- <c><![CDATA[known_hosts]]></c>, <c><![CDATA[id_rsa,
- id_dsa]]></c>, and
- <c><![CDATA[authorized_key]]></c>. Defaults to the
- directory normally referred to as
- <c><![CDATA[~/.ssh]]></c>.</p>
- </item>
- <tag><c><![CDATA[{system_dir, string()}]]></c></tag>
- <item>
- <p>Sets the system directory, containing the host key files
- that identify the host keys for <c>ssh</c>. Defaults to
- <c><![CDATA[/etc/ssh]]></c>. For security reasons,
- this directory is normally accessible only to the root user.</p>
- </item>
-
- <tag><c><![CDATA[{auth_methods, string()}]]></c></tag>
- <item>
- <p>Comma-separated string that determines which
- authentication methods that the server is to support and
- in what order they are tried. Defaults to
- <c><![CDATA["publickey,keyboard-interactive,password"]]></c></p>
- <p>Note that the client is free to use any order and to exclude methods.</p>
- </item>
-
- <tag><c><![CDATA[{auth_method_kb_interactive_data, PromptTexts}]]></c>
- <br/><c>where:</c>
- <br/><c>PromptTexts = kb_int_tuple() | fun(Peer::{IP::tuple(),Port::integer()}, User::string(), Service::string()) -> kb_int_tuple()</c>
- <br/><c>kb_int_tuple() = {Name::string(), Instruction::string(), Prompt::string(), Echo::boolean()}</c>
- </tag>
+ <datatype>
+ <name name="ssh_cli_daemon_option"/>
+ <desc>
+ <p>Provides your own CLI implementation in a daemon.</p>
+ <p>It is a channel callback module that implements a shell
+ and command execution. The shell's read-eval-print loop can be customized, using the
+ option <seealso marker="#type-shell_daemon_option"><c>shell</c></seealso>. This means less work than implementing
+ an own CLI channel. If <c>ssh_cli</c> is set to <c>no_cli</c>, the CLI channels
+ like <seealso marker="#type-shell_daemon_option"><c>shell</c></seealso>
+ and <seealso marker="#type-exec_daemon_option"><c>exec</c></seealso>
+ are disabled and only subsystem channels are allowed.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="authentication_daemon_options"/>
+ <name name="prompt_texts"/>
+ <name name="kb_int_tuple"/>
+ <name name="kb_int_fun_3"/>
+ <name name="pwdfun_2"/>
+ <name name="pwdfun_4"/>
+ <desc>
+ <taglist>
+ <tag><c>auth_method_kb_interactive_data</c></tag>
<item>
- <p>Sets the text strings that the daemon sends to the client for presentation to the user when using <c>keyboar-interactive</c> authentication. If the fun/3 is used, it is called when the actual authentication occurs and may therefore return dynamic data like time, remote ip etc.</p>
+ <p>Sets the text strings that the daemon sends to the client for presentation to the user when
+ using <c>keyboard-interactive</c> authentication.</p>
+ <p>If the fun/3 is used, it is called when the actual authentication occurs and may therefore
+ return dynamic data like time, remote ip etc.</p>
<p>The parameter <c>Echo</c> guides the client about need to hide the password.</p>
<p>The default value is:
- <c>{auth_method_kb_interactive_data, {"SSH server", "Enter password for \""++User++"\"", "password: ", false}></c></p>
+ <c>{auth_method_kb_interactive_data, {"SSH server", "Enter password for \""++User++"\"", "password: ", false}></c>
+ </p>
</item>
- <tag><c><![CDATA[{user_passwords, [{string() = User,
- string() = Password}]}]]></c></tag>
+ <tag><marker id="option-user_passwords"/><c>user_passwords</c></tag>
<item>
- <p>Provides passwords for password authentication. The passwords
- are used when someone tries to connect to the server and
- public key user-authentication fails. The option provides
+ <p>Provides passwords for password authentication. The passwords are used when someone tries
+ to connect to the server and public key user-authentication fails. The option provides
a list of valid usernames and the corresponding passwords.
</p>
</item>
- <tag><c><![CDATA[{password, string()}]]></c></tag>
+
+ <tag><marker id="option-password"/><c>password</c></tag>
<item>
- <p>Provides a global password that authenticates any
- user. From a security perspective this option makes
- the server very vulnerable.</p>
+ <p>Provides a global password that authenticates any user.</p>
+ <warning>
+ <p>Intended to facilitate testing.</p>
+ <p>From a security perspective this option makes the server very vulnerable.</p>
+ </warning>
</item>
- <tag><c><![CDATA[{preferred_algorithms, algs_list()}]]></c></tag>
+ <tag><marker id="option-pwdfun"/><c>pwdfun</c> with
+ <seealso marker="#type-pwdfun_4"><c>pwdfun_4()</c></seealso>
+ </tag>
<item>
- <p>List of algorithms to use in the algorithm negotiation. The default <c>algs_list()</c> can
- be obtained from <seealso marker="#default_algorithms/0">default_algorithms/0</seealso>.
+ <p>Provides a function for password validation. This could used for calling an external system or handeling
+ passwords stored as hash values.
</p>
- <p>If an alg_entry() is missing in the algs_list(), the default value is used for that entry.</p>
- <p>Here is an example of this option:</p>
- <code>
-{preferred_algorithms,
- [{public_key,['ssh-rsa','ssh-dss']},
- {cipher,[{client2server,['aes128-ctr']},
- {server2client,['aes128-cbc','3des-cbc']}]},
- {mac,['hmac-sha2-256','hmac-sha1']},
- {compression,[none,zlib]}
- ]
-}
-</code>
- <p>The example specifies different algorithms in the two directions (client2server and server2client),
- for cipher but specifies the same algorithms for mac and compression in both directions.
- The kex (key exchange) is implicit but public_key is set explicitly.</p>
-
- <p>For background and more examples see the <seealso marker="configure_algos#introduction">User's Guide</seealso>.</p>
+ <p>This fun can also be used to make delays in authentication tries for example by calling
+ <seealso marker="stdlib:timer#sleep/1">timer:sleep/1</seealso>.</p>
+ <p>To facilitate for instance counting of failed tries,
+ the <c>State</c> variable could be used. This state is per connection only. The first time the pwdfun
+ is called for a connection, the <c>State</c> variable has the value <c>undefined</c>.
+ </p>
+
+ <p>The fun should return:
+ </p>
+ <list type="bulleted">
+ <item><c>true</c> if the user and password is valid</item>
+ <item><c>false</c> if the user or password is invalid</item>
+ <item><c>disconnect</c> if a SSH_MSG_DISCONNECT message should be sent immediately. It will
+ be followed by a close of the underlying tcp connection.</item>
+ <item><c>{true, NewState:any()}</c> if the user and password is valid</item>
+ <item><c>{false, NewState:any()}</c> if the user or password is invalid</item>
+ </list>
- <warning>
- <p>Changing the values can make a connection less secure. Do not change unless you
- know exactly what you are doing. If you do not understand the values then you
- are not supposed to change them.</p>
- </warning>
+ <p>A third usage is to block login attempts from a missbehaving peer. The <c>State</c> described above
+ can be used for this. The return value <c>disconnect</c> is useful for this.</p>
</item>
- <tag><marker id="option_modify_algorithms"></marker>
- <c><![CDATA[{modify_algorithms, modify_algs_list()}]]></c></tag>
+ <tag><c>pwdfun</c> with
+ <seealso marker="#type-pwdfun_2"><c>pwdfun_2()</c></seealso>
+ </tag>
<item>
- <p>Modifies the list of algorithms to use in the algorithm negotiation. The modifications are
- applied after the option <c>preferred_algorithms</c> is applied (if existing)</p>
- <p>The possible modifications are to:</p>
- <list>
- <item><p>Append or prepend supported but not enabled algorithm(s) to the list of
- algorithms.</p><p>If the wanted algorithms already are in the list of algorithms, they will first
- be removed and then appended or prepended.
- </p>
- </item>
- <item><p>Remove (rm) one or more algorithms from the list of algorithms.</p></item>
+ <p>Provides a function for password validation. This function is called with user and password
+ as strings, and returns:</p>
+ <list type="bulleted">
+ <item><c>true</c> if the user and password is valid</item>
+ <item><c>false</c> if the user or password is invalid</item>
</list>
- <p>If an unsupported algorithm is in the list, it will be silently ignored</p>
-
- <p>Here is an example of this option:</p>
- <code>
-{modify_algorithms,
- [{prepend, [{kex, ['diffie-hellman-group1-sha1']}],
- {rm, [{compression, [none]}]}
- ]
-}
-</code>
- <p>The example specifies that:</p>
- <list>
- <item><p>the old key exchange algorithm 'diffie-hellman-group1-sha1' should be
- the main alternative. It will be the main alternative since it is prepened to the list</p>
- </item>
- <item><p>The compression algorithm none (= no compression) is removed so compression is enforced</p>
- </item>
- </list>
- <p>For background and more examples see the <seealso marker="configure_algos#introduction">User's Guide</seealso>.</p>
+ <p>This variant is kept for compatibility.</p>
</item>
+ </taglist>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{dh_gex_groups, [{Size=integer(),G=integer(),P=integer()}] | {file,filename()} {ssh_moduli_file,filename()} }]]></c></tag>
+ <datatype>
+ <name name="diffie_hellman_group_exchange_daemon_option"/>
+ <name name="explicit_group"/>
+ <name name="explicit_group_file"/>
+ <name name="ssh_moduli_file"/>
+ <desc>
+ <taglist>
+ <tag><c>dh_gex_groups</c></tag>
<item>
<p>Defines the groups the server may choose among when diffie-hellman-group-exchange is negotiated.
- See RFC 4419 for details. The three variants of this option are:
+ See
+ <url href="https://tools.ietf.org/html/rfc4419">RFC 4419</url>
+ for details. The three variants of this option are:
</p>
<taglist>
<tag><c>{Size=integer(),G=integer(),P=integer()}</c></tag>
@@ -704,7 +626,7 @@
</p>
</item>
- <tag><c><![CDATA[{dh_gex_limits,{Min=integer(),Max=integer()}}]]></c></tag>
+ <tag><c>dh_gex_limits</c></tag>
<item>
<p>Limits what a client can ask for in diffie-hellman-group-exchange.
The limits will be
@@ -715,57 +637,29 @@
</p>
<p>If <c>MaxUsed &lt; MinUsed</c> in a key exchange, it will fail with a disconnect.
</p>
- <p>See RFC 4419 for the function of the Max and Min values.</p>
- </item>
-
- <tag><c><![CDATA[{pwdfun, fun(User::string(), Password::string(), PeerAddress::{ip_adress(),port_number()}, State::any()) -> boolean() | disconnect | {boolean(),any()} }]]></c></tag>
- <item>
- <p>Provides a function for password validation. This could used for calling an external system or if
- passwords should be stored as a hash. The fun returns:
- </p>
- <list type="bulleted">
- <item><c>true</c> if the user and password is valid and</item>
- <item><c>false</c> otherwise.</item>
- </list>
- <p>This fun can also be used to make delays in authentication tries for example by calling
- <seealso marker="stdlib:timer#sleep/1">timer:sleep/1</seealso>. To facilitate counting of failed tries
- the <c>State</c> variable could be used. This state is per connection only. The first time the pwdfun
- is called for a connection, the <c>State</c> variable has the value <c>undefined</c>.
- The pwdfun can return - in addition to the values above - a new state
- as:
- </p>
- <list type="bulleted">
- <item><c>{true, NewState:any()}</c> if the user and password is valid or</item>
- <item><c>{false, NewState:any()}</c> if the user or password is invalid</item>
- </list>
- <p>A third usage is to block login attempts from a missbehaving peer. The <c>State</c> described above
- can be used for this. In addition to the responses above, the following return value is introduced:
- </p>
- <list type="bulleted">
- <item><c>disconnect</c> if the connection should be closed immediately after sending a SSH_MSG_DISCONNECT
- message.</item>
- </list>
- </item>
-
- <tag><c><![CDATA[{pwdfun, fun(User::string(), Password::string()) -> boolean()}]]></c></tag>
- <item>
- <p>Provides a function for password validation. This function is called
- with user and password as strings, and returns
- <c><![CDATA[true]]></c> if the password is valid and
- <c><![CDATA[false]]></c> otherwise.</p>
- <p>This option (<c>{pwdfun,fun/2}</c>) is the same as a subset of the previous
- (<c>{pwdfun,fun/4}</c>). It is kept for compatibility.</p>
+ <p>See
+ <url href="https://tools.ietf.org/html/rfc4419">RFC 4419</url>
+ for the function of the Max and Min values.</p>
</item>
+ </taglist>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{negotiation_timeout, integer()}]]></c></tag>
- <item>
- <p>Maximum time in milliseconds for the authentication negotiation.
- Defaults to 120000 (2 minutes). If the client fails to log in within this time,
- the connection is closed.
- </p>
- </item>
+ <datatype>
+ <name name="negotiation_timeout_daemon_option"/>
+ <desc>
+ <p>Maximum time in milliseconds for the authentication negotiation.
+ Defaults to 120000 ms (2 minutes). If the client fails to log in within this time,
+ the connection is closed.
+ </p>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{max_sessions, pos_integer()}]]></c></tag>
+ <datatype>
+ <name name="hardening_daemon_options"/>
+ <desc>
+ <taglist>
+ <tag><c>max_sessions</c></tag>
<item>
<p>The maximum number of simultaneous sessions that are accepted at any time
for this daemon. This includes sessions that are being authorized.
@@ -785,7 +679,7 @@
</p>
</item>
- <tag><c><![CDATA[{max_channels, pos_integer()}]]></c></tag>
+ <tag><c>max_channels</c></tag>
<item>
<p>The maximum number of channels with active remote subsystem that are accepted for
each connection to this daemon</p>
@@ -793,8 +687,7 @@
</p>
</item>
-
- <tag><c><![CDATA[{parallel_login, boolean()}]]></c></tag>
+ <tag><c>parallel_login</c></tag>
<item>
<p>If set to false (the default value), only one login is handled at a time.
If set to true, an unlimited number of login attempts are allowed simultaneously.
@@ -811,171 +704,640 @@
</warning>
</item>
- <tag><c><![CDATA[{minimal_remote_max_packet_size, non_negative_integer()}]]></c></tag>
+ <tag><c>minimal_remote_max_packet_size</c></tag>
<item>
- <p>The least maximum packet size that the daemon will accept in channel open requests from the client. The default value is 0.
+ <p>The least maximum packet size that the daemon will accept in channel open requests from the client.
+ The default value is 0.
</p>
</item>
+
+ </taglist>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="callbacks_daemon_options"/>
+ <desc>
+ <taglist>
+ <tag><c>connectfun</c></tag>
+ <item>
+ <p>Provides a fun to implement your own logging when a user authenticates to the server.</p>
+ </item>
- <tag><c><![CDATA[{id_string, random | string()}]]></c></tag>
+ <tag><c>failfun</c></tag>
<item>
- <p>The string the daemon will present to a connecting peer initially. The default value is "Erlang/VSN" where VSN is the ssh application version number.
- </p>
- <p>The value <c>random</c> will cause a random string to be created at each connection attempt. This is to make it a bit more difficult for a malicious peer to find the ssh software brand and version.
- </p>
+ <p>Provides a fun to implement your own logging when a user fails to authenticate.</p>
</item>
+ </taglist>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{send_ext_info, boolean()}]]></c></tag>
- <item>
- <p>Send a list of extensions to the client if the client has asked for it. See
- <url href="https://tools.ietf.org/html/draft-ietf-curdle-ssh-ext-info">Draft-ietf-curdle-ssh-ext-info (work in progress)</url> for details.
- </p>
- <p>Currently implemented extension is sending <c>server-sig-algs</c> which is the list of the server's preferred
- user's public key algorithms.
- </p>
- <p>Default value is <c>true</c>.
- </p>
- </item>
+ <datatype>
+ <name name="send_ext_info_daemon_option"/>
+ <desc>
+ <p>Make the server (daemon) tell the client that the server accepts extension negotiation, that is,
+ include <c>ext-info-s</c> in the kexinit message sent. See
+ <url href="https://tools.ietf.org/html/rfc8308">RFC 8308</url>
+ for details and <seealso marker="SSH_app#supported-ext-info">ssh(6)</seealso>
+ for a list of currently implemented extensions.
+ </p>
+ <p>Default value is <c>true</c> which is compatible with other implementations not supporting ext-info.
+ </p>
+ </desc>
+ </datatype>
- <!--tag><c><![CDATA[{recv_ext_info, boolean()}]]></c></tag>
- <item>
- <p>Tell the client that the server accepts extension negotiation. See
- <url href="https://tools.ietf.org/html/draft-ietf-curdle-ssh-ext-info">Draft-ietf-curdle-ssh-ext-info (work in progress)</url> for details.
- </p>
- <p>Default value is <c>true</c>.
- </p>
- </item-->
- <tag><c><![CDATA[{key_cb, key_cb()}]]></c></tag>
+ <!--................................................................-->
+ <datatype_title>Options common to clients and daemons</datatype_title>
+ <datatype>
+ <name name="common_options"/>
+ <name name="common_option"/>
+ <desc><p>The options above can be used both in clients and in daemons (servers). They are further explained below.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="profile_common_option"/>
+ <desc>
+ <p>Used together with <c>ip-address</c> and <c>port</c> to
+ uniquely identify a ssh daemon. This can be useful in a
+ virtualized environment, where there can be more that one
+ server that has the same <c>ip-address</c> and
+ <c>port</c>. If this property is not explicitly set, it is
+ assumed that the the <c>ip-address</c> and <c>port</c>
+ uniquely identifies the SSH daemon.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="max_idle_time_common_option"/>
+ <desc>
+ <p>Sets a time-out on a connection when no channels are open. Defaults to <c>infinity</c>.
+ The unit is milliseconds.
+ </p>
+ <p>The timeout is not active until channels are started, so it does
+ not limit the time from the connection creation to the first channel opening.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="rekey_limit_common_option"/>
+ <name name="limit_bytes"/>
+ <name name="limit_time"/>
+ <desc>
+ <p>Sets the limit when rekeying is to be initiated. Both the max time and max amount of data
+ could be configured:
+ </p>
+ <list>
+ <item><c>{Minutes, Bytes}</c> initiate rekeying when any of the limits are reached.</item>
+ <item><c>Bytes</c> initiate rekeying when <c>Bytes</c> number of bytes are transferred,
+ or at latest after one hour.</item>
+ </list>
+ <p>When a rekeying is done, both the timer and the byte counter are restarted.
+ Defaults to one hour and one GByte.</p>
+ <p>If <c>Minutes</c> is set to <c>infinity</c>, no rekeying will ever occur due to that max time has passed.
+ Setting <c>Bytes</c> to <c>infinity</c> will inhibit rekeying after a certain amount of data has been transferred.
+ If the option value is set to <c>{infinity, infinity}</c>, no rekeying will be initiated. Note that rekeying initiated
+ by the peer will still be performed.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="key_cb_common_option"/>
+ <desc>
+ <p>Module implementing the behaviour
+ <seealso marker="ssh_client_key_api">ssh_client_key_api</seealso> and/or
+ <seealso marker="ssh_server_key_api">ssh_server_key_api</seealso>.
+ Can be used to
+ customize the handling of public keys. If callback options are provided
+ along with the module name, they are made available to the callback
+ module via the options passed to it under the key 'key_cb_private'.
+ </p>
+ <p>The <c>Opts</c> defaults to <c>[]</c> when only the <c>Module</c> is specified.
+ </p>
+ <p>The default value of this option is <c>{ssh_file, []}</c>. See also the manpage of
+ <seealso marker="ssh:ssh_file">ssh_file</seealso>.
+ </p>
+ <p>A call to the call-back function <c>F</c> will be</p>
+ <code>
+ Module:F(..., [{key_cb_private,Opts}|UserOptions])
+ </code>
+ <p>where <c>...</c> are arguments to <c>F</c> as in
+ <seealso marker="ssh_client_key_api">ssh_client_key_api</seealso> and/or
+ <seealso marker="ssh_server_key_api">ssh_server_key_api</seealso>.
+ The <c>UserOptions</c> are the options given to
+ <seealso marker="ssh:ssh#connect-3">ssh:connect</seealso>,
+ <seealso marker="ssh:ssh#shell-1">ssh:shell</seealso> or
+ <seealso marker="ssh:ssh#daemon-2">ssh:daemon</seealso>.
+ </p>
+
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="pref_public_key_algs_common_option"/>
+ <desc>
+ <p>List of user (client) public key algorithms to try to use.</p>
+ <p>The default value is the <c>public_key</c> entry in the list returned by
+ <seealso marker="#default_algorithms/0">ssh:default_algorithms/0</seealso>.
+ </p>
+ <p>If there is no public key of a specified type available, the corresponding entry is ignored.
+ Note that the available set is dependent on the underlying cryptolib and current user's public keys.
+ </p>
+ <p>See also the option <seealso marker="ssh_file#type-user_dir_common_option"><c>user_dir</c></seealso>
+ for specifying the path to the user's keys.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="disconnectfun_common_option"/>
+ <desc>
+ <p>Provides a fun to implement your own logging when the peer disconnects.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="unexpectedfun_common_option"/>
+ <desc>
+ <p>Provides a fun to implement your own logging or other action when an unexpected message arrives.
+ If the fun returns <c>report</c> the usual info report is issued but if <c>skip</c> is returned no
+ report is generated.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="ssh_msg_debug_fun_common_option"/>
+ <desc>
+ <p>Provide a fun to implement your own logging of the SSH message SSH_MSG_DEBUG.
+ The last three parameters are from the message, see
+ <url href="https://tools.ietf.org/html/rfc4253#section-11.3">RFC 4253, section 11.3</url>.
+ The <seealso marker="#type-connection_ref"><c>connection_ref()</c></seealso> is the reference
+ to the connection on which the message arrived.
+ The return value from the fun is not checked.
+ </p>
+ <p>The default behaviour is ignore the message.
+ To get a printout for each message with <c>AlwaysDisplay = true</c>,
+ use for example <c>{ssh_msg_debug_fun, fun(_,true,M,_)-> io:format("DEBUG: ~p~n", [M]) end}</c></p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="id_string_common_option"/>
+ <desc>
+ <p>The string the daemon will present to a connecting peer initially.
+ The default value is "Erlang/VSN" where VSN is the ssh application version number.
+ </p>
+ <p>The value <c>random</c> will cause a random string to be created at each connection attempt.
+ This is to make it a bit more difficult for a malicious peer to find the ssh software brand and version.
+ </p>
+ <p>The value <c>{random, Nmin, Nmax}</c> will make a random string with at least <c>Nmin</c> characters and
+ at most <c>Nmax</c> characters.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="preferred_algorithms_common_option"/>
+ <name name="algs_list"/>
+ <name name="alg_entry"/>
+ <name name="kex_alg"/>
+ <name name="pubkey_alg"/>
+ <name name="cipher_alg"/>
+ <name name="mac_alg"/>
+ <name name="compression_alg"/>
+ <name name="double_algs"/>
+
+ <desc>
+ <p>List of algorithms to use in the algorithm negotiation. The default <c>algs_list()</c> can
+ be obtained from <seealso marker="#default_algorithms/0">default_algorithms/0</seealso>.
+ </p>
+ <p>If an alg_entry() is missing in the algs_list(), the default value is used for that entry.</p>
+ <p>Here is an example of this option:</p>
+ <code>
+ {preferred_algorithms,
+ [{public_key,['ssh-rsa','ssh-dss']},
+ {cipher,[{client2server,['aes128-ctr']},
+ {server2client,['aes128-cbc','3des-cbc']}]},
+ {mac,['hmac-sha2-256','hmac-sha1']},
+ {compression,[none,zlib]}
+ ]
+ }
+ </code>
+ <p>The example specifies different algorithms in the two directions (client2server and server2client),
+ for cipher but specifies the same algorithms for mac and compression in both directions.
+ The kex (key exchange) is implicit but public_key is set explicitly.</p>
+
+ <p>For background and more examples see the <seealso marker="configure_algos#introduction">User's Guide</seealso>.</p>
+
+ <p>If an algorithm name occurs more than once in a list, the behaviour is undefined. The tags in the property lists
+ are also assumed to occur at most one time.
+ </p>
+
+ <warning>
+ <p>Changing the values can make a connection less secure. Do not change unless you
+ know exactly what you are doing. If you do not understand the values then you
+ are not supposed to change them.</p>
+ </warning>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="modify_algorithms_common_option"/>
+ <name name="modify_algs_list"/>
+ <desc>
+ <p>Modifies the list of algorithms to use in the algorithm negotiation. The modifications are
+ applied after the option <c>preferred_algorithms</c> (if existing) is applied.</p>
+ <p>The algoritm for modifications works like this:</p>
+ <list>
<item>
- <p>Module implementing the behaviour <seealso
- marker="ssh_server_key_api">ssh_server_key_api</seealso>. Can be used to
- customize the handling of public keys. If callback options are provided
- along with the module name, they are made available to the callback
- module via the options passed to it under the key 'key_cb_private'.
+ <p>Input is the <c>modify_algs_list()</c> and a set of algorithms <c>A</c>
+ obtained from the <c>preferred_algorithms</c> option if existing, or else from the
+ <seealso marker="ssh#default_algorithms-0">ssh:default_algorithms/0</seealso>.
</p>
</item>
-
- <tag><c>{profile, atom()}</c></tag>
<item>
- <p>Used together with <c>ip-address</c> and <c>port</c> to
- uniquely identify a ssh daemon. This can be useful in a
- virtualized environment, where there can be more that one
- server that has the same <c>ip-address</c> and
- <c>port</c>. If this property is not explicitly set, it is
- assumed that the the <c>ip-address</c> and <c>port</c>
- uniquely identifies the SSH daemon.
- </p>
+ <p>The head of the <c>modify_algs_list()</c> modifies <c>A</c> giving the result <c>A'</c>.</p>
+ <p>The possible modifications are:</p>
+ <list>
+ <item>
+ <p>Append or prepend supported but not enabled algorithm(s) to the list of
+ algorithms. If the wanted algorithms already are in <c>A</c> they will first
+ be removed and then appended or prepended,
+ </p>
+ </item>
+ <item>
+ <p>Remove (rm) one or more algorithms from <c>A</c>.
+ </p>
+ </item>
+ </list>
</item>
-
- <tag><c><![CDATA[{fd, file_descriptor()}]]></c></tag>
- <item>
- <p>Allows an existing file-descriptor to be used
- (passed on to the transport protocol).</p></item>
- <tag><c><![CDATA[{failfun, fun(User::string(),
- PeerAddress::ip_address(), Reason::term()) -> _}]]></c></tag>
<item>
- <p>Provides a fun to implement your own logging when a user fails to authenticate.</p>
+ <p>Repeat the modification step with the tail of <c>modify_algs_list()</c> and the resulting
+ <c>A'</c>.
+ </p>
</item>
- <tag><c><![CDATA[{connectfun, fun(User::string(), PeerAddress::ip_address(),
- Method::string()) ->_}]]></c></tag>
- <item>
- <p>Provides a fun to implement your own logging when a user authenticates to the server.</p>
+ </list>
+ <p>If an unsupported algorithm is in the <c>modify_algs_list()</c>, it will be silently ignored</p>
+ <p>If there are more than one modify_algorithms options, the result is undefined.</p>
+ <p>Here is an example of this option:</p>
+ <code>
+ {modify_algorithms,
+ [{prepend, [{kex, ['diffie-hellman-group1-sha1']}],
+ {rm, [{compression, [none]}]}
+ ]
+ }
+ </code>
+ <p>The example specifies that:</p>
+ <list>
+ <item><p>the old key exchange algorithm 'diffie-hellman-group1-sha1' should be
+ the main alternative. It will be the main alternative since it is prepened to the list</p>
</item>
- <tag><c><![CDATA[{disconnectfun, fun(Reason:term()) -> _}]]></c></tag>
- <item>
- <p>Provides a fun to implement your own logging when a user disconnects from the server.</p>
+ <item><p>The compression algorithm none (= no compression) is removed so compression is enforced</p>
</item>
+ </list>
+ <p>For background and more examples see the <seealso marker="configure_algos#introduction">User's Guide</seealso>.</p>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{unexpectedfun, fun(Message:term(), Peer) -> report | skip }]]></c></tag>
- <item>
- <p>Provides a fun to implement your own logging or other action when an unexpected message arrives.
- If the fun returns <c>report</c> the usual info report is issued but if <c>skip</c> is returned no
- report is generated.</p>
- <p><c>Peer</c> is in the format of <c>{Host,Port}</c>.</p>
- </item>
- <tag><c><![CDATA[{idle_time, integer()}]]></c></tag>
- <item>
- <p>Sets a time-out on a connection when no channels are active.
- Defaults to <c>infinity</c>.</p>
- </item>
+ <datatype>
+ <name name="inet_common_option"/>
+ <desc>
+ <p>IP version to use when the host address is specified as <c>any</c>.</p>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{ssh_msg_debug_fun, fun(ConnectionRef::ssh_connection_ref(), AlwaysDisplay::boolean(), Msg::binary(), LanguageTag::binary()) -> _}]]></c></tag>
- <item>
- <p>Provide a fun to implement your own logging of the SSH message SSH_MSG_DEBUG. The last three parameters are from the message, see RFC4253, section 11.3. The <c>ConnectionRef</c> is the reference to the connection on which the message arrived. The return value from the fun is not checked.</p>
- <p>The default behaviour is ignore the message.
- To get a printout for each message with <c>AlwaysDisplay = true</c>, use for example <c>{ssh_msg_debug_fun, fun(_,true,M,_)-> io:format("DEBUG: ~p~n", [M]) end}</c></p>
- </item>
+ <datatype>
+ <name name="auth_methods_common_option"/>
+ <desc>
+ <p>Comma-separated string that determines which authentication methods that the client shall
+ support and in which order they are tried. Defaults to <c>"publickey,keyboard-interactive,password"</c>
+ </p>
+ <p>Note that the client is free to use any order and to exclude methods.
+ </p>
+ </desc>
+ </datatype>
- </taglist>
- </desc>
- </func>
+ <datatype>
+ <name name="fd_common_option"/>
+ <desc>
+ <p>Allows an existing file-descriptor to be used (passed on to the transport protocol).</p>
+ </desc>
+ </datatype>
- <func>
- <name>daemon_info(Daemon) -> {ok, [DaemonInfo]} | {error,Error}</name>
- <fsummary>Get info about a daemon</fsummary>
- <type>
- <v>DaemonInfo = {port,Port::pos_integer()} | {listen_address, any|ip_address()} | {profile,atom()}</v>
- <v>Port = integer()</v>
- <v>Error = bad_daemon_ref</v>
- </type>
+ <!--................................................................-->
+ <datatype_title>Other data types</datatype_title>
+
+ <datatype>
+ <name name="host"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="ip_port"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="mod_args"/>
<desc>
- <p>Returns a key-value list with information about the daemon. For now, only the listening port is returned. This is intended for the case the daemon is started with the port set to 0.</p>
</desc>
+ </datatype>
+
+ <datatype>
+ <name name="mod_fun_args"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="open_socket"/>
+ <desc>
+ <p>The socket is supposed to be result of a <seealso marker="kernel:gen_tcp#connect-3">gen_tcp:connect</seealso>
+ or a <seealso marker="kernel:gen_tcp#accept-1">gen_tcp:accept</seealso>. The socket must be in passive
+ mode (that is, opened with the option <c>{active,false})</c>.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="daemon_ref"/>
+ <desc>
+ <p>Opaque data type representing a daemon.</p>
+ <p>Returned by the functions <seealso marker="ssh#daemon-1"><c>daemon/1,2,3</c></seealso>.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name>connection_ref()</name>
+ <desc>
+ <p>Opaque data type representing a connection between a client and a server (daemon).</p>
+ <p>Returned by the functions
+ <seealso marker="ssh#connect-3"><c>connect/2,3,4</c></seealso> and
+ <seealso marker="ssh_sftp#start_channel-2"><c>ssh_sftp:start_channel/2,3</c></seealso>.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="channel_id"/>
+ <desc>
+ <p>Opaque data type representing a channel inside a connection.</p>
+ <p>Returned by the functions
+ <seealso marker="ssh_connection#session_channel/2">ssh_connection:session_channel/2,4</seealso>.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="connection_info_tuple"/>
+ <name name="version"/>
+ <name name="protocol_version"/>
+ <name name="software_version"/>
+ <name name="conn_info_algs"/>
+ <name name="conn_info_channels"/>
+ <desc>
+ <p>Return values from the
+ <seealso marker="#connection_info/1">connection_info/1</seealso> and
+ <seealso marker="#connection_info/2">connection_info/2</seealso> functions.
+ </p>
+ <p>In the <c>option</c> info tuple are only the options included that differs from the default values.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="daemon_info_tuple"/>
+ <desc>
+ <p>Return values from the
+ <seealso marker="#daemon_info/1">daemon_info/1</seealso> and
+ <seealso marker="#daemon_info/2">daemon_info/2</seealso> functions.
+ </p>
+ <p>In the <c>option</c> info tuple are only the options included that differs from the default values.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name>opaque_client_options</name>
+ <name>opaque_daemon_options</name>
+ <name>opaque_common_options</name>
+ <desc>
+ <marker id="type-opaque_client_options"/>
+ <marker id="type-opaque_daemon_options"/>
+ <marker id="type-opaque_common_options"/>
+ <p>Opaque types that define experimental options that are not to be used in products.</p>
+ </desc>
+ </datatype>
+ </datatypes>
+
+<!--
+ ================================================================
+ = Function definitions =
+ ================================================================
+-->
+
+ <funcs>
+
+<!-- CLOSE/1 -->
+ <func>
+ <name name="close" arity="1" since=""/>
+ <fsummary>Closes an SSH connection.</fsummary>
+ <desc><p>Closes an SSH connection.</p></desc>
</func>
+
+<!-- CONNECT/2 etc -->
+ <func>
+ <name since="">connect(Host, Port, Options) -> Result </name>
+ <name since="">connect(Host, Port, Options, NegotiationTimeout) -> Result </name>
+ <name since="OTP 19.0">connect(TcpSocket, Options) -> Result</name>
+ <name since="">connect(TcpSocket, Options, NegotiationTimeout) -> Result</name>
+ <fsummary>Connects to an SSH server.</fsummary>
+ <type>
+ <v>Host = <seealso marker="#type-host">host()</seealso></v>
+ <v>Port = <seealso marker="kernel:inet#type-port_number">inet:port_number()</seealso></v>
+ <v>Options = <seealso marker="#type-client_options">client_options()</seealso></v>
+ <v>TcpSocket = <seealso marker="#type-open_socket">open_socket()</seealso></v>
+ <v>NegotiationTimeout = timeout()</v>
+ <v>Result = {ok, <seealso marker="#type-connection_ref">connection_ref()</seealso>} | {error, term()}</v>
+ </type>
+ <desc>
+ <p>Connects to an SSH server at the <c>Host</c> on <c>Port</c>.
+ </p>
+ <p>As an alternative, an already open TCP socket could be passed to the function in <c>TcpSocket</c>.
+ The SSH initiation and negotiation will be initiated on that one with the SSH that should be at the
+ other end.
+ </p>
+ <p>No channel is started. This is done by calling <seealso marker="ssh_connection#session_channel/2">
+ ssh_connection:session_channel/[2, 4]</seealso>.
+ </p>
+ <p>The <c>NegotiationTimeout</c> is in milli-seconds. The default value is <c>infinity</c>.
+ For connection timeout, use the option
+ <seealso marker="#type-connect_timeout_client_option"><c>connect_timeout</c></seealso>.
+ </p>
+ </desc>
+ </func>
+
+<!-- CONNECTION_INFO/1, CONNECTION_INFO/2 -->
+ <func>
+ <name name="connection_info" arity="1" since=""/>
+ <name name="connection_info" arity="2" since=""/>
+ <fsummary>Retrieves information about a connection.</fsummary>
+ <desc>
+ <p>Returns information about a connection intended for e.g debugging or logging.
+ </p>
+ <p>When the <c>Key</c> is a single <c>Item</c>, the result is a single <c>InfoTuple</c>
+ </p>
+ </desc>
+ </func>
+
+<!-- SET_SOCK_OPTS/2 -->
+ <func>
+ <name name="set_sock_opts" arity="2" since=""/>
+ <fsummary>Set tcp socket options on connections</fsummary>
+ <desc>
+ <p>Sets tcp socket options on the tcp-socket below an ssh connection.</p>
+ <p>This function calls the
+ <seealso marker="kernel:inet#setopts/2">inet:setopts/2</seealso>, read that documentation and
+ for <seealso marker="kernel:gen_tcp#type-option">gen_tcp:option()</seealso>.
+ All gen_tcp socket options except <c>active</c>, <c>deliver</c>, <c>mode</c> and <c>packet</c>
+ are allowed. The excluded options are reserved by the SSH application.
+ </p>
+ <warning>
+ <p>This is an extremly dangerous function. You use it on your own risk.</p>
+ <p>Some options are OS and OS version dependent.
+ Do not use it unless you know what effect your option values will have
+ on an TCP stream.</p>
+ <p>Some values may destroy the functionality of the SSH protocol.
+ </p>
+ </warning>
+ </desc>
+ </func>
+
+<!-- GET_SOCK_OPTS/2 -->
+ <func>
+ <name name="get_sock_opts" arity="2" since=""/>
+ <fsummary>Get tcp socket options on connections</fsummary>
+ <desc>
+ <p>Get tcp socket option values of the tcp-socket below an ssh connection.</p>
+ <p>This function calls the
+ <seealso marker="kernel:inet#getopts/2">inet:getopts/2</seealso>, read that documentation.
+ </p>
+ </desc>
+ </func>
+
+<!-- DEAMON/1,2,3 -->
+ <func>
+ <name since="">daemon(Port | TcpSocket) -> Result</name>
+ <name since="">daemon(Port | TcpSocket, Options) -> Result</name>
+ <name since="">daemon(HostAddress, Port, Options) -> Result</name>
+ <fsummary>Starts a server listening for SSH connections.</fsummary>
+ <type>
+ <v>Port = integer()</v>
+ <v>TcpSocket = <seealso marker="#type-open_socket">open_socket()</seealso></v>
+ <v>Options = <seealso marker="#type-daemon_options">daemon_options()</seealso></v>
+ <v>HostAddress = <seealso marker="#type-host">host()</seealso> | any</v>
+ <v>Result = {ok, <seealso marker="#type-daemon_ref">daemon_ref()</seealso>} | {error, atom()}</v>
+ </type>
+ <desc>
+ <p>Starts a server listening for SSH connections on the given port. If the <c>Port</c> is 0,
+ a random free port is selected. See <seealso marker="#daemon_info/1">daemon_info/1</seealso>
+ about how to find the selected port number.
+ </p>
+ <p>As an alternative, an already open TCP socket could be passed to the function in <c>TcpSocket</c>.
+ The SSH initiation and negotiation will be initiated on that one when an SSH starts at the other end
+ of the TCP socket.
+ </p>
+ <p>For a description of the options, see <seealso marker="#type-daemon_options">Daemon Options</seealso>.
+ </p>
+ <p>Please note that by historical reasons both the <c>HostAddress</c> argument and the
+ <seealso marker="kernel:gen_tcp#type-connect_option">gen_tcp connect_option() <c>{ip,Address}</c></seealso>
+ set the listening address. This is a source of possible inconsistent settings.
+ </p>
+ <p>The rules for handling the two address passing options are:</p>
+ <list>
+ <item>if <c>HostAddress</c> is an IP-address, that IP-address is the listening address.
+ An 'ip'-option will be discarded if present.</item>
+ <item>if <c>HostAddress</c> is the atom <c>loopback</c>, the listening address
+ is <c>loopback</c> and an loopback address will be choosen by the underlying layers.
+ An 'ip'-option will be discarded if present.</item>
+
+ <item>if <c>HostAddress</c> is the atom <c>any</c> and no 'ip'-option is present, the listening address is
+ <c>any</c> and the socket will listen to all addresses</item>
+
+ <item>if <c>HostAddress</c> is <c>any</c> and an 'ip'-option is present, the listening address is
+ set to the value of the 'ip'-option</item>
+ </list>
+ </desc>
+ </func>
+
+<!-- DAEMON_INFO/1 -->
+ <func>
+ <name name="daemon_info" arity="1" since="OTP 19.0"/>
+ <name name="daemon_info" arity="2" since=""/>
+ <fsummary>Get info about a daemon</fsummary>
+ <desc>
+ <p>Returns information about a daemon intended for e.g debugging or logging.
+ </p>
+ <p>When the <c>Key</c> is a single <c>Item</c>, the result is a single <c>InfoTuple</c>
+ </p>
+ <p>Note that <c>daemon_info/1</c> and <c>daemon_info/2</c> returns different types
+ due to compatibility reasons.
+ </p>
+ </desc>
+ </func>
+
+
+<!-- DEFAULT_ALGORITHMS/0 -->
<func>
- <name>default_algorithms() -> algs_list()</name>
+ <name name="default_algorithms" arity="0" since="OTP 18.0"/>
<fsummary>Get a list declaring the supported algorithms</fsummary>
<desc>
<p>Returns a key-value list, where the keys are the different types of algorithms and the values are the
- algorithms themselves. An example:</p>
- <code>
-20> ssh:default_algorithms().
-[{kex,['diffie-hellman-group1-sha1']},
- {public_key,['ssh-rsa','ssh-dss']},
- {cipher,[{client2server,['aes128-ctr','aes128-cbc','3des-cbc']},
- {server2client,['aes128-ctr','aes128-cbc','3des-cbc']}]},
- {mac,[{client2server,['hmac-sha2-256','hmac-sha1']},
- {server2client,['hmac-sha2-256','hmac-sha1']}]},
- {compression,[{client2server,[none,zlib]},
- {server2client,[none,zlib]}]}]
-21>
-</code>
+ algorithms themselves.</p>
+ <p>See the <seealso marker="configure_algos#example_default_algorithms">User's Guide</seealso> for
+ an example.</p>
</desc>
</func>
+<!-- SHELL/1,2,3 -->
<func>
- <name>shell(Host) -> </name>
- <name>shell(Host, Option) -> </name>
- <name>shell(Host, Port, Option) -> </name>
- <name>shell(TcpSocket) -> _</name>
- <fsummary>Starts an interactive shell over an SSH server.</fsummary>
+ <name since="">shell(Host | TcpSocket) -> Result </name>
+ <name since="">shell(Host | TcpSocket, Options) -> Result </name>
+ <name since="">shell(Host, Port, Options) -> Result </name>
+ <fsummary>Starts an interactive shell on a remote SSH server.</fsummary>
<type>
- <v>Host = string()</v>
- <v>Port = integer()</v>
- <v>Options - see ssh:connect/3</v>
- <v>TcpSocket = port()</v>
- <d>The socket is supposed to be from <seealso marker="kernel:gen_tcp#connect-3">gen_tcp:connect</seealso> or <seealso marker="kernel:gen_tcp#accept-1">gen_tcp:accept</seealso> with option <c>{active,false}</c></d>
+ <v>Host = <seealso marker="#type-host">host()</seealso></v>
+ <v>TcpSocket = <seealso marker="#type-open_socket">open_socket()</seealso></v>
+ <v>Port = <seealso marker="kernel:inet#type-port_number">inet:port_number()</seealso></v>
+ <v>Options = <seealso marker="#type-client_options">client_options()</seealso></v>
+ <v>Result = ok | {error, Reason::term()}</v>
</type>
<desc>
- <p>Starts an interactive shell over an SSH server on the
- given <c>Host</c>. The function waits for user input,
- and does not return until the remote shell is ended (that is,
+ <p>Connects to an SSH server at <c>Host</c> and <c>Port</c> (defaults to 22) and starts an
+ interactive shell on that remote host.
+ </p>
+ <p>As an alternative, an already open TCP socket could be passed to the function in <c>TcpSocket</c>.
+ The SSH initiation and negotiation will be initiated on that one and finaly a shell will be started
+ on the host at the other end of the TCP socket.
+ </p>
+ <p>For a description of the options, see <seealso marker="#type-client_options">Client Options</seealso>.</p>
+ <p>The function waits for user input, and does not return until the remote shell is ended (that is,
exit from the shell).
</p>
</desc>
</func>
<func>
- <name>start() -> </name>
- <name>start(Type) -> ok | {error, Reason}</name>
+ <name name="start" arity="0" since=""/>
+ <name name="start" arity="1" since=""/>
<fsummary>Starts the SSH application.</fsummary>
- <type>
- <v>Type = permanent | transient | temporary</v>
- <v>Reason = term() </v>
- </type>
<desc>
<p>Utility function that starts the applications <c>crypto</c>, <c>public_key</c>,
and <c>ssh</c>. Default type is <c>temporary</c>.
@@ -985,11 +1347,8 @@
</func>
<func>
- <name>stop() -> ok | {error, Reason}</name>
+ <name name="stop" arity="0" since=""/>
<fsummary>Stops the <c>ssh</c> application.</fsummary>
- <type>
- <v>Reason = term()</v>
- </type>
<desc>
<p>Stops the <c>ssh</c> application.
For more information, see the <seealso marker="kernel:application">application(3)</seealso>
@@ -998,34 +1357,22 @@
</func>
<func>
- <name>stop_daemon(DaemonRef) -> </name>
- <name>stop_daemon(Address, Port) -> ok </name>
- <fsummary>Stops the listener and all connections started by
- the listener.</fsummary>
- <type>
- <v>DaemonRef = ssh_daemon_ref()</v>
- <v>Address = ip_address()</v>
- <v>Port = integer()</v>
- </type>
+ <name name="stop_daemon" arity="1" since=""/>
+ <name name="stop_daemon" arity="2" since=""/>
+ <name name="stop_daemon" arity="3" since="OTP 21.0"/>
+ <fsummary>Stops the listener and all connections started by the listener.</fsummary>
<desc>
- <p>Stops the listener and all connections started by
- the listener.</p>
+ <p>Stops the listener and all connections started by the listener.</p>
</desc>
</func>
<func>
- <name>stop_listener(DaemonRef) -> </name>
- <name>stop_listener(Address, Port) -> ok </name>
- <fsummary>Stops the listener, but leaves existing connections started
- by the listener operational.</fsummary>
- <type>
- <v>DaemonRef = ssh_daemon_ref()</v>
- <v>Address = ip_address()</v>
- <v>Port = integer()</v>
- </type>
+ <name name="stop_listener" arity="1" since=""/>
+ <name name="stop_listener" arity="2" since=""/>
+ <name name="stop_listener" arity="3" since="OTP 21.0"/>
+ <fsummary>Stops the listener, but leaves existing connections started by the listener operational.</fsummary>
<desc>
- <p>Stops the listener, but leaves existing connections started
- by the listener operational.</p>
+ <p>Stops the listener, but leaves existing connections started by the listener operational.</p>
</desc>
</func>
diff --git a/lib/ssh/doc/src/ssh_app.xml b/lib/ssh/doc/src/ssh_app.xml
index 1cbbdfcf38..0ff03cca3d 100644
--- a/lib/ssh/doc/src/ssh_app.xml
+++ b/lib/ssh/doc/src/ssh_app.xml
@@ -4,7 +4,7 @@
<appref>
<header>
<copyright>
- <year>2012</year><year>2017</year>
+ <year>2012</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -74,13 +74,18 @@
<c>id_ecdsa_key</c>,
<c>known_hosts</c>, and <c>authorized_keys</c> in ~/.ssh,
and for the host key files in <c>/etc/ssh</c>. These locations can be changed
- by the options <c>user_dir</c> and <c>system_dir</c>.
+ by the options
+ <seealso marker="ssh_file#type-user_dir_common_option"><c>user_dir</c></seealso> and
+ <seealso marker="ssh_file#type-system_dir_daemon_option"><c>system_dir</c></seealso>.
</p>
<p>Public key handling can also be customized through a callback module that
implements the behaviors
<seealso marker="ssh_client_key_api">ssh_client_key_api</seealso> and
<seealso marker="ssh_server_key_api">ssh_server_key_api</seealso>.
</p>
+ <p>See also the default callback module documentation in
+ <seealso marker="ssh_file">ssh_file</seealso>.
+ </p>
</section>
<section>
@@ -130,39 +135,52 @@
For the list on a particular installation, use the command
<seealso marker="ssh:ssh#default_algorithms/0">ssh:default_algorithms/0</seealso>.
The user may override the default algorithm configuration both on the server side and the client side.
- See the option <c>preferred_algorithms</c> in the <seealso marker="ssh:ssh#daemon/1">ssh:daemon/1,2,3</seealso> and
+ See the options
+ <seealso marker="ssh:ssh#type-preferred_algorithms_common_option">preferred_algorithms</seealso>
+ and
+ <seealso marker="ssh:ssh#type-modify_algorithms_common_option">modify_algorithms</seealso>
+ in the <seealso marker="ssh:ssh#daemon/1">ssh:daemon/1,2,3</seealso> and
<seealso marker="ssh:ssh#connect/3">ssh:connect/3,4</seealso> functions.
</p>
- <p>Supported algorithms are:</p>
+ <p>Supported algorithms are (in the default order):</p>
<marker id="supported_algos"></marker>
<taglist>
<tag>Key exchange algorithms</tag>
<item>
<list type="bulleted">
- <item>ecdh-sha2-nistp256</item>
<item>ecdh-sha2-nistp384</item>
<item>ecdh-sha2-nistp521</item>
- <item>diffie-hellman-group-exchange-sha1</item>
+ <item>ecdh-sha2-nistp256</item>
<item>diffie-hellman-group-exchange-sha256</item>
- <item>diffie-hellman-group14-sha1</item>
- <item>diffie-hellman-group14-sha256</item>
<item>diffie-hellman-group16-sha512</item>
<item>diffie-hellman-group18-sha512</item>
- <item>(diffie-hellman-group1-sha1, retired: can be enabled with the <c>preferred_algorithms</c> option)</item>
+ <item>diffie-hellman-group14-sha256</item>
+ <item>curve25519-sha256</item>
+ <item>curve25519-sha256@libssh.org</item>
+ <item>curve448-sha512</item>
+ <item>diffie-hellman-group14-sha1</item>
+ <item>diffie-hellman-group-exchange-sha1</item>
+ <item>(diffie-hellman-group1-sha1, retired: It can be enabled with the
+ <seealso marker="ssh:ssh#type-preferred_algorithms_common_option">preferred_algorithms</seealso>
+ or
+ <seealso marker="ssh:ssh#type-modify_algorithms_common_option">modify_algorithms</seealso>
+ options. Use for example the Option value <c>{modify_algorithms, [{append, [{kex,['diffie-hellman-group1-sha1']}]}]}</c>)</item>
</list>
</item>
<tag>Public key algorithms</tag>
<item>
<list type="bulleted">
- <item>ecdsa-sha2-nistp256</item>
<item>ecdsa-sha2-nistp384</item>
<item>ecdsa-sha2-nistp521</item>
+ <item>ecdsa-sha2-nistp256</item>
+ <item>ssh-ed25519</item>
+ <item>ssh-ed448</item>
<item>ssh-rsa</item>
- <item>ssh-dss</item>
<item>rsa-sha2-256</item>
<item>rsa-sha2-512</item>
+ <item>ssh-dss</item>
</list>
</item>
@@ -172,17 +190,25 @@
<item>hmac-sha2-256</item>
<item>hmac-sha2-512</item>
<item>hmac-sha1</item>
+ <item>(hmac-sha1-96 It can be enabled with the
+ <seealso marker="ssh:ssh#type-preferred_algorithms_common_option">preferred_algorithms</seealso>
+ or
+ <seealso marker="ssh:ssh#type-modify_algorithms_common_option">modify_algorithms</seealso>
+ options. Use for example the Option value <c>{modify_algorithms, [{append, [{mac,['hmac-sha1-96']}]}]}</c>)</item>
</list>
</item>
<tag>Encryption algorithms (ciphers)</tag>
<item>
<list type="bulleted">
- <item>aes128-gcm@openssh.com</item>
+ <item>chacha20-poly1305@openssh.com</item>
<item>aes256-gcm@openssh.com</item>
- <item>aes128-ctr</item>
- <item>aes192-ctr</item>
<item>aes256-ctr</item>
+ <item>aes192-ctr</item>
+ <item>aes128-gcm@openssh.com</item>
+ <item>aes128-ctr</item>
+ <item>aes256-cbc</item>
+ <item>aes192-cbc</item>
<item>aes128-cbc</item>
<item>3des-cbc</item>
<item>(AEAD_AES_128_GCM, not enabled per default)</item>
@@ -241,7 +267,11 @@
<item><url href="https://tools.ietf.org/html/rfc4253">RFC 4253</url>, The Secure Shell (SSH) Transport Layer Protocol.
<p>Except</p>
<list type="bulleted">
- <item>8.1. diffie-hellman-group1-sha1. Disabled by default, can be enabled with the <c>preferred_algorithms</c> option.</item>
+ <item>8.1. diffie-hellman-group1-sha1. Disabled by default, can be enabled with the
+ <seealso marker="ssh:ssh#type-preferred_algorithms_common_option">preferred_algorithms</seealso>
+ or
+ <seealso marker="ssh:ssh#type-modify_algorithms_common_option">modify_algorithms</seealso>
+ options.</item>
</list>
<p/>
</item>
@@ -280,7 +310,10 @@
<p><marker id="rfc5647_note"/>There is an ambiguity in the synchronized selection of cipher and mac algorithm.
This is resolved by OpenSSH in the ciphers aes128-gcm@openssh.com and aes256-gcm@openssh.com which are implemented.
If the explicit ciphers and macs AEAD_AES_128_GCM or AEAD_AES_256_GCM are needed,
- they could be enabled with the option preferred_algorithms.
+ they could be enabled with the options
+ <seealso marker="ssh:ssh#type-preferred_algorithms_common_option">preferred_algorithms</seealso>
+ or
+ <seealso marker="ssh:ssh#type-modify_algorithms_common_option">modify_algorithms</seealso>.
</p>
<warning>
<p>
@@ -322,18 +355,27 @@
<p>Deviations:</p>
<list type="bulleted">
<item>The <c>diffie-hellman-group1-sha1</c> is not enabled by default, but is still supported and can be enabled
- with the option <c>preferred-algorithms</c></item>
+ with the options
+ <seealso marker="ssh:ssh#type-preferred_algorithms_common_option">preferred_algorithms</seealso>
+ or
+ <seealso marker="ssh:ssh#type-modify_algorithms_common_option">modify_algorithms</seealso>.
+ </item>
<item>The questionable sha1-based algorithms <c>diffie-hellman-group-exchange-sha1</c> and
<c>diffie-hellman-group14-sha1</c> are still enabled by default for compatibility with ancient clients and servers.
- They can be disabled with the option <c>preferred-algorithms</c></item>
+ They can be disabled with the options
+ <seealso marker="ssh:ssh#type-preferred_algorithms_common_option">preferred_algorithms</seealso>
+ or
+ <seealso marker="ssh:ssh#type-modify_algorithms_common_option">modify_algorithms</seealso>.
+ They will be disabled by default when the draft is turned into an RFC.</item>
</list>
<p/>
</item>
- <item><url href="https://tools.ietf.org/html/draft-ietf-curdle-rsa-sha2">Draft-ietf-curdle-rsa-sha2 (work in progress)</url>, Use of RSA Keys with SHA-2 256 and 512 in Secure Shell (SSH).
+ <item><url href="https://tools.ietf.org/html/rfc8332">RFC 8332</url>, Use of RSA Keys with SHA-256 and SHA-512 in the Secure Shell (SSH) Protocol.
</item>
- <item><url href="https://tools.ietf.org/html/draft-ietf-curdle-ssh-ext-info">Draft-ietf-curdle-ssh-ext-info (work in progress)</url>, Extension Negotiation in Secure Shell (SSH).
+ <item><marker id="supported-ext-info"/>
+ <url href="https://tools.ietf.org/html/rfc8308">RFC 8308</url>, Extension Negotiation in the Secure Shell (SSH) Protocol.
<p>Implemented are:</p>
<list type="bulleted">
<item>The Extension Negotiation Mechanism</item>
@@ -341,7 +383,15 @@
</list>
<p/>
</item>
-
+
+ <item>
+ <url href="https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves">Secure Shell (SSH) Key Exchange Method using Curve25519 and Curve448 (work in progress)</url>
+ </item>
+
+ <item>
+ <url href="https://tools.ietf.org/html/draft-ietf-curdle-ssh-ed25519-ed448">Ed25519 and Ed448 public key algorithms for the Secure Shell (SSH) protocol (work in progress)</url>
+ </item>
+
</list>
</section>
diff --git a/lib/ssh/doc/src/ssh_channel.xml b/lib/ssh/doc/src/ssh_client_channel.xml
index 7b598494f7..e6683dbd0b 100644
--- a/lib/ssh/doc/src/ssh_channel.xml
+++ b/lib/ssh/doc/src/ssh_client_channel.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2009</year>
- <year>2016</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -23,21 +23,27 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>ssh_channel</title>
+ <title>ssh_client_channel</title>
<prepared></prepared>
<docno></docno>
<date></date>
<rev></rev>
</header>
- <module>ssh_channel</module>
- <modulesummary>-behaviour(ssh_channel).
+ <module since="OTP 21.0">ssh_client_channel</module>
+ <modulesummary>-behaviour(ssh_client_channel). (Replaces ssh_channel)
</modulesummary>
<description>
+ <note>
+ <p>This module replaces ssh_channel.</p>
+ <p>The old module is still available for compatibility, but should not be used for new programs.
+ The old module will not be maintained except for some error corrections
+ </p>
+ </note>
<p>SSH services (clients and servers) are implemented as channels
that are multiplexed over an SSH connection and communicates over
the <url href="http://www.ietf.org/rfc/rfc4254.txt"> SSH
Connection Protocol</url>. This module provides a callback API
- that takes care of generic channel aspects, such as flow control
+ that takes care of generic channel aspects for clients, such as flow control
and close messages. It 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
@@ -46,50 +52,28 @@
the <c>ssh</c> applications supervisor tree.
</p>
- <note><p>When implementing an <c>ssh</c> subsystem, use
- <c>-behaviour(ssh_daemon_channel)</c> instead of <c>-behaviour(ssh_channel)</c>.
- The reason is that the only relevant callback functions for subsystems are
- <c>init/1</c>, <c>handle_ssh_msg/2</c>, <c>handle_msg/2</c>, and <c>terminate/2</c>.
- So, the <c>ssh_daemon_channel</c> behaviour is a limited version of the
- <c>ssh_channel</c> behaviour.
- </p></note>
- </description>
+ <note><p>When implementing a <c>ssh</c> subsystem for daemons, use
+ <seealso marker="ssh_server_channel">-behaviour(ssh_server_channel)</seealso> (Replaces ssh_daemon_channel)
+ instead.
+ </p>
+ </note>
- <section>
- <title>DATA TYPES</title>
+ <dont>
+ <p>Functions in this module are not supposed to be called outside a module implementing this
+ behaviour!
+ </p>
+ </dont>
- <p>Type definitions that are used more than once in this module,
- or abstractions to indicate the intended use of the data
- type, or both:</p>
-
- <taglist>
- <tag><c>boolean() =</c></tag>
- <item><p><c>true | false</c></p></item>
- <tag><c>string() =</c></tag>
- <item><p>list of ASCII characters</p></item>
- <tag><c>timeout() =</c></tag>
- <item><p><c>infinity | integer()</c> in milliseconds</p></item>
- <tag><c>ssh_connection_ref() =</c></tag>
- <item><p>opaque() -as returned by
- <c>ssh:connect/3</c> or sent to an SSH channel process</p></item>
- <tag><c>ssh_channel_id() =</c></tag>
- <item><p><c>integer()</c></p></item>
- <tag><c>ssh_data_type_code() =</c></tag>
- <item><p><c>1</c> ("stderr") | <c>0</c> ("normal") are
- the valid values,
- see <url href="http://www.ietf.org/rfc/rfc4254.txt">RFC 4254</url>
- Section 5.2</p></item>
- </taglist>
- </section>
+ </description>
<funcs>
<func>
- <name>call(ChannelRef, Msg) -></name>
- <name>call(ChannelRef, Msg, Timeout) -> Reply | {error, Reason}</name>
+ <name since="OTP 21.0">call(ChannelRef, Msg) -></name>
+ <name since="OTP 21.0">call(ChannelRef, Msg, Timeout) -> Reply | {error, Reason}</name>
<fsummary>Makes a synchronous call to a channel.</fsummary>
<type>
<v>ChannelRef = pid() </v>
- <d>As returned by <seealso marker = "#start_link-4">ssh_channel:start_link/4</seealso></d>
+ <d>As returned by <seealso marker = "#start_link-4">start_link/4</seealso></d>
<v>Msg = term()</v>
<v>Timeout = timeout()</v>
<v>Reply = term()</v>
@@ -108,12 +92,12 @@
</func>
<func>
- <name>cast(ChannelRef, Msg) -> ok </name>
+ <name since="OTP 21.0">cast(ChannelRef, Msg) -> ok </name>
<fsummary>Sends an asynchronous message to the channel
ChannelRef and returns ok.</fsummary>
<type>
<v>ChannelRef = pid()</v>
- <d>As returned by <seealso marker = "#start_link-4">ssh_channel:start_link/4</seealso></d>
+ <d>As returned by <seealso marker = "#start_link-4">start_link/4</seealso></d>
<v>Msg = term()</v>
</type>
<desc>
@@ -126,29 +110,29 @@
</desc>
</func>
- <func>
- <name>enter_loop(State) -> _ </name>
- <fsummary>Makes an existing process an ssh_channel process.</fsummary>
+ <func>
+ <name since="OTP 21.0">enter_loop(State) -> _ </name>
+ <fsummary>Makes an existing process an ssh_client_channel (replaces ssh_channel) process.</fsummary>
<type>
<v>State = term()</v>
- <d>as returned by <seealso marker = "#init-1">ssh_channel:init/1</seealso></d>
+ <d>as returned by <seealso marker = "#init-1">init/1</seealso></d>
</type>
<desc>
- <p>Makes an existing process an <c>ssh_channel</c>
+ <p>Makes an existing process an <c>ssh_client_channel</c> (replaces ssh_channel)
process. Does not return, instead the calling process
- enters the <c>ssh_channel</c> process receive loop and become an
- <c>ssh_channel process</c>. The process must have been started using
+ enters the <c>ssh_client_channel</c> (replaces ssh_channel) process receive loop and become an
+ <c>ssh_client_channel</c> process. The process must have been started using
one of the start functions in <c>proc_lib</c>, see the <seealso
marker="stdlib:proc_lib">proc_lib(3)</seealso> manual page in STDLIB.
The user is responsible for any initialization of the process
- and must call <seealso marker = "#init-1">ssh_channel:init/1</seealso>.
+ and must call <seealso marker = "#init-1">init/1</seealso>.
</p>
</desc>
</func>
<func>
- <name>init(Options) -> {ok, State} | {ok, State, Timeout} | {stop, Reason} </name>
- <fsummary>Initiates an <c>ssh_channel</c> process.</fsummary>
+ <name since="OTP 21.0">init(Options) -> {ok, State} | {ok, State, Timeout} | {stop, Reason} </name>
+ <fsummary>Initiates an <c>ssh_client_channel</c> process.</fsummary>
<type>
<v>Options = [{Option, Value}]</v>
<v>State = term()</v>
@@ -160,18 +144,21 @@
The following options must be present:
</p>
<taglist>
- <tag><c><![CDATA[{channel_cb, atom()}]]></c></tag>
+ <tag><c>{channel_cb, atom()}</c></tag>
<item><p>The module that implements the channel behaviour.</p></item>
- <tag><c><![CDATA[{init_args(), list()}]]></c></tag>
+ <tag><c>{init_args(), list()}</c></tag>
<item><p>The list of arguments to the <c>init</c> function of the callback module.</p></item>
- <tag><c><![CDATA[{cm, connection_ref()}]]></c></tag>
- <item><p>Reference to the <c>ssh</c> connection as returned by <seealso
- marker="ssh#connect-3">ssh:connect/3</seealso></p></item>
+ <tag><c>{cm, </c><seealso marker="ssh:ssh#type-connection_ref">ssh:connection_ref()</seealso><c>}</c></tag>
+ <item><p>Reference to the <c>ssh</c> connection as returned by
+ <seealso marker="ssh#connect-3">ssh:connect/3</seealso>.
+ </p></item>
- <tag><c><![CDATA[{channel_id, channel_id()}]]></c></tag>
- <item><p>Id of the <c>ssh</c> channel.</p></item>
+ <tag><c>{channel_id, </c><seealso marker="ssh:ssh#type-channel_id">ssh:channel_id()</seealso><c>}</c></tag>
+ <item><p>Id of the <c>ssh</c> channel as returned by
+ <seealso marker="ssh_connection#session_channel/2">ssh_connection:session_channel/2,4</seealso>.
+ </p></item>
</taglist>
@@ -179,14 +166,14 @@
user. The user only needs to call if the
channel process needs to be started with help of
<c>proc_lib</c> instead of calling
- <c>ssh_channel:start/4</c> or
- <c>ssh_channel:start_link/4</c>.</p>
+ <c>start/4</c> or
+ <c>start_link/4</c>.</p>
</note>
</desc>
</func>
<func>
- <name>reply(Client, Reply) -> _</name>
+ <name since="OTP 21.0">reply(Client, Reply) -> _</name>
<fsummary>Sends a reply to a client.</fsummary>
<type>
<v>Client = opaque()</v>
@@ -201,26 +188,31 @@
the callback function <c>handle_call/3</c>.
<c>Reply</c> is an arbitrary term,
which is given back to the client as the return value of
- <seealso marker="#call-2">ssh_channel:call/[2,3].</seealso></p>
+ <seealso marker="#call-2">call/[2,3].</seealso></p>
</desc>
</func>
-
+
<func>
- <name>start(SshConnection, ChannelId, ChannelCb, CbInitArgs) -> </name>
- <name>start_link(SshConnection, ChannelId, ChannelCb, CbInitArgs) ->
+ <name since="OTP 21.0">start(SshConnection, ChannelId, ChannelCb, CbInitArgs) -> </name>
+ <name since="OTP 21.0">start_link(SshConnection, ChannelId, ChannelCb, CbInitArgs) ->
{ok, ChannelRef} | {error, Reason}</name>
<fsummary>Starts a process that handles an SSH channel.</fsummary>
<type>
- <v>SshConnection = ssh_connection_ref()</v>
- <v>ChannelId = ssh_channel_id()</v>
+ <v>SshConnection = <seealso marker="ssh:ssh#type-connection_ref">ssh:connection_ref()</seealso></v>
+ <d>As returned by <seealso marker="ssh#connect-3">ssh:connect/3</seealso></d>
+
+ <v>ChannelId = <seealso marker="ssh#type-channel_id">ssh:channel_id()</seealso></v>
<d>As returned by
<seealso marker ="ssh_connection#session_channel/2">
ssh_connection:session_channel/[2,4]</seealso>.</d>
+
<v>ChannelCb = atom()</v>
<d>Name of the module implementing the service-specific parts
of the channel.</d>
+
<v>CbInitArgs = [term()]</v>
<d>Argument list for the <c>init</c> function in the callback module.</d>
+
<v>ChannelRef = pid()</v>
</type>
<desc>
@@ -235,18 +227,24 @@
</funcs>
<section>
+ <title>Callback Functions</title>
+ <p>
+ The following functions are to be exported from a
+ <c>ssh_client_channel</c> callback module.
+ </p>
<marker id="cb_timeouts"></marker>
- <title>CALLBACK TIME-OUTS</title>
-
- <p>The time-out values that can be returned by the callback functions
- have the same semantics as in a <seealso marker="stdlib:gen_server">gen_server</seealso>.
- If the time-out occurs, <seealso marker="#Module:handle_msg-2">handle_msg/2</seealso>
- is called as <c>handle_msg(timeout, State)</c>.</p>
+ <section>
+ <title>Callback timeouts</title>
+ <p>The timeout values that can be returned by the callback functions
+ have the same semantics as in a <seealso marker="stdlib:gen_server">gen_server</seealso>.
+ If the time-out occurs, <seealso marker="#Module:handle_msg-2">handle_msg/2</seealso>
+ is called as <c>handle_msg(timeout, State)</c>.</p>
+ </section>
</section>
<funcs>
<func>
- <name>Module:code_change(OldVsn, State, Extra) -> {ok,
+ <name since="OTP 21.0">Module:code_change(OldVsn, State, Extra) -> {ok,
NewState}</name>
<fsummary>Converts process state when code is changed.</fsummary>
<type>
@@ -289,13 +287,13 @@
</func>
<func>
- <name>Module:init(Args) -> {ok, State} | {ok, State, timeout()} |
+ <name since="OTP 21.0">Module:init(Args) -> {ok, State} | {ok, State, timeout()} |
{stop, Reason}</name>
<fsummary>Makes necessary initializations and returns the
initial channel state if the initializations succeed.</fsummary>
<type>
<v>Args = term()</v>
- <d>Last argument to <c>ssh_channel:start_link/4</c>.</d>
+ <d>Last argument to <c>start_link/4</c>.</d>
<v>State = term()</v>
<v>Reason = term()</v>
</type>
@@ -304,41 +302,41 @@
state if the initializations succeed.
</p>
<p>For more detailed information on time-outs, see Section
- <seealso marker="#cb_timeouts">CALLBACK TIME-OUTS</seealso>. </p>
+ <seealso marker="#cb_timeouts">Callback timeouts</seealso>. </p>
</desc>
</func>
<func>
- <name>Module:handle_call(Msg, From, State) -> Result</name>
+ <name since="OTP 21.0">Module:handle_call(Msg, From, State) -> Result</name>
<fsummary>Handles messages sent by calling
- <c>ssh_channel:call/[2,3]</c>.</fsummary>
+ <c>call/[2,3]</c>.</fsummary>
<type>
<v>Msg = term()</v>
<v>From = opaque()</v>
<d>Is to be used as argument to
- <seealso marker="#reply-2">ssh_channel:reply/2</seealso></d>
+ <seealso marker="#reply-2">reply/2</seealso></d>
<v>State = term()</v>
<v>Result = {reply, Reply, NewState} | {reply, Reply, NewState, timeout()}
| {noreply, NewState} | {noreply , NewState, timeout()}
| {stop, Reason, Reply, NewState} | {stop, Reason, NewState} </v>
<v>Reply = term()</v>
- <d>Will be the return value of <seealso marker="#call-2">ssh_channel:call/[2,3]</seealso></d>
+ <d>Will be the return value of <seealso marker="#call-2">call/[2,3]</seealso></d>
<v>NewState = term()</v>
<v>Reason = term()</v>
</type>
<desc>
<p>Handles messages sent by calling
- <seealso marker="#call-2">ssh_channel:call/[2,3]</seealso>
+ <seealso marker="#call-2">call/[2,3]</seealso>
</p>
<p>For more detailed information on time-outs,, see Section
- <seealso marker="#cb_timeouts">CALLBACK TIME-OUTS</seealso>.</p>
+ <seealso marker="#cb_timeouts">Callback timeouts</seealso>.</p>
</desc>
</func>
<func>
- <name>Module:handle_cast(Msg, State) -> Result</name>
+ <name since="OTP 21.0">Module:handle_cast(Msg, State) -> Result</name>
<fsummary>Handles messages sent by calling
- <c>ssh_channel:cact/2</c>.</fsummary>
+ <c>cast/2</c>.</fsummary>
<type>
<v>Msg = term()</v>
<v>State = term()</v>
@@ -349,22 +347,22 @@
</type>
<desc>
<p>Handles messages sent by calling
- <c>ssh_channel:cast/2</c>.
+ <c>cast/2</c>.
</p>
<p>For more detailed information on time-outs, see Section
- <seealso marker="#cb_timeouts">CALLBACK TIME-OUTS</seealso>.</p>
+ <seealso marker="#cb_timeouts">Callback timeouts</seealso>.</p>
</desc>
</func>
<func>
- <name>Module:handle_msg(Msg, State) -> {ok, State} |
+ <name since="OTP 21.0">Module:handle_msg(Msg, State) -> {ok, State} |
{stop, ChannelId, State}</name>
<fsummary>Handles other messages than SSH connection protocol,
call, or cast messages sent to the channel.</fsummary>
<type>
<v>Msg = timeout | term()</v>
- <v>ChannelId = ssh_channel_id()</v>
+ <v>ChannelId = <seealso marker="ssh#type-channel_id">ssh:channel_id()</seealso></v>
<v>State = term() </v>
</type>
<desc>
@@ -376,11 +374,10 @@
function and all channels are to handle the following message.</p>
<taglist>
- <tag><c><![CDATA[{ssh_channel_up, ssh_channel_id(),
- ssh_connection_ref()}]]></c></tag>
+ <tag><c>{ssh_channel_up, </c><seealso marker="ssh:ssh#type-channel_id">ssh:channel_id()</seealso><c>, </c><seealso marker="ssh:ssh#type-connection_ref">ssh:connection_ref()</seealso><c>}</c></tag>
<item><p>This is the first message that the channel receives.
It is sent just before the <seealso
- marker="#init-1">ssh_channel:init/1</seealso> function
+ marker="#init-1">init/1</seealso> 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
@@ -392,25 +389,25 @@
</func>
<func>
- <name>Module:handle_ssh_msg(Msg, State) -> {ok, State} | {stop,
+ <name since="OTP 21.0">Module:handle_ssh_msg(Msg, State) -> {ok, State} | {stop,
ChannelId, State}</name>
<fsummary>Handles <c>ssh</c> connection protocol messages.</fsummary>
<type>
- <v>Msg = ssh_connection:event()</v>
- <v>ChannelId = ssh_channel_id()</v>
+ <v>Msg = <seealso marker="ssh_connection#type-event">ssh_connection:event()</seealso></v>
+ <v>ChannelId = <seealso marker="ssh#type-channel_id">ssh:channel_id()</seealso></v>
<v>State = term()</v>
</type>
<desc>
<p>Handles SSH Connection Protocol messages that may need
service-specific attention. For details,
- see <seealso marker="ssh_connection"> ssh_connection:event()</seealso>.
+ see <seealso marker="ssh_connection#type-event">ssh_connection:event()</seealso>.
</p>
<p>The following message is taken care of by the
- <c>ssh_channel</c> behavior.</p>
+ <c>ssh_client_channel</c> behavior.</p>
<taglist>
- <tag><c><![CDATA[{closed, ssh_channel_id()}]]></c></tag>
+ <tag><c>{closed, </c><seealso marker="ssh:ssh#type-channel_id">ssh:channel_id()</seealso><c>}</c></tag>
<item><p>The channel behavior sends a close message to the
other side, if such a message has not already been sent.
Then it terminates the channel with reason <c>normal</c>.</p></item>
@@ -419,7 +416,7 @@
</func>
<func>
- <name>Module:terminate(Reason, State) -> _</name>
+ <name since="OTP 21.0">Module:terminate(Reason, State) -> _</name>
<fsummary>Does cleaning up before channel process termination.
</fsummary>
<type>
diff --git a/lib/ssh/doc/src/ssh_client_key_api.xml b/lib/ssh/doc/src/ssh_client_key_api.xml
index 98a1676ca4..9f2f3013e5 100644
--- a/lib/ssh/doc/src/ssh_client_key_api.xml
+++ b/lib/ssh/doc/src/ssh_client_key_api.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2012</year>
- <year>2016</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -29,7 +29,7 @@
<date></date>
<rev></rev>
</header>
- <module>ssh_client_key_api</module>
+ <module since="OTP R16B">ssh_client_key_api</module>
<modulesummary>
-behaviour(ssh_client_key_api).
</modulesummary>
@@ -41,7 +41,7 @@
see the <seealso marker="SSH_app"> ssh(6)</seealso> application manual.</p>
</description>
- <section>
+ <!-- section>
<title>DATA TYPES</title>
<p>Type definitions that are used more than once in this module,
@@ -68,23 +68,34 @@
| 'rsa-sha2-256' | 'rsa-sha2-384' | 'rsa-sha2-512'
| 'ecdsa-sha2-nistp256' | 'ecdsa-sha2-nistp384' | 'ecdsa-sha2-nistp521' </c></p></item>
</taglist>
- </section>
+ </section -->
+
+ <datatypes>
+ <datatype>
+ <name name="client_key_cb_options"/>
+ <desc>
+ <p>Options provided to <seealso marker="ssh#connect-3">ssh:connect/[3,4]</seealso>.
+ </p>
+ <p>The option list given in the
+ <seealso marker="ssh#type-key_cb_common_option"><c>key_cb</c></seealso>
+ option is available with the key <c>key_cb_private</c>.
+ </p>
+ </desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>Module:add_host_key(HostNames, Key, ConnectOptions) -> ok | {error, Reason}</name>
+ <name since="OTP R16B">Module:add_host_key(HostNames, PublicHostKey, ConnectOptions) -> ok | {error, Reason}</name>
<fsummary>Adds a host key to the set of trusted host keys.</fsummary>
<type>
- <v>HostNames = string()</v>
- <d>Description of the host that owns the <c>PublicKey</c>.</d>
+ <v>HostNames = string()</v>
+ <d>Description of the host that owns the <c>PublicHostKey</c>.</d>
- <v>Key = public_key()</v>
- <d>Normally an RSA, DSA or ECDSA public key, but handling of other public keys can be added.</d>
+ <v>PublicHostKey = <seealso marker="public_key:public_key#type-public_key">public_key:public_key()</seealso></v>
+ <d>Of ECDSA keys, only the Normally an RSA, DSA or ECDSA public key, but handling of other public keys can be added.</d>
- <v>ConnectOptions = proplists:proplist()</v>
- <d>Options provided to <seealso marker="ssh#connect-3">ssh:connect/[3,4]</seealso>. The option list given in
- the <c>key_cb</c> option is available with the key <c>key_cb_private</c>.</d>
- <v>Reason = term().</v>
+ <v>ConnectOptions = <seealso marker="#type-client_key_cb_options">client_key_cb_options()</seealso></v>
</type>
<desc>
<p>Adds a host key to the set of trusted host keys.</p>
@@ -92,21 +103,19 @@
</func>
<func>
- <name>Module:is_host_key(Key, Host, Algorithm, ConnectOptions) -> Result</name>
+ <name since="OTP R16B">Module:is_host_key(Key, Host, Algorithm, ConnectOptions) -> Result</name>
<fsummary>Checks if a host key is trusted.</fsummary>
<type>
- <v>Key = public_key() </v>
+ <v>Key = <seealso marker="public_key:public_key#type-public_key">public_key:public_key()</seealso></v>
<d>Normally an RSA, DSA or ECDSA public key, but handling of other public keys can be added.</d>
<v>Host = string()</v>
<d>Description of the host.</d>
- <v>Algorithm = public_key_algorithm()</v>
+ <v>Algorithm = <seealso marker="ssh#type-pubkey_alg">ssh:pubkey_alg()</seealso></v>
<d>Host key algorithm.</d>
- <v>ConnectOptions = proplists:proplist() </v>
- <d>Options provided to <seealso marker="ssh#connect-3">ssh:connect/[3,4]</seealso>. The option list given in
- the <c>key_cb</c> option is available with the key <c>key_cb_private</c>.</d>
+ <v>ConnectOptions = <seealso marker="#type-client_key_cb_options">client_key_cb_options()</seealso></v>
<v>Result = boolean()</v>
</type>
@@ -116,18 +125,16 @@
</func>
<func>
- <name>Module:user_key(Algorithm, ConnectOptions) ->
+ <name since="OTP R16B">Module:user_key(Algorithm, ConnectOptions) ->
{ok, PrivateKey} | {error, Reason}</name>
<fsummary>Fetches the users <em>public key</em> matching the <c>Algorithm</c>.</fsummary>
<type>
- <v>Algorithm = public_key_algorithm()</v>
+ <v>Algorithm = <seealso marker="ssh#type-pubkey_alg">ssh:pubkey_alg()</seealso></v>
<d>Host key algorithm.</d>
- <v>ConnectOptions = proplists:proplist()</v>
- <d>Options provided to <seealso marker="ssh#connect-3">ssh:connect/[3,4]</seealso>. The option list given in
- the <c>key_cb</c> option is available with the key <c>key_cb_private</c>.</d>
+ <v>ConnectOptions = <seealso marker="#type-client_key_cb_options">client_key_cb_options()</seealso></v>
- <v>PrivateKey = private_key()</v>
+ <v>PrivateKey = <seealso marker="public_key:public_key#type-private_key">public_key:private_key()</seealso></v>
<d>Private key of the user matching the <c>Algorithm</c>.</d>
<v>Reason = term()</v>
diff --git a/lib/ssh/doc/src/ssh_connection.xml b/lib/ssh/doc/src/ssh_connection.xml
index f9ba5c5af9..e1689b68ba 100644
--- a/lib/ssh/doc/src/ssh_connection.xml
+++ b/lib/ssh/doc/src/ssh_connection.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2008</year>
- <year>2015</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -30,7 +30,7 @@
<date></date>
<rev></rev>
</header>
- <module>ssh_connection</module>
+ <module since="">ssh_connection</module>
<modulesummary>
This module provides API functions to send SSH Connection Protocol
events to the other side of an SSH channel.
@@ -40,128 +40,119 @@
<p>The <url href="http://www.ietf.org/rfc/rfc4254.txt">SSH Connection Protocol</url>
is used by clients and servers, that is, SSH channels, to communicate over the
SSH connection. The API functions in this module send SSH Connection Protocol events,
- which are received as messages by the remote channel.
- If the receiving channel is an Erlang process, the
- messages have the format
- <c><![CDATA[{ssh_cm, ssh_connection_ref(), ssh_event_msg()}]]></c>.
- If the <seealso marker="ssh_channel">ssh_channel</seealso> behavior is used to
+ which are received as messages by the remote channel handling the remote channel.
+ The Erlang format of thoose messages is
+ (see also <seealso marker="#type-event">below</seealso>):
+ </p>
+ <p><c>{ssh_cm, </c><seealso marker="ssh:ssh#type-connection_ref">ssh:connection_ref()</seealso><c>, </c><seealso marker="#type-channel_msg"><c>channel_msg()</c></seealso><c>}</c>
+ </p>
+ <p>
+ If the <seealso marker="ssh_client_channel">ssh_client_channel</seealso> behavior is used to
implement the channel process, these messages are handled by
- <seealso marker="ssh_channel#Module:handle_ssh_msg-2">handle_ssh_msg/2</seealso>.</p>
+ <seealso marker="ssh_client_channel#Module:handle_ssh_msg-2">handle_ssh_msg/2</seealso>.</p>
</description>
- <section>
- <title>DATA TYPES</title>
-
- <p>Type definitions that are used more than once in this module,
- or abstractions to indicate the intended use of the data
- type, or both:</p>
-
- <taglist>
- <tag><c>boolean() =</c></tag>
- <item><p><c>true | false </c></p></item>
- <tag><c>string() =</c></tag>
- <item><p>list of ASCII characters</p></item>
- <tag><c>timeout() =</c></tag>
- <item><p><c>infinity | integer()</c> in milliseconds</p></item>
- <tag><c>ssh_connection_ref() =</c></tag>
- <item><p>opaque() -as returned by
- <c>ssh:connect/3</c> or sent to an SSH channel processes</p></item>
- <tag><c>ssh_channel_id() =</c></tag>
- <item><p><c>integer()</c></p></item>
- <tag><c>ssh_data_type_code() =</c></tag>
- <item><p><c>1</c> ("stderr") | <c>0</c> ("normal") are
- valid values, see
- <url href="http://www.ietf.org/rfc/rfc4254.txt">RFC 4254</url> Section 5.2.</p></item>
- <tag><c>ssh_request_status() =</c></tag>
- <item><p> <c>success | failure</c></p></item>
- <tag><c>event() =</c></tag>
- <item><p><c>{ssh_cm, ssh_connection_ref(), ssh_event_msg()}</c></p></item>
- <tag><c>ssh_event_msg() =</c></tag>
- <item><p><c>data_events() | status_events() | terminal_events()</c></p></item>
- <tag><c>reason() =</c></tag>
- <item><p><c>timeout | closed</c></p></item>
- </taglist>
-
- <taglist>
- <tag><em>data_events()</em></tag>
- <item>
- <taglist>
- <tag><c><![CDATA[{data, ssh_channel_id(), ssh_data_type_code(), Data :: binary()}]]></c></tag>
- <item><p>Data has arrived on the channel. This event is sent as a
- result of calling <seealso marker="ssh_connection#send-3">
- ssh_connection:send/[3,4,5]</seealso>.</p></item>
-
- <tag><c><![CDATA[{eof, ssh_channel_id()}]]></c></tag>
- <item><p>Indicates that the other side sends no more data.
- This event is sent as a result of calling <seealso
- marker="ssh_connection#send_eof-2"> ssh_connection:send_eof/2</seealso>.
- </p></item>
- </taglist>
- </item>
-
- <tag><em>status_events()</em></tag>
- <item>
+ <datatypes>
+ <datatype>
+ <name name="ssh_data_type_code"/>
+ <desc>
+ <p>The valid values are <c>0</c> ("normal") and <c>1</c> ("stderr"), see
+ <url href="https://tools.ietf.org/html/rfc4254#page-8">RFC 4254, Section 5.2</url>.</p>
+ </desc>
+ </datatype>
- <taglist>
- <tag><c><![CDATA[{signal, ssh_channel_id(), ssh_signal()}]]></c></tag>
- <item><p>A signal can be delivered to the remote process/service
- using the following message. Some systems do not support
- signals, in which case they are to ignore this message. There is
- currently no function to generate this event as the signals
- referred to are on OS-level and not something generated by an
- Erlang program.</p></item>
+ <datatype>
+ <name name="result"/>
+ <name name="reason"/>
+ <desc>
+ <p>The result of a call.</p>
+ <p>If the request reached the peer, was handled and the response
+ reached the requesting node the <seealso marker="#type-req_status">req_status()</seealso>
+ is the status reported from the peer.</p>
+ <p>If not, the <seealso marker="#type-reason">reason()</seealso> indicates what went wrong:</p>
+ <taglist>
+ <tag><c>closed</c></tag>
+ <item>indicates that the channel or connection was closed when trying to send the request
+ </item>
+ <tag><c>timeout</c></tag>
+ <item>indicates that the operation exceeded a time limit
+ </item>
+ </taglist>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{exit_signal, ssh_channel_id(), ExitSignal :: string(), ErrorMsg ::string(),
- LanguageString :: string()}]]></c></tag>
+ <datatype>
+ <name name="req_status"/>
+ <desc>
+ <p>The status of a request.
+ Coresponds to the <c>SSH_MSG_CHANNEL_SUCCESS</c> and <c>SSH_MSG_CHANNEL_FAILURE</c> values in
+ <url href="https://tools.ietf.org/html/rfc4254#section-5.4">RFC 4254, Section 5.4</url>.
+ </p>
+ </desc>
+ </datatype>
- <item><p>A remote execution can terminate violently because of a signal.
- Then this message can be received. For details on valid string
- values, see <url href="http://www.ietf.org/rfc/rfc4254.txt">RFC 4254</url>
- Section 6.10, which shows a special case of these signals.</p></item>
+ <datatype_title>SSH Connection Protocol: General</datatype_title>
+ <datatype>
+ <name name="event"/>
+ <name name="channel_msg"/>
+ <desc>
+ <p>As mentioned in the introduction, the
+ <url href="https://tools.ietf.org/html/rfc4254">SSH Connection Protocol</url>
+ events are handled as messages. When writing a channel handling process without using
+ the support by the <seealso marker="ssh_client_channel">ssh_client_channel</seealso>
+ behavior the process must handle thoose messages.
+ </p>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{exit_status, ssh_channel_id(), ExitStatus :: integer()}]]></c></tag>
- <item><p>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 <c>exit_status</c> usually means that the command
- terminated successfully. This event is sent as a result of calling
- <seealso marker="ssh_connection#exit_status-3">
- ssh_connection:exit_status/3</seealso>.</p></item>
+ <datatype>
+ <name name="want_reply"/>
+ <desc>
+ <p>Messages that include a <c>WantReply</c> expect the channel handling
+ process to call <seealso marker="ssh_connection#reply_request-4">
+ ssh_connection:reply_request/4</seealso>
+ with the boolean value of <c>WantReply</c> as the second argument.</p>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{closed, ssh_channel_id()}]]></c></tag>
- <item><p>This event is sent as a result of calling
- <seealso marker="ssh_connection#close-2">ssh_connection:close/2</seealso>.
- Both the handling of this event and sending it are taken care of by the
- <seealso marker="ssh_channel">ssh_channel</seealso> behavior.</p></item>
- </taglist>
- </item>
+ <datatype_title>Data Transfer (RFC 4254, section 5.2)</datatype_title>
+ <datatype>
+ <name name="data_ch_msg"/>
+ <desc>
+ <p>Data has arrived on the channel. This event is sent as a result of calling
+ <seealso marker="ssh_connection#send-3"> ssh_connection:send/[3,4,5]</seealso>.
+ </p>
+ </desc>
+ </datatype>
- <tag><em>terminal_events()</em></tag>
- <item>
- <p>Channels implementing a shell and command execution on the
- server side are to handle the following messages that can be sent by client-
- channel processes.</p>
+ <datatype_title>Closing a Channel (RFC 4254, section 5.3)</datatype_title>
+ <datatype>
+ <name name="eof_ch_msg"/>
+ <desc>
+ <p>Indicates that the other side sends no more data. This event is sent as a result of calling
+ <seealso marker="ssh_connection#send_eof-2"> ssh_connection:send_eof/2</seealso>.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="closed_ch_msg"/>
+ <desc>
+ <p>This event is sent as a result of calling
+ <seealso marker="ssh_connection#close-2">ssh_connection:close/2</seealso>.
+ Both the handling of this event and sending it are taken care of by the
+ <seealso marker="ssh_client_channel">ssh_client_channel</seealso> behavior.</p>
+ </desc>
+ </datatype>
- <p>Events that include a <c>WantReply</c> expect the event handling
- process to call <seealso marker="ssh_connection#reply_request-4">
- ssh_connection:reply_request/4</seealso>
- with the boolean value of <c>WantReply</c> as the second argument.</p>
- <taglist>
- <tag><c><![CDATA[{env, ssh_channel_id(), WantReply :: boolean(),
- Var ::string(), Value :: string()}]]></c></tag>
- <item><p>Environment variables can be passed to the shell/command
- to be started later. This event is sent as a result of calling <seealso
- marker="ssh_connection#setenv-5"> ssh_connection:setenv/5</seealso>.
- </p></item>
-
- <tag><c><![CDATA[{pty, ssh_channel_id(),
- WantReply :: boolean(), {Terminal :: string(), CharWidth :: integer(),
- RowHeight :: integer(), PixelWidth :: integer(), PixelHeight :: integer(),
- TerminalModes :: [{Opcode :: atom() | integer(),
- Value :: integer()}]}}]]></c></tag>
- <item><p>A pseudo-terminal has been requested for the
+ <datatype_title>Requesting a Pseudo-Terminal (RFC 4254, section 6.2)</datatype_title>
+ <datatype>
+ <name name="pty_ch_msg"/>
+ <name name="term_mode"/>
+ <desc>
+ <p>A pseudo-terminal has been requested for the
session. <c>Terminal</c> is the value of the TERM environment
variable value, that is, <c>vt100</c>. Zero dimension parameters must
be ignored. The character/row dimensions override the pixel
@@ -169,86 +160,131 @@
drawable area of the window. <c>Opcode</c> in the
<c>TerminalModes</c> list is the mnemonic name, represented
as a lowercase Erlang atom, defined in
- <url href="http://www.ietf.org/rfc/rfc4254.txt">RFC 4254</url>, Section 8.
+ <url href="https://tools.ietf.org/html/rfc4254#section-8">RFC 4254</url>, Section 8.
It can also be an <c>Opcode</c> if the mnemonic name is not listed in the
RFC. Example: <c>OP code: 53, mnemonic name ECHO erlang atom:
echo</c>. This event is sent as a result of calling <seealso
- marker="ssh_connection#ptty_alloc/4">ssh_connection:ptty_alloc/4</seealso>.</p></item>
+ marker="ssh_connection#ptty_alloc/4">ssh_connection:ptty_alloc/4</seealso>.</p>
+ </desc>
+ </datatype>
+
+
+ <datatype_title>Environment Variable Passing (RFC 4254, section 6.4)</datatype_title>
+ <datatype>
+ <name name="env_ch_msg"/>
+ <desc>
+ <p>Environment variables can be passed to the shell/command
+ to be started later. This event is sent as a result of calling <seealso
+ marker="ssh_connection#setenv-5"> ssh_connection:setenv/5</seealso>.
+ </p>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{shell, WantReply :: boolean()}]]></c></tag>
- <item><p>This message requests that the user default shell
+
+ <datatype_title>Starting a Shell or Command (RFC 4254, section 6.5)</datatype_title>
+ <datatype>
+ <name name="shell_ch_msg"/>
+ <desc>
+ <p>This message requests that the user default shell
is started at the other end. This event is sent as a result of calling
<seealso marker="ssh_connection#shell-2"> ssh_connection:shell/2</seealso>.
- </p></item>
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="exec_ch_msg"/>
+ <desc>
+ <p>This message requests that the server starts
+ execution of the given command. This event is sent as a result of calling <seealso
+ marker="ssh_connection#exec-4">ssh_connection:exec/4 </seealso>.
+ </p>
+ </desc>
+ </datatype>
+
- <tag><c><![CDATA[{window_change, ssh_channel_id(), CharWidth() :: integer(),
- RowHeight :: integer(), PixWidth :: integer(), PixHeight :: integer()}]]></c></tag>
- <item><p>When the window (terminal) size changes on the client
+ <datatype_title>Window Dimension Change Message (RFC 4254, section 6.7)</datatype_title>
+ <datatype>
+ <name name="window_change_ch_msg"/>
+ <desc>
+ <p>When the window (terminal) size changes on the client
side, it <em>can</em> send a message to the server side to inform it of
- the new dimensions. No API function generates this event.</p></item>
+ the new dimensions. No API function generates this event.</p>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{exec, ssh_channel_id(),
- WantReply :: boolean(), Cmd :: string()}]]></c></tag>
- <item><p>This message requests that the server starts
- execution of the given command. This event is sent as a result of calling <seealso
- marker="ssh_connection#exec-4">ssh_connection:exec/4 </seealso>.
- </p></item>
- </taglist>
- </item>
- </taglist>
- </section>
+ <datatype_title>Signals (RFC 4254, section 6.9)</datatype_title>
+ <datatype>
+ <name name="signal_ch_msg"/>
+ <desc>
+ <p>A signal can be delivered to the remote process/service
+ using the following message. Some systems do not support
+ signals, in which case they are to ignore this message. There is
+ currently no function to generate this event as the signals
+ referred to are on OS-level and not something generated by an
+ Erlang program.</p>
+ </desc>
+ </datatype>
+
+
+ <datatype_title>Returning Exit Status (RFC 4254, section 6.10)</datatype_title>
+ <datatype>
+ <name name="exit_status_ch_msg"/>
+ <desc>
+ <p>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 <c>exit_status</c> usually means that the command
+ terminated successfully. This event is sent as a result of calling
+ <seealso marker="ssh_connection#exit_status-3">
+ ssh_connection:exit_status/3</seealso>.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="exit_signal_ch_msg"/>
+ <desc>
+ <p>A remote execution can terminate violently because of a signal.
+ Then this message can be received. For details on valid string
+ values, see <url href="https://tools.ietf.org/html/rfc4254#section-6.10">RFC 4254</url>
+ Section 6.10, which shows a special case of these signals.</p>
+ </desc>
+ </datatype>
+
+ </datatypes>
+
<funcs>
<func>
- <name>adjust_window(ConnectionRef, ChannelId, NumOfBytes) -> ok</name>
+ <name since="" name="adjust_window" arity="3"/>
<fsummary>Adjusts the SSH flow control window.</fsummary>
- <type>
- <v>ConnectionRef = ssh_connection_ref()</v>
- <v>ChannelId = ssh_channel_id()</v>
- <v>NumOfBytes = integer()</v>
- </type>
- <desc>
+ <desc>
<p>Adjusts the SSH flow control window. This is to be done by both the
client- and server-side channel processes.</p>
- <note><p>Channels implemented with the <seealso marker="ssh_channel"> ssh_channel</seealso>
+ <note><p>Channels implemented with the <seealso marker="ssh_client_channel"> ssh_client_channel</seealso>
behavior do not normally need to call this function as flow control
is handled by the behavior. The behavior adjusts the window every time
- the callback <seealso marker="ssh_channel#Module:handle_ssh_msg-2">
+ the callback <seealso marker="ssh_client_channel#Module:handle_ssh_msg-2">
handle_ssh_msg/2</seealso> returns after processing channel data.</p></note>
</desc>
</func>
<func>
- <name>close(ConnectionRef, ChannelId) -> ok</name>
+ <name since="" name="close" arity="2"/>
<fsummary>Sends a close message on the channel <c>ChannelId</c>.</fsummary>
- <type>
- <v>ConnectionRef = ssh_connection_ref()</v>
- <v>ChannelId = ssh_channel_id()</v>
- </type>
<desc>
<p>A server- or client-channel process can choose to close their session by
sending a close event.
</p>
-
- <note><p>This function is called by the <c>ssh_channel</c>
+ <note><p>This function is called by the <c>ssh_client_channel</c>
behavior when the channel is terminated, see <seealso
- marker="ssh_channel"> ssh_channel(3)</seealso>. Thus, channels implemented
+ marker="ssh_client_channel"> ssh_client_channel(3)</seealso>. Thus, channels implemented
with the behavior are not to call this function explicitly.</p></note>
</desc>
</func>
<func>
- <name>exec(ConnectionRef, ChannelId, Command, TimeOut) -> ssh_request_status() |
- {error, reason()}</name>
+ <name since="" name="exec" arity="4"/>
<fsummary>Requests that the server starts the execution of the given command.</fsummary>
- <type>
- <v>ConnectionRef = ssh_connection_ref()</v>
- <v>ChannelId = ssh_channel_id()</v>
- <v>Command = string()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Is to be called by a client-channel process to request that the server starts
executing the given command. The result is several messages according to the
@@ -256,41 +292,34 @@
request is a one-time execution that closes the channel when it is done.</p>
<taglist>
- <tag><c>N x {ssh_cm, ssh_connection_ref(),
- {data, ssh_channel_id(), ssh_data_type_code(), Data :: binary()}}</c></tag>
+ <tag>N x <seealso marker="#type-data_ch_msg">data message(s)</seealso></tag>
<item><p>The result of executing the command can be only one line
or thousands of lines depending on the command.</p></item>
- <tag><c>0 or 1 x {ssh_cm, ssh_connection_ref(), {eof, ssh_channel_id()}}</c></tag>
+ <tag>0 or 1 x <seealso marker="#type-eof_ch_msg">eof message</seealso></tag>
<item><p>Indicates that no more data is to be sent.</p></item>
- <tag><c>0 or 1 x {ssh_cm,
- ssh_connection_ref(), {exit_signal,
- ssh_channel_id(), ExitSignal :: string(), ErrorMsg :: string(), LanguageString :: string()}}</c></tag>
+ <tag>0 or 1 x <seealso marker="#type-exit_signal_ch_msg">exit signal message</seealso></tag>
<item><p>Not all systems send signals. For details on valid string
values, see RFC 4254, Section 6.10</p></item>
-
- <tag><c>0 or 1 x {ssh_cm, ssh_connection_ref(), {exit_status,
- ssh_channel_id(), ExitStatus :: integer()}}</c></tag>
- <item><p>It is recommended by the SSH Connection Protocol to send this
- message, but that is not always the case.</p></item>
-
- <tag><c>1 x {ssh_cm, ssh_connection_ref(),
- {closed, ssh_channel_id()}}</c></tag>
- <item><p>Indicates that the <c>ssh_channel</c> started for the
- execution of the command has now been shut down.</p></item>
+
+ <tag>0 or 1 x <seealso marker="#type-exit_status_ch_msg">exit status message</seealso></tag>
+ <item><p>It is recommended by the SSH Connection Protocol to send this
+ message, but that is not always the case.</p></item>
+
+ <tag>1 x <seealso marker="#type-closed_ch_msg">closed status message</seealso></tag>
+ <item><p>Indicates that the <c>ssh_client_channel</c> started for the
+ execution of the command has now been shut down.</p></item>
</taglist>
+ <p>See the User's Guide section on
+ <seealso marker="using_ssh#one-time-execution">One-Time Execution</seealso> for examples.
+ </p>
</desc>
</func>
<func>
- <name>exit_status(ConnectionRef, ChannelId, Status) -> ok</name>
+ <name since="" name="exit_status" arity="3"/>
<fsummary>Sends the exit status of a command to the client.</fsummary>
- <type>
- <v>ConnectionRef = ssh_connection_ref() </v>
- <v>ChannelId = ssh_channel_id()</v>
- <v>Status = integer()</v>
- </type>
<desc>
<p>Is to be called by a server-channel process to send the exit status of a command
to the client.</p>
@@ -298,16 +327,10 @@
</func>
<func>
- <name>ptty_alloc(ConnectionRef, ChannelId, Options) -></name>
- <name>ptty_alloc(ConnectionRef, ChannelId, Options, Timeout) -> > ssh_request_status() |
- {error, reason()}</name>
+ <name since="OTP 17.5" name="ptty_alloc" arity="3"/>
+ <name since="OTP 17.4" name="ptty_alloc" arity="4"/>
<fsummary>Sends an SSH Connection Protocol <c>pty_req</c>,
to allocate a pseudo-terminal.</fsummary>
- <type>
- <v>ConnectionRef = ssh_connection_ref()</v>
- <v>ChannelId = ssh_channel_id()</v>
- <v>Options = proplists:proplist()</v>
- </type>
<desc>
<p>Sends an SSH Connection Protocol <c>pty_req</c>, to allocate a pseudo-terminal.
Is to be called by an SSH client process.</p>
@@ -339,14 +362,8 @@
</func>
<func>
- <name>reply_request(ConnectionRef, WantReply, Status, ChannelId) -> ok</name>
+ <name since="" name="reply_request" arity="4"/>
<fsummary>Sends status replies to requests that want such replies.</fsummary>
- <type>
- <v>ConnectionRef = ssh_connection_ref()</v>
- <v>WantReply = boolean()</v>
- <v>Status = ssh_request_status()</v>
- <v>ChannelId = ssh_channel_id()</v>
- </type>
<desc>
<p>Sends status replies to requests where the requester has
stated that it wants a status report, that is, <c>WantReply = true</c>.
@@ -357,18 +374,19 @@
</func>
<func>
- <name>send(ConnectionRef, ChannelId, Data) -></name>
- <name>send(ConnectionRef, ChannelId, Data, Timeout) -></name>
- <name>send(ConnectionRef, ChannelId, Type, Data) -></name>
- <name>send(ConnectionRef, ChannelId, Type, Data, TimeOut) ->
- ok | {error, timeout} | {error, closed}</name>
+ <name since="">send(ConnectionRef, ChannelId, Data) -></name>
+ <name since="">send(ConnectionRef, ChannelId, Data, Timeout) -></name>
+ <name since="">send(ConnectionRef, ChannelId, Type, Data) -></name>
+ <name since="">send(ConnectionRef, ChannelId, Type, Data, TimeOut) ->
+ ok | Error</name>
<fsummary>Sends channel data.</fsummary>
<type>
- <v>ConnectionRef = ssh_connection_ref()</v>
- <v>ChannelId = ssh_channel_id()</v>
+ <v>ConnectionRef = <seealso marker="ssh:ssh#type-connection_ref">ssh:connection_ref()</seealso></v>
+ <v>ChannelId = <seealso marker="ssh:ssh#type-channel_id">ssh:channel_id()</seealso></v>
<v>Data = iodata()</v>
- <v>Type = ssh_data_type_code()</v>
+ <v>Type = <seealso marker="#type-ssh_data_type_code">ssh_data_type_code()</seealso></v>
<v>Timeout = timeout()</v>
+ <v>Error = {error, <seealso marker="#type-reason">reason()</seealso>}</v>
</type>
<desc>
<p>Is to be called by client- and server-channel processes to send data to each other.
@@ -380,29 +398,17 @@
</func>
<func>
- <name>send_eof(ConnectionRef, ChannelId) -> ok | {error, closed}</name>
+ <name since="" name="send_eof" arity="2"/>
<fsummary>Sends EOF on channel <c>ChannelId</c>.</fsummary>
- <type>
- <v>ConnectionRef = ssh_connection_ref()</v>
- <v>ChannelId = ssh_channel_id()</v>
- </type>
<desc>
<p>Sends EOF on channel <c>ChannelId</c>.</p>
</desc>
</func>
<func>
- <name>session_channel(ConnectionRef, Timeout) -></name>
- <name>session_channel(ConnectionRef, InitialWindowSize,
- MaxPacketSize, Timeout) -> {ok, ssh_channel_id()} | {error, reason()}</name>
+ <name since="" name="session_channel" arity="2"/>
+ <name since="" name="session_channel" arity="4"/>
<fsummary>Opens a channel for an SSH session.</fsummary>
- <type>
- <v>ConnectionRef = ssh_connection_ref()</v>
- <v>InitialWindowSize = integer()</v>
- <v>MaxPacketSize = integer()</v>
- <v>Timeout = timeout()</v>
- <v>Reason = term()</v>
- </type>
<desc>
<p>Opens a channel for an SSH session. The channel id returned from this function
is the id used as input to the other functions in this module.</p>
@@ -410,17 +416,9 @@
</func>
<func>
- <name>setenv(ConnectionRef, ChannelId, Var, Value, TimeOut) -> ssh_request_status() |
- {error, reason()}</name>
+ <name since="" name="setenv" arity="5"/>
<fsummary>Environment variables can be passed to the
shell/command to be started later.</fsummary>
- <type>
- <v>ConnectionRef = ssh_connection_ref()</v>
- <v>ChannelId = ssh_channel_id()</v>
- <v>Var = string()</v>
- <v>Value = string()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Environment variables can be passed before starting the
shell/command. Is to be called by a client channel processes.</p>
@@ -428,31 +426,23 @@
</func>
<func>
- <name>shell(ConnectionRef, ChannelId) -> ssh_request_status() | {error, closed}
- </name>
+ <name since="" name="shell" arity="2"/>
<fsummary>Requests that the user default shell (typically defined in
/etc/passwd in Unix systems) is to be executed at the server end.</fsummary>
- <type>
- <v>ConnectionRef = ssh_connection_ref()</v>
- <v>ChannelId = ssh_channel_id()</v>
- </type>
<desc>
<p>Is to be called by a client channel process to request that the user default
shell (typically defined in /etc/passwd in Unix systems) is executed
at the server end.</p>
+ <p>Note: the return value is <c>ok</c> instead of <c>success</c> unlike in other
+ functions in this module. This is a fault that was introduced so long ago that
+ any change would break a large number of existing software.
+ </p>
</desc>
</func>
<func>
- <name>subsystem(ConnectionRef, ChannelId, Subsystem, Timeout) -> ssh_request_status() |
- {error, reason()}</name>
+ <name since="" name="subsystem" arity="4"/>
<fsummary>Requests to execute a predefined subsystem on the server.</fsummary>
- <type>
- <v>ConnectionRef = ssh_connection_ref()</v>
- <v>ChannelId = ssh_channel_id()</v>
- <v>Subsystem = string()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Is to 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_file.xml b/lib/ssh/doc/src/ssh_file.xml
new file mode 100644
index 0000000000..f1fef09083
--- /dev/null
+++ b/lib/ssh/doc/src/ssh_file.xml
@@ -0,0 +1,285 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2018</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>ssh_file</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ </header>
+ <module since="OTP 21.2">ssh_file</module>
+ <modulesummary>Default callback module for the client's and server's database operations in the ssh application</modulesummary>
+ <description>
+ <p>This module is the default callback handler for the client's and the server's user and host "database" operations.
+ All data, for instance key pairs, are stored in files in the normal file system. This page documents the files, where they
+ are stored and configuration options for this callback module.
+ </p>
+ <p>The intention is to be compatible with the
+ <url href="http://www.openssh.com">OpenSSH</url>
+ storage in files. Therefore it mimics directories and filenames of
+ <url href="http://www.openssh.com">OpenSSH</url>.
+ </p>
+
+ <p>Ssh_file implements the <seealso marker="ssh:ssh_server_key_api">ssh_server_key_api</seealso> and
+ the <seealso marker="ssh:ssh_client_key_api">ssh_client_key_api</seealso>.
+ This enables the user to make an own interface using for example a database handler.
+ </p>
+ <p>Such another callback module could be used by setting the option
+ <seealso marker="ssh:ssh#type-key_cb_common_option"><c>key_cb</c></seealso>
+ when starting a client or a server (with for example
+ <seealso marker="ssh:ssh#connect-3">ssh:connect</seealso>,
+ <seealso marker="ssh:ssh#daemon-2">ssh:daemon</seealso> of
+ <seealso marker="ssh:ssh#shell-1">ssh:shell</seealso>
+ ).
+ </p>
+
+ <note>
+ <p>The functions are <i>Callbacks</i> for the SSH app. They are not intended to be called from the user's code!
+ </p>
+ </note>
+ </description>
+
+ <section>
+ <title>Files, directories and who uses them</title>
+ <section>
+ <title>Daemons</title>
+ <p>Daemons uses all files stored in the <seealso marker="#SYSDIR">SYSDIR</seealso> directory.
+ </p>
+ <p>Optionaly, in case of <c>publickey</c> authorization, one or more of the remote user's public keys
+ in the <seealso marker="#USERDIR">USERDIR</seealso> directory are used.
+ See the files
+ <seealso marker="#USERDIR-authorized_keys"><c>USERDIR/authorized_keys</c></seealso> and
+ <seealso marker="#USERDIR-authorized_keys2"><c>USERDIR/authorized_keys2</c></seealso>.
+ </p>
+ </section>
+
+ <section>
+ <title>Clients</title>
+ <p>Clients uses all files stored in the <seealso marker="#USERDIR">USERDIR</seealso> directory.
+ </p>
+ </section>
+
+ <section>
+ <title>Directory contents</title>
+ <taglist>
+ <tag><marker id="LOCALUSER"/>LOCALUSER</tag>
+ <item><p>The user name of the OS process running the Erlang virtual machine (emulator).</p>
+ </item>
+
+ <tag><marker id="SYSDIR"/>SYSDIR</tag>
+ <item><p>This is the directory holding the server's files:</p>
+ <list>
+ <item><marker id="SYSDIR-ssh_host_dsa_key"/><c>ssh_host_dsa_key</c> - private dss host key (optional)</item>
+ <item><marker id="SYSDIR-ssh_host_rsa_key"/><c>ssh_host_rsa_key</c> - private rsa host key (optional)</item>
+ <item><marker id="SYSDIR-ssh_host_ecdsa_key"/><c>ssh_host_ecdsa_key</c> - private ecdsa host key (optional)</item>
+ <item><marker id="SYSDIR-ssh_host_ed25519_key"/><c>ssh_host_ed25519_key</c> - private eddsa host key for curve 25519 (optional)</item>
+ <item><marker id="SYSDIR-ssh_host_ed448_key"/><c>ssh_host_ed448_key</c> - private eddsa host key for curve 448 (optional)</item>
+ </list>
+ <p>At least one host key must be defined. The default value of SYSDIR is <marker id="#/etc/ssh"/><c>/etc/ssh</c>.
+ </p>
+ <p>For security reasons, this directory is normally accessible only to the root user.
+ </p>
+ <p>To change the SYSDIR, see the <seealso marker="#type-system_dir_daemon_option">system_dir</seealso> option.
+ </p>
+ </item>
+
+ <tag><marker id="USERDIR"/>USERDIR</tag>
+ <item><p>This is the directory holding the files:</p>
+ <list>
+ <item><marker id="USERDIR-authorized_keys"/><c>authorized_keys</c>
+ and, as second alternative
+ <marker id="USERDIR-authorized_keys2"/><c>authorized_keys2</c> -
+ the user's public keys are stored concatenated in one of those files.
+ </item>
+ <item><marker id="USERDIR-known_hosts"/><c>known_hosts</c> - host keys from hosts visited
+ concatenated. The file is created and used by the client.</item>
+ <item><marker id="USERDIR-id_dsa"/><c>id_dsa</c> - private dss user key (optional)</item>
+ <item><marker id="USERDIR-id_rsa"/><c>id_rsa</c> - private rsa user key (optional)</item>
+ <item><marker id="USERDIR-id_ecdsa"/><c>id_ecdsa</c> - private ecdsa user key (optional)</item>
+ <item><marker id="USERDIR-id_ed25519"/><c>id_ed25519</c> - private eddsa user key for curve 25519 (optional)</item>
+ <item><marker id="USERDIR-id_ed448"/><c>id_ed448</c> - private eddsa user key for curve 448 (optional)</item>
+ </list>
+ <p>The default value of USERDIR is <c>/home/</c><seealso marker="#LOCALUSER"><c>LOCALUSER</c></seealso><c>/.ssh</c>.
+ </p>
+ <p>To change the USERDIR, see the <seealso marker="#type-user_dir_common_option">user_dir</seealso> option
+ </p>
+ </item>
+ </taglist>
+ </section>
+ </section>
+
+ <datatypes>
+ <datatype_title>Options for the default ssh_file callback module</datatype_title>
+ <datatype>
+ <name name="user_dir_common_option"/>
+ <desc>
+ <p>Sets the <seealso marker="#USERDIR">user directory</seealso>.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="user_dir_fun_common_option"/>
+ <name name="user2dir"/>
+ <desc>
+ <p>Sets the <seealso marker="#USERDIR">user directory</seealso> dynamically
+ by evaluating the <c>user2dir</c> function.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="system_dir_daemon_option"/>
+ <desc>
+ <p>Sets the <seealso marker="#SYSDIR">system directory</seealso>.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="pubkey_passphrase_client_options"/>
+ <desc>
+ <p>If the user's DSA, RSA or ECDSA key is protected by a passphrase, it can be
+ supplied with thoose options.
+ </p>
+ <p>Note that EdDSA passhrases (Curves 25519 and 448) are not implemented.</p>
+ </desc>
+ </datatype>
+
+ </datatypes>
+
+ <funcs>
+ <func>
+ <name since="OTP 21.2">host_key(Algorithm, DaemonOptions) -> {ok, Key} | {error, Reason}</name>
+ <fsummary></fsummary>
+ <desc>
+ <p><strong>Types and description</strong></p>
+ <p>See the api description in
+ <seealso marker="ssh:ssh_server_key_api#Module:host_key-2">ssh_server_key_api, Module:host_key/2</seealso>.
+ </p>
+ <p><strong>Options</strong></p>
+ <list>
+ <item><seealso marker="#type-system_dir_daemon_option">system_dir</seealso></item>
+ <!-- item>dsa_pass_phrase</item -->
+ <!-- item>rsa_pass_phrase</item -->
+ <!-- item>ecdsa_pass_phrase</item -->
+ </list>
+ <p><strong>Files</strong></p>
+ <list>
+ <item><seealso marker="#SYSDIR-ssh_host_rsa_key"><c>SYSDIR/ssh_host_rsa_key</c></seealso></item>
+ <item><seealso marker="#SYSDIR-ssh_host_dsa_key"><c>SYSDIR/ssh_host_dsa_key</c></seealso></item>
+ <item><seealso marker="#SYSDIR-ssh_host_ecdsa_key"><c>SYSDIR/ssh_host_ecdsa_key</c></seealso></item>
+ <item><seealso marker="#SYSDIR-ssh_host_ed25519_key"><c>SYSDIR/ssh_host_ed25519_key</c></seealso></item>
+ <item><seealso marker="#SYSDIR-ssh_host_ed448_key"><c>SYSDIR/ssh_host_ed448_key</c>c></seealso></item>
+ </list>
+ </desc>
+ </func>
+
+ <func>
+ <name since="OTP 21.2">is_auth_key(PublicUserKey, User, DaemonOptions) -> Result</name>
+ <fsummary></fsummary>
+ <desc>
+ <p><strong>Types and description</strong></p>
+ <p>See the api description in
+ <seealso marker="ssh:ssh_server_key_api#Module:is_auth_key-3">ssh_server_key_api: Module:is_auth_key/3</seealso>.
+ </p>
+ <p><strong>Options</strong></p>
+ <list>
+ <item><seealso marker="#type-user_dir_fun_common_option">user_dir_fun</seealso></item>
+ <item><seealso marker="#type-user_dir_common_option">user_dir</seealso></item>
+ </list>
+ <p><strong>Files</strong></p>
+ <list>
+ <item><seealso marker="#USERDIR-authorized_keys"><c>USERDIR/authorized_keys</c></seealso></item>
+ <item><seealso marker="#USERDIR-authorized_keys2"><c>USERDIR/authorized_keys2</c></seealso></item>
+ </list>
+ </desc>
+ </func>
+
+ <func>
+ <name since="OTP 21.2">add_host_key(HostNames, PublicHostKey, ConnectOptions) -> ok | {error, Reason}</name>
+ <fsummary></fsummary>
+ <desc>
+ <p><strong>Types and description</strong></p>
+ <p>See the api description in
+ <seealso marker="ssh:ssh_client_key_api#Module:add_host_key-3">ssh_client_key_api, Module:add_host_key/3</seealso>.
+ </p>
+ <p><strong>Option</strong></p>
+ <list>
+ <item><seealso marker="#type-user_dir_common_option">user_dir</seealso></item>
+ </list>
+ <p><strong>File</strong></p>
+ <list>
+ <item><seealso marker="#USERDIR-known_hosts"><c>USERDIR/known_hosts</c></seealso></item>
+ </list>
+ </desc>
+ </func>
+
+ <func>
+ <name since="OTP 21.2">is_host_key(Key, Host, Algorithm, ConnectOptions) -> Result</name>
+ <fsummary></fsummary>
+ <desc>
+ <p><strong>Types and description</strong></p>
+ <p>See the api description in
+ <seealso marker="ssh:ssh_client_key_api#Module:is_host_key-4">ssh_client_key_api, Module:is_host_key/4</seealso>.
+ </p>
+ <p><strong>Option</strong></p>
+ <list>
+ <item><seealso marker="#type-user_dir_common_option">user_dir</seealso></item>
+ </list>
+ <p><strong>File</strong></p>
+ <list>
+ <item><seealso marker="#USERDIR-known_hosts"><c>USERDIR/known_hosts</c></seealso></item>
+ </list>
+ </desc>
+ </func>
+
+ <func>
+ <name since="OTP 21.2">user_key(Algorithm, ConnectOptions) -> {ok, PrivateKey} | {error, Reason}</name>
+ <fsummary></fsummary>
+ <desc>
+ <p><strong>Types and description</strong></p>
+ <p>See the api description in
+ <seealso marker="ssh:ssh_client_key_api#Module:user_key-2">ssh_client_key_api, Module:user_key/2</seealso>.
+ </p>
+ <p><strong>Options</strong></p>
+ <list>
+ <item><seealso marker="#type-user_dir_common_option">user_dir</seealso></item>
+ <item><seealso marker="#type-pubkey_passphrase_client_options">dsa_pass_phrase</seealso></item>
+ <item><seealso marker="#type-pubkey_passphrase_client_options">rsa_pass_phrase</seealso></item>
+ <item><seealso marker="#type-pubkey_passphrase_client_options">ecdsa_pass_phrase</seealso></item>
+ </list>
+ <p>Note that EdDSA passhrases (Curves 25519 and 448) are not implemented.</p>
+ <p><strong>Files</strong></p>
+ <list>
+ <item><seealso marker="#USERDIR-id_dsa"><c>USERDIR/id_dsa</c></seealso></item>
+ <item><seealso marker="#USERDIR-id_rsa"><c>USERDIR/id_rsa</c></seealso></item>
+ <item><seealso marker="#USERDIR-id_ecdsa"><c>USERDIR/id_ecdsa</c></seealso></item>
+ <item><seealso marker="#USERDIR-id_ed25519"><c>USERDIR/id_ed25519</c></seealso></item>
+ <item><seealso marker="#USERDIR-id_ed448"><c>USERDIR/id_ed448</c></seealso></item>
+ </list>
+ </desc>
+ </func>
+
+ </funcs>
+
+</erlref>
diff --git a/lib/ssh/doc/src/ssh_protocol.xml b/lib/ssh/doc/src/ssh_protocol.xml
index a0032ab449..0d99a96997 100644
--- a/lib/ssh/doc/src/ssh_protocol.xml
+++ b/lib/ssh/doc/src/ssh_protocol.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2013</year><year>2016</year>
+ <year>2013</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -87,8 +87,10 @@
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 <seealso
- marker="ssh_channel">ssh_channel</seealso> behaviour makes it easy to
+ channel. The
+ <seealso marker="ssh_client_channel">ssh_client_channel</seealso> /
+ <seealso marker="ssh_server_channel">ssh_server_channel</seealso> (Replaces ssh_daemon_channel)
+ behaviours makes it easy to
write your own SSH client/server processes that use flow
control. It handles generic parts of SSH channel management and
lets you focus on the application logic.
diff --git a/lib/ssh/doc/src/ssh_server_channel.xml b/lib/ssh/doc/src/ssh_server_channel.xml
new file mode 100644
index 0000000000..87c745c9fb
--- /dev/null
+++ b/lib/ssh/doc/src/ssh_server_channel.xml
@@ -0,0 +1,176 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2009</year>
+ <year>2018</year>
+ <holder>Ericsson AB, All Rights Reserved</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ The Initial Developer of the Original Code is Ericsson AB.
+ </legalnotice>
+ <title>ssh_server_channel</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ </header>
+ <module since="OTP 21.0">ssh_server_channel</module>
+ <modulesummary>-behaviour(ssh_server_channel). (Replaces ssh_daemon_channel)
+ </modulesummary>
+ <description>
+ <note>
+ <p>This module replaces ssh_daemon_channel.</p>
+ <p>The old module is still available for compatibility, but should not be used for new programs.
+ The old module will not be maintained except for some error corrections
+ </p>
+ </note>
+
+ <p>SSH services (clients and servers) are implemented as channels
+ that are multiplexed over an SSH connection and communicates over
+ the <url href="http://www.ietf.org/rfc/rfc4254.txt"> SSH
+ Connection Protocol</url>. This module provides a callback API
+ that takes care of generic channel aspects for daemons, such as flow control
+ and close messages. It 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 <c>ssh</c> applications supervisor tree.
+ </p>
+
+ <note><p>When implementing a client subsystem handler, use
+ <seealso marker="ssh_client_channel">-behaviour(ssh_client_channel)</seealso> instead.
+ </p>
+ </note>
+
+ </description>
+
+ <section>
+ <title>Callback Functions</title>
+ <p>
+ The following functions are to be exported from a
+ <c>ssh_server_channel</c> callback module.
+ </p>
+ </section>
+
+ <funcs>
+ <func>
+ <name since="OTP 21.0">Module:init(Args) -> {ok, State} | {ok, State, timeout()} |
+ {stop, Reason}</name>
+ <fsummary>Makes necessary initializations and returns the
+ initial channel state if the initializations succeed.</fsummary>
+ <type>
+ <v>Args = term()</v>
+ <d>Last argument to <c>start_link/4</c>.</d>
+ <v>State = term()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Makes necessary initializations and returns the initial channel
+ state if the initializations succeed.
+ </p>
+ <p>The time-out values that can be returned
+ have the same semantics as in a <seealso marker="stdlib:gen_server">gen_server</seealso>.
+ If the time-out occurs, <seealso marker="#Module:handle_msg-2">handle_msg/2</seealso>
+ is called as <c>handle_msg(timeout, State)</c>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name since="OTP 21.0">Module:handle_msg(Msg, State) -> {ok, State} |
+ {stop, ChannelId, State}</name>
+
+ <fsummary>Handles other messages than SSH connection protocol,
+ call, or cast messages sent to the channel.</fsummary>
+ <type>
+ <v>Msg = timeout | term()</v>
+ <v>ChannelId = <seealso marker="ssh#type-channel_id">ssh:channel_id()</seealso></v>
+ <v>State = term() </v>
+ </type>
+ <desc>
+ <p>Handles other messages than SSH Connection Protocol, call, or
+ cast messages sent to the channel.
+ </p>
+
+ <p>Possible Erlang 'EXIT' messages is to be handled by this
+ function and all channels are to handle the following message.</p>
+
+ <taglist>
+ <tag><c>{ssh_channel_up, </c><seealso marker="ssh:ssh#type-channel_id">ssh:channel_id()</seealso><c>, </c><seealso marker="ssh:ssh#type-connection_ref">ssh:connection_ref()</seealso><c>}</c></tag>
+ <item><p>This is the first message that the channel receives.
+ 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, ignore it by
+ immediately returning <c>{ok, State}</c>.
+ </p></item>
+ </taglist>
+ </desc>
+ </func>
+
+ <func>
+ <name since="OTP 21.0">Module:handle_ssh_msg(Msg, State) -> {ok, State} | {stop,
+ ChannelId, State}</name>
+ <fsummary>Handles <c>ssh</c> connection protocol messages.</fsummary>
+ <type>
+ <v>Msg = <seealso marker="ssh_connection#type-event">ssh_connection:event()</seealso></v>
+ <v>ChannelId = <seealso marker="ssh#type-channel_id">ssh:channel_id()</seealso></v>
+ <v>State = term()</v>
+ </type>
+ <desc>
+ <p>Handles SSH Connection Protocol messages that may need
+ service-specific attention. For details,
+ see <seealso marker="ssh_connection#type-event">ssh_connection:event()</seealso>.
+ </p>
+
+ <p>The following message is taken care of by the
+ <c>ssh_server_channel</c> behavior.</p>
+
+ <taglist>
+ <tag><c>{closed, </c><seealso marker="ssh:ssh#type-channel_id">ssh:channel_id()</seealso><c>}</c></tag>
+ <item><p>The channel behavior sends a close message to the
+ other side, if such a message has not already been sent.
+ Then it terminates the channel with reason <c>normal</c>.</p></item>
+ </taglist>
+ </desc>
+ </func>
+
+ <func>
+ <name since="OTP 21.0">Module:terminate(Reason, State) -> _</name>
+ <fsummary>Does cleaning up before channel process termination.
+ </fsummary>
+ <type>
+ <v>Reason = term()</v>
+ <v>State = term()</v>
+ </type>
+ <desc>
+ <p>This function is called by a channel process when it is
+ about to terminate. Before this function is called, <seealso
+ marker="ssh_connection#close-2"> ssh_connection:close/2
+ </seealso> is called, if it has not been called earlier.
+ This function does any necessary cleaning
+ up. When it returns, the channel process terminates with
+ reason <c>Reason</c>. The return value is ignored.
+ </p>
+ </desc>
+ </func>
+
+ </funcs>
+
+</erlref>
diff --git a/lib/ssh/doc/src/ssh_server_key_api.xml b/lib/ssh/doc/src/ssh_server_key_api.xml
index c6808b95d1..013a788a4a 100644
--- a/lib/ssh/doc/src/ssh_server_key_api.xml
+++ b/lib/ssh/doc/src/ssh_server_key_api.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2012</year>
- <year>2015</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -29,7 +29,7 @@
<date></date>
<rev></rev>
</header>
- <module>ssh_server_key_api</module>
+ <module since="OTP R16B">ssh_server_key_api</module>
<modulesummary>
-behaviour(ssh_server_key_api).
</modulesummary>
@@ -41,7 +41,7 @@
see the <seealso marker="SSH_app"> ssh(6)</seealso> application manual.</p>
</description>
- <section>
+ <!-- section>
<title>DATA TYPES</title>
<p>Type definitions that are used more than once in this module,
@@ -69,22 +69,40 @@
| 'rsa-sha2-256' | 'rsa-sha2-384' | 'rsa-sha2-512'
| 'ecdsa-sha2-nistp256' | 'ecdsa-sha2-nistp384' | 'ecdsa-sha2-nistp521' </c></p></item>
</taglist>
- </section>
+ </section -->
+ <datatypes>
+ <datatype>
+ <name name="daemon_key_cb_options"/>
+ <desc>
+ <p>Options provided to <seealso marker="ssh#daemon-2">ssh:daemon/2,3</seealso>.
+ </p>
+ <p>The option list given in the
+ <seealso marker="ssh#type-key_cb_common_option"><c>key_cb</c></seealso>
+ option is available with the key <c>key_cb_private</c>.
+ </p>
+ </desc>
+ </datatype>
+ </datatypes>
+
<funcs>
<func>
- <name>Module:host_key(Algorithm, DaemonOptions) ->
+ <name since="OTP R16B">Module:host_key(Algorithm, DaemonOptions) ->
{ok, Key} | {error, Reason}</name>
<fsummary>Fetches the host’s private key.</fsummary>
<type>
- <v>Algorithm = public_key_algorithm()</v>
+ <v>Algorithm = <seealso marker="ssh#type-pubkey_alg">ssh:pubkey_alg()</seealso></v>
<d>Host key algorithm.</d>
- <v>DaemonOptions = proplists:proplist()</v>
- <d>Options provided to <seealso marker="ssh#daemon-2">ssh:daemon/[2,3]</seealso>. The option list given in
- the <c>key_cb</c> option is available with the key <c>key_cb_private</c>.</d>
- <v>Key = private_key() | crypto:engine_key_ref()</v>
+
+ <v>DaemonOptions = <seealso marker="#type-daemon_key_cb_options">daemon_key_cb_options()</seealso></v>
+
+ <v>PrivateKey = <seealso marker="public_key:public_key#type-private_key">public_key:private_key()</seealso>
+ | <seealso marker="crypto:crypto#type-engine_key_ref">crypto:engine_key_ref()</seealso>
+ </v>
+
<d>Private key of the host matching the <c>Algorithm</c>.
It may be a reference to a 'ssh-rsa', rsa-sha2-* or 'ssh-dss' (NOT ecdsa) key stored in a loaded Engine.</d>
+
<v>Reason = term()</v>
</type>
<desc>
@@ -93,16 +111,17 @@
</func>
<func>
- <name>Module:is_auth_key(Key, User, DaemonOptions) -> Result</name>
+ <name since="OTP R16B">Module:is_auth_key(PublicUserKey, User, DaemonOptions) -> Result</name>
<fsummary>Checks if the user key is authorized.</fsummary>
<type>
- <v>Key = public_key()</v>
+ <v>PublicUserKey = <seealso marker="public_key:public_key#type-public_key">public_key:public_key()</seealso></v>
<d>Normally an RSA, DSA or ECDSA public key, but handling of other public keys can be added</d>
+
<v>User = string()</v>
<d>User owning the public key.</d>
- <v>DaemonOptions = proplists:proplist()</v>
- <d>Options provided to <seealso marker="ssh#daemon-2">ssh:daemon/[2,3]</seealso>. The option list given in
- the <c>key_cb</c> option is available with the key <c>key_cb_private</c>.</d>
+
+ <v>DaemonOptions = <seealso marker="#type-daemon_key_cb_options">daemon_key_cb_options()</seealso></v>
+
<v>Result = boolean()</v>
</type>
<desc>
diff --git a/lib/ssh/doc/src/ssh_sftp.xml b/lib/ssh/doc/src/ssh_sftp.xml
index f367560b5f..f9f1e0953b 100644
--- a/lib/ssh/doc/src/ssh_sftp.xml
+++ b/lib/ssh/doc/src/ssh_sftp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2005</year><year>2017</year>
+ <year>2005</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -29,7 +29,7 @@
<rev></rev>
<file>ssh_sftp.sgml</file>
</header>
- <module>ssh_sftp</module>
+ <module since="">ssh_sftp</module>
<modulesummary>SFTP client.</modulesummary>
<description>
<p>This module implements an SSH FTP (SFTP) client. SFTP is a
@@ -37,60 +37,112 @@
SSH.</p>
</description>
- <section>
- <title>DATA TYPES</title>
- <p>Type definitions that are used more than once in this module,
- or abstractions to indicate the intended use of the data type, or both:
- </p>
-
- <taglist>
- <tag><c>reason()</c></tag>
- <item>
- <p>= <c>atom() | string() | tuple() </c>A description of the reason why an operation failed.</p>
- <p>
- The <c>atom()</c> value is formed from the sftp error codes in the protocol-level responses as defined in
- <url href="https://tools.ietf.org/id/draft-ietf-secsh-filexfer-13.txt">draft-ietf-secsh-filexfer-13.txt</url>
- section 9.1.
- </p>
- <p>
+ <datatypes>
+ <datatype>
+ <name name="sftp_option"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype_title>Error cause</datatype_title>
+ <datatype>
+ <name name="reason"/>
+ <desc>
+ <p>A description of the reason why an operation failed.</p>
+ <p>The <c>atom()</c> value is formed from the sftp error codes in the protocol-level responses as defined in
+ <url href="https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#page-49">draft-ietf-secsh-filexfer-13</url>
+ section 9.1.
The codes are named as <c>SSH_FX_*</c> which are transformed into lowercase of the star-part.
E.g. the error code <c>SSH_FX_NO_SUCH_FILE</c>
will cause the <c>reason()</c> to be <c>no_such_file</c>.
</p>
<p>The <c>string()</c> reason is the error information from the server in case of an exit-signal. If that information is empty, the reason is the exit signal name.
</p>
- <p>The <c>tuple()</c> reason are other errors like the <c>{exit_status,integer()}</c> if the exit status is not 0.
+ <p>The <c>tuple()</c> reason are other errors like for example <c>{exit_status,1}</c>.
</p>
- </item>
+ </desc>
+ </datatype>
- <tag><c>ssh_connection_ref() =</c></tag>
- <item><p><c>opaque()</c> - as returned by
- <seealso marker="ssh#connect-3"><c>ssh:connect/3</c></seealso></p></item>
+ <datatype_title>Crypto operations for open_tar</datatype_title>
+ <datatype>
+ <name name="tar_crypto_spec"/>
+ <name name="encrypt_spec"/>
+ <name name="decrypt_spec"/>
+ <desc>
+ <p>Specifies the encryption or decryption applied to tar files when using
+ <seealso marker="#open_tar/3">open_tar/3</seealso> or
+ <seealso marker="#open_tar/4">open_tar/4</seealso>.
+ </p>
+ <p>The encryption or decryption is applied to the generated stream of
+ bytes prior to sending the resulting stream to the SFTP server.
+ </p>
+ <p>For code examples see Section
+ <seealso marker="using_ssh#example-with-encryption">Example with encryption</seealso>
+ in the ssh Users Guide.
+ </p>
+ </desc>
+ </datatype>
- <tag><c>timeout()</c></tag>
- <item><p>= <c>infinity | integer()</c> in milliseconds. Default infinity.</p></item>
- </taglist>
- </section>
+ <datatype>
+ <name name="init_fun"/>
+ <name name="chunk_size"/>
+ <name name="crypto_state"/>
+ <desc>
+ <p>The <c>init_fun()</c> in the
+ <seealso marker="#type-tar_crypto_spec">tar_crypto_spec</seealso>
+ is applied once prior to any other <c>crypto</c>
+ operation. The intention is that this function initiates the encryption or
+ decryption for example by calling
+ <seealso marker="crypto:crypto#crypto_init/4">crypto:crypto_init/4</seealso>
+ or similar. The <c>crypto_state()</c> is the state such a function may return.
+ </p>
+ <p>If the selected cipher needs to have the input data partioned into
+ blocks of a certain size, the <c>init_fun()</c> should return the second
+ form of return value with the <c>chunk_size()</c> set to the block size.
+ If the <c>chunk_size()</c> is <c>undefined</c>, the size of the <c>PlainBin</c>s varies,
+ because this is intended for stream crypto, whereas a fixed <c>chunk_size()</c> is intended for block crypto.
+ A <c>chunk_size()</c> can be changed in the return from the <c>crypto_fun()</c>.
+ The value can be changed between <c>pos_integer()</c> and <c>undefined</c>.
+ </p>
+ </desc>
+ </datatype>
- <section>
- <title>Time-outs</title>
- <p>If the request functions for the SFTP channel return <c>{error, timeout}</c>,
- no answer was received from the server within the expected time.</p>
- <p>The request may have reached the server and may have been performed.
- However, no answer was received from the server within the expected time.</p>
- </section>
+ <datatype>
+ <name name="crypto_fun"/>
+ <name name="crypto_result"/>
+ <desc>
+ <p>The initial <c>crypto_state()</c> returned from the
+ <seealso marker="#type-init_fun">init_fun()</seealso>
+ is folded into repeated applications of the <c>crypto_fun()</c> in the
+ <seealso marker="#type-tar_crypto_spec">tar_crypto_spec</seealso>.
+ The binary returned from that fun is sent to the remote SFTP server and
+ the new <c>crypto_state()</c> is used in the next call of the
+ <c>crypto_fun()</c>.
+ </p>
+ <p>If the <c>crypto_fun()</c> reurns a <c>chunk_size()</c>, that value
+ is as block size for further blocks in calls to <c>crypto_fun()</c>.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="final_fun"/>
+ <desc>
+ <p>If doing encryption,
+ the <c>final_fun()</c> in the
+ <seealso marker="#type-tar_crypto_spec">tar_crypto_spec</seealso>
+ is applied to the last piece of data.
+ The <c>final_fun()</c> is responsible for padding (if needed) and
+ encryption of that last piece.
+ </p>
+ </desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>apread(ChannelPid, Handle, Position, Len) -> {async, N} | {error, reason()}</name>
+ <name name="apread" arity="4" since=""/>
<fsummary>Reads asynchronously from an open file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Handle = term()</v>
- <v>Position = integer()</v>
- <v>Len = integer()</v>
- <v>N = term()</v>
- </type>
<desc><p>The <c><![CDATA[apread/4]]></c> function reads from a specified position,
combining the <seealso marker="#position-3"><c>position/3</c></seealso> and
<seealso marker="#aread-3"><c>aread/3</c></seealso> functions.</p>
@@ -98,17 +150,8 @@
</func>
<func>
- <name>apwrite(ChannelPid, Handle, Position, Data) -> {async, N} | {error, reason()}</name>
+ <name name="apwrite" arity="4" since=""/>
<fsummary>Writes asynchronously to an open file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Handle = term()</v>
- <v>Position = integer()</v>
- <v>Len = integer()</v>
- <v>Data = binary()</v>
- <v>Timeout = timeout()</v>
- <v>N = term()</v>
- </type>
<desc><p>The <c><![CDATA[apwrite/4]]></c> function writes to a specified position,
combining the <seealso marker="#position-3"><c>position/3</c></seealso> and
<seealso marker="#awrite-3"><c>awrite/3</c></seealso> functions.</p>
@@ -116,15 +159,8 @@
</func>
<func>
- <name>aread(ChannelPid, Handle, Len) -> {async, N} | {error, reason()}</name>
+ <name name="aread" arity="3" since=""/>
<fsummary>Reads asynchronously from an open file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Handle = term()</v>
- <v>Position = integer()</v>
- <v>Len = integer()</v>
- <v>N = term()</v>
- </type>
<desc>
<p>Reads from an open file, without waiting for the result. If the
handle is valid, the function returns <c><![CDATA[{async, N}]]></c>, where <c>N</c>
@@ -137,16 +173,8 @@
</func>
<func>
- <name>awrite(ChannelPid, Handle, Data) -> {async, N} | {error, reason()}</name>
+ <name name="awrite" arity="3" since=""/>
<fsummary>Writes asynchronously to an open file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Handle = term()</v>
- <v>Position = integer()</v>
- <v>Len = integer()</v>
- <v>Data = binary()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Writes to an open file, without waiting for the result. If the
handle is valid, the function returns <c><![CDATA[{async, N}]]></c>, where <c>N</c>
@@ -159,28 +187,18 @@
</func>
<func>
- <name>close(ChannelPid, Handle) -></name>
- <name>close(ChannelPid, Handle, Timeout) -> ok | {error, reason()}</name>
+ <name name="close" arity="2" since=""/>
+ <name name="close" arity="3" since=""/>
<fsummary>Closes an open handle.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Handle = term()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Closes a handle to an open file or directory on the server.</p>
</desc>
</func>
<func>
- <name>delete(ChannelPid, Name) -></name>
- <name>delete(ChannelPid, Name, Timeout) -> ok | {error, reason()}</name>
+ <name name="delete" arity="2" since=""/>
+ <name name="delete" arity="3" since=""/>
<fsummary>Deletes a file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Name = string()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Deletes the file specified by <c><![CDATA[Name]]></c>.
</p>
@@ -188,14 +206,9 @@
</func>
<func>
- <name>del_dir(ChannelPid, Name) -></name>
- <name>del_dir(ChannelPid, Name, Timeout) -> ok | {error, reason()}</name>
+ <name name="del_dir" arity="2" since=""/>
+ <name name="del_dir" arity="3" since=""/>
<fsummary>Deletes an empty directory.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Name = string()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Deletes a directory specified by <c><![CDATA[Name]]></c>.
The directory must be empty before it can be successfully deleted.
@@ -204,16 +217,9 @@
</func>
<func>
- <name>list_dir(ChannelPid, Path) -></name>
- <name>list_dir(ChannelPid, Path, Timeout) -> {ok, Filenames} | {error, reason()}</name>
+ <name name="list_dir" arity="2" since=""/>
+ <name name="list_dir" arity="3" since=""/>
<fsummary>Lists the directory.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Path = string()</v>
- <v>Filenames = [Filename]</v>
- <v>Filename = string()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Lists the given directory on the server, returning the
filenames as a list of strings.</p>
@@ -221,14 +227,9 @@
</func>
<func>
- <name>make_dir(ChannelPid, Name) -></name>
- <name>make_dir(ChannelPid, Name, Timeout) -> ok | {error, reason()}</name>
+ <name name="make_dir" arity="2" since=""/>
+ <name name="make_dir" arity="3" since=""/>
<fsummary>Creates a directory.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Name = string()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Creates a directory specified by <c><![CDATA[Name]]></c>. <c><![CDATA[Name]]></c>
must be a full path to a new directory. The directory can only be
@@ -237,14 +238,9 @@
</func>
<func>
- <name>make_symlink(ChannelPid, Name, Target) -></name>
- <name>make_symlink(ChannelPid, Name, Target, Timeout) -> ok | {error, reason()}</name>
+ <name name="make_symlink" arity="3" since=""/>
+ <name name="make_symlink" arity="4" since=""/>
<fsummary>Creates a symbolic link.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Name = string()</v>
- <v>Target = string()</v>
- </type>
<desc>
<p>Creates a symbolic link pointing to <c><![CDATA[Target]]></c> with the
name <c><![CDATA[Name]]></c>.
@@ -252,32 +248,19 @@
</desc>
</func>
- <func>
- <name>open(ChannelPid, File, Mode) -></name>
- <name>open(ChannelPid, File, Mode, Timeout) -> {ok, Handle} | {error, reason()}</name>
+ <func>
+ <name name="open" arity="3" since=""/>
+ <name name="open" arity="4" since=""/>
<fsummary>Opens a file and returns a handle.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>File = string()</v>
- <v>Mode = [Modeflag]</v>
- <v>Modeflag = read | write | creat | trunc | append | binary</v>
- <v>Timeout = timeout()</v>
- <v>Handle = term()</v>
- </type>
<desc>
<p>Opens a file on the server and returns a handle, which
can be used for reading or writing.</p>
</desc>
</func>
<func>
- <name>opendir(ChannelPid, Path) -></name>
- <name>opendir(ChannelPid, Path, Timeout) -> {ok, Handle} | {error, reason()}</name>
+ <name name="opendir" arity="2" since=""/>
+ <name name="opendir" arity="3" since=""/>
<fsummary>Opens a directory and returns a handle.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Path = string()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Opens a handle to a directory on the server. The handle
can be used for reading directory contents.</p>
@@ -285,72 +268,36 @@
</func>
<func>
- <name>open_tar(ChannelPid, Path, Mode) -></name>
- <name>open_tar(ChannelPid, Path, Mode, Timeout) -> {ok, Handle} | {error, reason()}</name>
+ <name name="open_tar" arity="3" since="OTP 17.4"/>
+ <name name="open_tar" arity="4" since="OTP 17.4"/>
<fsummary>Opens a tar file on the server to which <c>ChannelPid</c>
is connected and returns a handle.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Path = string()</v>
- <v>Mode = [read] | [write] | [read,EncryptOpt] | [write,DecryptOpt]</v>
- <v>EncryptOpt = {crypto,{InitFun,EncryptFun,CloseFun}}</v>
- <v>DecryptOpt = {crypto,{InitFun,DecryptFun}}</v>
- <v>InitFun = (fun() -> {ok,CryptoState}) | (fun() -> {ok,CryptoState,ChunkSize})</v>
- <v>CryptoState = any()</v>
- <v>ChunkSize = undefined | pos_integer()</v>
- <v>EncryptFun = (fun(PlainBin,CryptoState) -> EncryptResult)</v>
- <v>EncryptResult = {ok,EncryptedBin,CryptoState} | {ok,EncryptedBin,CryptoState,ChunkSize}</v>
- <v>PlainBin = binary()</v>
- <v>EncryptedBin = binary()</v>
- <v>DecryptFun = (fun(EncryptedBin,CryptoState) -> DecryptResult)</v>
- <v>DecryptResult = {ok,PlainBin,CryptoState} | {ok,PlainBin,CryptoState,ChunkSize}</v>
- <v>CloseFun = (fun(PlainBin,CryptoState) -> {ok,EncryptedBin})</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Opens a handle to a tar file on the server, associated with <c>ChannelPid</c>.
- The handle can be used for remote tar creation and extraction, as defined by the
- <seealso marker="stdlib:erl_tar#init-3">erl_tar:init/3</seealso> function.
- </p>
-
- <p> For code exampel see Section
- <seealso marker="using_ssh">SFTP Client with TAR Compression and Encryption</seealso> in
- the ssh Users Guide. </p>
-
- <p>The <c>crypto</c> mode option is applied to the generated stream of bytes prior to sending
- them to the SFTP server. This is intended for encryption but can be used for other
- purposes.
+ The handle can be used for remote tar creation and extraction. The actual writing
+ and reading is performed by calls to
+ <seealso marker="stdlib:erl_tar#add-3">erl_tar:add/3,4</seealso> and
+ <seealso marker="stdlib:erl_tar#extract-2">erl_tar:extract/2</seealso>.
+ Note: The
+ <seealso marker="stdlib:erl_tar#init-3">erl_tar:init/3</seealso> function should not
+ be called, that one is called by this open_tar function.
</p>
- <p>The <c>InitFun</c> is applied once
- prior to any other <c>crypto</c> operation. The returned <c>CryptoState</c> is then folded into
- repeated applications of the <c>EncryptFun</c> or <c>DecryptFun</c>. The binary returned
- from those funs are sent further to the remote SFTP server. Finally, if doing encryption,
- the <c>CloseFun</c> is applied to the last piece of data. The <c>CloseFun</c> is
- responsible for padding (if needed) and encryption of that last piece.
+ <p>For code examples see Section
+ <seealso marker="using_ssh#sftp-client-with-tar-compression">SFTP Client with TAR Compression</seealso>
+ in the ssh Users Guide.
</p>
- <p>The <c>ChunkSize</c> defines the size of the <c>PlainBin</c>s that <c>EncodeFun</c> is applied
- to. If the <c>ChunkSize</c> is <c>undefined</c>, the size of the <c>PlainBin</c>s varies,
- because this is intended for stream crypto, whereas a fixed <c>ChunkSize</c> is intended for block crypto.
- <c>ChunkSize</c>s can be changed in the return from the <c>EncryptFun</c> or
- <c>DecryptFun</c>. The value can be changed between <c>pos_integer()</c> and <c>undefined</c>.
+ <p>The <c>crypto</c> mode option is explained in the data types section above, see
+ <seealso marker="#Crypto operations for open_tar">Crypto operations for open_tar</seealso>.
+ Encryption is assumed if the <c>Mode</c> contains <c>write</c>, and
+ decryption if the <c>Mode</c> contains <c>read</c>.
</p>
-
</desc>
</func>
<func>
- <name>position(ChannelPid, Handle, Location) -></name>
- <name>position(ChannelPid, Handle, Location, Timeout) -> {ok, NewPosition | {error, reason()}</name>
+ <name name="position" arity="3" since=""/>
+ <name name="position" arity="4" since=""/>
<fsummary>Sets the file position of a file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Handle = term()</v>
- <v>Location = Offset
- | {bof, Offset} | {cur, Offset} | {eof, Offset} | bof | cur | eof</v>
- <v>Offset = integer()</v>
- <v>Timeout = timeout()</v>
- <v>NewPosition = integer()</v>
- </type>
<desc>
<p>Sets the file position of the file referenced by <c><![CDATA[Handle]]></c>.
Returns <c><![CDATA[{ok, NewPosition}]]></c> (as an absolute offset) if
@@ -384,17 +331,9 @@
</func>
<func>
- <name>pread(ChannelPid, Handle, Position, Len) -></name>
- <name>pread(ChannelPid, Handle, Position, Len, Timeout) -> {ok, Data} | eof | {error, reason()}</name>
+ <name name="pread" arity="4" since=""/>
+ <name name="pread" arity="5" since=""/>
<fsummary>Reads from an open file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Handle = term()</v>
- <v>Position = integer()</v>
- <v>Len = integer()</v>
- <v>Timeout = timeout()</v>
- <v>Data = string() | binary()</v>
- </type>
<desc><p>The <c><![CDATA[pread/3,4]]></c> function reads from a specified position,
combining the <seealso marker="#position-3"><c>position/3</c></seealso> and
<seealso marker="#read-3"><c>read/3,4</c></seealso> functions.</p>
@@ -402,16 +341,9 @@
</func>
<func>
- <name>pwrite(ChannelPid, Handle, Position, Data) -> ok</name>
- <name>pwrite(ChannelPid, Handle, Position, Data, Timeout) -> ok | {error, reason()}</name>
+ <name name="pwrite" arity="4" since=""/>
+ <name name="pwrite" arity="5" since=""/>
<fsummary>Writes to an open file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Handle = term()</v>
- <v>Position = integer()</v>
- <v>Data = iolist()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc><p>The <c><![CDATA[pwrite/3,4]]></c> function writes to a specified position,
combining the <seealso marker="#position-3"><c>position/3</c></seealso> and
<seealso marker="#write-3"><c>write/3,4</c></seealso> functions.</p>
@@ -419,17 +351,9 @@
</func>
<func>
- <name>read(ChannelPid, Handle, Len) -></name>
- <name>read(ChannelPid, Handle, Len, Timeout) -> {ok, Data} | eof | {error, reason()}</name>
+ <name name="read" arity="3" since=""/>
+ <name name="read" arity="4" since=""/>
<fsummary>Reads from an open file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Handle = term()</v>
- <v>Position = integer()</v>
- <v>Len = integer()</v>
- <v>Timeout = timeout()</v>
- <v>Data = string() | binary()</v>
- </type>
<desc>
<p>Reads <c><![CDATA[Len]]></c> bytes from the file referenced by
<c><![CDATA[Handle]]></c>. Returns <c><![CDATA[{ok, Data}]]></c>, <c><![CDATA[eof]]></c>, or
@@ -441,32 +365,19 @@
</desc>
</func>
- <func>
- <name>read_file(ChannelPid, File) -></name>
- <name>read_file(ChannelPid, File, Timeout) -> {ok, Data} | {error, reason()}</name>
+ <func>
+ <name name="read_file" arity="2" since=""/>
+ <name name="read_file" arity="3" since=""/>
<fsummary>Reads a file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>File = string()</v>
- <v>Data = binary()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Reads a file from the server, and returns the data in a binary.</p>
</desc>
</func>
- <func>
- <name>read_file_info(ChannelPid, Name) -></name>
- <name>read_file_info(ChannelPid, Name, Timeout) -> {ok, FileInfo} | {error, reason()}</name>
+ <func>
+ <name name="read_file_info" arity="2" since=""/>
+ <name name="read_file_info" arity="3" since=""/>
<fsummary>Gets information about a file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Name = string()</v>
- <v>Handle = term()</v>
- <v>Timeout = timeout()</v>
- <v>FileInfo = record()</v>
- </type>
<desc>
<p>Returns a <c><![CDATA[file_info]]></c> record from the file system object specified by
<c><![CDATA[Name]]></c> or <c><![CDATA[Handle]]></c>. See
@@ -475,38 +386,26 @@
</p>
<p>
Depending on the underlying OS:es links might be followed and info on the final file, directory
- etc is returned. See <seealso marker="#read_link_info-2">ssh_sftp::read_link_info/2</seealso>
+ etc is returned. See <seealso marker="#read_link_info-2">read_link_info/2</seealso>
on how to get information on links instead.
</p>
</desc>
</func>
<func>
- <name>read_link(ChannelPid, Name) -></name>
- <name>read_link(ChannelPid, Name, Timeout) -> {ok, Target} | {error, reason()}</name>
+ <name name="read_link" arity="2" since=""/>
+ <name name="read_link" arity="3" since=""/>
<fsummary>Reads symbolic link.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Name = string()</v>
- <v>Target = string()</v>
- </type>
<desc>
<p>Reads the link target from the symbolic link specified by <c><![CDATA[name]]></c>.
</p>
</desc>
</func>
- <func>
- <name>read_link_info(ChannelPid, Name) -> {ok, FileInfo} | {error, reason()}</name>
- <name>read_link_info(ChannelPid, Name, Timeout) -> {ok, FileInfo} | {error, reason()}</name>
+ <func>
+ <name since="" name="read_link_info" arity="2"/>
+ <name since="" name="read_link_info" arity="3"/>
<fsummary>Gets information about a symbolic link.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Name = string()</v>
- <v>Handle = term()</v>
- <v>Timeout = timeout()</v>
- <v>FileInfo = record()</v>
- </type>
<desc>
<p>Returns a <c><![CDATA[file_info]]></c> record from the symbolic
link specified by <c><![CDATA[Name]]></c> or <c><![CDATA[Handle]]></c>.
@@ -518,15 +417,9 @@
</func>
<func>
- <name>rename(ChannelPid, OldName, NewName) -> </name>
- <name>rename(ChannelPid, OldName, NewName, Timeout) -> ok | {error, reason()}</name>
+ <name since="" name="rename" arity="3"/>
+ <name since="" name="rename" arity="4"/>
<fsummary>Renames a file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>OldName = string()</v>
- <v>NewName = string()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Renames a file named <c><![CDATA[OldName]]></c> and gives it the name
<c><![CDATA[NewName]]></c>.
@@ -535,26 +428,28 @@
</func>
<func>
- <name>start_channel(ConnectionRef) -></name>
- <name>start_channel(ConnectionRef, Options) ->
- {ok, Pid} | {error, reason()|term()}</name>
+ <name since="">start_channel(ConnectionRef) -></name>
+ <name since="">start_channel(ConnectionRef, SftpOptions) ->
+ {ok, ChannelPid} | Error</name>
- <name>start_channel(Host, Options) -></name>
- <name>start_channel(Host, Port, Options) ->
- {ok, Pid, ConnectionRef} | {error, reason()|term()}</name>
-
- <name>start_channel(TcpSocket) -></name>
- <name>start_channel(TcpSocket, Options) ->
- {ok, Pid, ConnectionRef} | {error, reason()|term()}</name>
+ <name since="">start_channel(Host) -></name>
+ <name since="">start_channel(Host, Options) -></name>
+ <name since="">start_channel(Host, Port, Options) -></name>
+ <name since="">start_channel(TcpSocket) -></name>
+ <name since="">start_channel(TcpSocket, Options) ->
+ {ok, ChannelPid, ConnectionRef} | Error</name>
<fsummary>Starts an SFTP client.</fsummary>
<type>
- <v>Host = string()</v>
- <v>ConnectionRef = ssh_connection_ref()</v>
- <v>Port = integer()</v>
- <v>TcpSocket = port()</v>
- <d>The socket is supposed to be from <seealso marker="kernel:gen_tcp#connect-3">gen_tcp:connect</seealso> or <seealso marker="kernel:gen_tcp#accept-1">gen_tcp:accept</seealso> with option <c>{active,false}</c></d>
- <v>Options = [{Option, Value}]</v>
+ <v>Host = <seealso marker="ssh:ssh#type-host">ssh:host()</seealso></v>
+ <v>Port = <seealso marker="kernel:inet#type-port_number">inet:port_number()</seealso></v>
+ <v>TcpSocket = <seealso marker="ssh:ssh#type-open_socket">ssh:open_socket()</seealso></v>
+ <v>Options = [ <seealso marker="#type-sftp_option">sftp_option()</seealso>
+ | <seealso marker="ssh:ssh#type-client_option">ssh:client_option()</seealso> ]</v>
+ <v>SftpOptions = [ <seealso marker="#type-sftp_option">sftp_option()</seealso> ]</v>
+ <v>ChannelPid = pid()</v>
+ <v>ConnectionRef = <seealso marker="ssh:ssh#type-connection_ref">ssh:connection_ref()</seealso></v>
+ <v>Error = {error, <seealso marker="#type-reason">reason()</seealso>}</v>
</type>
<desc>
<p>If no connection reference is provided, a connection is set
@@ -595,11 +490,8 @@
</func>
<func>
- <name>stop_channel(ChannelPid) -> ok</name>
+ <name since="" name="stop_channel" arity="1"/>
<fsummary>Stops the SFTP client channel.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- </type>
<desc>
<p>Stops an SFTP channel. Does not close the SSH connection.
Use <seealso marker="ssh#close-1">ssh:close/1</seealso> to close it.</p>
@@ -607,16 +499,9 @@
</func>
<func>
- <name>write(ChannelPid, Handle, Data) -></name>
- <name>write(ChannelPid, Handle, Data, Timeout) -> ok | {error, reason()}</name>
+ <name since="" name="write" arity="3"/>
+ <name since="" name="write" arity="4"/>
<fsummary>Writes to an open file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Handle = term()</v>
- <v>Position = integer()</v>
- <v>Data = iolist()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Writes <c><![CDATA[data]]></c> to the file referenced by <c><![CDATA[Handle]]></c>.
The file is to be opened with <c><![CDATA[write]]></c> or <c><![CDATA[append]]></c>
@@ -626,15 +511,9 @@
</func>
<func>
- <name>write_file(ChannelPid, File, Iolist) -></name>
- <name>write_file(ChannelPid, File, Iolist, Timeout) -> ok | {error, reason()}</name>
+ <name since="" name="write_file" arity="3"/>
+ <name since="" name="write_file" arity="4"/>
<fsummary>Writes a file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>File = string()</v>
- <v>Iolist = iolist()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Writes a file to the server. The file is created if it does not exist
but overwritten if it exists.</p>
@@ -642,15 +521,9 @@
</func>
<func>
- <name>write_file_info(ChannelPid, Name, Info) -></name>
- <name>write_file_info(ChannelPid, Name, Info, Timeout) -> ok | {error, reason()}</name>
+ <name since="" name="write_file_info" arity="3"/>
+ <name since="" name="write_file_info" arity="4"/>
<fsummary>Writes information for a file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Name = string()</v>
- <v>Info = record()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Writes file information from a <c><![CDATA[file_info]]></c> record to the
file specified by <c><![CDATA[Name]]></c>. See
diff --git a/lib/ssh/doc/src/ssh_sftpd.xml b/lib/ssh/doc/src/ssh_sftpd.xml
index 1be29b3b29..0d7b340399 100644
--- a/lib/ssh/doc/src/ssh_sftpd.xml
+++ b/lib/ssh/doc/src/ssh_sftpd.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2005</year><year>2016</year>
+ <year>2005</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -29,43 +29,29 @@
<rev></rev>
<file>ssh_sftpd.sgml</file>
</header>
- <module>ssh_sftpd</module>
+ <module since="">ssh_sftpd</module>
<modulesummary>Specifies the channel process to handle an SFTP subsystem.</modulesummary>
<description>
<p>Specifies a channel process to handle an SFTP subsystem.</p>
</description>
- <section>
- <title>DATA TYPES</title>
- <taglist>
- <tag><c>subsystem_spec() =</c></tag>
- <item><p><c>{subsystem_name(), {channel_callback(), channel_init_args()}}</c></p></item>
- <tag><c>subsystem_name() =</c></tag>
- <item><p><c>"sftp"</c></p></item>
- <tag><c>channel_callback() =</c></tag>
- <item><p><c>atom()</c> - Name of the Erlang module implementing the subsystem using the
- <c>ssh_channel</c> behavior, see the
- <seealso marker="ssh_channel">ssh_channel(3)</seealso> manual page.</p></item>
- <tag><c>channel_init_args() =</c></tag>
- <item><p><c>list()</c> - The one given as argument to function <c>subsystem_spec/1</c>.</p></item>
- </taglist>
- </section>
<funcs>
<func>
- <name>subsystem_spec(Options) -> subsystem_spec()</name>
+ <name name="subsystem_spec" arity="1" since=""/>
<fsummary>Returns the subsystem specification that allows an SSH daemon to handle the subsystem "sftp".</fsummary>
- <type>
- <v>Options = [{Option, Value}]</v>
- </type>
<desc>
<p>Is to be used together with <c>ssh:daemon/[1,2,3]</c></p>
+ <p>The <c>Name</c> is <c>"sftp"</c> and
+ <c>CbMod</c> is the name of the Erlang module implementing the subsystem using the
+ <seealso marker="ssh_server_channel">ssh_server_channel</seealso> (replaces ssh_daemon_channel) behaviour.
+ </p>
<p>Options:</p>
<taglist>
- <tag><c><![CDATA[{cwd, String}]]></c></tag>
+ <tag><c>cwd</c></tag>
<item>
<p>Sets the initial current working directory for the server.</p>
</item>
- <tag><c><![CDATA[{file_handler, CallbackModule}]]></c></tag>
+ <tag><c>file_handler</c></tag>
<item>
<p>Determines which module to call for accessing
the file server. The default value is <c>ssh_sftpd_file</c>, which uses the
@@ -73,13 +59,13 @@
APIs to access the standard OTP file server. This option can be used to plug in
other file servers.</p>
</item>
- <tag><c><![CDATA[{max_files, Integer}]]></c></tag>
+ <tag><c>max_files</c></tag>
<item>
<p>The default value is <c>0</c>, which means that there is no upper limit.
If supplied, the number of filenames returned to the SFTP client per <c>READDIR</c>
request is limited to at most the given value.</p>
</item>
- <tag><c><![CDATA[{root, String}]]></c></tag>
+ <tag><c>root</c></tag>
<item>
<p>Sets the SFTP root directory. Then the user cannot see any files
above this root. If, for example, the root directory is set to <c>/tmp</c>,
@@ -87,7 +73,7 @@
<c>cd /etc</c>, the user moves to <c>/tmp/etc</c>.
</p>
</item>
- <tag><c><![CDATA[{sftpd_vsn, integer()}]]></c></tag>
+ <tag><c>sftpd_vsn</c></tag>
<item>
<p>Sets the SFTP version to use. Defaults to 5. Version 6 is under
development and limited.</p>
diff --git a/lib/ssh/doc/src/terminology.xml b/lib/ssh/doc/src/terminology.xml
new file mode 100644
index 0000000000..db1e08970d
--- /dev/null
+++ b/lib/ssh/doc/src/terminology.xml
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2018</year>
+ <year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>Terminology</title>
+ <prepared></prepared>
+ <docno></docno>
+ <approved></approved>
+ <date></date>
+ <rev></rev>
+ <file>terminology.xml</file>
+ </header>
+
+ <section>
+ <title>General Information</title>
+ <p>In the following terms that may cause confusion are explained.
+ </p>
+ </section>
+
+ <section>
+ <title>The term "user"</title>
+ <p>A "user" is a term that everyone understands intuitively. However, the understandings may differ which can
+ cause confusion.
+ </p>
+ <p>The term is used differently in <url href="http://www.openssh.com">OpenSSH</url> and SSH in Erlang/OTP.
+ The reason is the different environments and use cases that are not immediatly obvious.
+ </p>
+ <p>This chapter aims at explaining the differences and giving a rationale for why Erlang/OTP handles "user" as
+ it does.
+ </p>
+
+ <section>
+ <title>In OpenSSH</title>
+ <p>Many have been in contact with the command 'ssh' on a Linux machine (or similar) to remotly log in on
+ another machine. One types
+ </p>
+ <code>ssh host</code>
+ <p>to log in on the machine named <c>host</c>. The command prompts for your password on the remote <c>host</c> and
+ then you can read, write and execute as your <i>user name</i> has rights on the remote <c>host</c>. There are
+ stronger variants with pre-distributed keys or certificates, but that are for now just details in the
+ authentication process.
+ </p>
+ <p>You could log in as the user <c>anotheruser</c> with
+ </p>
+ <code>ssh anotheruser@host</code>
+ <p>and you will then be enabled to act as <c>anotheruser</c> on the <c>host</c> if authorized correctly.
+ </p>
+ <p>So what does <i>"your user name has rights"</i> mean? In a UNIX/Linux/etc context it is exactly as that context:
+ The <i>user</i> could read, write and execute programs according to the OS rules.
+ In addition, the user has a home directory (<c>$HOME</c>) and there is a <c>$HOME/.ssh/</c> directory
+ with ssh-specific files.
+ </p>
+ <section>
+ <title>SSH password authentication</title>
+ <p>When SSH tries to log in to a host, the ssh protocol communicates the user name (as a string) and a password.
+ The remote ssh server checks that there is such a user defined and that the provided password is acceptable.
+ </p>
+ <p>If so, the user is authorized.
+ </p>
+ </section>
+ <section>
+ <title>SSH public key authentication</title>
+ <p>This is a stronger method where the ssh protocol brings the user name, the user's public key and some
+ cryptographic information which we could ignore here.
+ </p>
+ <p>The ssh server on the remote host checks:
+ </p>
+ <list>
+ <item>That the <i>user</i> has a home directory,</item>
+ <item>that home directory contains a .ssh/ directory and</item>
+ <item>the .ssh/ directory contains the public key just received in the <c>authorized_keys</c> file</item>
+ </list>
+ <p>if so, the user is authorized.
+ </p>
+ </section>
+ <section>
+ <title>The SSH server on UNIX/Linux/etc after a succesful authentication</title>
+ <p>After a succesful incoming authentication, a new process runs as the just authenticated user.</p>
+ <p>Next step is to start a service according to the ssh request. In case of a request of a shell,
+ a new one is started which handles the OS-commands that arrives from the client (that's "you").
+ </p>
+ <p>In case of a sftp request, an sftp server is started in with the user's rights. So it could read, write or delete
+ files if allowed for that user.
+ </p>
+ </section>
+ </section>
+
+ <section>
+ <title>In Erlang/OTP SSH</title>
+ <p>For the Erlang/OTP SSH server the situation is different. The server executes in an Erlang process
+ in the Erlang emulator which in turn executes in an OS process. The emulator does not try to change its
+ user when authenticated over the SSH protocol.
+ So the remote user name is only for authentication purposes in the Erlang/OTP SSH application.
+ </p>
+ <section>
+ <title>Password authentication in Erlang SSH</title>
+ <p>The Erlang/OTP SSH server checks the user name and password in the following order:
+ </p>
+ <list type="ordered">
+ <item>If a
+ <seealso marker="ssh:ssh#option-pwdfun"><c>pwdfun</c></seealso>
+ is defined, that one is called and the returned boolean is the authentication result.
+ </item>
+ <item>Else, if the
+ <seealso marker="ssh:ssh#option-user_passwords"><c>user_passwords</c></seealso>
+ option is defined and the username and the password matches, the authentication is a success.
+ </item>
+ <item>Else, if the option
+ <seealso marker="ssh:ssh#option-password"><c>password</c></seealso>
+ is defined and matches the password the authentication is a success.
+ Note that the use of this option is not recommended in non-test code.
+ </item>
+ </list>
+ </section>
+ <section>
+ <title>Public key authentication in Erlang SSH</title>
+ <p>The user name, public key and cryptographic data (a signature) that is sent by the client, are used as follows
+ (some steps left out for clearity):
+ </p>
+ <list type="ordered">
+ <item>A callback module is selected using the options
+ <seealso marker="ssh:ssh#type-key_cb_common_option"><c>key_cb</c></seealso>.
+ </item>
+ <item>The callback module is used to check that the provided public key is one of the user's pre-stored.
+ In case of the default callback module, the files <c>authorized_keys</c> and <c>authorized_keys2</c>
+ are searched in a directory found in the following order:
+ <list>
+ <item>If the option
+ <seealso marker="ssh:ssh_file#type-user_dir_fun_common_option"><c>user_dir_fun</c></seealso>
+ is defined, that fun is called and the returned directory is used,
+ </item>
+ <item>Else, If the option
+ <seealso marker="ssh:ssh_file#type-user_dir_common_option"><c>user_dir</c></seealso>
+ is defined, that directory is used,
+ </item>
+ <item>Else the subdirectory <c>.ssh</c> in the home directory of the user executing
+ the OS process of the Erlang emulator is used.
+ </item>
+ </list>
+ If the provided public key is not found, the authentication fails.
+ </item>
+ <item>Finally, if the provided public key is found, the signature provided by the client is checked with
+ the public key.
+ </item>
+ </list>
+ </section>
+ <section>
+ <title>The Erlang/OTP SSH server after a succesful authentication</title>
+ <p>After a successful authentication an <i>Erlang process</i> is handling the service request from the remote
+ ssh client. The rights of that process are those of the user of the OS process running the Erlang emulator.
+ </p>
+ <p>If a shell service request arrives to the server, an <i>Erlang shell</i> is opened in the server's emulator.
+ The rights in that shell is independent of the just authenticated user.
+ </p>
+ <p>In case of an sftp request, an sftp server is started with the rights of the user of the Erlang emulator's OS
+ process. So with sftp the authenticated user does not influence the rights.
+ </p>
+ <p>So after an authentication, the user name is not used anymore and has no influence.
+ </p>
+ </section>
+ </section>
+ </section>
+</chapter>
+
diff --git a/lib/ssh/doc/src/usersguide.xml b/lib/ssh/doc/src/usersguide.xml
index d902df6848..8a4df208d8 100644
--- a/lib/ssh/doc/src/usersguide.xml
+++ b/lib/ssh/doc/src/usersguide.xml
@@ -4,7 +4,7 @@
<part xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>2012</year><year>2016</year>
+ <year>2012</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -36,5 +36,6 @@
</description>
<xi:include href="introduction.xml"/>
<xi:include href="using_ssh.xml"/>
+ <xi:include href="terminology.xml"/>
<xi:include href="configure_algos.xml"/>
</part>
diff --git a/lib/ssh/doc/src/using_ssh.xml b/lib/ssh/doc/src/using_ssh.xml
index ab307624e6..a3d5efbe06 100644
--- a/lib/ssh/doc/src/using_ssh.xml
+++ b/lib/ssh/doc/src/using_ssh.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2012</year>
- <year>2017</year>
+ <year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -58,70 +58,68 @@
<c>ssh:shell/1</c> client to connect to the <em>openssh</em> daemon running on a
host called <em>tarlop</em>:</p>
- <code type="erl" >
- 1> ssh:start().
- ok
- 2> {ok, S} = ssh:shell("tarlop").
- otptest@tarlop:> pwd
- /home/otptest
- otptest@tarlop:> exit
- logout
- 3>
- </code>
+ <pre>
+1> <input>ssh:start().</input>
+ok
+2> <input>{ok, S} = ssh:shell("tarlop").</input>
+otptest@tarlop:> <input>pwd</input>
+/home/otptest
+otptest@tarlop:> <input>exit</input>
+logout
+3> </pre>
</section>
<section>
<marker id="Running an Erlang ssh Daemon"></marker>
<title>Running an Erlang ssh Daemon</title>
- <p>The <c>system_dir</c> option must be a directory containing a host
- key file and it defaults to <c>/etc/ssh</c>. For details, see Section
- Configuration Files in <seealso
- marker="SSH_app">ssh(6)</seealso>.
+ <p>The
+ <seealso marker="ssh_file#type-system_dir_daemon_option"><c>system_dir</c></seealso>
+ option must be a directory containing a host key file and it defaults to <c>/etc/ssh</c>.
+ For details, see Section Configuration Files in <seealso marker="SSH_app">ssh(6)</seealso>.
</p>
<note><p>Normally, the <c>/etc/ssh</c> directory is only readable by root.</p>
</note>
- <p>The option <c>user_dir</c> defaults to directory <c>users ~/.ssh</c>.</p>
+ <p>The option <seealso marker="ssh_file#type-user_dir_common_option"><c>user_dir</c></seealso>
+ defaults to directory <c>users ~/.ssh</c>.</p>
<p><em>Step 1.</em> To run the example without root privileges,
generate new keys and host keys:</p>
- <code>
- $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
- [...]
- </code>
+ <pre>
+$bash> <input>ssh-keygen -t rsa -f /tmp/ssh_daemon/ssh_host_rsa_key</input>
+[...]
+$bash> <input>ssh-keygen -t rsa -f /tmp/otptest_user/.ssh/id_rsa</input>
+[...] </pre>
<p><em>Step 2.</em> Create the file <c>/tmp/otptest_user/.ssh/authorized_keys</c>
and add the content of <c>/tmp/otptest_user/.ssh/id_rsa.pub</c>.</p>
+ <marker id="start-daemon-step3"></marker>
<p><em>Step 3.</em> Start the Erlang <c>ssh</c> daemon:</p>
- <code type="erl">
- 1> ssh:start().
- ok
- 2> {ok, Sshd} = ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"},
- {user_dir, "/tmp/otptest_user/.ssh"}]).
- {ok,&lt;0.54.0>}
- 3>
- </code>
+ <pre>
+1> <input>ssh:start().</input>
+ok
+2> <input>{ok, Sshd} = ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"},
+ {user_dir, "/tmp/otptest_user/.ssh"}]).</input>
+{ok,&lt;0.54.0>}
+3> </pre>
<p><em>Step 4.</em> Use the <em>openssh</em> client from a shell to connect
to the Erlang <c>ssh</c> daemon:</p>
- <code>
- $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>
- </code>
+ <pre>
+$bash> <input>ssh tarlop -p 8989 -i /tmp/otptest_user/.ssh/id_rsa \
+ -o UserKnownHostsFile=/tmp/otptest_user/.ssh/known_hosts</input>
+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)? <input>yes</input>
+Warning: Permanently added 'tarlop' (RSA) to the list of known hosts.
+Eshell V5.10 (abort with ^G)
+1> </pre>
<p>There are two ways of shutting down an <c>ssh</c> daemon,
see <em>Step 5a</em> and <em>Step 5b</em>.</p>
@@ -130,61 +128,299 @@
stops the listener but leaves existing connections, started by the listener,
operational:</p>
- <code type="erl">
- 3> ssh:stop_listener(Sshd).
- ok
- 4>
- </code>
+ <pre>
+3> <input>ssh:stop_listener(Sshd).</input>
+ok
+4> </pre>
<p><em>Step 5b.</em> Shut down the Erlang <c>ssh</c> daemon so that it
stops the listener and all connections started by the listener:</p>
- <code type="erl">
- 3> ssh:stop_daemon(Sshd)
- ok
- 4>
- </code>
-
+ <pre>
+3> <input>ssh:stop_daemon(Sshd).</input>
+ok
+4> </pre>
</section>
<section>
<title>One-Time Execution</title>
+ <section>
+ <marker id="simple-client-example"/>
+ <title>Erlang client contacting OS standard ssh server</title>
<p>In the following example, the Erlang shell is the client process
- that receives the channel replies.</p>
-
- <note><p>The number of received messages in this example depends on which OS
- and which shell that is used on the machine running the <c>ssh</c> daemon.
- See also <seealso marker="ssh_connection#exec-4">ssh_connection:exec/4</seealso>.
- </p></note>
-
- <p>Do a one-time execution of a remote command over <c>ssh</c>:</p>
-
- <code type="erl" >
- 1> ssh:start().
- ok
- 2> {ok, ConnectionRef} = ssh:connect("tarlop", 22, []).
- {ok,&lt;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,&lt;0.57.0>,{data,0,0,&lt;&lt;"/home/otptest\n">>}}
- Shell got {ssh_cm,&lt;0.57.0>,{eof,0}}
- Shell got {ssh_cm,&lt;0.57.0>,{exit_status,0,0}}
- Shell got {ssh_cm,&lt;0.57.0>,{closed,0}}
- ok
- 6>
- </code>
-
- <p>Notice that only the channel is closed. The connection is still up and can
- handle other channels:</p>
+ that receives the channel replies as Erlang messages.</p>
+
+ <p>Do an one-time execution of a remote OS command ("pwd") over <c>ssh</c> to the
+ ssh server of the OS at the host "tarlop":</p>
+
+ <pre>
+1> <input>ssh:start().</input>
+ok
+2> <input>{ok, ConnectionRef} = ssh:connect("tarlop", 22, []).</input>
+{ok,&lt;0.57.0>}
+3> <input>{ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).</input>
+{ok,0}
+4> <input>success = ssh_connection:exec(ConnectionRef, ChannelId, "pwd", infinity).</input>
+5> <input>flush().</input> % Get all pending messages. NOTE: ordering may vary!
+Shell got {ssh_cm,&lt;0.57.0>,{data,0,0,&lt;&lt;"/home/otptest\n">>}}
+Shell got {ssh_cm,&lt;0.57.0>,{eof,0}}
+Shell got {ssh_cm,&lt;0.57.0>,{exit_status,0,0}}
+Shell got {ssh_cm,&lt;0.57.0>,{closed,0}}
+ok
+6> <input>ssh:connection_info(ConnectionRef, channels).</input>
+{channels,[]}
+7></pre>
+
+ <p>See <seealso marker="ssh_connection#description">ssh_connection</seealso> and
+ <seealso marker="ssh_connection#exec-4">ssh_connection:exec/4</seealso>
+ for finding documentation of the channel messages.</p>
+
+ <p>To collect the channel messages in a program, use <c>receive...end</c> instead of <c>flush/1</c>:</p>
+ <pre>
+5> <input>receive</input>
+5> <input> {ssh_cm, ConnectionRef, {data, ChannelId, Type, Result}} when Type == 0 -></input>
+5> <input> {ok,Result}</input>
+5> <input> {ssh_cm, ConnectionRef, {data, ChannelId, Type, Result}} when Type == 1 -></input>
+5> <input> {error,Result}</input>
+5> <input>end.</input>
+{ok,&lt;&lt;"/home/otptest\n">>}
+6></pre>
+
+
+ <p>Note that only the exec channel is closed after the one-time execution.
+ The connection is still up and can handle previously opened channels. It is also
+ possible to open a new channel:</p>
+
+ <pre>
+% try to open a new channel to check if the ConnectionRef is still open
+7> <input>{ok, NewChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).</input>
+{ok,1}
+8></pre>
+
+ <p>To close the connection, call the function <seealso marker="ssh#close-1"><c>ssh:close(ConnectionRef)</c></seealso>.
+ As an alternative, set the option
+ <seealso marker="ssh#type-max_idle_time_common_option"><c>{idle_time, 1}</c></seealso>
+ when opening the connection. This will cause the connection to be closed automaticaly when there are
+ no channels open for the specified time period, in this case 1 ms.
+ </p>
+ </section>
+
+ <section>
+ <title>OS standard client and Erlang daemon (server)</title>
+ <p>An Erlang SSH daemon could be called for one-time execution of a "command". The "command" must be
+ as if entered into the erlang shell, that is a sequence of Erlang
+ <seealso marker="doc/reference_manual:expressions">expressions</seealso> ended by a period (.).
+ Variables bound in that sequence will keep their bindings throughout the expression sequence.
+ The bindings are disposed when the result is returned.</p>
+ <p>Here is an example of a suitable expression sequence:</p>
+ <pre>
+A=1, B=2, 3 == (A + B).</pre>
+ <p>It evaluates to <c>true</c> if submitted to the Erlang daemon started in
+ <seealso marker="#start-daemon-step3">Step 3</seealso> above:</p>
+ <pre>
+$bash> <input>ssh tarlop -p 8989 "A=1, B=2, 3 == (A + B)."</input>
+true
+$bash></pre>
+
+ <p>The same example but now using the Erlang ssh client to contact the Erlang server:</p>
+ <pre>
+1> <input>{ok, ConnectionRef} = ssh:connect("tarlop", 8989, []).</input>
+{ok,&lt;0.216.0>}
+2> <input>{ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).</input>
+{ok,0}
+3> <input>success = ssh_connection:exec(ConnectionRef, ChannelId,
+ "A=1, B=2, 3 == (A + B).",
+ infinity).</input>
+success
+4> <input>flush().</input>
+Shell got {ssh_cm,&lt;0.216.0>,{data,0,0,&lt;&lt;"true">>}}
+Shell got {ssh_cm,&lt;0.216.0>,{exit_status,0,0}}
+Shell got {ssh_cm,&lt;0.216.0>,{eof,0}}
+Shell got {ssh_cm,&lt;0.216.0>,{closed,0}}
+ok
+5></pre>
+
+ <p>Note that Erlang shell specific functions and control sequences like for example
+ <c>h().</c> are not supported.
+ </p>
+ </section>
+
+ <section>
+ <title>I/O from a function called in an Erlang ssh daemon</title>
+
+ <p>Output to stdout on the server side is also displayed as well as the resulting term
+ from the function call:</p>
+ <pre>
+$bash> <input>ssh tarlop -p 8989 'io:format("Hello!~n~nHow are ~p?~n",[you]).'</input>
+Hello!
+
+How are you?
+ok
+$bash></pre>
+
+ <p>And similar for reading from stdin. As an example we use
+ <seealso marker="stdlib:io#read-1">io:read/1</seealso> which
+ displays the argument as a prompt on stdout, reads a term from stdin and returns it
+ in an ok-tuple:</p>
+ <pre>
+$bash> <input>ssh tarlop -p 8989 'io:read("write something: ").'</input>
+write something: <input>[a,b,c].</input>
+{ok,[a,b,c]}
+$bash></pre>
+
+ <p>The same example but using the Erlang ssh client:</p>
+ <pre>
+Eshell V10.5.2 (abort with ^G)
+1> <input>ssh:start().</input>
+ok
+2> <input>{ok, ConnectionRef} = ssh:connect(loopback, 8989, []).</input>
+{ok,&lt;0.92.0>}
+3> <input>{ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).</input>
+{ok,0}
+4> <input>success = ssh_connection:exec(ConnectionRef, ChannelId,
+ "io:read(\"write something: \").",
+ infinity).</input>
+success
+5> <input>flush().</input>
+Shell got {ssh_cm,&lt;0.92.0>,{data,0,0,&lt;&lt;"write something: ">>}}
+ok
+% All data is sent as binaries with string contents:
+6> <input>ok = ssh_connection:send(ConnectionRef, ChannelId, &lt;&lt;"[a,b,c].">>).</input>
+ok
+7> <input>flush().</input>
+ok
+%% Nothing is received, because the io:read/1
+%% requires the input line to end with a newline.
+
+%% Send a newline (it could have been included in the last send):
+8> <input>ssh_connection:send(ConnectionRef, ChannelId, &lt;&lt;"\n">>).</input>
+ok
+9> <input>flush().</input>
+Shell got {ssh_cm,&lt;0.92.0>,{data,0,0,&lt;&lt;"{ok,[a,b,c]}">>}}
+Shell got {ssh_cm,&lt;0.92.0>,{exit_status,0,0}}
+Shell got {ssh_cm,&lt;0.92.0>,{eof,0}}
+Shell got {ssh_cm,&lt;0.92.0>,{closed,0}}
+ok
+10></pre>
+ </section>
+
+ <section>
+ <title>Configuring the server's (daemon's) command execution</title>
+ <p>Every time a daemon <seealso marker="#running-an-erlang-ssh-daemon">is started</seealso>, it enables
+ one-time execution of commands as described in the
+ <seealso marker="#simple-client-example">previous section</seealso> unless explicitly disabled.
+ </p>
+
+ <p>There is often a need to configure some other exec evaluator to tailor the input language or
+ restrict the possible functions to call. There are two ways of doing this which will be shown with examples
+ below. See <seealso marker="ssh#daemon-2">ssh:daemon/2,3</seealso> and
+ <seealso marker="ssh#type-exec_daemon_option">exec_daemon_option()</seealso>) for details.</p>
+ <p>Examples of the two ways to configure the exec evaluator:</p>
+ <list type="ordered">
+ <item>Disable one-time execution.<br/>
+ To modify the daemon start example above to reject one-time execution requests,
+ we change <seealso marker="#start-daemon-step3">Step 3</seealso> by adding the option
+ <c>{exec, disabled}</c>
+ to:
+ <pre>
+1> <input>ssh:start().</input>
+ok
+2> <input>{ok, Sshd} = ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"},
+ {user_dir, "/tmp/otptest_user/.ssh"},
+ {exec, disabled}
+ ]).</input>
+{ok,&lt;0.54.0>}
+3> </pre>
+ <p>A call to that daemon will return the text "Prohibited." on stderr (depending on the client and OS),
+ and the exit status 255:</p>
+ <pre>
+$bash> <input>ssh tarlop -p 8989 "test."</input>
+Prohibited.
+$bash> <input>echo $?</input>
+255
+$bash> </pre>
+ <p>And the Erlang client library also returns the text "Prohibited." on data type 1 instead of the normal 0
+ and exit status 255:</p>
+ <pre>
+2> <input>{ok, ConnectionRef} = ssh:connect(loopback, 8989, []).</input>
+{ok,&lt;0.92.0>}
+3> <input>{ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).</input>
+{ok,0}
+4> <input>success = ssh_connection:exec(ConnectionRef, ChannelId, "test."</input>
+success
+5> <input>flush().</input>
+Shell got {ssh_cm,&lt;0.106.0>,{data,0,1,&lt;&lt;"Prohibited.">>}}
+Shell got {ssh_cm,&lt;0.106.0>,{exit_status,0,255}}
+Shell got {ssh_cm,&lt;0.106.0>,{eof,0}}
+Shell got {ssh_cm,&lt;0.106.0>,{closed,0}}
+ok
+6></pre>
+ </item>
+
+ <item>Install an alternative evaluator.<br/>
+ Start the damon with a reference to a <c>fun()</c> that handles the evaluation:
+ <pre>
+1> <input>ssh:start().</input>
+ok
+2> <input>MyEvaluator = fun("1") -> {ok, some_value};
+ ("2") -> {ok, some_other_value};
+ ("3") -> {ok, V} = io:read("input erlang term>> "),
+ {ok, V};
+ (Err) -> {error,{bad_input,Err}}
+ end.</input>
+3> <input>{ok, Sshd} = ssh:daemon(1234, [{system_dir, "/tmp/ssh_daemon"},
+ {user_dir, "/tmp/otptest_user/.ssh"},
+ {exec, {direct,MyEvaluator}}
+ ]).</input>
+{ok,&lt;0.275.0>}
+4></pre>
+ and call it:
+ <pre>
+$bash> <input>ssh localhost -p 1234 1</input>
+some_value
+$bash> <input>ssh localhost -p 1234 2</input>
+some_other_value
+# I/O works:
+$bash> <input>ssh localhost -p 1234 3</input>
+input erlang term>> <input>abc.</input>
+abc
+# Check that Erlang evaluation is disabled:
+$bash> <input>ssh localhost -p 1234 1+ 2.</input>
+**Error** {bad_input,"1+ 2."}
+$bash> </pre>
+ Note that spaces are preserved and that no point (.) is needed at the end - that was required
+ by the default evaluator.
+ <p>The error return in the Erlang client (The text as data type 1 and exit_status 255):</p>
+ <pre>
+2> <input>{ok, ConnectionRef} = ssh:connect(loopback, 1234, []).</input>
+{ok,&lt;0.92.0>}
+3> <input>{ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).</input>
+{ok,0}
+4> <input>success = ssh_connection:exec(ConnectionRef, ChannelId, "1+ 2."</input>
+success
+5> <input>flush().</input>
+Shell got {ssh_cm,&lt;0.106.0>,{data,0,1,&lt;&lt;"**Error** {bad_input,\"1+ 2.\"}">>}}
+Shell got {ssh_cm,&lt;0.106.0>,{exit_status,0,255}}
+Shell got {ssh_cm,&lt;0.106.0>,{eof,0}}
+Shell got {ssh_cm,&lt;0.106.0>,{closed,0}}
+ok
+6></pre>
+ <p>The <c>fun()</c> in the exec option could take up to three arguments
+ (<c>Cmd</c>, <c>User</c> and <c>ClientAddress</c>). See
+ the <seealso marker="ssh#type-exec_daemon_option">exec_daemon_option()</seealso> for the details.</p>
+ </item>
+ </list>
+
+
+ <note><p>An old, discouraged and undocumented way of installing an alternative evaluator exists.</p>
+ <p>It still works, but lacks
+ for example I/O possibility. It is because of that compatibility we need
+ the <c>{direct,...}</c> construction.
+ </p>
+ </note>
+ </section>
- <code type="erl" >
- 6> {ok, NewChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).
- {ok,1}
- ...
- </code>
</section>
<section>
@@ -192,27 +428,26 @@
<p>Start the Erlang <c>ssh</c> daemon with the SFTP subsystem:</p>
- <code type="erl" >
- 1> ssh:start().
- ok
- 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,&lt;0.54.0>}
- 3>
- </code>
+ <pre>
+1> <input>ssh:start().</input>
+ok
+2> <input>ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"},
+ {user_dir, "/tmp/otptest_user/.ssh"},
+ {subsystems, [ssh_sftpd:subsystem_spec(
+ [{cwd, "/tmp/sftp/example"}])
+ ]}]).</input>
+{ok,&lt;0.54.0>}
+3> </pre>
<p>Run the OpenSSH SFTP client:</p>
- <code type="erl">
- $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
- sftp>
- </code>
+ <pre>
+$bash> <input>sftp -oPort=8989 -o IdentityFile=/tmp/otptest_user/.ssh/id_rsa \
+ -o UserKnownHostsFile=/tmp/otptest_user/.ssh/known_hosts tarlop</input>
+Connecting to tarlop...
+sftp> <input>pwd</input>
+Remote working directory: /tmp/sftp/example
+sftp> </pre>
</section>
<section>
@@ -220,35 +455,39 @@
<p>Fetch a file with the Erlang SFTP client:</p>
- <code type="erl" >
- 1> ssh:start().
- ok
- 2> {ok, ChannelPid, Connection} = ssh_sftp:start_channel("tarlop", []).
- {ok,&lt;0.57.0>,&lt;0.51.0>}
- 3> ssh_sftp:read_file(ChannelPid, "/home/otptest/test.txt").
- {ok,&lt;&lt;"This is a test file\n">>}
- </code>
+ <pre>
+1> <input>ssh:start().</input>
+ok
+2> <input>{ok, ChannelPid, Connection} = ssh_sftp:start_channel("tarlop", []).</input>
+{ok,&lt;0.57.0>,&lt;0.51.0>}
+3> <input>ssh_sftp:read_file(ChannelPid, "/home/otptest/test.txt").</input>
+{ok,&lt;&lt;"This is a test file\n">>} </pre>
</section>
<section>
- <title>SFTP Client with TAR Compression and Encryption</title>
-
- <p>Example of writing and then reading a tar file follows:</p>
+ <title>SFTP Client with TAR Compression</title>
+ <section>
+ <title>Basic example</title>
+ <p>This is an example of writing and then reading a tar file:</p>
<code type="erl">
- {ok,HandleWrite} = ssh_sftp:open_tar(ChannelPid, ?tar_file_name, [write]),
- ok = erl_tar:add(HandleWrite, .... ),
- ok = erl_tar:add(HandleWrite, .... ),
- ...
- ok = erl_tar:add(HandleWrite, .... ),
- ok = erl_tar:close(HandleWrite),
-
- %% And for reading
- {ok,HandleRead} = ssh_sftp:open_tar(ChannelPid, ?tar_file_name, [read]),
- {ok,NameValueList} = erl_tar:extract(HandleRead,[memory]),
- ok = erl_tar:close(HandleRead),
+{ok,HandleWrite} = ssh_sftp:open_tar(ChannelPid, ?tar_file_name, [write]),
+ok = erl_tar:add(HandleWrite, .... ),
+ok = erl_tar:add(HandleWrite, .... ),
+...
+ok = erl_tar:add(HandleWrite, .... ),
+ok = erl_tar:close(HandleWrite),
+
+%% And for reading
+{ok,HandleRead} = ssh_sftp:open_tar(ChannelPid, ?tar_file_name, [read]),
+{ok,NameValueList} = erl_tar:extract(HandleRead,[memory]),
+ok = erl_tar:close(HandleRead),
</code>
+ </section>
- <p>The previous write and read example can be extended with encryption and decryption as follows:</p>
+ <section>
+ <title>Example with encryption</title>
+ <p>The previous <seealso marker="using_ssh#basic-example">Basic example</seealso>
+ can be extended with encryption and decryption as follows:</p>
<code type="erl">
%% First three parameters depending on which crypto type we select:
Key = &lt;&lt;"This is a 256 bit key. abcdefghi">>,
@@ -296,8 +535,10 @@ Cr = {InitFun,DecryptFun},
ok = erl_tar:close(HandleRead),
</code>
</section>
+ </section>
<section>
+ <marker id="usersguide_creating_a_subsystem"/>
<title>Creating a Subsystem</title>
<p>A small <c>ssh</c> subsystem that echoes N bytes can be implemented as shown
@@ -305,7 +546,7 @@ ok = erl_tar:close(HandleRead),
<code type="erl" >
-module(ssh_echo_server).
--behaviour(ssh_daemon_channel).
+-behaviour(ssh_server_channel). % replaces ssh_daemon_channel
-record(state, {
n,
id,
@@ -359,31 +600,31 @@ terminate(_Reason, _State) ->
as described in Section <seealso marker="#Running an Erlang ssh Daemon">
Running an Erlang ssh Daemon</seealso>:</p>
- <code type="erl" >
- 1> ssh:start().
- ok
- 2> ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"},
- {user_dir, "/tmp/otptest_user/.ssh"}
- {subsystems, [{"echo_n", {ssh_echo_server, [10]}}]}]).
- {ok,&lt;0.54.0>}
- 3>
- </code>
-
- <code type="erl" >
- 1> ssh:start().
- ok
- 2>{ok, ConnectionRef} = ssh:connect("tarlop", 8989, [{user_dir, "/tmp/otptest_user/.ssh"}]).
- {ok,&lt;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, &lt;0.57.0>, {data, 0, 1, "0123456789"}}
- {ssh_msg, &lt;0.57.0>, {eof, 0}}
- {ssh_msg, &lt;0.57.0>, {closed, 0}}
- 7> {error, closed} = ssh_connection:send(ConnectionRef, ChannelId, "10", infinity).
- </code>
-<p>See also <seealso marker="ssh_channel"> ssh_channel(3)</seealso>.</p>
+ <pre>
+1> <input>ssh:start().</input>
+ok
+2> <input>ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"},
+ {user_dir, "/tmp/otptest_user/.ssh"}
+ {subsystems, [{"echo_n", {ssh_echo_server, [10]}}]}]).</input>
+{ok,&lt;0.54.0>}
+3> </pre>
+
+ <pre>
+1> <input>ssh:start().</input>
+ok
+2> <input>{ok, ConnectionRef} = ssh:connect("tarlop", 8989,
+ [{user_dir, "/tmp/otptest_user/.ssh"}]).</input>
+ {ok,&lt;0.57.0>}
+3> <input>{ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).</input>
+4> <input>success = ssh_connection:subsystem(ConnectionRef, ChannelId, "echo_n", infinity).</input>
+5> <input>ok = ssh_connection:send(ConnectionRef, ChannelId, "0123456789", infinity).</input>
+6> <input>flush().</input>
+{ssh_msg, &lt;0.57.0>, {data, 0, 1, "0123456789"}}
+{ssh_msg, &lt;0.57.0>, {eof, 0}}
+{ssh_msg, &lt;0.57.0>, {closed, 0}}
+7> <input>{error, closed} = ssh_connection:send(ConnectionRef, ChannelId, "10", infinity).</input> </pre>
+
+<p>See also <seealso marker="ssh_client_channel">ssh_client_channel(3)</seealso> (replaces ssh_channel(3)).</p>
</section>